tor-browser

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

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

Bug 2004596: Move grid absolute reflow after grid area is added to overflow. r=layout-reviewers,layout-anchor-positioning-reviewers,emilio

Adjusted ordering:

1. In-flow reflow
2. Overflow adjustment using grid-area + grid item margin rects from step 1
3. Abspos reflow, using overflow area from step 2 as scrollable containing
   block if the abspos element in question has a default anchor.

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

Diffstat:
Mlayout/generic/nsGridContainerFrame.cpp | 129++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mlayout/generic/nsGridContainerFrame.h | 5+++++
2 files changed, 74 insertions(+), 60 deletions(-)

diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp @@ -9299,46 +9299,55 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aGridRI, aDesiredSize.mOverflowAreas.UnionWith(ocBounds); aStatus.MergeCompletionStatusFrom(ocStatus); + return bSize; +} + +void nsGridContainerFrame::ReflowAbsoluteChildren(GridReflowInput& aGridRI, + const LogicalRect& aContentArea, + nscoord aContentBSize, + ReflowOutput& aDesiredSize, + nsReflowStatus& aStatus) { + WritingMode wm = aGridRI.mReflowInput->GetWritingMode(); auto* absoluteContainer = GetAbsoluteContainingBlock(); // We have prepared the absolute frames when initializing GridReflowInput. - if (absoluteContainer && absoluteContainer->HasAbsoluteFrames()) { - // 'gridOrigin' is the origin of the grid (the start of the first track), - // with respect to the grid container's padding-box (CB). - LogicalMargin pad(aGridRI.mReflowInput->ComputedLogicalPadding(wm)); - const LogicalPoint gridOrigin(wm, pad.IStart(wm), pad.BStart(wm)); - const LogicalRect gridCB(wm, 0, 0, - aContentArea.ISize(wm) + pad.IStartEnd(wm), - bSize + pad.BStartEnd(wm)); - const nsSize gridCBPhysicalSize = gridCB.Size(wm).GetPhysicalSize(wm); - size_t i = 0; - for (nsIFrame* child : absoluteContainer->GetChildList()) { - MOZ_ASSERT(i < aGridRI.mAbsPosItems.Length()); - MOZ_ASSERT(aGridRI.mAbsPosItems[i].mFrame == child); - GridArea& area = aGridRI.mAbsPosItems[i].mArea; - LogicalRect itemCB = - aGridRI.ContainingBlockForAbsPos(area, gridOrigin, gridCB); - // AbsoluteContainingBlock::Reflow uses physical coordinates. - nsRect* cb = child->GetProperty(GridItemContainingBlockRect()); - if (!cb) { - cb = new nsRect; - child->SetProperty(GridItemContainingBlockRect(), cb); - } - *cb = itemCB.GetPhysicalRect(wm, gridCBPhysicalSize); - ++i; - } - const auto border = aGridRI.mReflowInput->ComputedPhysicalBorder(); - const nsPoint borderShift{border.left, border.top}; - const nsRect paddingRect(borderShift, gridCBPhysicalSize); - // XXX: To optimize the performance, set the flags only when the CB width - // or height actually changes. - AbsPosReflowFlags flags{ - AbsPosReflowFlag::AllowFragmentation, AbsPosReflowFlag::CBWidthChanged, - AbsPosReflowFlag::CBHeightChanged, AbsPosReflowFlag::IsGridContainerCB}; - absoluteContainer->Reflow(this, PresContext(), *aGridRI.mReflowInput, - aStatus, paddingRect, flags, - &aDesiredSize.mOverflowAreas); + if (!absoluteContainer || !absoluteContainer->HasAbsoluteFrames()) { + return; } - return bSize; + // 'gridOrigin' is the origin of the grid (the start of the first track), + // with respect to the grid container's padding-box (CB). + LogicalMargin pad(aGridRI.mReflowInput->ComputedLogicalPadding(wm)); + const LogicalPoint gridOrigin(wm, pad.IStart(wm), pad.BStart(wm)); + const LogicalRect gridCB(wm, 0, 0, + aContentArea.ISize(wm) + pad.IStartEnd(wm), + aContentBSize + pad.BStartEnd(wm)); + const nsSize gridCBPhysicalSize = gridCB.Size(wm).GetPhysicalSize(wm); + size_t i = 0; + for (nsIFrame* child : absoluteContainer->GetChildList()) { + MOZ_ASSERT(i < aGridRI.mAbsPosItems.Length()); + MOZ_ASSERT(aGridRI.mAbsPosItems[i].mFrame == child); + GridArea& area = aGridRI.mAbsPosItems[i].mArea; + LogicalRect itemCB = + aGridRI.ContainingBlockForAbsPos(area, gridOrigin, gridCB); + // AbsoluteContainingBlock::Reflow uses physical coordinates. + nsRect* cb = child->GetProperty(GridItemContainingBlockRect()); + if (!cb) { + cb = new nsRect; + child->SetProperty(GridItemContainingBlockRect(), cb); + } + *cb = itemCB.GetPhysicalRect(wm, gridCBPhysicalSize); + ++i; + } + const auto border = aGridRI.mReflowInput->ComputedPhysicalBorder(); + const nsPoint borderShift{border.left, border.top}; + const nsRect paddingRect(borderShift, gridCBPhysicalSize); + // XXX: To optimize the performance, set the flags only when the CB width + // or height actually changes. + AbsPosReflowFlags flags{ + AbsPosReflowFlag::AllowFragmentation, AbsPosReflowFlag::CBWidthChanged, + AbsPosReflowFlag::CBHeightChanged, AbsPosReflowFlag::IsGridContainerCB}; + absoluteContainer->Reflow(this, PresContext(), *aGridRI.mReflowInput, + aStatus, paddingRect, flags, + &aDesiredSize.mOverflowAreas); } nscoord nsGridContainerFrame::ComputeBSizeForResolvingRowSizes( @@ -9603,29 +9612,6 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, contentBSize = ReflowChildren(gridRI, contentArea, containerSize, aDesiredSize, aStatus); - contentBSize = std::max(contentBSize - consumedBSize, 0); - - // Skip our block-end border if we're INCOMPLETE. - if (!aStatus.IsComplete() && !gridRI.mSkipSides.BEnd() && - StyleBorder()->mBoxDecorationBreak != StyleBoxDecorationBreak::Clone) { - bp.BEnd(wm) = nscoord(0); - } - - LogicalSize desiredSize(wm, computedISize + bp.IStartEnd(wm), - contentBSize + bp.BStartEnd(wm)); - aDesiredSize.SetSize(wm, desiredSize); - nsRect frameRect(0, 0, aDesiredSize.Width(), aDesiredSize.Height()); - aDesiredSize.mOverflowAreas.UnionAllWith(frameRect); - - if (repositionChildren) { - nsPoint physicalDelta(aDesiredSize.Width() - bp.LeftRight(wm), 0); - for (const auto& item : gridRI.mGridItems) { - auto* child = item.mFrame; - child->MovePositionBy(physicalDelta); - ConsiderChildOverflow(aDesiredSize.mOverflowAreas, child); - } - } - if (Style()->GetPseudoType() == PseudoStyleType::scrolledContent) { // Per spec, the grid area is included in a grid container's scrollable // overflow region [1], as well as the padding on the end-edge sides that @@ -9672,6 +9658,29 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, } aDesiredSize.mOverflowAreas.UnionAllWith(gridItemMarginBoxBounds); } + ReflowAbsoluteChildren(gridRI, contentArea, contentBSize, aDesiredSize, aStatus); + contentBSize = std::max(contentBSize - consumedBSize, 0); + + // Skip our block-end border if we're INCOMPLETE. + if (!aStatus.IsComplete() && !gridRI.mSkipSides.BEnd() && + StyleBorder()->mBoxDecorationBreak != StyleBoxDecorationBreak::Clone) { + bp.BEnd(wm) = nscoord(0); + } + + LogicalSize desiredSize(wm, computedISize + bp.IStartEnd(wm), + contentBSize + bp.BStartEnd(wm)); + aDesiredSize.SetSize(wm, desiredSize); + nsRect frameRect(0, 0, aDesiredSize.Width(), aDesiredSize.Height()); + aDesiredSize.mOverflowAreas.UnionAllWith(frameRect); + + if (repositionChildren) { + nsPoint physicalDelta(aDesiredSize.Width() - bp.LeftRight(wm), 0); + for (const auto& item : gridRI.mGridItems) { + auto* child = item.mFrame; + child->MovePositionBy(physicalDelta); + ConsiderChildOverflow(aDesiredSize.mOverflowAreas, child); + } + } // TODO: fix align-tracks alignment in fragments if ((IsRowMasonry() && !prevInFlow) || IsColMasonry()) { diff --git a/layout/generic/nsGridContainerFrame.h b/layout/generic/nsGridContainerFrame.h @@ -398,6 +398,11 @@ class nsGridContainerFrame final : public nsContainerFrame, const LogicalRect& aContentArea, const nsSize& aContainerSize, ReflowOutput& aDesiredSize, nsReflowStatus& aStatus); + void ReflowAbsoluteChildren(GridReflowInput& aGridRI, + const LogicalRect& aContentArea, + nscoord aContentBSize, + ReflowOutput& aDesiredSize, + nsReflowStatus& aStatus); /** * Helper to implement IntrinsicISize().