tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1b61767689e5fbbe68d7f751d1950b542c4e2901
parent e68d92a91aac8905aae22bb4a5d66f551448a8e6
Author: David Shin <dshin@mozilla.com>
Date:   Thu, 18 Dec 2025 22:12:11 +0000

Bug 2004596: Modify containing block with both grid and position-area. r=layout-anchor-positioning-reviewers,layout-reviewers,emilio

Current position-area computation is spec-complaint so that it can handle
anchors outside of its containing block, so we can simply feed the result
of the grid adjusted containing block.

Differential Revision: https://phabricator.services.mozilla.com/D277052

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 98+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Dtesting/web-platform/meta/css/css-anchor-position/position-area-in-grid.html.ini | 6------
2 files changed, 56 insertions(+), 48 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -1210,54 +1210,68 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( aAnchorPosResolutionCache, firstTryIndex == currentFallbackIndex); auto cb = [&]() { - if (aAnchorPosResolutionCache) { - const auto defaultAnchorInfo = - AnchorPositioningUtils::ResolveAnchorPosRect( - aKidFrame, aDelegatingFrame, nullptr, false, - aAnchorPosResolutionCache); - if (defaultAnchorInfo) { - auto positionArea = aKidFrame->StylePosition()->mPositionArea; - if (!positionArea.IsNone()) { - // Offset should be up to, but not including the containing block's - // scroll offset. - const auto offset = AnchorPositioningUtils::GetScrollOffsetFor( - aAnchorPosResolutionCache->mReferenceData - ->CompensatingForScrollAxes(), - aKidFrame, aAnchorPosResolutionCache->mDefaultAnchorCache); - // Imagine an abspos container with a scroller in it, and then an - // anchor in it, where the anchor is visually in the middle of the - // scrollport. Then, when the scroller moves such that the anchor's - // left edge is on that of the scrollports, w.r.t. containing block, - // the anchor is zero left offset horizontally. The position-area - // grid needs to account for this. - const auto scrolledAnchorRect = defaultAnchorInfo->mRect - offset; - StylePositionArea resolvedPositionArea{}; - const auto scrolledAnchorCb = AnchorPositioningUtils:: - AdjustAbsoluteContainingBlockRectForPositionArea( - scrolledAnchorRect + aOriginalContainingBlockRect.TopLeft(), - aOriginalScrollableContainingBlockRect, - aKidFrame->GetWritingMode(), - aDelegatingFrame->GetWritingMode(), positionArea, - &resolvedPositionArea); - return ContainingBlockRect{ - offset, resolvedPositionArea, - aOriginalScrollableContainingBlockRect, - // Unscroll the CB by canceling out the previously applied - // scroll offset (See above), the offset will be applied later. - scrolledAnchorCb + offset}; - } - return ContainingBlockRect{aOriginalScrollableContainingBlockRect}; + // The current containing block, with ongoing modifications. + // Starts as a local containing block. + nsRect containingBlock = aOriginalContainingBlockRect; + const auto defaultAnchorInfo = [&]() -> Maybe<AnchorPosInfo> { + if (!aAnchorPosResolutionCache) { + return Nothing{}; } + return AnchorPositioningUtils::ResolveAnchorPosRect( + aKidFrame, aDelegatingFrame, nullptr, false, + aAnchorPosResolutionCache); + }(); + if (defaultAnchorInfo) { + // Presence of a valid default anchor causes us to use the scrollable + // containing block. + // https://github.com/w3c/csswg-drafts/issues/12552#issuecomment-3210696721 + containingBlock = aOriginalScrollableContainingBlockRect; } + // https://drafts.csswg.org/css-position/#original-cb + // Handle grid-based adjustment first... if (isGrid) { - // TODO(emilio, bug 2004596): This adjustment is supposed to also - // restrict the position-area rect above... const auto border = aDelegatingFrame->GetUsedBorder(); const nsPoint borderShift{border.left, border.top}; // Shift in by border of the overall grid container. - return ContainingBlockRect{nsGridContainerFrame::GridItemCB(aKidFrame) + - borderShift}; + containingBlock = + nsGridContainerFrame::GridItemCB(aKidFrame) + borderShift; + if (!defaultAnchorInfo) { + return ContainingBlockRect{containingBlock}; + } + } + // ... Then the position-area based adjustment. + if (defaultAnchorInfo) { + auto positionArea = aKidFrame->StylePosition()->mPositionArea; + if (!positionArea.IsNone()) { + // Offset should be up to, but not including the containing block's + // scroll offset. + const auto offset = AnchorPositioningUtils::GetScrollOffsetFor( + aAnchorPosResolutionCache->mReferenceData + ->CompensatingForScrollAxes(), + aKidFrame, aAnchorPosResolutionCache->mDefaultAnchorCache); + // Imagine an abspos container with a scroller in it, and then an + // anchor in it, where the anchor is visually in the middle of the + // scrollport. Then, when the scroller moves such that the anchor's + // left edge is on that of the scrollports, w.r.t. containing block, + // the anchor is zero left offset horizontally. The position-area + // grid needs to account for this. + const auto scrolledAnchorRect = defaultAnchorInfo->mRect - offset; + StylePositionArea resolvedPositionArea{}; + const auto scrolledAnchorCb = AnchorPositioningUtils:: + AdjustAbsoluteContainingBlockRectForPositionArea( + scrolledAnchorRect + aOriginalContainingBlockRect.TopLeft(), + containingBlock, aKidFrame->GetWritingMode(), + aDelegatingFrame->GetWritingMode(), positionArea, + &resolvedPositionArea); + return ContainingBlockRect{ + offset, resolvedPositionArea, + aOriginalScrollableContainingBlockRect, + // Unscroll the CB by canceling out the previously applied + // scroll offset (See above), the offset will be applied later. + scrolledAnchorCb + offset}; + } + return ContainingBlockRect{containingBlock}; } if (ViewportFrame* viewport = do_QueryFrame(aDelegatingFrame)) { @@ -1269,7 +1283,7 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( dom::ViewTransition::SnapshotContainingBlockRect( viewport->PresContext())}; } - return ContainingBlockRect{aOriginalContainingBlockRect}; + return ContainingBlockRect{containingBlock}; }(); if (aAnchorPosResolutionCache) { const auto& originalCb = cb.mMaybeScrollableRect; diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-in-grid.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-in-grid.html.ini @@ -1,6 +0,0 @@ -[position-area-in-grid.html] - [Offsets for position-area: span-bottom span-left and insets: {"left":"auto","right":"auto","top":"auto","bottom":"auto"}] - expected: FAIL - - [Offsets for position-area: span-bottom span-left and insets: {"left":"10px","right":"10px","top":"10px","bottom":"10px"}] - expected: FAIL