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:
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,