Filter out stale accessibility events.
This commit is contained in:
1 parent
9e15f8652d
commit
f23e89ed93
10 files changed
+469
-2
No files matched your search
@@ -398,6 +398,15 @@ func (adapter *Adapter) enrichNativeWindowEvent(event *C.AtspiEvent, target *C.A
|
||||
|
||||
//export cthulhuAtspiEventCallback
|
||||
func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
dispatch_native_event(event, userData, false, 0)
|
||||
}
|
||||
|
||||
//export cthulhuAtspiSelectionCallback
|
||||
func cthulhuAtspiSelectionCallback(event *C.AtspiEvent, userData unsafe.Pointer, epoch C.uint64_t) {
|
||||
dispatch_native_event(event, userData, true, uint64(epoch))
|
||||
}
|
||||
|
||||
func dispatch_native_event(event *C.AtspiEvent, userData unsafe.Pointer, deferredSelection bool, selectionEpoch uint64) {
|
||||
if event == nil || userData == nil {
|
||||
return
|
||||
}
|
||||
@@ -408,6 +417,9 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
return
|
||||
}
|
||||
secureEpoch := adapter.secureEpoch.Load()
|
||||
if deferredSelection && (selectionEpoch != secureEpoch || adapter.secure.Load()) {
|
||||
return
|
||||
}
|
||||
// Retire copied header identities even while locked. Tab lifecycle only
|
||||
// checks roles; it never captures text or presents output.
|
||||
nativeEventType := C.GoString(C.cthulhu_event_type(event))
|
||||
@@ -422,10 +434,20 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
}
|
||||
eventType := canonicalObjectChangeEventType(nativeEventType)
|
||||
originID := nativeObjectID(event.source)
|
||||
adapter.retireEchoFocus(eventType, int(C.cthulhu_event_detail1(event)), originID)
|
||||
// Retired GTK cells can emit hundreds of obsolete focus/selection claims
|
||||
// during a rebuild. Leave lifecycle retirement on its established path,
|
||||
// but avoid all snapshot and foreground queries for known-dead targets.
|
||||
switch eventType {
|
||||
case FocusEvent, FocusedStateEvent, SelectedStateEvent, SelectionChangedEvent, ActiveDescendantEvent:
|
||||
if C.cthulhu_accessible_known_dead(event.source) != 0 ||
|
||||
eventType == ActiveDescendantEvent && C.cthulhu_accessible_known_dead(C.cthulhu_event_active_descendant(event)) != 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
if eventType == AccessibleNameEvent || eventType == DefunctStateEvent && C.cthulhu_event_detail1(event) != 0 {
|
||||
C.cthulhu_forget_menu_checkability(event.source)
|
||||
}
|
||||
adapter.retireEchoFocus(eventType, int(C.cthulhu_event_detail1(event)), originID)
|
||||
if eventType != DefunctStateEvent || C.cthulhu_event_detail1(event) != 0 {
|
||||
adapter.retireLibreOfficeHeaders(event.source, eventType, originID)
|
||||
}
|
||||
@@ -438,6 +460,18 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
}
|
||||
|
||||
adapter.applySecureReset()
|
||||
gtkSelection := eventType == SelectionChangedEvent && C.cthulhu_gtk_table(event.source, 0) != 0
|
||||
// Structural events which only invalidate caches do not need a captured
|
||||
// selection between every removed row. A structural event that survives
|
||||
// invalidation below still flushes before its ordinary presentation path.
|
||||
selectionBoundary := eventType != DefunctStateEvent && !strings.HasPrefix(eventType, ChildrenChangedEvent)
|
||||
if !deferredSelection && selectionBoundary {
|
||||
if gtkSelection {
|
||||
C.cthulhu_flush_other_selection(adapter.callbackData, event.source)
|
||||
} else {
|
||||
C.cthulhu_flush_selection(adapter.callbackData)
|
||||
}
|
||||
}
|
||||
adapter.refreshForeground()
|
||||
if isDocumentLifecycleEvent(eventType) || eventType == DefunctStateEvent && C.cthulhu_event_detail1(event) != 0 {
|
||||
adapter.deferredLiveRegions.take(originID)
|
||||
@@ -505,6 +539,13 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
adapter.backgroundEventsFiltered.Add(1)
|
||||
return
|
||||
}
|
||||
// Seed an unknown toolkit identity only after foreground filtering, so a
|
||||
// background provider never delays this path with a toolkit lookup.
|
||||
if !deferredSelection && eventType == SelectionChangedEvent &&
|
||||
(gtkSelection || C.cthulhu_gtk_table(event.source, 1) != 0) {
|
||||
C.cthulhu_defer_selection(adapter.callbackData, event, C.uint64_t(secureEpoch))
|
||||
return
|
||||
}
|
||||
if tab := addedSelectedBrowserTab(event, eventType); tab != nil {
|
||||
defer C.g_object_unref(C.gpointer(tab))
|
||||
returnedTarget = tab
|
||||
@@ -517,6 +558,9 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
if invalidated && webNotification == nil && eventType == ChildrenAddedEvent && (live.politeness == "" || live.politeness == "off") {
|
||||
return
|
||||
}
|
||||
if !deferredSelection && !selectionBoundary {
|
||||
C.cthulhu_flush_selection(adapter.callbackData)
|
||||
}
|
||||
deferLive, completeLive := adapter.prepare_live_region(event, eventType, originID, live)
|
||||
if deferLive {
|
||||
return
|
||||
@@ -532,6 +576,13 @@ func cthulhuAtspiEventCallback(event *C.AtspiEvent, userData unsafe.Pointer) {
|
||||
if target == nil {
|
||||
return
|
||||
}
|
||||
if (eventType == FocusEvent || eventType == FocusedStateEvent || eventType == SelectedStateEvent ||
|
||||
eventType == ActiveDescendantEvent || eventType == SelectionChangedEvent) && C.cthulhu_accessible_known_dead(target) != 0 {
|
||||
if ownedTarget {
|
||||
C.g_object_unref(C.gpointer(target))
|
||||
}
|
||||
return
|
||||
}
|
||||
refreshNativeEventTarget(event, target, eventType)
|
||||
snapshot, popupFor, payload := adapter.captureNativeEventContent(event, target, eventType, originID, live, completeLive)
|
||||
eventType, inlineMenuID := normalizeNativeMenuFocus(event, target, eventType, originID, &snapshot)
|
||||
|
||||
Reference in new issue
Block a user