58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
// Cthulhu screen reader.
|
|
// 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/input"
|
|
)
|
|
|
|
// pendingPresentation owns one coalesced event and its captured input intent.
|
|
// Only the main event loop accesses it; timers never run presentation callbacks.
|
|
// Replacing or clearing an event disconnects its old timer from the select loop.
|
|
type pendingPresentation struct {
|
|
event atspi.Event
|
|
intent input.Intent
|
|
timer *time.Timer
|
|
ready <-chan time.Time
|
|
}
|
|
|
|
func (pending *pendingPresentation) schedule(event atspi.Event, intent input.Intent, delay time.Duration) {
|
|
pending.clear()
|
|
pending.event, pending.intent = event, intent
|
|
pending.timer = time.NewTimer(delay)
|
|
pending.ready = pending.timer.C
|
|
}
|
|
|
|
func (pending *pendingPresentation) clear() {
|
|
if pending.timer != nil {
|
|
pending.timer.Stop()
|
|
}
|
|
*pending = pendingPresentation{}
|
|
}
|
|
|
|
func (pending *pendingPresentation) take() (atspi.Event, input.Intent) {
|
|
event, intent := pending.event, pending.intent
|
|
pending.clear()
|
|
return event, intent
|
|
}
|
|
|
|
// pendingPresentations bounds delayed presentation to one event per family.
|
|
// Its lifetime is the event loop's lifetime, including adapter closure.
|
|
type pendingPresentations struct {
|
|
caret pendingPresentation
|
|
terminalFocus pendingPresentation
|
|
terminalDeletion pendingPresentation
|
|
}
|
|
|
|
func (pending *pendingPresentations) clear() {
|
|
pending.caret.clear()
|
|
pending.terminalFocus.clear()
|
|
pending.terminalDeletion.clear()
|
|
}
|