mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 886646 - Part 6: Implement sticky positioning, calculated on reflow and scroll. r=dbaron, r=dholbert
This commit is contained in:
parent
84181a5ffd
commit
b3400abc97
@ -29,6 +29,7 @@
|
||||
#include "nsViewportFrame.h"
|
||||
#include "nsSVGTextFrame2.h"
|
||||
#include "nsSVGTextPathFrame.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include "nsIRootBox.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -326,7 +327,7 @@ RestyleManager::RecomputePosition(nsIFrame* aFrame)
|
||||
aFrame->SchedulePaint();
|
||||
|
||||
// For relative positioning, we can simply update the frame rect
|
||||
if (display->mPosition == NS_STYLE_POSITION_RELATIVE) {
|
||||
if (display->IsRelativelyPositionedStyle()) {
|
||||
switch (display->mDisplay) {
|
||||
case NS_STYLE_DISPLAY_TABLE_CAPTION:
|
||||
case NS_STYLE_DISPLAY_TABLE_CELL:
|
||||
@ -345,17 +346,27 @@ RestyleManager::RecomputePosition(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
nsIFrame* cb = aFrame->GetContainingBlock();
|
||||
const nsSize size = cb->GetContentRectRelativeToSelf().Size();
|
||||
nsPoint position = aFrame->GetNormalPosition();
|
||||
nsMargin newOffsets;
|
||||
|
||||
// Move the frame
|
||||
nsHTMLReflowState::ComputeRelativeOffsets(
|
||||
cb->StyleVisibility()->mDirection,
|
||||
aFrame, size.width, size.height, newOffsets);
|
||||
NS_ASSERTION(newOffsets.left == -newOffsets.right &&
|
||||
newOffsets.top == -newOffsets.bottom,
|
||||
"ComputeRelativeOffsets should return valid results");
|
||||
if (display->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||
StickyScrollContainer::ComputeStickyOffsets(aFrame);
|
||||
} else {
|
||||
MOZ_ASSERT(NS_STYLE_POSITION_RELATIVE == display->mPosition,
|
||||
"Unexpected type of positioning");
|
||||
const nsSize size = cb->GetContentRectRelativeToSelf().Size();
|
||||
|
||||
nsHTMLReflowState::ComputeRelativeOffsets(
|
||||
cb->StyleVisibility()->mDirection,
|
||||
aFrame, size.width, size.height, newOffsets);
|
||||
NS_ASSERTION(newOffsets.left == -newOffsets.right &&
|
||||
newOffsets.top == -newOffsets.bottom,
|
||||
"ComputeRelativeOffsets should return valid results");
|
||||
}
|
||||
|
||||
nsPoint position = aFrame->GetNormalPosition();
|
||||
|
||||
// This handles both relative and sticky positioning.
|
||||
nsHTMLReflowState::ApplyRelativePositioning(aFrame, newOffsets, &position);
|
||||
aFrame->SetPosition(position);
|
||||
|
||||
|
@ -29,6 +29,10 @@ class OverflowChangedTracker
|
||||
{
|
||||
public:
|
||||
|
||||
OverflowChangedTracker() :
|
||||
mSubtreeRoot(nullptr)
|
||||
{}
|
||||
|
||||
~OverflowChangedTracker()
|
||||
{
|
||||
NS_ASSERTION(mEntryList.empty(), "Need to flush before destroying!");
|
||||
@ -67,6 +71,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subtree root to limit overflow updates. This must be set if and
|
||||
* only if currently reflowing aSubtreeRoot, to ensure overflow changes will
|
||||
* still propagate correctly.
|
||||
*/
|
||||
void SetSubtreeRoot(const nsIFrame* aSubtreeRoot) {
|
||||
mSubtreeRoot = aSubtreeRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the overflow of all added frames, and clear the entry list.
|
||||
*
|
||||
@ -100,7 +113,7 @@ public:
|
||||
}
|
||||
if (updateParent) {
|
||||
nsIFrame *parent = frame->GetParent();
|
||||
if (parent) {
|
||||
if (parent && parent != mSubtreeRoot) {
|
||||
if (!mEntryList.contains(Entry(parent, entry->mDepth - 1, false))) {
|
||||
mEntryList.insert(new Entry(parent, entry->mDepth - 1, false));
|
||||
}
|
||||
@ -165,6 +178,9 @@ private:
|
||||
|
||||
/* A list of frames to process, sorted by their depth in the frame tree */
|
||||
SplayTree<Entry, Entry> mEntryList;
|
||||
|
||||
/* Don't update overflow of this frame or its ancestors. */
|
||||
const nsIFrame* mSubtreeRoot;
|
||||
};
|
||||
|
||||
class RestyleTracker {
|
||||
|
252
layout/generic/StickyScrollContainer.cpp
Normal file
252
layout/generic/StickyScrollContainer.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sts=2 et sw=2 tw=80: */
|
||||
/* 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"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "RestyleTracker.h"
|
||||
|
||||
using namespace mozilla::css;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void DestroyStickyScrollContainer(void* aPropertyValue)
|
||||
{
|
||||
delete static_cast<StickyScrollContainer*>(aPropertyValue);
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(StickyScrollContainerProperty,
|
||||
DestroyStickyScrollContainer)
|
||||
|
||||
StickyScrollContainer::StickyScrollContainer(nsIScrollableFrame* aScrollFrame)
|
||||
: mScrollFrame(aScrollFrame)
|
||||
, mScrollPosition()
|
||||
{
|
||||
mScrollFrame->AddScrollPositionListener(this);
|
||||
}
|
||||
|
||||
StickyScrollContainer::~StickyScrollContainer()
|
||||
{
|
||||
mScrollFrame->RemoveScrollPositionListener(this);
|
||||
}
|
||||
|
||||
// static
|
||||
StickyScrollContainer*
|
||||
StickyScrollContainer::StickyScrollContainerForFrame(nsIFrame* aFrame)
|
||||
{
|
||||
nsIScrollableFrame* scrollFrame =
|
||||
nsLayoutUtils::GetNearestScrollableFrame(aFrame->GetParent(),
|
||||
nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
||||
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
|
||||
NS_ASSERTION(scrollFrame, "Need a scrolling container");
|
||||
FrameProperties props = static_cast<nsIFrame*>(do_QueryFrame(scrollFrame))->
|
||||
Properties();
|
||||
StickyScrollContainer* s = static_cast<StickyScrollContainer*>
|
||||
(props.Get(StickyScrollContainerProperty()));
|
||||
if (!s) {
|
||||
s = new StickyScrollContainer(scrollFrame);
|
||||
props.Set(StickyScrollContainerProperty(), s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// static
|
||||
StickyScrollContainer*
|
||||
StickyScrollContainer::GetStickyScrollContainerForScrollFrame(nsIFrame* aFrame)
|
||||
{
|
||||
FrameProperties props = aFrame->Properties();
|
||||
return static_cast<StickyScrollContainer*>
|
||||
(props.Get(StickyScrollContainerProperty()));
|
||||
}
|
||||
|
||||
static nscoord
|
||||
ComputeStickySideOffset(Side aSide, const nsStyleSides& aOffset,
|
||||
nscoord aPercentBasis)
|
||||
{
|
||||
if (eStyleUnit_Auto == aOffset.GetUnit(aSide)) {
|
||||
return NS_AUTOOFFSET;
|
||||
} else {
|
||||
return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis,
|
||||
aOffset.Get(aSide));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
StickyScrollContainer::ComputeStickyOffsets(nsIFrame* aFrame)
|
||||
{
|
||||
nsIScrollableFrame* scrollableFrame =
|
||||
nsLayoutUtils::GetNearestScrollableFrame(aFrame->GetParent(),
|
||||
nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
||||
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
|
||||
|
||||
if (!scrollableFrame) {
|
||||
// Not sure how this would happen, but bail if it does.
|
||||
NS_ERROR("Couldn't find a scrollable frame");
|
||||
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
|
||||
FrameProperties props = aFrame->Properties();
|
||||
nsMargin* offsets = static_cast<nsMargin*>
|
||||
(props.Get(nsIFrame::ComputedStickyOffsetProperty()));
|
||||
if (offsets) {
|
||||
*offsets = computedOffsets;
|
||||
} else {
|
||||
props.Set(nsIFrame::ComputedStickyOffsetProperty(),
|
||||
new nsMargin(computedOffsets));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
|
||||
nsRect* aContain) const
|
||||
{
|
||||
aStick->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
|
||||
aContain->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
|
||||
|
||||
const nsMargin* computedOffsets = static_cast<nsMargin*>(
|
||||
aFrame->Properties().Get(nsIFrame::ComputedStickyOffsetProperty()));
|
||||
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");
|
||||
|
||||
nsRect rect = aFrame->GetRect();
|
||||
nsMargin margin = aFrame->GetUsedMargin();
|
||||
|
||||
// Containing block limits
|
||||
if (cbFrame != scrolledFrame) {
|
||||
nsMargin cbBorderPadding = cbFrame->GetUsedBorderAndPadding();
|
||||
aContain->SetRect(nsPoint(cbBorderPadding.left, cbBorderPadding.top) -
|
||||
aFrame->GetParent()->GetOffsetTo(cbFrame),
|
||||
cbFrame->GetContentRectRelativeToSelf().Size() -
|
||||
rect.Size());
|
||||
aContain->Deflate(margin);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
StickyScrollContainer::UpdatePositions(nsPoint aScrollPosition,
|
||||
nsIFrame* aSubtreeRoot)
|
||||
{
|
||||
NS_ASSERTION(!aSubtreeRoot || aSubtreeRoot == do_QueryFrame(mScrollFrame),
|
||||
"If reflowing, should be reflowing the scroll frame");
|
||||
mScrollPosition = aScrollPosition;
|
||||
|
||||
OverflowChangedTracker oct;
|
||||
oct.SetSubtreeRoot(aSubtreeRoot);
|
||||
for (nsTArray<nsIFrame*>::size_type i = 0; i < mFrames.Length(); i++) {
|
||||
nsIFrame* f = mFrames[i];
|
||||
if (aSubtreeRoot) {
|
||||
// Reflowing the scroll frame, so recompute offsets.
|
||||
ComputeStickyOffsets(f);
|
||||
}
|
||||
f->SetPosition(ComputePosition(f));
|
||||
oct.AddFrame(f);
|
||||
}
|
||||
oct.Flush();
|
||||
}
|
||||
|
||||
void
|
||||
StickyScrollContainer::ScrollPositionWillChange(nscoord aX, nscoord aY)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
StickyScrollContainer::ScrollPositionDidChange(nscoord aX, nscoord aY)
|
||||
{
|
||||
UpdatePositions(nsPoint(aX, aY), nullptr);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
90
layout/generic/StickyScrollContainer.h
Normal file
90
layout/generic/StickyScrollContainer.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sts=2 et sw=2 tw=80: */
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef StickyScrollContainer_h
|
||||
#define StickyScrollContainer_h
|
||||
|
||||
#include "nsPoint.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
|
||||
class nsRect;
|
||||
class nsIFrame;
|
||||
class nsIScrollableFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class StickyScrollContainer MOZ_FINAL : public nsIScrollPositionListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Find the StickyScrollContainer associated with the scroll container of
|
||||
* the given frame, creating it if necessary.
|
||||
*/
|
||||
static StickyScrollContainer* StickyScrollContainerForFrame(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Find the StickyScrollContainer associated with the given scroll frame,
|
||||
* if it exists.
|
||||
*/
|
||||
static StickyScrollContainer* GetStickyScrollContainerForScrollFrame(nsIFrame* aScrollFrame);
|
||||
|
||||
void AddFrame(nsIFrame* aFrame) {
|
||||
mFrames.AppendElement(aFrame);
|
||||
}
|
||||
void RemoveFrame(nsIFrame* aFrame) {
|
||||
mFrames.RemoveElement(aFrame);
|
||||
}
|
||||
|
||||
// Compute the offsets for a sticky position element
|
||||
static void ComputeStickyOffsets(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Compute the position of a sticky positioned frame, based on information
|
||||
* stored in its properties along with our scroll frame and scroll position.
|
||||
*/
|
||||
nsPoint ComputePosition(nsIFrame* aFrame) const;
|
||||
|
||||
/**
|
||||
* Compute and set the position of all sticky frames, given the current
|
||||
* scroll position of the scroll frame. If not in reflow, aSubtreeRoot should
|
||||
* be null; otherwise, overflow-area updates will be limited to not affect
|
||||
* aSubtreeRoot or its ancestors.
|
||||
*/
|
||||
void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot);
|
||||
|
||||
// nsIScrollPositionListener
|
||||
virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) MOZ_OVERRIDE;
|
||||
virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
StickyScrollContainer(nsIScrollableFrame* aScrollFrame);
|
||||
~StickyScrollContainer();
|
||||
|
||||
/**
|
||||
* 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|.
|
||||
*/
|
||||
void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
|
||||
nsRect* aContain) const;
|
||||
|
||||
friend void DestroyStickyScrollContainer(void* aPropertyValue);
|
||||
|
||||
nsIScrollableFrame* const mScrollFrame;
|
||||
nsTArray<nsIFrame*> mFrames;
|
||||
nsPoint mScrollPosition;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* StickyScrollContainer_h */
|
@ -45,6 +45,7 @@ EXPORTS.mozilla.layout += [
|
||||
CPP_SOURCES += [
|
||||
'FrameChildList.cpp',
|
||||
'ScrollbarActivity.cpp',
|
||||
'StickyScrollContainer.cpp',
|
||||
'TextOverflow.cpp',
|
||||
'nsAbsoluteContainingBlock.cpp',
|
||||
'nsBRFrame.cpp',
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "gfxContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include "nsFontInflationData.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "nsRegion.h"
|
||||
@ -510,6 +511,9 @@ nsFrame::Init(nsIContent* aContent,
|
||||
// property, so we can set this bit here and then ignore it.
|
||||
mState |= NS_FRAME_MAY_BE_TRANSFORMED;
|
||||
}
|
||||
if (disp->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||
StickyScrollContainer::StickyScrollContainerForFrame(this)->AddFrame(this);
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::FontSizeInflationEnabled(PresContext()) || !GetParent()
|
||||
#ifdef DEBUG
|
||||
@ -588,6 +592,11 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(this);
|
||||
|
||||
if (StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||
StickyScrollContainer::StickyScrollContainerForFrame(this)->
|
||||
RemoveFrame(this);
|
||||
}
|
||||
|
||||
// Get the view pointer now before the frame properties disappear
|
||||
// when we call NotifyDestroyingFrame()
|
||||
nsView* view = GetView();
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsThemeConstants.h"
|
||||
#include "nsSVGIntegrationUtils.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
@ -827,6 +828,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
state.mContentsOverflowAreas + mInner.mScrolledFrame->GetPosition());
|
||||
}
|
||||
|
||||
mInner.UpdateSticky();
|
||||
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
||||
if (!InInitialReflow() && !mInner.mHadNonInitialReflow) {
|
||||
@ -3544,6 +3546,8 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
|
||||
mInner.mHadNonInitialReflow = true;
|
||||
}
|
||||
|
||||
mInner.UpdateSticky();
|
||||
|
||||
// Set up overflow areas for block frames for the benefit of
|
||||
// text-overflow.
|
||||
nsIFrame* f = mInner.mScrolledFrame->GetContentInsertionFrame();
|
||||
@ -3713,6 +3717,17 @@ nsGfxScrollFrameInner::UpdateOverflow()
|
||||
return mOuter->nsContainerFrame::UpdateOverflow();
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxScrollFrameInner::UpdateSticky()
|
||||
{
|
||||
StickyScrollContainer* ssc = StickyScrollContainer::
|
||||
GetStickyScrollContainerForScrollFrame(mOuter);
|
||||
if (ssc) {
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(mOuter);
|
||||
ssc->UpdatePositions(scrollFrame->GetScrollPosition(), mOuter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxScrollFrameInner::AdjustScrollbarRectForResizer(
|
||||
nsIFrame* aFrame, nsPresContext* aPresContext,
|
||||
|
@ -276,6 +276,8 @@ public:
|
||||
|
||||
bool UpdateOverflow();
|
||||
|
||||
void UpdateSticky();
|
||||
|
||||
// adjust the scrollbar rectangle aRect to account for any visible resizer.
|
||||
// aHasResizer specifies if there is a content resizer, however this method
|
||||
// will also check if a widget resizer is present as well.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsFontInflationData.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -32,6 +33,7 @@
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::layout;
|
||||
|
||||
enum eNormalLineHeightControl {
|
||||
@ -842,6 +844,9 @@ nsHTMLReflowState::ApplyRelativePositioning(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* display = aFrame->StyleDisplay();
|
||||
if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
|
||||
*aPosition += nsPoint(aComputedOffsets.left, aComputedOffsets.top);
|
||||
} else if (NS_STYLE_POSITION_STICKY == display->mPosition) {
|
||||
*aPosition = StickyScrollContainer::StickyScrollContainerForFrame(aFrame)->
|
||||
ComputePosition(aFrame);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1940,8 +1945,11 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
|
||||
|
||||
// Compute our offsets if the element is relatively positioned. We need
|
||||
// the correct containing block width and height here, which is why we need
|
||||
// to do it after all the quirks-n-such above.
|
||||
if (mStyleDisplay->IsRelativelyPositioned(frame)) {
|
||||
// to do it after all the quirks-n-such above. (If the element is sticky
|
||||
// positioned, we need to wait until the scroll container knows its size,
|
||||
// so we compute offsets from StickyScrollContainer::UpdatePositions.)
|
||||
if (mStyleDisplay->IsRelativelyPositioned(frame) &&
|
||||
NS_STYLE_POSITION_RELATIVE == mStyleDisplay->mPosition) {
|
||||
uint8_t direction = NS_STYLE_DIRECTION_LTR;
|
||||
if (cbrs && NS_STYLE_DIRECTION_RTL == cbrs->mStyleVisibility->mDirection) {
|
||||
direction = NS_STYLE_DIRECTION_RTL;
|
||||
|
@ -927,6 +927,7 @@ public:
|
||||
NS_DECLARE_FRAME_PROPERTY(IBSplitSpecialPrevSibling, nullptr)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(NormalPositionProperty, DestroyPoint)
|
||||
NS_DECLARE_FRAME_PROPERTY(ComputedStickyOffsetProperty, DestroyMargin)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
|
||||
NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
|
||||
|
Loading…
Reference in New Issue
Block a user