// Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "git.stormux.org/storm/cthulhu/internal/atspi" "git.stormux.org/storm/cthulhu/internal/review" ) // The event loop retains classification, not authority, alongside its current // snapshot. Every replacement clears it, including a native update of the same // object. Only complete owned document ancestry can opt Where Am I into export. type currentSpeechSource struct { origin speechOrigin focus atspi.ObjectID epoch uint64 } func (state *eventLoopState) setCurrent(snapshot atspi.Snapshot) { state.currentRevision++ state.current = snapshot state.currentSpeech = currentSpeechSource{} } func (state *eventLoopState) setCurrentDocument(result review.Result) { state.setCurrent(result.DocumentPosition.Snapshot) sources := result.DocumentCaretContext if result.Err != nil || !state.current.ID().Valid() || len(sources) == 0 || sources[0].ID() != state.current.ID() { return } origin := review_speech_origin(sources) if source := accessibility_speech_origin(state.current); source != speechOriginLocal { origin = source } state.currentSpeech = currentSpeechSource{origin: origin, focus: result.DocumentFocus, epoch: result.DocumentEpoch} } func (handler *eventReviewHandler) currentSpeechOrigin() speechOrigin { source := handler.state.currentSpeech if handler.objectReview == nil || !source.focus.Valid() || source.focus != handler.objectReview.Focus() || !handler.objectReview.CurrentDocumentResult(review.Result{DocumentEpoch: source.epoch}) { return speechOriginUnknown } return source.origin }