Files
cthulhu/internal/app/prompt_presentation.go

57 lines
2.1 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 (
"git.stormux.org/storm/cthulhu/internal/atspi"
"git.stormux.org/storm/cthulhu/internal/presentation"
)
type promptPresentation struct {
state *eventLoopState
event atspi.Event
activation bool
focus bool
}
func newPromptPresentation(state *eventLoopState, event atspi.Event) promptPresentation {
control := event.Source.Role == "button" || event.Source.Role == "tree table" || event.Source.Role == "table cell"
return promptPresentation{
state: state,
event: event,
activation: event.Type == atspi.WindowActivatedEvent && control && event.WindowMessage != "",
focus: isFocusGainEvent(event) && control && state.pendingPromptWindow.Valid() && event.Window == state.pendingPromptWindow,
}
}
func (prompt promptPresentation) focusSpeech(spoken, fallback presentation.Speech) (presentation.Speech, presentation.Speech) {
if prompt.focus && !prompt.state.pendingPromptTextAnnounced && prompt.event.WindowMessage != "" {
spoken = spoken.Prepend(prompt.event.WindowMessage, ", ")
fallback = spoken
}
return spoken, fallback
}
func (prompt promptPresentation) appendFocus() bool {
return prompt.focus && (prompt.state.pendingPromptTextAnnounced || prompt.event.WindowMessage != "")
}
func (prompt promptPresentation) finishFocus() {
if isFocusGainEvent(prompt.event) && (prompt.event.Source.Role == "button" || prompt.event.Source.Role == "tree table" || prompt.event.Source.Role == "table cell") {
prompt.state.pendingPromptWindow = atspi.ObjectID{}
prompt.state.pendingPromptTextAnnounced = false
}
}
func (prompt promptPresentation) rememberWindow() {
if (prompt.event.Type == atspi.WindowCreateEvent || prompt.event.Type == atspi.WindowActivatedEvent) &&
(prompt.event.Source.Role == "alert" || prompt.event.Source.Role == "frame" || prompt.activation) &&
prompt.event.Window.Valid() {
prompt.state.pendingPromptWindow = prompt.event.Window
prompt.state.pendingPromptTextAnnounced = prompt.event.Source.Text != "" || prompt.activation
}
}