Bug 1765460 part 2: Add the scroll offset of the parent in ParentRelativeBounds. r=morgan

This means that cached bounds stay the same regardless of scroll offset.
The scroll position gets subtracted later when calculating absolute bounds.

Differential Revision: https://phabricator.services.mozilla.com/D144392
This commit is contained in:
James Teh 2022-04-26 07:05:50 +00:00
parent 38d42cbd8e
commit 4e63bbff78
3 changed files with 54 additions and 9 deletions

View File

@ -672,22 +672,34 @@ nsRect LocalAccessible::ParentRelativeBounds() {
}
nsIFrame* boundingFrame = FindNearestAccessibleAncestorFrame();
nsRect unionRect =
nsLayoutUtils::GetAllInFlowRectsUnion(frame, boundingFrame);
nsRect result = nsLayoutUtils::GetAllInFlowRectsUnion(frame, boundingFrame);
if (unionRect.IsEmpty()) {
if (result.IsEmpty()) {
// If we end up with a 0x0 rect from above (or one with negative
// height/width) we should try using the ink overflow rect instead. If we
// use this rect, our relative bounds will match the bounds of what
// appears visually. We do this because some web authors (icloud.com for
// example) employ things like 0x0 buttons with visual overflow. Without
// this, such frames aren't navigable by screen readers.
nsRect overflow = frame->InkOverflowRectRelativeToSelf();
nsLayoutUtils::TransformRect(frame, boundingFrame, overflow);
return overflow;
result = frame->InkOverflowRectRelativeToSelf();
nsLayoutUtils::TransformRect(frame, boundingFrame, result);
}
return unionRect;
if (nsIScrollableFrame* sf =
mParent == mDoc
? mDoc->PresShellPtr()->GetRootScrollFrameAsScrollable()
: boundingFrame->GetScrollTargetFrame()) {
// If boundingFrame has a scroll position, result is currently relative
// to that. Instead, we want result to remain the same regardless of
// scrolling. We then subtract the scroll position later when calculating
// absolute bounds. We do this because we don't want to push cache
// updates for the bounds of all descendants every time we scroll.
nsPoint scrollPos = sf->GetScrollPosition().ApplyResolution(
mDoc->PresShellPtr()->GetResolution());
result.MoveBy(scrollPos.x, scrollPos.y);
}
return result;
}
return nsRect();

View File

@ -424,6 +424,9 @@ class LocalAccessible : public nsISupports, public Accessible {
/**
* Return boundaries rect relative to the frame of the parent accessible.
* The returned bounds are the same regardless of whether the parent is
* scrolled. This means the scroll position must be later subtracted to
* calculate absolute coordinates.
*/
virtual nsRect ParentRelativeBounds();

View File

@ -27,6 +27,16 @@ function testCachedScrollPosition(acc, expectedX, expectedY) {
);
}
function getCachedBounds(acc) {
let cachedBounds = "";
try {
cachedBounds = acc.cache.getStringProperty("relative-bounds");
} catch (e) {
ok(false, "Unable to fetch cached bounds from cache!");
}
return cachedBounds;
}
/**
* Test bounds of accessibles after scrolling
*/
@ -52,8 +62,15 @@ addAccessibleTask(
await testBoundsInContent(docAcc, "square", browser);
await testBoundsInContent(docAcc, "rect", browser);
// Scroll rect into view, but also make it reflow so we can be sure the
// bounds are correct for reflowed frames.
await invokeContentTask(browser, [], () => {
content.document.getElementById("rect").scrollIntoView();
const rect = content.document.getElementById("rect");
rect.scrollIntoView();
rect.style.width = "300px";
rect.offsetTop; // Flush layout.
rect.style.width = "200px";
rect.offsetTop; // Flush layout.
});
await waitForContentPaint(browser);
@ -87,6 +104,8 @@ addAccessibleTask(
() => testCachedScrollPosition(docAcc, 0, 0),
"Correct initial scroll position."
);
const rectAcc = findAccessibleChildByID(docAcc, "rect");
const rectInitialBounds = getCachedBounds(rectAcc);
await invokeContentTask(browser, [], () => {
content.document.getElementById("square").scrollIntoView();
@ -101,8 +120,14 @@ addAccessibleTask(
"Correct scroll position after first scroll."
);
// Scroll rect into view, but also make it reflow so we can be sure the
// bounds are correct for reflowed frames.
await invokeContentTask(browser, [], () => {
content.document.getElementById("rect").scrollIntoView();
const rect = content.document.getElementById("rect");
rect.scrollIntoView();
rect.style.width = "300px";
rect.offsetTop;
rect.style.width = "200px";
});
await waitForContentPaint(browser);
@ -113,6 +138,11 @@ addAccessibleTask(
() => testCachedScrollPosition(docAcc, 0, 7100),
"Correct final scroll position."
);
await untilCacheIs(
() => getCachedBounds(rectAcc),
rectInitialBounds,
"Cached relative bounds don't change when scrolling"
);
},
{ iframe: true, remoteIframe: true }
);