Bug 1305957 part 4 - Add basic ScrollAnchorContainer implementation. r=hiro

This commit adds a barebones class called 'ScrollAnchorContainer' that will
contain most of the logic for scroll anchoring. It is owned as a member of
ScrollFrameHelper, and has the same lifetime.

Differential Revision: https://phabricator.services.mozilla.com/D13267

--HG--
extra : rebase_source : 41f6f7691af60401f18f98a89f1878cfad2e74d3
extra : source : 3033401ef320414ef5f489c53526d015c38a89d7
This commit is contained in:
Ryan Hunt 2018-11-27 15:18:03 -06:00
Родитель 3627f69c8f
Коммит 91f41f3a0a
6 изменённых файлов: 134 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 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/. */
#include "ScrollAnchorContainer.h"
#include "nsGfxScrollFrame.h"
#include "nsLayoutUtils.h"
#define ANCHOR_LOG(...)
// #define ANCHOR_LOG(...) printf_stderr("ANCHOR: " __VA_ARGS__)
namespace mozilla {
namespace layout {
ScrollAnchorContainer::ScrollAnchorContainer(ScrollFrameHelper* aScrollFrame)
: mScrollFrame(aScrollFrame) {}
ScrollAnchorContainer::~ScrollAnchorContainer() {}
ScrollAnchorContainer* ScrollAnchorContainer::FindFor(nsIFrame* aFrame) {
aFrame = aFrame->GetParent();
if (!aFrame) {
return nullptr;
}
nsIScrollableFrame* nearest = nsLayoutUtils::GetNearestScrollableFrame(
aFrame, nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
if (nearest) {
return nearest->GetAnchor();
}
return nullptr;
}
nsIFrame* ScrollAnchorContainer::Frame() const { return mScrollFrame->mOuter; }
nsIScrollableFrame* ScrollAnchorContainer::ScrollableFrame() const {
return Frame()->GetScrollTargetFrame();
}
} // namespace layout
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 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/. */
#ifndef mozilla_layout_ScrollAnchorContainer_h_
#define mozilla_layout_ScrollAnchorContainer_h_
namespace mozilla {
class ScrollFrameHelper;
} // namespace mozilla
namespace mozilla {
namespace layout {
/**
* A scroll anchor container finds a descendent element of a scrollable frame
* to be an anchor node. After every reflow, the scroll anchor will apply
* scroll adjustments to keep the anchor node in the same relative position.
*
* See: https://drafts.csswg.org/css-scroll-anchoring/
*/
class ScrollAnchorContainer final {
public:
explicit ScrollAnchorContainer(ScrollFrameHelper* aScrollFrame);
~ScrollAnchorContainer();
/**
* Returns the nearest scroll anchor container that could select aFrame as an
* anchor node.
*/
static ScrollAnchorContainer* FindFor(nsIFrame* aFrame);
/**
* Returns the frame that owns this scroll anchor container. This is always
* non-null.
*/
nsIFrame* Frame() const;
/**
* Returns the frame that owns this scroll anchor container as a scrollable
* frame. This is always non-null.
*/
nsIScrollableFrame* ScrollableFrame() const;
private:
// The owner of this scroll anchor container
ScrollFrameHelper* mScrollFrame;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_ScrollAnchorContainer_h_

Просмотреть файл

@ -145,6 +145,7 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.layout += [
'FrameChildList.h',
'ScrollAnchorContainer.h',
]
UNIFIED_SOURCES += [
@ -202,6 +203,7 @@ UNIFIED_SOURCES += [
'ReflowInput.cpp',
'ReflowOutput.cpp',
'RubyUtils.cpp',
'ScrollAnchorContainer.cpp',
'ScrollAnimationBezierPhysics.cpp',
'ScrollAnimationMSDPhysics.cpp',
'ScrollbarActivity.cpp',

Просмотреть файл

@ -1960,6 +1960,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot)
mLastUpdateFramesPos(-1, -1),
mDisplayPortAtLastFrameUpdate(),
mScrollParentID(mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID),
mAnchor(this),
mAllowScrollOriginDowngrade(false),
mHadDisplayPortAtLastFrameUpdate(false),
mNeverHasVerticalScrollbar(false),

Просмотреть файл

@ -25,6 +25,7 @@
#include "TextOverflow.h"
#include "ScrollVelocityQueue.h"
#include "mozilla/PresState.h"
#include "mozilla/layout/ScrollAnchorContainer.h"
class nsPresContext;
class nsIPresShell;
@ -52,6 +53,7 @@ class ScrollFrameHelper : public nsIReflowCallback {
typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
class AsyncScroll;
class AsyncSmoothMSDScroll;
@ -566,6 +568,8 @@ class ScrollFrameHelper : public nsIReflowCallback {
// Timer to remove the displayport some time after scrolling has stopped
nsCOMPtr<nsITimer> mDisplayPortExpiryTimer;
ScrollAnchorContainer mAnchor;
bool mAllowScrollOriginDowngrade : 1;
bool mHadDisplayPortAtLastFrameUpdate : 1;
bool mNeverHasVerticalScrollbar : 1;
@ -723,6 +727,7 @@ class nsHTMLScrollFrame : public nsContainerFrame,
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::ScrollReflowInput ScrollReflowInput;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
friend nsHTMLScrollFrame* NS_NewHTMLScrollFrame(nsIPresShell* aPresShell,
ComputedStyle* aStyle,
bool aIsRoot);
@ -1112,6 +1117,14 @@ class nsHTMLScrollFrame : public nsContainerFrame,
return mHelper.IsRootScrollFrameOfDocument();
}
virtual const ScrollAnchorContainer* GetAnchor() const override {
return &mHelper.mAnchor;
}
virtual ScrollAnchorContainer* GetAnchor() override {
return &mHelper.mAnchor;
}
// Return the scrolled frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override {
aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));
@ -1174,6 +1187,7 @@ class nsXULScrollFrame final : public nsBoxFrame,
public:
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsXULScrollFrame)
@ -1577,6 +1591,14 @@ class nsXULScrollFrame final : public nsBoxFrame,
return mHelper.IsRootScrollFrameOfDocument();
}
virtual const ScrollAnchorContainer* GetAnchor() const override {
return &mHelper.mAnchor;
}
virtual ScrollAnchorContainer* GetAnchor() override {
return &mHelper.mAnchor;
}
// Return the scrolled frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override {
aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));

Просмотреть файл

@ -39,6 +39,9 @@ struct ScrollMetadata;
class Layer;
class LayerManager;
} // namespace layers
namespace layout {
class ScrollAnchorContainer;
} // namespace layout
} // namespace mozilla
/**
@ -51,6 +54,7 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
NS_DECL_QUERYFRAME_TARGET(nsIScrollableFrame)
@ -548,6 +552,12 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
* all (ie XUL documents) even though they may contain other scroll frames.
*/
virtual bool IsRootScrollFrameOfDocument() const = 0;
/**
* Returns the scroll anchor associated with this scrollable frame.
*/
virtual const ScrollAnchorContainer* GetAnchor() const = 0;
virtual ScrollAnchorContainer* GetAnchor() = 0;
};
#endif