Bug 2057630 Part 2 - Return the result in a struct from StickyScrollContainer::ComputeStickyLimits(). r=layout-reviewers,emilio

`ComputeStickyLimits()` returned its two rectangles through outparams.
Return them in a struct instead, which is easier to use at the call
sites.

Differential Revision: https://phabricator.services.mozilla.com/D324787
This commit is contained in:
Ting-Yu Lin
2026-09-12 19:49:20 +00:00
committed by tlin@mozilla.com
parent 56ab4b6060
commit f92e5fb2fc
2 changed files with 53 additions and 53 deletions
+36 -42
View File
@@ -110,10 +110,8 @@ static constexpr nscoord gUnboundedExtent = nscoord_MAX;
static constexpr nscoord gUnboundedPositive =
gUnboundedNegative + gUnboundedExtent;
void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
nsRect* aStick,
nsRect* aContain,
StickyLimitSpace aSpace) const {
StickyScrollContainer::StickyLimits StickyScrollContainer::ComputeStickyLimits(
nsIFrame* aFrame, StickyLimitSpace aSpace) const {
NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame),
"Can't sticky position individual continuations");
@@ -121,17 +119,16 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
? nsPoint()
: mScrollPosition;
aStick->SetRect(gUnboundedNegative, gUnboundedNegative, gUnboundedExtent,
gUnboundedExtent);
aContain->SetRect(gUnboundedNegative, gUnboundedNegative, gUnboundedExtent,
gUnboundedExtent);
const nsRect unbounded(gUnboundedNegative, gUnboundedNegative,
gUnboundedExtent, gUnboundedExtent);
StickyLimits limits{unbounded, unbounded};
const nsMargin* computedOffsets =
aFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
if (!computedOffsets) {
// We haven't reflowed the scroll frame yet, so offsets haven't been
// computed. Bail.
return;
return limits;
}
nsIFrame* scrolledFrame = mScrollContainerFrame->GetScrolledFrame();
@@ -163,11 +160,11 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
// area, since we want the content box.
MOZ_ASSERT(cbFrame->GetUsedBorder() == nsMargin(),
"How did the ::-moz-scrolled-frame end up with border?");
*aContain = cbFrame->ScrollableOverflowRectRelativeToSelf();
aContain->Deflate(cbFrame->GetUsedPadding());
nsLayoutUtils::TransformRect(cbFrame, aFrame->GetParent(), *aContain);
limits.mContain = cbFrame->ScrollableOverflowRectRelativeToSelf();
limits.mContain.Deflate(cbFrame->GetUsedPadding());
nsLayoutUtils::TransformRect(cbFrame, aFrame->GetParent(), limits.mContain);
} else {
*aContain = nsLayoutUtils::GetAllInFlowRectsUnion(
limits.mContain = nsLayoutUtils::GetAllInFlowRectsUnion(
cbFrame, aFrame->GetParent(),
nsLayoutUtils::GetAllInFlowRectsFlag::UseContentBox);
}
@@ -176,15 +173,15 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
aFrame, aFrame->GetParent(),
nsLayoutUtils::GetAllInFlowRectsFlag::UseMarginBoxWithAutoResolvedAsZero);
// Deflate aContain by the difference between the union of aFrame's
// Deflate mContain by the difference between the union of aFrame's
// continuations' margin boxes and the union of their border boxes, so that
// by keeping aFrame within aContain, we keep the union of the margin boxes
// by keeping aFrame within mContain, we keep the union of the margin boxes
// within the containing block's content box.
aContain->Deflate(marginRect - rect);
limits.mContain.Deflate(marginRect - rect);
// Deflate aContain by the border-box size, to form a constraint on the
// Deflate mContain by the border-box size, to form a constraint on the
// upper-left corner of aFrame and continuations.
aContain->Deflate(nsMargin(0, rect.width, rect.height, 0));
limits.mContain.Deflate(nsMargin(0, rect.width, rect.height, 0));
nsMargin sfPadding = scrolledFrame->GetUsedPadding();
nsPoint sfOffset = aFrame->GetParent()->GetOffsetTo(scrolledFrame);
@@ -224,44 +221,45 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
// aFrame and its continuations, but our consumers expect the limits to be
// on the position of aFrame, so we need to shift the limits by the
// difference.
// - For |aContain| we're otherwise done, so we apply the offset directly.
// - For |aStick| we apply the offset as part of setting |aStick| (applying
// it via `MoveBy` after we set |aStick| would trash any sentinel values).
// - For |mContain| we're otherwise done, so we apply the offset directly.
// - For |mStick| we apply the offset as part of setting |mStick| (applying
// it via `MoveBy` after we set |mStick| would trash any sentinel values).
const nsPoint frameOffset = aFrame->GetPosition() - rect.TopLeft();
aContain->MoveBy(frameOffset);
limits.mContain.MoveBy(frameOffset);
// Top
if (computedOffsets->top != NS_AUTOOFFSET) {
aStick->SetTopEdge(scrollPosition.y + sfPadding.top + effectiveOffsets.top -
sfOffset.y + frameOffset.y);
limits.mStick.SetTopEdge(scrollPosition.y + sfPadding.top +
effectiveOffsets.top - sfOffset.y + frameOffset.y);
}
// Bottom
if (computedOffsets->bottom != NS_AUTOOFFSET) {
aStick->SetBottomEdge(scrollPosition.y + sfPadding.top + sfSize.height -
effectiveOffsets.bottom - rect.height - sfOffset.y +
frameOffset.y);
limits.mStick.SetBottomEdge(scrollPosition.y + sfPadding.top +
sfSize.height - effectiveOffsets.bottom -
rect.height - sfOffset.y + frameOffset.y);
}
// Left
if (computedOffsets->left != NS_AUTOOFFSET) {
aStick->SetLeftEdge(scrollPosition.x + sfPadding.left +
effectiveOffsets.left - sfOffset.x + frameOffset.x);
limits.mStick.SetLeftEdge(scrollPosition.x + sfPadding.left +
effectiveOffsets.left - sfOffset.x +
frameOffset.x);
}
// Right
if (computedOffsets->right != NS_AUTOOFFSET) {
aStick->SetRightEdge(scrollPosition.x + sfPadding.left + sfSize.width -
effectiveOffsets.right - rect.width - sfOffset.x +
frameOffset.x);
limits.mStick.SetRightEdge(scrollPosition.x + sfPadding.left +
sfSize.width - effectiveOffsets.right -
rect.width - sfOffset.x + frameOffset.x);
}
return limits;
}
nsPoint StickyScrollContainer::ComputePosition(nsIFrame* aFrame) const {
nsRect stick;
nsRect contain;
ComputeStickyLimits(aFrame, &stick, &contain);
const auto [stick, contain] = ComputeStickyLimits(aFrame);
nsPoint position = aFrame->GetNormalPosition();
@@ -290,9 +288,7 @@ void StickyScrollContainer::GetScrollRanges(nsIFrame* aFrame,
nsIFrame* firstCont =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
nsRect stickRect;
nsRect containRect;
ComputeStickyLimits(firstCont, &stickRect, &containRect);
const auto [stickRect, containRect] = ComputeStickyLimits(firstCont);
nsRectAbsolute stick = nsRectAbsolute::FromRect(stickRect);
nsRectAbsolute contain = nsRectAbsolute::FromRect(containRect);
@@ -367,10 +363,8 @@ StickyScrollContainer::GetStickyScrollRangesForAxis(
return result;
}
nsRect stick;
nsRect contain;
ComputeStickyLimits(firstCont, &stick, &contain,
StickyLimitSpace::IgnoreCurrentScroll);
const auto [stick, contain] =
ComputeStickyLimits(firstCont, StickyLimitSpace::IgnoreCurrentScroll);
const nsPoint normalPosition = firstCont->GetNormalPosition();
const nscoord normal = isVertical ? normalPosition.y : normalPosition.x;
+17 -11
View File
@@ -145,25 +145,31 @@ class StickyScrollContainer final {
private:
/**
* Whether ComputeStickyLimits() positions its aStick outparam (the
* sticky-limits rectangle) relative to the current scroll position, or as
* if the scroll position were zero (in which case the result is independent
* of the current scroll position).
* Whether ComputeStickyLimits() positions its returned StickyLimits::mStick
* rectangle relative to the current scroll position, or as if the scroll
* position were zero (in which case the result is independent of the current
* scroll position).
*/
enum class StickyLimitSpace : uint8_t {
RelativeToCurrentScroll,
IgnoreCurrentScroll,
};
struct StickyLimits {
// Based on the scroll container.
nsRect mStick;
// Based on the containing block.
nsRect mContain;
};
/**
* Compute two rectangles that determine sticky positioning: |aStick|, based
* on the scroll container, and |aContain|, based on the containing block.
* Sticky positioning keeps the frame position (its upper-left corner) always
* within |aContain| and secondarily within |aStick|.
* Compute the two rectangles that determine sticky positioning. Sticky
* positioning keeps the frame position (its upper-left corner) always within
* |mContain| and secondarily within |mStick|.
*/
void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick, nsRect* aContain,
StickyLimitSpace aSpace =
StickyLimitSpace::RelativeToCurrentScroll) const;
StickyLimits ComputeStickyLimits(
nsIFrame* aFrame, StickyLimitSpace aSpace =
StickyLimitSpace::RelativeToCurrentScroll) const;
ScrollContainerFrame* const mScrollContainerFrame;
DepthOrderedFrameList mFrames;