Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 79927d64201a2baed8ee1604f9c46cc4aa3c14c2
https://github.com/WebKit/WebKit/commit/79927d64201a2baed8ee1604f9c46cc4aa3c14c2
Author: Tyler Wilcock <[email protected]>
Date: 2026-07-01 (Wed, 01 Jul 2026)
Changed paths:
A
LayoutTests/accessibility/ios-simulator/local-frame-content-scroll-geometry-expected.txt
A
LayoutTests/accessibility/ios-simulator/local-frame-content-scroll-geometry.html
A
LayoutTests/accessibility/ios-simulator/local-frame-root-scroll-geometry-expected.txt
A
LayoutTests/accessibility/ios-simulator/local-frame-root-scroll-geometry.html
A LayoutTests/accessibility/resources/scrollable-iframe-content.html
M Source/WebCore/accessibility/AXObjectCache.cpp
M Source/WebCore/accessibility/AXObjectCache.h
M Source/WebCore/accessibility/AccessibilityObject.cpp
M Source/WebCore/accessibility/AccessibilityScrollView.cpp
M Source/WebCore/accessibility/AccessibilityScrollView.h
Log Message:
-----------
AX: After ACCESSIBILITY_LOCAL_FRAME, VoiceOver can read stale element
geometry after a frame scrolls its own content
https://bugs.webkit.org/show_bug.cgi?id=318158
rdar://179106823
Reviewed by Dominic Mazzoni.
With ENABLE(ACCESSIBILITY_LOCAL_FRAME), local frames compose an element's screen
position the same way remote frames do: a cached per-frame
AXFrameGeometry.screenPosition
(the frame's content origin on screen, with the frame's scroll baked in when it
was
sampled) plus the element's content-space rect. That cached geometry is
refreshed only
by an asynchronous re-push, so when a frame scrolls its own content, e.g. a
horizontal
CSS-column page-turn in Apple Books, the baked-in scroll goes stale until the
re-push
lands. An assistive technology reading in that window gets a mispositioned
rect, so
paginated content lands off the viewport and VoiceOver cannot reach it.
Stop depending on the re-push for a frame's own scroll. In convertFrameToSpace,
read the
current scroll live (we are on the main thread here), undo the stale sampled
scroll baked
into screenPosition, and re-apply the current scroll. In steady state the two
are equal
and this is a no-op. During the race it keeps the read correct. To carry the
sampled scroll
to the reader, capture it in AXObjectCache::setFrameGeometry and expose it via
frameViewOriginScrollPosition().
Also fix the related first-access case: when accessibility turns on,
frameGeometry()
returned the default {0,0} origin while it kicked off the asynchronous request,
so an AT
that walks and caches frames immediately would receive mispositioned rects.
Compute the
screen position synchronously on that first main-thread access instead, falling
back to
the asynchronous request only when it can't be computed in-process.
*
LayoutTests/accessibility/ios-simulator/local-frame-content-scroll-geometry-expected.txt:
Added.
*
LayoutTests/accessibility/ios-simulator/local-frame-content-scroll-geometry.html:
Added.
* LayoutTests/accessibility/resources/scrollable-iframe-content.html: Added.
* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::setFrameGeometry):
* Source/WebCore/accessibility/AXObjectCache.h:
* Source/WebCore/accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::convertFrameToSpace const):
* Source/WebCore/accessibility/AccessibilityScrollView.cpp:
(WebCore::AccessibilityScrollView::frameGeometry const):
(WebCore::AccessibilityScrollView::frameViewOriginScrollPosition const):
* Source/WebCore/accessibility/AccessibilityScrollView.h:
Canonical link: https://commits.webkit.org/316341@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications