tor-browser

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

commit cfcfba76dec6d8785a9d50903d3f0d95d2aea206
parent e915c14e16844649816d88a0f694a7066453285c
Author: David Shin <dshin@mozilla.com>
Date:   Fri,  7 Nov 2025 17:57:07 +0000

Bug 1996832: Pass in border-offset padding rect for abspos cb computation. r=layout-anchor-positioning-reviewers,layout-reviewers,emilio

This gets confusing because insets are computed against the padding rect, but
we store all frame rect information w.r.t. border rect - Add documentation to
make that fact more explicit.

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

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 38++++++++++++++++----------------------
Mlayout/generic/AbsoluteContainingBlock.h | 6++++--
Mlayout/generic/nsBlockFrame.cpp | 18++++++++++--------
Mlayout/generic/nsContainerFrame.cpp | 7++-----
4 files changed, 32 insertions(+), 37 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -1122,7 +1122,11 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( const auto cb = [&]() { if (isGrid) { // TODO(emilio): how does position-area interact with grid? - return ContainingBlockRect{nsGridContainerFrame::GridItemCB(aKidFrame)}; + 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}; } auto positionArea = aKidFrame->StylePosition()->mPositionArea; @@ -1153,8 +1157,8 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( StylePositionArea resolvedPositionArea{}; const auto scrolledAnchorCb = AnchorPositioningUtils:: AdjustAbsoluteContainingBlockRectForPositionArea( - scrolledAnchorRect, aOriginalContainingBlockRect, - aKidFrame->GetWritingMode(), + scrolledAnchorRect + aOriginalContainingBlockRect.TopLeft(), + aOriginalContainingBlockRect, aKidFrame->GetWritingMode(), aDelegatingFrame->GetWritingMode(), positionArea, &resolvedPositionArea); return ContainingBlockRect{offset, resolvedPositionArea, @@ -1360,16 +1364,14 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( (offsets.BStart(outerWM) + kidMarginBox.BSize(outerWM)); } - LogicalRect rect(outerWM, - border.StartOffset(outerWM) + - offsets.StartOffset(outerWM) + - margin.StartOffset(outerWM), - kidSize); - nsRect r = rect.GetPhysicalRect( - outerWM, cbSize.GetPhysicalSize(outerWM) + - border.Size(outerWM).GetPhysicalSize(outerWM)); + LogicalRect rect( + outerWM, offsets.StartOffset(outerWM) + margin.StartOffset(outerWM), + kidSize); + nsRect r = rect.GetPhysicalRect(outerWM, cbSize.GetPhysicalSize(outerWM)); - // Offset the frame rect by the given origin of the absolute CB. + // So far, we've positioned against the padding edge of the containing + // block, which is necessary for inset computation. However, the position + // of a frame originates against the border box. r += cb.mRect.TopLeft(); if (cb.mAnchorShiftInfo) { // Push the frame out to where the anchor is. @@ -1429,23 +1431,15 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( }(); const auto fits = aStatus.IsComplete() && [&]() { - // TODO(dshin, bug 1996832): This should probably be done at call sites of - // `AbsoluteContainingBlock::Reflow`. - const auto paddingEdgeShift = [&]() { - const auto border = aDelegatingFrame->GetUsedBorder(); - return nsPoint{border.left, border.top}; - }(); - auto overflowCheckRect = cb.mRect + paddingEdgeShift; + auto overflowCheckRect = cb.mRect; if (aAnchorPosResolutionCache && cb.mAnchorShiftInfo) { overflowCheckRect = GrowOverflowCheckRect(overflowCheckRect, aKidFrame->GetNormalRect(), cb.mAnchorShiftInfo->mResolvedArea); aAnchorPosResolutionCache->mReferenceData->mContainingBlockRect = overflowCheckRect; - const auto originalContainingBlockRect = - aOriginalContainingBlockRect + paddingEdgeShift; return AnchorPositioningUtils::FitsInContainingBlock( - overflowCheckRect, originalContainingBlockRect, + overflowCheckRect, aOriginalContainingBlockRect, aKidFrame->GetRect()); } return overflowCheckRect.Contains(aKidFrame->GetRect()); diff --git a/layout/generic/AbsoluteContainingBlock.h b/layout/generic/AbsoluteContainingBlock.h @@ -75,10 +75,12 @@ class AbsoluteContainingBlock { * @param aOverflowAreas, if non-null, is unioned with (in the local * coordinate space) the overflow areas of the absolutely positioned * children. - * * @param aReflowStatus This function merges in the statuses of the absolutely * positioned children's reflows. - * + * @param aContainingBlock Rect representing the area where absolute + * positioned children can be positioned. Generally, this is the padding rect + * of `aDelegatingFrame` (Which would not have a valid mRect set during + * reflow), offset against the `aDelegatingFrame`'s border rect. * @param aFlags zero or more AbsPosReflowFlags */ void Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext, diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp @@ -1720,11 +1720,12 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, !(isRoot && NS_UNCONSTRAINEDSIZE == aReflowInput.ComputedHeight()) && aMetrics.Height() != oldSize.height; - const LogicalSize containingBlockSize = - aMetrics.Size(parentWM) - - aReflowInput.ComputedLogicalBorder(parentWM).Size(parentWM); - nsRect containingBlock(nsPoint(0, 0), - containingBlockSize.GetPhysicalSize(parentWM)); + const LogicalRect containingBlock = [&]() { + LogicalRect rect{parentWM, LogicalPoint{parentWM}, + aMetrics.Size(parentWM)}; + rect.Deflate(parentWM, aReflowInput.ComputedLogicalBorder(parentWM)); + return rect; + }(); AbsPosReflowFlags flags{AbsPosReflowFlag::AllowFragmentation}; if (cbWidthChanged) { flags += AbsPosReflowFlag::CBWidthChanged; @@ -1736,9 +1737,10 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, // calculating hypothetical position of absolutely-positioned // frames. SetupLineCursorForQuery(); - absoluteContainer->Reflow(this, aPresContext, aReflowInput, reflowStatus, - containingBlock, flags, - &aMetrics.mOverflowAreas); + absoluteContainer->Reflow( + this, aPresContext, aReflowInput, reflowStatus, + containingBlock.GetPhysicalRect(parentWM, aMetrics.PhysicalSize()), + flags, &aMetrics.mOverflowAreas); } } diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp @@ -981,11 +981,8 @@ void nsContainerFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext, // The containing block for the abs pos kids is formed by our padding edge. nsMargin usedBorder = GetUsedBorder(); - nscoord containingBlockWidth = - std::max(0, aDesiredSize.Width() - usedBorder.LeftRight()); - nscoord containingBlockHeight = - std::max(0, aDesiredSize.Height() - usedBorder.TopBottom()); - nsRect containingBlock(0, 0, containingBlockWidth, containingBlockHeight); + nsRect containingBlock(nsPoint{}, aDesiredSize.PhysicalSize()); + containingBlock.Deflate(usedBorder); // XXX: To optimize the performance, set the flags only when the CB width or // height actually changes. AbsPosReflowFlags flags{AbsPosReflowFlag::AllowFragmentation,