67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package review
|
|
|
|
import "git.stormux.org/storm/cthulhu/internal/atspi"
|
|
|
|
// DocumentDiagnostics records bounded metadata for one navigation command. It
|
|
// never reads native objects or retains accessible text for diagnostic purposes.
|
|
type DocumentDiagnostics struct {
|
|
Attempts []DocumentAttempt `json:"attempts"`
|
|
CaptureAttempts int `json:"capture_attempts"`
|
|
CursorRecreated bool `json:"cursor_recreated"`
|
|
FocusRecovered bool `json:"focus_recovered"`
|
|
}
|
|
|
|
type DocumentAttempt struct {
|
|
Focus atspi.ObjectID `json:"focus"`
|
|
Before DocumentState `json:"before"`
|
|
Synced DocumentState `json:"synced"`
|
|
After DocumentState `json:"after"`
|
|
Recovery string `json:"recovery"`
|
|
Stage string `json:"stage"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
type DocumentState struct {
|
|
Document atspi.ObjectID `json:"document"`
|
|
Object atspi.ObjectID `json:"object"`
|
|
Focus atspi.ObjectID `json:"focus"`
|
|
TextParent atspi.ObjectID `json:"text_parent"`
|
|
Offset int `json:"offset"`
|
|
Origin string `json:"origin"`
|
|
Active bool `json:"active"`
|
|
}
|
|
|
|
func (cursor *DocumentCursor) diagnostic_state() DocumentState {
|
|
if cursor == nil {
|
|
return DocumentState{}
|
|
}
|
|
cursor.mu.Lock()
|
|
defer cursor.mu.Unlock()
|
|
if len(cursor.places) == 0 {
|
|
return DocumentState{}
|
|
}
|
|
place := cursor.places[len(cursor.places)-1]
|
|
origin := "native"
|
|
switch place.origin {
|
|
case StructuralNavigation:
|
|
origin = "structural"
|
|
case CaretNavigation:
|
|
origin = "caret"
|
|
}
|
|
return DocumentState{Document: place.document.ID(), Object: place.object.ID(),
|
|
Focus: place.focus.ID(), TextParent: place.textParent.ID(), Offset: place.offset,
|
|
Origin: origin, Active: cursor.active == place.document}
|
|
}
|
|
|
|
func (result *Result) record_document_attempt(cursor *DocumentCursor, attempt DocumentAttempt, err error) {
|
|
attempt.After = cursor.diagnostic_state()
|
|
if err != nil {
|
|
attempt.Error = err.Error()
|
|
}
|
|
result.DocumentDiagnostics.Attempts = append(result.DocumentDiagnostics.Attempts, attempt)
|
|
}
|