Bug 1404181 - Part 15: Compute scrollbar thumb AGR state in advance, rather than setting it during building. r?mstange draft
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 28 Sep 2017 13:48:05 +1300
changeset 682097 1aeea17d510b477db1af8f7e666cf31749df999d
parent 682096 989ec9fdcf7bf408eecdc55ea884b434b3921786
child 682098 df8f9c6c2050e606a09d9fd61f49d2f1089ef64f
push id85000
push usermwoodrow@mozilla.com
push dateWed, 18 Oct 2017 03:52:13 +0000
reviewersmstange
bugs1404181
milestone58.0a1
Bug 1404181 - Part 15: Compute scrollbar thumb AGR state in advance, rather than setting it during building. r?mstange MozReview-Commit-ID: D9eQy8f2kw
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
layout/painting/nsDisplayList.cpp
layout/xul/nsSliderFrame.cpp
layout/xul/nsSliderFrame.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2111,30 +2111,16 @@ nsLayoutUtils::IsFixedPosFrameInDisplayP
   nsIFrame* parent = aFrame->GetParent();
   if (!parent || parent->GetParent() ||
       aFrame->StyleDisplay()->mPosition != NS_STYLE_POSITION_FIXED) {
     return false;
   }
   return ViewportHasDisplayPort(aFrame->PresContext());
 }
 
-NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ScrollbarThumbLayerized, bool)
-
-/* static */ void
-nsLayoutUtils::SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize)
-{
-  aThumbFrame->SetProperty(ScrollbarThumbLayerized(), aLayerize);
-}
-
-bool
-nsLayoutUtils::IsScrollbarThumbLayerized(nsIFrame* aThumbFrame)
-{
-  return aThumbFrame->GetProperty(ScrollbarThumbLayerized());
-}
-
 // static
 nsIScrollableFrame*
 nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame,
                                                      Direction aDirection)
 {
   NS_ASSERTION(aFrame, "GetNearestScrollableFrameForDirection expects a non-null frame");
   for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     nsIScrollableFrame* scrollableFrame = do_QueryFrame(f);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -595,28 +595,16 @@ public:
    * Return true if aFrame is a fixed-pos frame and is a child of a viewport
    * which has a displayport. These frames get special treatment from the compositor.
    * aDisplayPort, if non-null, is set to the display port rectangle (relative to
    * the viewport).
    */
   static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
 
   /**
-   * Store whether aThumbFrame wants its own layer. This sets a property on
-   * the frame.
-   */
-  static void SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize);
-
-  /**
-   * Returns whether aThumbFrame wants its own layer due to having called
-   * SetScrollbarThumbLayerization.
-   */
-  static bool IsScrollbarThumbLayerized(nsIFrame* aThumbFrame);
-
-  /**
     * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
     */
   static nsIScrollableFrame* GetScrollableFrameFor(const nsIFrame *aScrolledFrame);
 
   /**
    * GetNearestScrollableFrameForDirection locates the first ancestor of
    * aFrame (or aFrame itself) that is scrollable with overflow:scroll or
    * overflow:auto in the given direction and where either the scrollbar for
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -891,16 +891,19 @@ public:
   }
   NS_IMETHOD PostScrolledAreaEventForCurrentArea() override {
     mHelper.PostScrolledAreaEvent();
     return NS_OK;
   }
   virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) override {
     return mHelper.IsScrollingActive(aBuilder);
   }
+  virtual bool IsMaybeScrollingActive() const override {
+    return mHelper.IsMaybeScrollingActive();
+  }
   virtual bool MayBeAsynchronouslyScrolled() override {
     return mHelper.MayBeAsynchronouslyScrolled();
   }
   virtual bool IsProcessingAsyncScroll() override {
     return mHelper.IsProcessingAsyncScroll();
   }
   virtual void ResetScrollPositionForLayerPixelAlignment() override {
     mHelper.ResetScrollPositionForLayerPixelAlignment();
@@ -1329,16 +1332,19 @@ public:
   }
   NS_IMETHOD PostScrolledAreaEventForCurrentArea() override {
     mHelper.PostScrolledAreaEvent();
     return NS_OK;
   }
   virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) override {
     return mHelper.IsScrollingActive(aBuilder);
   }
+  virtual bool IsMaybeScrollingActive() const override {
+    return mHelper.IsMaybeScrollingActive();
+  }
   virtual bool MayBeAsynchronouslyScrolled() override {
     return mHelper.MayBeAsynchronouslyScrolled();
   }
   virtual bool IsProcessingAsyncScroll() override {
     return mHelper.IsProcessingAsyncScroll();
   }
   virtual void ResetScrollPositionForLayerPixelAlignment() override {
     mHelper.ResetScrollPositionForLayerPixelAlignment();
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -312,16 +312,22 @@ public:
   /**
    * Returns true if this scrollframe is being "actively scrolled".
    * This basically means that we should allocate resources in the
    * expectation that scrolling is going to happen.
    */
   virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) = 0;
 
   /**
+   * Same as the above except doesn't take into account will-change budget,
+   * which means that it can be called during display list building.
+   */
+  virtual bool IsMaybeScrollingActive() const = 0;
+
+  /**
    * Returns true if this scroll frame might be scrolled
    * asynchronously by the compositor.
    */
   virtual bool MayBeAsynchronouslyScrolled() = 0;
 
   /**
    * Returns true if the scrollframe is currently processing an async
    * or smooth scroll.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -78,16 +78,17 @@
 #include "mozilla/GeckoRestyleManager.h"
 #include "nsCaret.h"
 #include "nsISelection.h"
 #include "nsDOMTokenList.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "nsCSSProps.h"
 #include "nsPluginFrame.h"
 #include "nsSVGMaskFrame.h"
+#include "nsSliderFrame.h"
 #include "nsTableCellFrame.h"
 #include "nsTableColFrame.h"
 #include "ClientLayerManager.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "mozilla/layers/WebRenderMessages.h"
 #include "mozilla/layers/WebRenderScrollData.h"
@@ -1648,17 +1649,18 @@ nsDisplayListBuilder::IsAnimatedGeometry
     // for background-attachment:fixed elements.
     return AGR_YES;
   }
 
 
   // Treat the slider thumb as being as an active scrolled root when it wants
   // its own layer so that it can move without repainting.
   if (parentType == LayoutFrameType::Slider) {
-    if (nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
+    nsIScrollableFrame* sf = static_cast<nsSliderFrame*>(parent)->GetScrollFrame();
+    if (sf && sf->IsMaybeScrollingActive()) {
       return AGR_YES;
     }
     result = AGR_MAYBE;
   }
 
   if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
     if (IsStickyFrameActive(this, aFrame, parent)) {
       return AGR_YES;
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -374,17 +374,16 @@ nsSliderFrame::BuildDisplayListForChildr
     // We do this here and not in the thumb's nsBoxFrame::BuildDisplayList so
     // that the event region that gets created for the thumb is included in
     // the nsDisplayOwnLayer contents.
 
     uint32_t flags = aBuilder->GetCurrentScrollbarFlags();
     mozilla::layers::FrameMetrics::ViewID scrollTargetId =
       aBuilder->GetCurrentScrollbarTarget();
     bool thumbGetsLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
-    nsLayoutUtils::SetScrollbarThumbLayerization(thumb, thumbGetsLayer);
 
     if (thumbGetsLayer) {
       MOZ_ASSERT((flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR) ||
                  (flags & nsDisplayOwnLayer::VERTICAL_SCROLLBAR));
       bool isHorizontal = (flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR);
       ScrollDirection scrollDirection = isHorizontal
           ? ScrollDirection::HORIZONTAL
           : ScrollDirection::VERTICAL;
@@ -1067,16 +1066,32 @@ ScrollFrameWillBuildScrollInfoLayer(nsIF
     if (UsesSVGEffects(current)) {
       return true;
     }
     current = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(current);
   }
   return false;
 }
 
+nsIScrollableFrame* nsSliderFrame::GetScrollFrame()
+{
+  nsIFrame* scrollbarBox = GetScrollbar();
+  if (!scrollbarBox) {
+    return nullptr;
+  }
+
+  nsContainerFrame* scrollFrame = scrollbarBox->GetParent();
+  if (!scrollFrame) {
+    return nullptr;
+  }
+
+  nsIScrollableFrame* scrollFrameAsScrollable = do_QueryFrame(scrollFrame);
+  return scrollFrameAsScrollable;
+}
+
 void
 nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
 {
   if (!aEvent->mFlags.mHandledByAPZ) {
     return;
   }
 
   if (!gfxPlatform::GetPlatform()->SupportsApzDragInput()) {
--- a/layout/xul/nsSliderFrame.h
+++ b/layout/xul/nsSliderFrame.h
@@ -132,16 +132,19 @@ public:
   // scrolled frame.
   float GetThumbRatio() const;
 
   // Notify the slider frame than an async scrollbar drag requested in
   // StartAPZDrag() was rejected by APZ, and the slider frame should
   // fall back to main-thread dragging.
   void AsyncScrollbarDragRejected();
 
+  // Returns the associated scrollframe that contains this slider if any.
+  nsIScrollableFrame* GetScrollFrame();
+
   bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const override;
 
 private:
 
   bool GetScrollToClick();
   nsIFrame* GetScrollbar();
   bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent);
   bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent);