99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package app
|
|
|
|
import (
|
|
"time"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
|
"git.stormux.org/storm/cthulhu/internal/config"
|
|
"git.stormux.org/storm/cthulhu/internal/notification"
|
|
"git.stormux.org/storm/cthulhu/internal/webscripts"
|
|
)
|
|
|
|
// webScriptController is owned by processEventsWithInput. Delayed presentation
|
|
// runs in that loop, preserving event order without timer callback goroutines.
|
|
type webScriptController struct {
|
|
registry webscripts.Registry
|
|
timer *time.Timer
|
|
due <-chan time.Time
|
|
speech speechEnqueuer
|
|
notifications *notification.Presenter
|
|
braille interface {
|
|
Flash(string, config.BrailleOptions) bool
|
|
}
|
|
live *liveSettings
|
|
gate *focusGate
|
|
}
|
|
|
|
func (controller *webScriptController) handle(event atspi.Event) bool {
|
|
retiring := event.Type == atspi.WindowDestroyedEvent || event.Type == atspi.DefunctStateEvent && event.Detail1 != 0
|
|
if retiring {
|
|
id := event.Source.ID()
|
|
if event.Type == atspi.WindowDestroyedEvent && event.Window.Valid() {
|
|
id = event.Window
|
|
}
|
|
controller.registry.Retire(id.BusName, id.Path)
|
|
}
|
|
messages, handled := controller.registry.Receive(event.Source.ApplicationProcess,
|
|
event.Type, event.Detail1, event.WebNotification, time.Now())
|
|
controller.present(messages)
|
|
if handled || retiring {
|
|
controller.schedule()
|
|
}
|
|
return handled
|
|
}
|
|
|
|
func (controller *webScriptController) schedule() {
|
|
deadline := controller.registry.Deadline()
|
|
controller.due = nil
|
|
if controller.timer != nil {
|
|
controller.timer.Stop()
|
|
}
|
|
if deadline.IsZero() {
|
|
return
|
|
}
|
|
if controller.timer == nil {
|
|
controller.timer = time.NewTimer(time.Until(deadline))
|
|
} else {
|
|
controller.timer.Reset(time.Until(deadline))
|
|
}
|
|
controller.due = controller.timer.C
|
|
}
|
|
|
|
func (controller *webScriptController) flush() {
|
|
if controller.gate.Locked() {
|
|
controller.reset()
|
|
return
|
|
}
|
|
controller.present(controller.registry.Flush(time.Now()))
|
|
controller.schedule()
|
|
}
|
|
|
|
func (controller *webScriptController) present(messages []string) {
|
|
if controller.gate.Locked() {
|
|
return
|
|
}
|
|
for _, message := range messages {
|
|
controller.notifications.Save(message, notification.SaveOptions{AppName: "Steam", Source: "steam"})
|
|
if controller.braille != nil {
|
|
options := config.DefaultSettings().Braille
|
|
if controller.live != nil {
|
|
options = controller.live.Load().Braille
|
|
}
|
|
controller.braille.Flash(message, options)
|
|
}
|
|
controller.speech.Interrupt()
|
|
controller.speech.Enqueue(speechRequest{
|
|
Text: message, Role: "notification", Cause: "steam-notification", BypassFocusGate: true,
|
|
})
|
|
}
|
|
}
|
|
|
|
func (controller *webScriptController) reset() {
|
|
controller.registry.Reset()
|
|
controller.schedule()
|
|
}
|