Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: f3b6d2ac3f94074de46b2e61b19f48bf46a191db
      
https://github.com/WebKit/WebKit/commit/f3b6d2ac3f94074de46b2e61b19f48bf46a191db
  Author: Tyler Wilcock <[email protected]>
  Date:   2026-05-18 (Mon, 18 May 2026)

  Changed paths:
    A LayoutTests/accessibility/dialog-focus-on-open-expected.txt
    A LayoutTests/accessibility/dialog-focus-on-open.html
    M LayoutTests/platform/glib/TestExpectations
    M Source/WebCore/accessibility/mac/AXObjectCacheMac.mm

  Log Message:
  -----------
  AX: VoiceOver generally does not automatically move into dialogs, despite 
presence of the autofocus attribute and / or explicit focus() calls
https://bugs.webkit.org/show_bug.cgi?id=314893
rdar://177167634

Reviewed by Dominic Mazzoni.

When a <dialog> opens and the page focuses an element inside it (e.g. a heading
with tabindex="-1"), VoiceOver fails to move its cursor onto the focused 
element.

When dialog.show() runs, the dialog's content gets renderers and a 
children-changed
update is queued on the dialog's parent, but the actual subtree walk that adds 
new
descendants to the isolated tree's pending appends doesn't happen until
processQueuedNodeUpdates runs (via the snapshot timer, fired after
performDeferredCacheUpdate). When the deferred focus change runs first,
setIsolatedTreeFocusedObject writes the heading's AXID into focusedNodeID, but 
the
heading's AXIsolatedObject isn't in the reader-thread node map yet. Inside
NSAccessibilityHandleFocusChanged, AppKit synchronously calls
[NSApp accessibilityFocusedUIElement] on the same call stack. That lands on our
wrapper, goes through the AX thread to focusedNode(), and returns nil because 
the
focused AXID has no corresponding AXIsolatedObject. AppKit's currentElement is 
nil,
so it skips NSAccessibilityPostNotification entirely and VoiceOver is never 
told.

Fix this by calling processQueuedIsolatedNodeUpdates in 
platformHandleFocusedUIElementChanged
before NSAccessibilityHandleFocusChanged, so the focused object's subtree is in 
the
isolated tree before AppKit's synchronous focused-element query.

Also drop the callOnMainThread around the test-only 
accessibilityPostedNotification
call so the test path matches the timing of AppKit's synchronous
[NSApp accessibilityFocusedUIElement] query. With the previous async dispatch,
performDeferredCacheUpdate finished before the test JS listener fired, masking 
the
bug. Tests that need to dirty style/layout in the listener should defer it via
setTimeout (see focus-in-remote-frame.html), since real ATs cannot
synchronously dirty style/layout, and doing so in the middle of
performDeferredCacheUpdate breaks the invariant of layout needing to be
clean for the duration of the function.

* LayoutTests/accessibility/dialog-focus-on-open-expected.txt: Added.
* LayoutTests/accessibility/dialog-focus-on-open.html: Added.
* Source/WebCore/accessibility/mac/AXObjectCacheMac.mm:
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):

Canonical link: https://commits.webkit.org/313425@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to