Reset master to testing content
This commit is contained in:
1 parent
0f2587b719
commit
42afa2a56c
1483 files changed
+145308
-938069
No files matched your search
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package atspi
|
||||
|
||||
// IsEchoEditField requires positive editable metadata. Text roles alone also
|
||||
// describe labels and read-only documents; terminals are not edit fields.
|
||||
func IsEchoEditField(snapshot Snapshot) bool {
|
||||
return snapshot.Editable && !snapshot.ReadOnly && !snapshot.Defunct &&
|
||||
snapshot.Role != "password text" && snapshot.Role != "terminal"
|
||||
}
|
||||
|
||||
type echoFocus struct {
|
||||
object, origin, window ObjectID
|
||||
epoch uint64
|
||||
editable bool
|
||||
}
|
||||
|
||||
// EditFieldFocused reads copied metadata only. The GLib owner publishes it;
|
||||
// foreground epochs reject stale focus even before queued events are consumed.
|
||||
func (adapter *Adapter) EditFieldFocused() bool {
|
||||
focus := adapter.echoFocus.Load()
|
||||
foreground := adapter.Foreground()
|
||||
return !adapter.secure.Load() && focus != nil && focus.editable &&
|
||||
focus.epoch == foreground.Epoch && (!foreground.Client.Known || foreground.Client.Window != 0)
|
||||
}
|
||||
|
||||
func (adapter *Adapter) observeEchoFocus(event Event) {
|
||||
if event.ForegroundMismatch || event.Foreground.Epoch != adapter.Foreground().Epoch {
|
||||
return
|
||||
}
|
||||
current := adapter.echoFocus.Load()
|
||||
if event.Type == WindowActivatedEvent && !event.Source.Focused {
|
||||
if current != nil && event.Window != current.window {
|
||||
adapter.echoFocus.Store(nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
gain := event.Type == FocusEvent || event.Type == FocusedStateEvent && event.Detail1 != 0 ||
|
||||
event.Type == WindowActivatedEvent && event.Source.Focused
|
||||
if !gain && (current == nil || current.object != event.Source.ID()) {
|
||||
return
|
||||
}
|
||||
if !event.Source.ID().Valid() {
|
||||
return
|
||||
}
|
||||
origin := NewObjectID(event.Source.BusName, event.OriginPath)
|
||||
if !gain && current != nil {
|
||||
origin = current.origin
|
||||
}
|
||||
adapter.echoFocus.Store(&echoFocus{object: event.Source.ID(), origin: origin,
|
||||
window: event.Window, epoch: event.Foreground.Epoch,
|
||||
editable: IsEchoEditField(event.Source) && event.Source.Focused})
|
||||
}
|
||||
|
||||
// Retire before filtering focus losses or dead objects out of speech delivery.
|
||||
func (adapter *Adapter) retireEchoFocus(kind string, detail int, source ObjectID) {
|
||||
current := adapter.echoFocus.Load()
|
||||
if current == nil {
|
||||
return
|
||||
}
|
||||
matched := source == current.object || source == current.origin || source == current.window
|
||||
if (kind == FocusedStateEvent && detail == 0 || kind == DefunctStateEvent && detail != 0 ||
|
||||
kind == WindowDestroyedEvent || kind == WindowDeactivatedEvent) && matched ||
|
||||
(kind == FocusEvent || kind == FocusedStateEvent && detail != 0) && source.BusName == current.object.BusName {
|
||||
adapter.echoFocus.Store(nil)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user