2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2013-09-06 17:35:16 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* compute sticky positioning, both during reflow and when the scrolling
|
|
|
|
* container scrolls
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StickyScrollContainer.h"
|
2018-03-25 20:16:39 +03:00
|
|
|
|
|
|
|
#include "mozilla/OverflowChangedTracker.h"
|
2013-09-06 17:35:16 +04:00
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsIScrollableFrame.h"
|
|
|
|
#include "nsLayoutUtils.h"
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
2016-01-28 06:23:59 +03:00
|
|
|
NS_DECLARE_FRAME_PROPERTY_DELETABLE(StickyScrollContainerProperty,
|
|
|
|
StickyScrollContainer)
|
2013-09-06 17:35:16 +04:00
|
|
|
|
|
|
|
StickyScrollContainer::StickyScrollContainer(nsIScrollableFrame* aScrollFrame)
|
|
|
|
: mScrollFrame(aScrollFrame), mScrollPosition() {
|
|
|
|
mScrollFrame->AddScrollPositionListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
StickyScrollContainer::~StickyScrollContainer() {
|
|
|
|
mScrollFrame->RemoveScrollPositionListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2013-09-12 03:30:56 +04:00
|
|
|
StickyScrollContainer* StickyScrollContainer::GetStickyScrollContainerForFrame(
|
|
|
|
nsIFrame* aFrame) {
|
2013-09-06 17:35:16 +04:00
|
|
|
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetNearestScrollableFrame(
|
|
|
|
aFrame->GetParent(), nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
|
|
|
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
|
2013-09-12 03:30:56 +04:00
|
|
|
if (!scrollFrame) {
|
|
|
|
// We might not find any, for instance in the case of
|
|
|
|
// <html style="position: fixed">
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-11-29 18:11:25 +03:00
|
|
|
nsIFrame* frame = do_QueryFrame(scrollFrame);
|
2017-05-27 14:36:00 +03:00
|
|
|
StickyScrollContainer* s =
|
|
|
|
frame->GetProperty(StickyScrollContainerProperty());
|
2013-09-06 17:35:16 +04:00
|
|
|
if (!s) {
|
|
|
|
s = new StickyScrollContainer(scrollFrame);
|
2017-05-27 14:36:00 +03:00
|
|
|
frame->SetProperty(StickyScrollContainerProperty(), s);
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2013-11-23 13:48:26 +04:00
|
|
|
// static
|
|
|
|
void StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary(
|
|
|
|
nsIFrame* aFrame, nsIFrame* aOldParent) {
|
|
|
|
nsIScrollableFrame* oldScrollFrame = nsLayoutUtils::GetNearestScrollableFrame(
|
|
|
|
aOldParent, nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
|
|
|
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
|
|
|
|
if (!oldScrollFrame) {
|
|
|
|
// XXX maybe aFrame has sticky descendants that can be sticky now, but
|
|
|
|
// we aren't going to handle that.
|
|
|
|
return;
|
|
|
|
}
|
2017-05-27 14:36:00 +03:00
|
|
|
|
|
|
|
StickyScrollContainer* oldSSC =
|
|
|
|
static_cast<nsIFrame*>(do_QueryFrame(oldScrollFrame))
|
|
|
|
->GetProperty(StickyScrollContainerProperty());
|
2013-11-23 13:48:26 +04:00
|
|
|
if (!oldSSC) {
|
|
|
|
// aOldParent had no sticky descendants, so aFrame doesn't have any sticky
|
|
|
|
// descendants, and we're done here.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto i = oldSSC->mFrames.Length();
|
|
|
|
while (i-- > 0) {
|
|
|
|
nsIFrame* f = oldSSC->mFrames[i];
|
|
|
|
StickyScrollContainer* newSSC = GetStickyScrollContainerForFrame(f);
|
|
|
|
if (newSSC != oldSSC) {
|
|
|
|
oldSSC->RemoveFrame(f);
|
2013-12-13 21:46:59 +04:00
|
|
|
if (newSSC) {
|
|
|
|
newSSC->AddFrame(f);
|
|
|
|
}
|
2013-11-23 13:48:26 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-06 17:35:16 +04:00
|
|
|
// static
|
|
|
|
StickyScrollContainer*
|
|
|
|
StickyScrollContainer::GetStickyScrollContainerForScrollFrame(
|
|
|
|
nsIFrame* aFrame) {
|
2017-05-27 14:36:00 +03:00
|
|
|
return aFrame->GetProperty(StickyScrollContainerProperty());
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
|
2019-01-26 13:00:44 +03:00
|
|
|
static nscoord ComputeStickySideOffset(
|
|
|
|
Side aSide, const StyleRect<LengthPercentageOrAuto>& aOffset,
|
|
|
|
nscoord aPercentBasis) {
|
|
|
|
auto& side = aOffset.Get(aSide);
|
|
|
|
if (side.IsAuto()) {
|
2013-09-06 17:35:16 +04:00
|
|
|
return NS_AUTOOFFSET;
|
|
|
|
}
|
2019-01-26 13:00:44 +03:00
|
|
|
return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis, side);
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void StickyScrollContainer::ComputeStickyOffsets(nsIFrame* aFrame) {
|
|
|
|
nsIScrollableFrame* scrollableFrame =
|
|
|
|
nsLayoutUtils::GetNearestScrollableFrame(
|
|
|
|
aFrame->GetParent(), nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
|
|
|
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
|
|
|
|
|
|
|
|
if (!scrollableFrame) {
|
2013-09-12 03:30:56 +04:00
|
|
|
// Bail.
|
2013-09-06 17:35:16 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSize scrollContainerSize = scrollableFrame->GetScrolledFrame()
|
|
|
|
->GetContentRectRelativeToSelf()
|
|
|
|
.Size();
|
|
|
|
|
|
|
|
nsMargin computedOffsets;
|
|
|
|
const nsStylePosition* position = aFrame->StylePosition();
|
|
|
|
|
|
|
|
computedOffsets.left = ComputeStickySideOffset(eSideLeft, position->mOffset,
|
|
|
|
scrollContainerSize.width);
|
|
|
|
computedOffsets.right = ComputeStickySideOffset(eSideRight, position->mOffset,
|
|
|
|
scrollContainerSize.width);
|
|
|
|
computedOffsets.top = ComputeStickySideOffset(eSideTop, position->mOffset,
|
|
|
|
scrollContainerSize.height);
|
|
|
|
computedOffsets.bottom = ComputeStickySideOffset(
|
|
|
|
eSideBottom, position->mOffset, scrollContainerSize.height);
|
|
|
|
|
|
|
|
// Store the offset
|
2017-05-27 14:36:00 +03:00
|
|
|
nsMargin* offsets = aFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
|
2013-09-06 17:35:16 +04:00
|
|
|
if (offsets) {
|
|
|
|
*offsets = computedOffsets;
|
|
|
|
} else {
|
2017-05-27 14:36:00 +03:00
|
|
|
aFrame->SetProperty(nsIFrame::ComputedOffsetProperty(),
|
|
|
|
new nsMargin(computedOffsets));
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
static nscoord gUnboundedNegative = nscoord_MIN / 2;
|
|
|
|
static nscoord gUnboundedExtent = nscoord_MAX;
|
|
|
|
static nscoord gUnboundedPositive = gUnboundedNegative + gUnboundedExtent;
|
|
|
|
|
2013-09-06 17:35:16 +04:00
|
|
|
void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
|
|
|
|
nsRect* aStick,
|
|
|
|
nsRect* aContain) const {
|
2014-02-07 05:45:31 +04:00
|
|
|
NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame),
|
2013-09-14 03:53:48 +04:00
|
|
|
"Can't sticky position individual continuations");
|
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
aStick->SetRect(gUnboundedNegative, gUnboundedNegative, gUnboundedExtent,
|
|
|
|
gUnboundedExtent);
|
|
|
|
aContain->SetRect(gUnboundedNegative, gUnboundedNegative, gUnboundedExtent,
|
|
|
|
gUnboundedExtent);
|
2013-09-06 17:35:16 +04:00
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
const nsMargin* computedOffsets =
|
2017-05-27 14:36:00 +03:00
|
|
|
aFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
|
2013-09-06 17:35:16 +04:00
|
|
|
if (!computedOffsets) {
|
|
|
|
// We haven't reflowed the scroll frame yet, so offsets haven't been
|
|
|
|
// computed. Bail.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame* scrolledFrame = mScrollFrame->GetScrolledFrame();
|
|
|
|
nsIFrame* cbFrame = aFrame->GetContainingBlock();
|
|
|
|
NS_ASSERTION(cbFrame == scrolledFrame ||
|
|
|
|
nsLayoutUtils::IsProperAncestorFrame(scrolledFrame, cbFrame),
|
|
|
|
"Scroll frame should be an ancestor of the containing block");
|
|
|
|
|
2013-09-14 03:53:48 +04:00
|
|
|
nsRect rect =
|
|
|
|
nsLayoutUtils::GetAllInFlowRectsUnion(aFrame, aFrame->GetParent());
|
2013-09-06 17:35:16 +04:00
|
|
|
|
2017-12-01 23:29:05 +03:00
|
|
|
// FIXME(bug 1421660): Table row groups aren't supposed to be containing
|
|
|
|
// blocks, but we treat them as such (maybe it's the right thing to do!).
|
|
|
|
// Anyway, not having this basically disables position: sticky on table cells,
|
|
|
|
// which would be really unfortunate, and doesn't match what other browsers
|
|
|
|
// do.
|
|
|
|
if (cbFrame != scrolledFrame && cbFrame->IsTableRowGroupFrame()) {
|
|
|
|
cbFrame = cbFrame->GetContainingBlock();
|
|
|
|
}
|
|
|
|
|
2013-12-03 23:28:32 +04:00
|
|
|
// Containing block limits for the position of aFrame relative to its parent.
|
|
|
|
// The margin box of the sticky element stays within the content box of the
|
|
|
|
// contaning-block element.
|
2013-09-06 17:35:16 +04:00
|
|
|
if (cbFrame != scrolledFrame) {
|
2013-12-03 23:28:32 +04:00
|
|
|
*aContain = nsLayoutUtils::GetAllInFlowRectsUnion(
|
|
|
|
cbFrame, aFrame->GetParent(), nsLayoutUtils::RECTS_USE_CONTENT_BOX);
|
|
|
|
nsRect marginRect = nsLayoutUtils::GetAllInFlowRectsUnion(
|
|
|
|
aFrame, aFrame->GetParent(), nsLayoutUtils::RECTS_USE_MARGIN_BOX);
|
|
|
|
|
|
|
|
// Deflate aContain 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
|
|
|
|
// within the containing block's content box.
|
|
|
|
aContain->Deflate(marginRect - rect);
|
|
|
|
|
|
|
|
// Deflate aContain by the border-box size, to form a constraint on the
|
|
|
|
// upper-left corner of aFrame and continuations.
|
2013-09-14 03:53:48 +04:00
|
|
|
aContain->Deflate(nsMargin(0, rect.width, rect.height, 0));
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsMargin sfPadding = scrolledFrame->GetUsedPadding();
|
|
|
|
nsPoint sfOffset = aFrame->GetParent()->GetOffsetTo(scrolledFrame);
|
|
|
|
|
|
|
|
// Top
|
|
|
|
if (computedOffsets->top != NS_AUTOOFFSET) {
|
|
|
|
aStick->SetTopEdge(mScrollPosition.y + sfPadding.top +
|
|
|
|
computedOffsets->top - sfOffset.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSize sfSize = scrolledFrame->GetContentRectRelativeToSelf().Size();
|
|
|
|
|
|
|
|
// Bottom
|
|
|
|
if (computedOffsets->bottom != NS_AUTOOFFSET &&
|
|
|
|
(computedOffsets->top == NS_AUTOOFFSET ||
|
|
|
|
rect.height <= sfSize.height - computedOffsets->TopBottom())) {
|
|
|
|
aStick->SetBottomEdge(mScrollPosition.y + sfPadding.top + sfSize.height -
|
|
|
|
computedOffsets->bottom - rect.height - sfOffset.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t direction = cbFrame->StyleVisibility()->mDirection;
|
|
|
|
|
|
|
|
// Left
|
|
|
|
if (computedOffsets->left != NS_AUTOOFFSET &&
|
|
|
|
(computedOffsets->right == NS_AUTOOFFSET ||
|
|
|
|
direction == NS_STYLE_DIRECTION_LTR ||
|
|
|
|
rect.width <= sfSize.width - computedOffsets->LeftRight())) {
|
|
|
|
aStick->SetLeftEdge(mScrollPosition.x + sfPadding.left +
|
|
|
|
computedOffsets->left - sfOffset.x);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Right
|
|
|
|
if (computedOffsets->right != NS_AUTOOFFSET &&
|
|
|
|
(computedOffsets->left == NS_AUTOOFFSET ||
|
|
|
|
direction == NS_STYLE_DIRECTION_RTL ||
|
|
|
|
rect.width <= sfSize.width - computedOffsets->LeftRight())) {
|
|
|
|
aStick->SetRightEdge(mScrollPosition.x + sfPadding.left + sfSize.width -
|
|
|
|
computedOffsets->right - rect.width - sfOffset.x);
|
|
|
|
}
|
2013-09-14 03:53:48 +04:00
|
|
|
|
|
|
|
// These limits are for the bounding box of aFrame's continuations. Convert
|
|
|
|
// to limits for aFrame itself.
|
2013-12-03 23:28:32 +04:00
|
|
|
nsPoint frameOffset = aFrame->GetPosition() - rect.TopLeft();
|
|
|
|
aStick->MoveBy(frameOffset);
|
|
|
|
aContain->MoveBy(frameOffset);
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsPoint StickyScrollContainer::ComputePosition(nsIFrame* aFrame) const {
|
|
|
|
nsRect stick;
|
|
|
|
nsRect contain;
|
|
|
|
ComputeStickyLimits(aFrame, &stick, &contain);
|
|
|
|
|
|
|
|
nsPoint position = aFrame->GetNormalPosition();
|
|
|
|
|
|
|
|
// For each sticky direction (top, bottom, left, right), move the frame along
|
|
|
|
// the appropriate axis, based on the scroll position, but limit this to keep
|
|
|
|
// the element's margin box within the containing block.
|
|
|
|
position.y = std::max(position.y, std::min(stick.y, contain.YMost()));
|
|
|
|
position.y = std::min(position.y, std::max(stick.YMost(), contain.y));
|
|
|
|
position.x = std::max(position.x, std::min(stick.x, contain.XMost()));
|
|
|
|
position.x = std::min(position.x, std::max(stick.XMost(), contain.x));
|
|
|
|
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
2018-03-06 02:08:18 +03:00
|
|
|
void StickyScrollContainer::GetScrollRanges(nsIFrame* aFrame,
|
|
|
|
nsRectAbsolute* aOuter,
|
|
|
|
nsRectAbsolute* aInner) const {
|
2016-07-12 19:36:31 +03:00
|
|
|
// We need to use the first in flow; continuation frames should not move
|
|
|
|
// relative to each other and should get identical scroll ranges.
|
|
|
|
// Also, ComputeStickyLimits requires this.
|
2013-09-25 23:28:08 +04:00
|
|
|
nsIFrame* firstCont =
|
2014-02-07 05:45:31 +04:00
|
|
|
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
|
2013-09-25 23:28:08 +04:00
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
nsRect stickRect;
|
|
|
|
nsRect containRect;
|
|
|
|
ComputeStickyLimits(firstCont, &stickRect, &containRect);
|
|
|
|
|
2018-03-06 02:08:18 +03:00
|
|
|
nsRectAbsolute stick = nsRectAbsolute::FromRect(stickRect);
|
|
|
|
nsRectAbsolute contain = nsRectAbsolute::FromRect(containRect);
|
2013-09-12 08:24:32 +04:00
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
aOuter->SetBox(gUnboundedNegative, gUnboundedNegative, gUnboundedPositive,
|
|
|
|
gUnboundedPositive);
|
|
|
|
aInner->SetBox(gUnboundedNegative, gUnboundedNegative, gUnboundedPositive,
|
|
|
|
gUnboundedPositive);
|
2013-09-12 08:24:32 +04:00
|
|
|
|
2016-11-15 03:01:37 +03:00
|
|
|
const nsPoint normalPosition = firstCont->GetNormalPosition();
|
2013-09-12 08:24:32 +04:00
|
|
|
|
|
|
|
// Bottom and top
|
2018-02-09 23:40:13 +03:00
|
|
|
if (stick.YMost() != gUnboundedPositive) {
|
|
|
|
aOuter->SetTopEdge(contain.Y() - stick.YMost());
|
2013-09-12 08:24:32 +04:00
|
|
|
aInner->SetTopEdge(normalPosition.y - stick.YMost());
|
|
|
|
}
|
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
if (stick.Y() != gUnboundedNegative) {
|
|
|
|
aInner->SetBottomEdge(normalPosition.y - stick.Y());
|
|
|
|
aOuter->SetBottomEdge(contain.YMost() - stick.Y());
|
2013-09-12 08:24:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Right and left
|
2018-02-09 23:40:13 +03:00
|
|
|
if (stick.XMost() != gUnboundedPositive) {
|
|
|
|
aOuter->SetLeftEdge(contain.X() - stick.XMost());
|
2013-09-12 08:24:32 +04:00
|
|
|
aInner->SetLeftEdge(normalPosition.x - stick.XMost());
|
|
|
|
}
|
|
|
|
|
2018-02-09 23:40:13 +03:00
|
|
|
if (stick.X() != gUnboundedNegative) {
|
|
|
|
aInner->SetRightEdge(normalPosition.x - stick.X());
|
|
|
|
aOuter->SetRightEdge(contain.XMost() - stick.X());
|
2013-09-12 08:24:32 +04:00
|
|
|
}
|
2016-11-15 03:01:37 +03:00
|
|
|
|
|
|
|
// Make sure |inner| does not extend outside of |outer|. (The consumers of
|
|
|
|
// the Layers API, to which this information is propagated, expect this
|
|
|
|
// invariant to hold.) The calculated value of |inner| can sometimes extend
|
|
|
|
// outside of |outer|, for example due to margin collapsing, since
|
|
|
|
// GetNormalPosition() returns the actual position after margin collapsing,
|
|
|
|
// while |contain| is calculated based on the frame's GetUsedMargin() which
|
|
|
|
// is pre-collapsing.
|
|
|
|
// Note that this doesn't necessarily solve all problems stemming from
|
|
|
|
// comparing pre- and post-collapsing margins (TODO: find a proper solution).
|
|
|
|
*aInner = aInner->Intersect(*aOuter);
|
2018-12-22 01:37:28 +03:00
|
|
|
if (aInner->IsEmpty()) {
|
|
|
|
// This might happen if aInner didn't intersect aOuter at all initially,
|
|
|
|
// in which case aInner is empty and outside aOuter. Make sure it doesn't
|
|
|
|
// extend outside aOuter.
|
|
|
|
*aInner = aInner->MoveInsideAndClamp(*aOuter);
|
|
|
|
}
|
2013-09-12 08:24:32 +04:00
|
|
|
}
|
|
|
|
|
2013-09-14 03:53:48 +04:00
|
|
|
void StickyScrollContainer::PositionContinuations(nsIFrame* aFrame) {
|
2014-02-07 05:45:31 +04:00
|
|
|
NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame),
|
2013-09-14 03:53:48 +04:00
|
|
|
"Should be starting from the first continuation");
|
2014-03-26 22:45:17 +04:00
|
|
|
nsPoint translation = ComputePosition(aFrame) - aFrame->GetNormalPosition();
|
2013-09-14 03:53:48 +04:00
|
|
|
|
|
|
|
// Move all continuation frames by the same amount.
|
2013-09-25 23:28:08 +04:00
|
|
|
for (nsIFrame* cont = aFrame; cont;
|
2014-02-07 05:45:31 +04:00
|
|
|
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
|
2014-03-26 22:45:17 +04:00
|
|
|
cont->SetPosition(cont->GetNormalPosition() + translation);
|
2013-09-14 03:53:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-06 17:35:16 +04:00
|
|
|
void StickyScrollContainer::UpdatePositions(nsPoint aScrollPosition,
|
|
|
|
nsIFrame* aSubtreeRoot) {
|
2013-09-13 21:04:23 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsIFrame* scrollFrameAsFrame = do_QueryFrame(mScrollFrame);
|
|
|
|
NS_ASSERTION(!aSubtreeRoot || aSubtreeRoot == scrollFrameAsFrame,
|
|
|
|
"If reflowing, should be reflowing the scroll frame");
|
|
|
|
}
|
|
|
|
#endif
|
2013-09-06 17:35:16 +04:00
|
|
|
mScrollPosition = aScrollPosition;
|
|
|
|
|
|
|
|
OverflowChangedTracker oct;
|
|
|
|
oct.SetSubtreeRoot(aSubtreeRoot);
|
|
|
|
for (nsTArray<nsIFrame*>::size_type i = 0; i < mFrames.Length(); i++) {
|
|
|
|
nsIFrame* f = mFrames[i];
|
2014-02-07 05:45:31 +04:00
|
|
|
if (!nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(f)) {
|
2013-09-25 23:28:08 +04:00
|
|
|
// This frame was added in nsFrame::Init before we knew it wasn't
|
2014-02-07 05:45:33 +04:00
|
|
|
// the first ib-split-sibling.
|
2013-09-25 23:28:08 +04:00
|
|
|
mFrames.RemoveElementAt(i);
|
|
|
|
--i;
|
|
|
|
continue;
|
|
|
|
}
|
2013-09-14 03:53:48 +04:00
|
|
|
|
2013-09-06 17:35:16 +04:00
|
|
|
if (aSubtreeRoot) {
|
|
|
|
// Reflowing the scroll frame, so recompute offsets.
|
|
|
|
ComputeStickyOffsets(f);
|
|
|
|
}
|
2013-09-14 03:53:48 +04:00
|
|
|
// mFrames will only contain first continuations, because we filter in
|
|
|
|
// nsIFrame::Init.
|
|
|
|
PositionContinuations(f);
|
|
|
|
|
2014-03-14 04:21:25 +04:00
|
|
|
f = f->GetParent();
|
|
|
|
if (f != aSubtreeRoot) {
|
|
|
|
for (nsIFrame* cont = f; cont;
|
|
|
|
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
|
|
|
|
oct.AddFrame(cont, OverflowChangedTracker::CHILDREN_CHANGED);
|
|
|
|
}
|
2013-09-14 03:53:48 +04:00
|
|
|
}
|
2013-09-06 17:35:16 +04:00
|
|
|
}
|
|
|
|
oct.Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StickyScrollContainer::ScrollPositionWillChange(nscoord aX, nscoord aY) {}
|
|
|
|
|
|
|
|
void StickyScrollContainer::ScrollPositionDidChange(nscoord aX, nscoord aY) {
|
|
|
|
UpdatePositions(nsPoint(aX, aY), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla
|