Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdc924d25e |
No files matched your search
@@ -485,6 +485,12 @@ public:
|
||||
*/
|
||||
virtual nsCanvasFrame* GetCanvasFrame() const = 0;
|
||||
|
||||
/**
|
||||
* Returns whether the scollable frame need to have a position adjustment
|
||||
* based on scroll-anchoring.
|
||||
*/
|
||||
virtual void ScrollableFrameNeedsAnchorAdjustment(nsIScrollableFrame* aFrame) = 0;
|
||||
|
||||
/**
|
||||
* Tell the pres shell that a frame needs to be marked dirty and needs
|
||||
* Reflow. It's OK if this is an ancestor of the frame needing reflow as
|
||||
|
||||
@@ -1225,6 +1225,7 @@ PresShell::Destroy()
|
||||
}
|
||||
|
||||
mFramesToDirty.Clear();
|
||||
mScrollAnchorAdjustments.Clear();
|
||||
|
||||
if (mViewManager) {
|
||||
// Clear the view manager's weak pointer back to |this| in case it
|
||||
@@ -2049,6 +2050,11 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
mFramesToDirty.RemoveEntry(aFrame);
|
||||
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aFrame);
|
||||
if (scrollableFrame) {
|
||||
mScrollAnchorAdjustments.RemoveEntry(scrollableFrame);
|
||||
}
|
||||
} else {
|
||||
// We must delete this property in situ so that its destructor removes the
|
||||
// frame from FrameLayerBuilder::DisplayItemData::mFrameList -- otherwise
|
||||
@@ -2583,6 +2589,12 @@ PresShell::VerifyHasDirtyRootAncestor(nsIFrame* aFrame)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
PresShell::ScrollableFrameNeedsAnchorAdjustment(nsIScrollableFrame* aFrame)
|
||||
{
|
||||
mScrollAnchorAdjustments.PutEntry(aFrame);
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
|
||||
nsFrameState aBitToAdd,
|
||||
@@ -4106,12 +4118,21 @@ PresShell::FlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
||||
didLayoutFlush = true;
|
||||
mFrameConstructor->RecalcQuotesAndCounters();
|
||||
viewManager->FlushDelayedResize(true);
|
||||
if (ProcessReflowCommands(flushType < Flush_Layout) && mContentToScrollTo) {
|
||||
// We didn't get interrupted. Go ahead and scroll to our content
|
||||
DoScrollContentIntoView();
|
||||
if (ProcessReflowCommands(flushType < Flush_Layout)) {
|
||||
// Apply scroll offset updates for scroll anchors.
|
||||
for (auto iter = mScrollAnchorAdjustments.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIScrollableFrame* frame = iter.Get()->GetKey();
|
||||
frame->ApplyScrollAnchorOffsetAdjustment();
|
||||
}
|
||||
mScrollAnchorAdjustments.Clear();
|
||||
|
||||
if (mContentToScrollTo) {
|
||||
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
|
||||
mContentToScrollTo = nullptr;
|
||||
// We didn't get interrupted; go ahead and scroll to our content.
|
||||
DoScrollContentIntoView();
|
||||
if (mContentToScrollTo) {
|
||||
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
|
||||
mContentToScrollTo = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10833,6 +10854,7 @@ PresShell::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
||||
}
|
||||
*aPresShellSize += mApproximatelyVisibleFrames.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
*aPresShellSize += mFramesToDirty.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
*aPresShellSize += mScrollAnchorAdjustments.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
*aPresShellSize += aArenaObjectsSize->mOther;
|
||||
|
||||
if (nsStyleSet* styleSet = StyleSet()->GetAsGecko()) {
|
||||
|
||||
@@ -129,6 +129,8 @@ public:
|
||||
virtual nsIPageSequenceFrame* GetPageSequenceFrame() const override;
|
||||
virtual nsCanvasFrame* GetCanvasFrame() const override;
|
||||
|
||||
virtual void ScrollableFrameNeedsAnchorAdjustment(nsIScrollableFrame* aFrame) override;
|
||||
|
||||
virtual void FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
|
||||
nsFrameState aBitToAdd,
|
||||
ReflowRootHandling aRootHandling =
|
||||
@@ -427,9 +429,10 @@ public:
|
||||
|
||||
void SetNextPaintCompressed() { mNextPaintCompressed = true; }
|
||||
|
||||
protected:
|
||||
virtual ~PresShell();
|
||||
|
||||
protected:
|
||||
|
||||
void HandlePostedReflowCallbacks(bool aInterruptible);
|
||||
void CancelPostedReflowCallbacks();
|
||||
|
||||
@@ -852,6 +855,8 @@ protected:
|
||||
// Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
|
||||
// we finish reflowing mCurrentReflowRoot.
|
||||
nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesToDirty;
|
||||
|
||||
nsTHashtable<nsPtrHashKey<nsIScrollableFrame> > mScrollAnchorAdjustments;
|
||||
|
||||
// Reflow roots that need to be reflowed.
|
||||
nsTArray<nsIFrame*> mDirtyRoots;
|
||||
|
||||
@@ -688,6 +688,20 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
}
|
||||
}
|
||||
|
||||
if (HasAnyStateBits(NS_FRAME_IS_SCROLL_ANCHOR)) {
|
||||
// Find the nearest scroll frame, that's the one that marked us as a
|
||||
// scroll anchor
|
||||
nsIFrame* currentFrame = this;
|
||||
while (currentFrame) {
|
||||
nsIScrollableFrame* scrollTarget = currentFrame->GetScrollTargetFrame();
|
||||
if (scrollTarget) {
|
||||
scrollTarget->ScrollAnchorWillDestroy();
|
||||
break;
|
||||
}
|
||||
currentFrame = currentFrame->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (HasCSSAnimations() || HasCSSTransitions() ||
|
||||
EffectSet::GetEffectSet(this)) {
|
||||
// If no new frame for this element is created by the end of the
|
||||
@@ -814,6 +828,35 @@ AddAndRemoveImageAssociations(nsFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::MaybeNotifyScrollAnchor()
|
||||
{
|
||||
bool isScrollAnchor = HasAnyStateBits(NS_FRAME_IS_SCROLL_ANCHOR);
|
||||
bool containsScrollAnchor = HasAnyStateBits(NS_FRAME_CONTAINS_SCROLL_ANCHOR);
|
||||
|
||||
if (isScrollAnchor) {
|
||||
printf_stderr("nsIFrame(%p)::MaybeNotifyScrollAnchor scroll anchor offset changed, queueing adjustment.\n", this);
|
||||
}
|
||||
if (containsScrollAnchor) {
|
||||
printf_stderr("nsIFrame(%p)::MaybeNotifyScrollAnchor offset for scroll anchor container changed, queueing adjustment.\n", this);
|
||||
}
|
||||
MOZ_ASSERT(!(isScrollAnchor && containsScrollAnchor));
|
||||
|
||||
if (isScrollAnchor || containsScrollAnchor) {
|
||||
// Find the nearest scroll frame, that's the one that marked us as a
|
||||
// scroll anchor
|
||||
nsIFrame* currentFrame = this;
|
||||
while (currentFrame) {
|
||||
nsIScrollableFrame* scrollTarget = currentFrame->GetScrollTargetFrame();
|
||||
if (scrollTarget) {
|
||||
PresShell().ScrollableFrameNeedsAnchorAdjustment(scrollTarget);
|
||||
break;
|
||||
}
|
||||
currentFrame = currentFrame->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subclass hook for style post processing
|
||||
/* virtual */ void
|
||||
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||
@@ -2902,6 +2945,13 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
aBuilder->AdjustWindowDraggingRegion(child);
|
||||
child->BuildDisplayList(aBuilder, aLists);
|
||||
/* // Visualise scroll anchor
|
||||
if (child->HasAnyStateBits(NS_FRAME_IS_SCROLL_ANCHOR)) {
|
||||
nsRect bounds = child->GetContentRectRelativeToSelf() +
|
||||
aBuilder->ToReferenceFrame(child);
|
||||
list.AppendToTop(MakeDisplayItem<nsDisplaySolidColor>(aBuilder, child, bounds, NS_RGBA(255, 0, 0, 55)));
|
||||
}
|
||||
// */
|
||||
aBuilder->DisplayCaret(child, aLists.Content());
|
||||
#ifdef DEBUG
|
||||
DisplayDebugBorders(aBuilder, child, aLists);
|
||||
@@ -2916,6 +2966,13 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayListCollection pseudoStack(aBuilder);
|
||||
aBuilder->AdjustWindowDraggingRegion(child);
|
||||
child->BuildDisplayList(aBuilder, pseudoStack);
|
||||
/* // Visualise scroll anchor
|
||||
if (child->HasAnyStateBits(NS_FRAME_IS_SCROLL_ANCHOR)) {
|
||||
nsRect bounds = child->GetContentRectRelativeToSelf() +
|
||||
aBuilder->ToReferenceFrame(child);
|
||||
list.AppendToTop(MakeDisplayItem<nsDisplaySolidColor>(aBuilder, child, bounds, NS_RGBA(255, 0, 0, 55)));
|
||||
}
|
||||
// */
|
||||
aBuilder->DisplayCaret(child, pseudoStack.Content());
|
||||
|
||||
list.AppendToTop(pseudoStack.BorderBackground());
|
||||
|
||||
@@ -266,6 +266,12 @@ FRAME_STATE_BIT(Generic, 53, NS_FRAME_IS_NONDISPLAY)
|
||||
// Frame has a LayerActivityProperty property
|
||||
FRAME_STATE_BIT(Generic, 54, NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)
|
||||
|
||||
// For scroll-anchoring
|
||||
FRAME_STATE_BIT(Generic, 55, NS_FRAME_CONTAINS_SCROLL_ANCHOR)
|
||||
FRAME_STATE_BIT(Generic, 56, NS_FRAME_IS_SCROLL_ANCHOR)
|
||||
|
||||
// Bit 57 is currently unused
|
||||
|
||||
// Set for all descendants of MathML sub/supscript elements (other than the
|
||||
// base frame) to indicate that the SSTY font feature should be used.
|
||||
FRAME_STATE_BIT(Generic, 58, NS_FRAME_MATHML_SCRIPT_DESCENDANT)
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "nsSVGIntegrationUtils.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxPrefs.h"
|
||||
@@ -2022,6 +2023,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
|
||||
, mScrolledFrame(nullptr)
|
||||
, mScrollCornerBox(nullptr)
|
||||
, mResizerBox(nullptr)
|
||||
, mAnchorNode(nullptr)
|
||||
, mOuter(aOuter)
|
||||
, mAsyncScroll(nullptr)
|
||||
, mAsyncSmoothMSDScroll(nullptr)
|
||||
@@ -2033,6 +2035,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
|
||||
, mScrollPosAtLastPaint(0, 0)
|
||||
, mRestorePos(-1, -1)
|
||||
, mLastPos(-1, -1)
|
||||
, mLastAnchorPos(0, 0)
|
||||
, mScrollPosForLayerPixelAlignment(-1, -1)
|
||||
, mLastUpdateFramesPos(-1, -1)
|
||||
, mHadDisplayPortAtLastFrameUpdate(false)
|
||||
@@ -2250,6 +2253,146 @@ ScrollFrameHelper::GetScrollPositionCSSPixels()
|
||||
return CSSIntPoint::FromAppUnitsRounded(GetScrollPosition());
|
||||
}
|
||||
|
||||
static void
|
||||
MarkAsScrollAnchorNode(nsIFrame* aScrolledFrame, nsIFrame* aAnchorNode)
|
||||
{
|
||||
aAnchorNode->AddStateBits(NS_FRAME_IS_SCROLL_ANCHOR);
|
||||
nsIFrame* containsAnchor = aAnchorNode->GetParent();
|
||||
while (containsAnchor && containsAnchor != aScrolledFrame) {
|
||||
containsAnchor->AddStateBits(NS_FRAME_CONTAINS_SCROLL_ANCHOR);
|
||||
containsAnchor = containsAnchor->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UnmarkAsScrollAnchorNode(nsIFrame* aScrolledFrame, nsIFrame* aAnchorNode)
|
||||
{
|
||||
aAnchorNode->RemoveStateBits(NS_FRAME_IS_SCROLL_ANCHOR);
|
||||
nsIFrame* containsAnchor = aAnchorNode->GetParent();
|
||||
while (containsAnchor && containsAnchor != aScrolledFrame) {
|
||||
containsAnchor->RemoveStateBits(NS_FRAME_CONTAINS_SCROLL_ANCHOR);
|
||||
containsAnchor = containsAnchor->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
static nsRect
|
||||
FindScrollAnchorRect(nsIFrame* aScrollableFrame, nsIFrame* aAnchorNode)
|
||||
{
|
||||
nsRect rect = aAnchorNode->GetContentRectRelativeToSelf();
|
||||
rect.MoveBy(aAnchorNode->GetOffsetTo(aScrollableFrame->GetParent()));
|
||||
return rect;
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::UpdateScrollAnchor()
|
||||
{
|
||||
printf_stderr("\nnsGfxScrollFrame(%p)::UpdateScrollAnchor scrollport=(%d, %d)x(%d, %d)\n",
|
||||
this,
|
||||
mScrollPort.x,
|
||||
mScrollPort.y,
|
||||
mScrollPort.width,
|
||||
mScrollPort.height);
|
||||
MOZ_ASSERT(mScrolledFrame);
|
||||
|
||||
nsIFrame* oldAnchorNode = mAnchorNode;
|
||||
for (nsIFrame* kid : mScrolledFrame->PrincipalChildList()) {
|
||||
nsIFrame* candidate = SelectScrollAnchorImpl(kid);
|
||||
if (candidate) {
|
||||
mAnchorNode = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldAnchorNode != mAnchorNode) {
|
||||
if (oldAnchorNode) {
|
||||
UnmarkAsScrollAnchorNode(mScrolledFrame, oldAnchorNode);
|
||||
// Make sure we stop highlighting the old anchor
|
||||
oldAnchorNode->InvalidateFrame();
|
||||
}
|
||||
if (mAnchorNode) {
|
||||
MarkAsScrollAnchorNode(mScrolledFrame, mAnchorNode);
|
||||
// Make sure we start highlighting the new anchor
|
||||
mAnchorNode->InvalidateFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (mAnchorNode) {
|
||||
mLastAnchorPos = FindScrollAnchorRect(mOuter, mAnchorNode).TopLeft();
|
||||
} else {
|
||||
mLastAnchorPos = nsPoint();
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
ScrollFrameHelper::SelectScrollAnchorImpl(nsIFrame* aNode)
|
||||
{
|
||||
nsRect rect = FindScrollAnchorRect(mOuter, aNode);
|
||||
|
||||
bool excludedSubtree =
|
||||
aNode->IsTransformed() ||
|
||||
aNode->GetType() == mozilla::LayoutFrameType::Placeholder ||
|
||||
aNode->GetType() == mozilla::LayoutFrameType::Inline ||
|
||||
aNode->GetType() == mozilla::LayoutFrameType::Line ||
|
||||
aNode->IsRelativelyPositioned(); // should exclude only sticky, this was easier
|
||||
bool opaqueSubtree = aNode->GetType() == mozilla::LayoutFrameType::Scroll;
|
||||
|
||||
nsCString tag;
|
||||
nsIFrame::ListTag(tag, aNode);
|
||||
|
||||
if (excludedSubtree) {
|
||||
printf_stderr("Found excluded subtree [frame=%s]\n",
|
||||
tag.get());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool fullyVisible = mScrollPort.Contains(rect) && !rect.IsEmpty();
|
||||
|
||||
// If this frame is fully visible then select it as the scroll anchor
|
||||
if (fullyVisible) {
|
||||
printf_stderr("Found contained frame [frame=%s rect=(%d, %d)x(%d, %d)]\n",
|
||||
tag.get(),
|
||||
rect.x,
|
||||
rect.y,
|
||||
rect.width,
|
||||
rect.height);
|
||||
|
||||
return aNode;
|
||||
}
|
||||
|
||||
// If this frame is partially visible then examine its children for a better
|
||||
// scroll anchor
|
||||
if (mScrollPort.Intersects(rect)) {
|
||||
printf_stderr("Found intersected frame [frame=%s rect=(%d, %d)x(%d, %d)]\n",
|
||||
tag.get(),
|
||||
rect.x,
|
||||
rect.y,
|
||||
rect.width,
|
||||
rect.height);
|
||||
|
||||
// This frame is opaque and can be a scroll anchor, but its contents should
|
||||
// not be scroll anchors
|
||||
if (opaqueSubtree) {
|
||||
return aNode;
|
||||
}
|
||||
|
||||
// Try to find a deeper frame that is fully visible in the scroll port
|
||||
for (nsIFrame* kid : aNode->PrincipalChildList()) {
|
||||
nsIFrame* candidate = SelectScrollAnchorImpl(kid);
|
||||
if (candidate) {
|
||||
printf_stderr("Using a closer child frame [frame=%p]\n", candidate);
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
printf_stderr("Fallback to intersected frame [frame=%s]\n",
|
||||
tag.get());
|
||||
|
||||
return aNode;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* this method wraps calls to ScrollToImpl(), either in one shot or incrementally,
|
||||
* based on the setting of the smoothness scroll pref
|
||||
@@ -2833,6 +2976,7 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
|
||||
mScrollGeneration = ++sScrollGenerationCounter;
|
||||
|
||||
ScrollVisual();
|
||||
UpdateScrollAnchor();
|
||||
|
||||
bool schedulePaint = true;
|
||||
if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && gfxPrefs::APZPaintSkipping()) {
|
||||
@@ -4342,6 +4486,7 @@ ScrollFrameHelper::ReloadChildFrames()
|
||||
mVScrollbarBox = nullptr;
|
||||
mScrollCornerBox = nullptr;
|
||||
mResizerBox = nullptr;
|
||||
mAnchorNode = nullptr;
|
||||
|
||||
for (nsIFrame* frame : mOuter->PrincipalChildList()) {
|
||||
nsIContent* content = frame->GetContent();
|
||||
@@ -6250,3 +6395,42 @@ ScrollFrameHelper::UsesContainerScrolling() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::ScrollAnchorWillDestroy()
|
||||
{
|
||||
if (mAnchorNode) {
|
||||
UnmarkAsScrollAnchorNode(mScrolledFrame, mAnchorNode);
|
||||
mAnchorNode = nullptr;
|
||||
mLastAnchorPos = nsPoint();
|
||||
// XXX Should we calculate a new one anchor here, or push a callback
|
||||
// to do that at a safer time?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::ApplyScrollAnchorOffsetAdjustment()
|
||||
{
|
||||
MOZ_ASSERT(mAnchorNode);
|
||||
|
||||
nsPoint currentAnchorPos = FindScrollAnchorRect(mOuter, mAnchorNode).TopLeft();
|
||||
nsPoint adjustment = currentAnchorPos - mLastAnchorPos;
|
||||
nsIntPoint adjustmentDevicePixels = adjustment
|
||||
.ToNearestPixels(mOuter->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
printf_stderr("nsGfxScrollFrame(%p)::ApplyScrollAnchorOffsetAdjustment adjustment=(%d, %d)\n",
|
||||
this,
|
||||
adjustmentDevicePixels.x,
|
||||
adjustmentDevicePixels.y);
|
||||
|
||||
nsIFrame* scrollAnchor = mAnchorNode;
|
||||
|
||||
ScrollBy(adjustmentDevicePixels,
|
||||
nsIScrollableFrame::DEVICE_PIXELS,
|
||||
nsIScrollableFrame::INSTANT,
|
||||
nullptr,
|
||||
nsGkAtoms::relative);
|
||||
|
||||
// The last scroll anchor offset should be updated within ScrollToImpl and
|
||||
// the scroll anchor should not have changed
|
||||
MOZ_ASSERT(scrollAnchor == mAnchorNode);
|
||||
}
|
||||
@@ -458,6 +458,11 @@ public:
|
||||
return mSuppressScrollbarRepaints;
|
||||
}
|
||||
|
||||
|
||||
void ScrollAnchorWillDestroy();
|
||||
|
||||
void ApplyScrollAnchorOffsetAdjustment();
|
||||
|
||||
// owning references to the nsIAnonymousContentCreator-built content
|
||||
nsCOMPtr<nsIContent> mHScrollbarContent;
|
||||
nsCOMPtr<nsIContent> mVScrollbarContent;
|
||||
@@ -472,6 +477,7 @@ public:
|
||||
nsIFrame* mScrolledFrame;
|
||||
nsIFrame* mScrollCornerBox;
|
||||
nsIFrame* mResizerBox;
|
||||
nsIFrame* mAnchorNode;
|
||||
nsContainerFrame* mOuter;
|
||||
RefPtr<AsyncScroll> mAsyncScroll;
|
||||
RefPtr<AsyncSmoothMSDScroll> mAsyncSmoothMSDScroll;
|
||||
@@ -500,6 +506,11 @@ public:
|
||||
// other than trying to restore mRestorePos.
|
||||
nsPoint mLastPos;
|
||||
|
||||
// The last scroll position of the scroll anchor node. This is in the same
|
||||
// coordinate space as mScrollPort, that is, relative to the parent of this
|
||||
// scrollable frame.
|
||||
nsPoint mLastAnchorPos;
|
||||
|
||||
nsExpirationState mActivityExpirationState;
|
||||
|
||||
nsCOMPtr<nsITimer> mScrollActivityTimer;
|
||||
@@ -619,6 +630,9 @@ protected:
|
||||
bool mOldSuppressValue;
|
||||
};
|
||||
|
||||
void UpdateScrollAnchor();
|
||||
nsIFrame* SelectScrollAnchorImpl(nsIFrame* aNode);
|
||||
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
@@ -1047,6 +1061,14 @@ public:
|
||||
virtual mozilla::a11y::AccType AccessibleType() override;
|
||||
#endif
|
||||
|
||||
virtual void ScrollAnchorWillDestroy() override {
|
||||
mHelper.ScrollAnchorWillDestroy();
|
||||
}
|
||||
|
||||
virtual void ApplyScrollAnchorOffsetAdjustment() override {
|
||||
mHelper.ApplyScrollAnchorOffsetAdjustment();
|
||||
}
|
||||
|
||||
protected:
|
||||
nsHTMLScrollFrame(nsStyleContext* aContext, bool aIsRoot);
|
||||
void SetSuppressScrollbarUpdate(bool aSuppress) {
|
||||
@@ -1471,6 +1493,14 @@ public:
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||
#endif
|
||||
|
||||
virtual void ScrollAnchorWillDestroy() override {
|
||||
mHelper.ScrollAnchorWillDestroy();
|
||||
}
|
||||
|
||||
virtual void ApplyScrollAnchorOffsetAdjustment() override {
|
||||
mHelper.ApplyScrollAnchorOffsetAdjustment();
|
||||
}
|
||||
|
||||
protected:
|
||||
nsXULScrollFrame(nsStyleContext* aContext, bool aIsRoot,
|
||||
bool aClipAllDescendants);
|
||||
|
||||
@@ -861,6 +861,7 @@ public:
|
||||
} else {
|
||||
mRect = aRect;
|
||||
}
|
||||
MaybeNotifyScrollAnchor();
|
||||
}
|
||||
/**
|
||||
* Set this frame's rect from a logical rect in its own writing direction
|
||||
@@ -922,6 +923,7 @@ public:
|
||||
// the top right of the frame instead of the top left.
|
||||
mRect.MoveTo(aPt.GetPhysicalPoint(aWritingMode,
|
||||
aContainerSize - mRect.Size()));
|
||||
MaybeNotifyScrollAnchor();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2742,6 +2744,8 @@ public:
|
||||
const nsRect* aFrameDamageRect = nullptr,
|
||||
uint32_t aFlags = 0);
|
||||
|
||||
void MaybeNotifyScrollAnchor();
|
||||
|
||||
/**
|
||||
* Returns a rect that encompasses everything that might be painted by
|
||||
* this frame. This includes this frame, all its descendant frames, this
|
||||
|
||||
@@ -475,6 +475,9 @@ public:
|
||||
virtual ScrollSnapInfo GetScrollSnapInfo() const = 0;
|
||||
|
||||
virtual void SetScrollsClipOnUnscrolledOutOfFlow() = 0;
|
||||
|
||||
virtual void ScrollAnchorWillDestroy() = 0;
|
||||
virtual void ApplyScrollAnchorOffsetAdjustment() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user