Files
cthulhu/internal/app/event_announcement.go

44 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 (
"strings"
"time"
"git.stormux.org/storm/cthulhu/internal/atspi"
)
// presentAnnouncement speaks an object:announcement payload, mirroring Orca:
// the provider's text is presented verbatim. All provider announcements queue
// under the reader's input-driven interruption policy. Announcements commonly come from
// providers that never own focus (a compositor announcing a workspace
// switch, for example), so no focus or foreground ownership is required and
// none is taken. The caller's lock gate has already run; the speech output
// gate still rejects the request while the screen is locked.
func (handler *accessibilityEventHandler) presentAnnouncement(event atspi.Event) {
text := strings.TrimSpace(event.Payload)
if text == "" {
return
}
state := handler.state
// Some providers force re-emission of an unchanged message by altering
// trailing whitespace. Treat one trimmed repeat from the same provider
// inside the live-region dedupe window as the same announcement.
if text == state.lastAnnouncement && event.Source.BusName == state.lastAnnouncementBus &&
time.Since(state.lastAnnouncementAt) < 300*time.Millisecond {
return
}
state.lastAnnouncement, state.lastAnnouncementBus, state.lastAnnouncementAt = text, event.Source.BusName, time.Now()
handler.speech.Enqueue(speechRequest{
Text: text,
Role: "system",
Cause: atspi.AnnouncementEvent,
Append: true,
BypassFocusGate: true,
})
}