Repository navigation
feat(macos): Emit geometry notifications so VoiceOver tracks moved content - #826
Open
William-Selna wants to merge 2 commits into
Open
William-Selna wants to merge 2 commits into
William-Selna wants to merge 2 commits into
Conversation
…ntent When content moves under a stationary VoiceOver cursor -- the canonical case being a scroll while the cursor sits on an element inside the viewport -- the macOS adapter gave VoiceOver no signal that geometry had changed, so the cursor highlight stayed drawn at the element's old frame until some unrelated trigger made VoiceOver re-read it. The element's accessibilityFrame was correct the whole time; nothing prompted a re-read. Two complementary additions fix that: * The event generator compares each updated node's bounding box and queues a single NSAccessibilityLayoutChangedNotification per tree update, posted on the focused element (root fallback) with no user info. Both details matter: NSAccessibilityUIElementsKey marks elements as added or changed, which makes VoiceOver move focus and re-announce, and posting one notification per moved node fires at scroll rate with the same effect. * Adapter::scroll_settled_event, surfaced on SubclassingAdapter, re-posts the focus notification on the still-focused node. That is the documented trigger that makes VoiceOver re-read an element's frame and re-anchor its cursor. Toolkits call it once per scroll gesture, after the scroll offset settles, never once per frame. This brings macOS closer to the Unix adapter, which already emits ObjectEvent::BoundsChanged on a bounds and transform delta. EventGenerator no longer holds the Context. It only used it to build the QueuedEvents at the end, so the Adapter now does that instead, which lets the event generator be unit tested without AppKit and therefore without pinning the tests to the main thread.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When content moves under a stationary VoiceOver cursor (for example a scroll with the cursor on an element inside the viewport), the macOS adapter emits nothing, so the cursor highlight stays at the element's old frame until something unrelated makes VoiceOver re-read it.
This queues one
NSAccessibilityLayoutChangedNotificationper tree update that changed any exposed node's bounds, posted on the focused element without user info, and addsAdapter::scroll_settled_eventso a toolkit can re-post the focus notification once per scroll gesture, which is what actually makes VoiceOver re-anchor its cursor.Although Chromium, WebKit and Firefox post nothing on scroll and live with the stale highlight, the Unix adapter already emits
BoundsChanged, so this would create parity between platforms.Although Chromium, WebKit and Firefox post nothing on scroll and live with the stale highlight.
I verified the implementation live with VoiceOver on MacOS
Also moves
QueuedEventsconstruction out ofEventGeneratorso the batching logic is unit-testable without AppKit.