136 lines
4.6 KiB
Go
136 lines
4.6 KiB
Go
// Cthulhu screen reader.
|
|
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation, either version 3 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
|
|
|
package review
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
|
)
|
|
|
|
// TreeCapturer performs native AT-SPI capture. Worker is the only runtime
|
|
// caller so capture latency cannot block the event or command loops.
|
|
type TreeCapturer interface {
|
|
CaptureDesktop(context.Context) (*atspi.AccessibleTree, error)
|
|
CaptureReviewWindow(context.Context, atspi.ObjectID) (*atspi.AccessibleTree, error)
|
|
CaptureDocument(context.Context, atspi.ObjectID) (*atspi.AccessibleTree, error)
|
|
CaptureDocumentText(context.Context, atspi.ObjectID) (*atspi.AccessibleTree, error)
|
|
}
|
|
|
|
// Fresh providers cannot reuse text from a previous review command.
|
|
type FreshReviewWindowCapturer interface{ FreshReviewWindow(atspi.ObjectID) bool }
|
|
|
|
// Resolve optional native operations without hiding the adapter's dynamic
|
|
// capabilities behind a capture router. Reserved provider IDs return nil.
|
|
type NativeCapturerResolver interface {
|
|
NativeCapturerFor(atspi.ObjectID) TreeCapturer
|
|
}
|
|
|
|
func (worker *Worker) nativeCapturerFor(id atspi.ObjectID) TreeCapturer {
|
|
if resolver, ok := worker.capturer.(NativeCapturerResolver); ok {
|
|
return resolver.NativeCapturerFor(id)
|
|
}
|
|
return worker.capturer
|
|
}
|
|
|
|
// Result describes one requested navigation step. A boundary has Moved false
|
|
// and no error; Position remains the current object in that case.
|
|
type Result struct {
|
|
ReadAllContext context.Context
|
|
ReadAllLines []atspi.DocumentLine
|
|
ReadAllProgress func(int)
|
|
ReadAllPosition bool
|
|
DocumentEpoch uint64
|
|
Elapsed time.Duration
|
|
CaptureDuration time.Duration
|
|
CaptureReason error
|
|
DocumentTarget DocumentTarget
|
|
DocumentCaretCommand DocumentCaretCommand
|
|
DocumentActivate bool
|
|
DocumentFragment bool
|
|
DocumentCaretText string
|
|
DocumentCaretRawText string
|
|
DocumentCaretLine *atspi.DocumentLine
|
|
DocumentTablePrefix string
|
|
DocumentTableSuffix string
|
|
|
|
DocumentTableRowHeader, DocumentTableColumnHeader string
|
|
|
|
DocumentCaretStart int
|
|
DocumentCaretEnd int
|
|
DocumentCaretContext []atspi.Snapshot
|
|
DocumentBrailleLine *atspi.DocumentCaretText
|
|
DocumentBrailleErr error
|
|
DocumentSoundErr error
|
|
DocumentBackwards bool
|
|
DocumentLevel int
|
|
DocumentWrapped bool
|
|
DocumentNativeCaret bool
|
|
DocumentBrailleRoute bool
|
|
DocumentPosition DocumentPosition
|
|
DocumentFocus atspi.ObjectID
|
|
Direction Direction
|
|
Position Position
|
|
Moved bool
|
|
Err error
|
|
CaretErr error
|
|
FlatUnit FlatUnit
|
|
FlatSpeech FlatSpeech
|
|
FlatStep int
|
|
FlatPosition FlatPosition
|
|
FlatFocus atspi.ObjectID
|
|
DocumentLine bool
|
|
DocumentLineRequest uint64
|
|
DocumentLineData atspi.DocumentLine
|
|
DocumentLineFocus atspi.ObjectID
|
|
DocumentLineText string
|
|
}
|
|
|
|
// request uses the existing ordered dispatch contract: native caret, Say All
|
|
// progress, Say All capture, document line, structural target, caret command,
|
|
// activation, fragment, flat unit, then object direction. Flags are deliberately
|
|
// retained; epoch and timeout retirement depend on their distinct combinations.
|
|
type request struct {
|
|
brailleRoute *documentBrailleRequest
|
|
interest *interestRequest
|
|
nativeCaret bool
|
|
nativeCaretFocus atspi.ObjectID
|
|
nativeCaretOffset int
|
|
readAll context.Context
|
|
readPosition *DocumentPosition
|
|
readTree *atspi.AccessibleTree
|
|
readFocus atspi.ObjectID
|
|
documentEpoch uint64
|
|
queuedAt time.Time
|
|
target DocumentTarget
|
|
caretCommand DocumentCaretCommand
|
|
activate bool
|
|
fragment string
|
|
backwards bool
|
|
level int
|
|
direction Direction
|
|
unit FlatUnit
|
|
flatSpeech FlatSpeech
|
|
step int
|
|
line bool
|
|
lineRequest uint64
|
|
lineFocus atspi.ObjectID
|
|
lineOffset int
|
|
}
|