Bug 1253860 - Add a flag on scroll frames indicating if they have an APZ counterpart. r?mstange
MozReview-Commit-ID: 4zm2nbxl3cq
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -119,16 +119,20 @@ ScrollFrameTo(nsIScrollableFrame* aFrame
* and actual scroll positions.
*/
static void
ScrollFrame(nsIContent* aContent,
FrameMetrics& aMetrics)
{
// Scroll the window to the desired spot
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
+ if (sf) {
+ sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
+ }
+
bool scrollUpdated = false;
CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);
if (scrollUpdated) {
if (aMetrics.IsScrollInfoLayer()) {
// In cases where the APZ scroll offset is different from the content scroll
// offset, we want to interpret the margins as relative to the APZ scroll
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1109,16 +1109,22 @@ static bool IsFocused(nsIContent* aConte
aContent = aContent->GetParent();
}
return aContent ? nsContentUtils::IsFocusedContent(aContent) : false;
}
#endif
void
+ScrollFrameHelper::SetScrollableByAPZ(bool aScrollable)
+{
+ mScrollableByAPZ = aScrollable;
+}
+
+void
ScrollFrameHelper::SetZoomableByAPZ(bool aZoomable)
{
if (mZoomableByAPZ != aZoomable) {
// We might be changing the result of WantAsyncScroll() so schedule a
// paint to make sure we pick up the result of that change.
mZoomableByAPZ = aZoomable;
mOuter->SchedulePaint();
}
@@ -1867,16 +1873,17 @@ ScrollFrameHelper::ScrollFrameHelper(nsC
, mHasBeenScrolledRecently(false)
, mCollapsedResizer(false)
, mWillBuildScrollableLayer(false)
, mIsScrollParent(false)
, mIsScrollableLayerInRootContainer(false)
, mHasBeenScrolled(false)
, mIgnoreMomentumScroll(false)
, mTransformingByAPZ(false)
+ , mScrollableByAPZ(false)
, mZoomableByAPZ(false)
, mVelocityQueue(aOuter->PresContext())
, mAsyncScrollEvent(END_DOM)
{
if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) {
mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter));
}
@@ -2376,16 +2383,19 @@ RemoveDisplayPortCallback(nsITimer* aTim
// displayport back on it. Although the displayport will "flicker" off and
// back on, the layer itself should never disappear, because this all
// happens between actual painting. If the displayport is reset to a
// different position that's ok; this scrollframe hasn't been scrolled
// recently and so the reset should be correct.
nsLayoutUtils::RemoveDisplayPort(helper->mOuter->GetContent());
nsLayoutUtils::ExpireDisplayPortOnAsyncScrollableAncestor(helper->mOuter);
helper->mOuter->SchedulePaint();
+ // Be conservative and unflag this this scrollframe as being scrollable by
+ // APZ. If it is still scrollable this will get flipped back soon enough.
+ helper->mScrollableByAPZ = false;
}
void ScrollFrameHelper::MarkNotRecentlyScrolled()
{
if (!mHasBeenScrolledRecently)
return;
mHasBeenScrolledRecently = false;
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -379,16 +379,17 @@ public:
// because we have special behaviour for it when APZ scrolling is active.
mOuter->SchedulePaint();
}
NotifyPluginFrames(aTransforming ? BEGIN_APZ : END_APZ);
}
bool IsTransformingByAPZ() const {
return mTransformingByAPZ;
}
+ void SetScrollableByAPZ(bool aScrollable);
void SetZoomableByAPZ(bool aZoomable);
bool UsesContainerScrolling() const;
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort);
void NotifyImageVisibilityUpdate();
@@ -560,16 +561,20 @@ public:
// True if the events synthesized by OSX to produce momentum scrolling should
// be ignored. Reset when the next real, non-synthesized scroll event occurs.
bool mIgnoreMomentumScroll:1;
// True if the APZ is in the process of async-transforming this scrollframe,
// (as best as we can tell on the main thread, anyway).
bool mTransformingByAPZ:1;
+ // True if APZ can scroll this frame asynchronously (i.e. it has an APZC
+ // set up for this frame and it's not a scrollinfo layer).
+ bool mScrollableByAPZ:1;
+
// True if the APZ is allowed to zoom this scrollframe.
bool mZoomableByAPZ:1;
mozilla::layout::ScrollVelocityQueue mVelocityQueue;
protected:
/**
* @note This method might destroy the frame, pres shell and other objects.
@@ -957,16 +962,19 @@ public:
}
virtual void SetTransformingByAPZ(bool aTransforming) override {
mHelper.SetTransformingByAPZ(aTransforming);
}
bool IsTransformingByAPZ() const override {
return mHelper.IsTransformingByAPZ();
}
+ void SetScrollableByAPZ(bool aScrollable) override {
+ mHelper.SetScrollableByAPZ(aScrollable);
+ }
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
@@ -1352,16 +1360,19 @@ public:
mHelper.SetTransformingByAPZ(aTransforming);
}
virtual bool UsesContainerScrolling() const override {
return mHelper.UsesContainerScrolling();
}
bool IsTransformingByAPZ() const override {
return mHelper.IsTransformingByAPZ();
}
+ void SetScrollableByAPZ(bool aScrollable) override {
+ mHelper.SetScrollableByAPZ(aScrollable);
+ }
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort) override {
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
}
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -415,16 +415,24 @@ public:
* Mark the scrollbar frames for reflow.
*/
virtual void MarkScrollbarsDirtyForReflow() const = 0;
virtual void SetTransformingByAPZ(bool aTransforming) = 0;
virtual bool IsTransformingByAPZ() const = 0;
/**
+ * Notify this scroll frame that it can be scrolled by APZ. In particular,
+ * this is called *after* the APZ code has created an APZC for this scroll
+ * frame and verified that it is not a scrollinfo layer. Therefore, setting an
+ * async transform on it is actually user visible.
+ */
+ virtual void SetScrollableByAPZ(bool aScrollable) = 0;
+
+ /**
* Notify this scroll frame that it can be zoomed by APZ.
*/
virtual void SetZoomableByAPZ(bool aZoomable) = 0;
/**
* Whether or not this frame uses containerful scrolling.
*/
virtual bool UsesContainerScrolling() const = 0;