Bug 1349750 - Add an 'is async-draggable' flag to ScrollThumbData. r=kats
authorBotond Ballo <botond@mozilla.com>
Fri, 05 May 2017 16:17:06 -0400
changeset 408669 9b08e1862d706350eda189a688b0ca1fd8f6dcd1
parent 408668 1c1eb8a23e87b05fbc7443757203ae6c8cc33849
child 408670 a243424febf24192b66b21eea2a455307888c85a
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1349750
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1349750 - Add an 'is async-draggable' flag to ScrollThumbData. r=kats This flag is set to false if there are any conditions that only the main thread knows about that prevent the thumb from being async-dragged. MozReview-Commit-ID: Gl7f7bY0QnA
gfx/layers/LayerAttributes.h
layout/xul/nsSliderFrame.cpp
--- a/gfx/layers/LayerAttributes.h
+++ b/gfx/layers/LayerAttributes.h
@@ -17,36 +17,42 @@ template <typename T> struct ParamTraits
 namespace mozilla {
 namespace layers {
 
 // Data stored for scroll thumb container layers.
 struct ScrollThumbData {
   ScrollThumbData()
     : mDirection(ScrollDirection::NONE)
     , mThumbRatio(0.0f)
+    , mIsAsyncDraggable(false)
   {}
   ScrollThumbData(ScrollDirection aDirection,
                   float aThumbRatio,
-                  CSSCoord aThumbLength)
+                  CSSCoord aThumbLength,
+                  bool aIsAsyncDraggable)
     : mDirection(aDirection)
     , mThumbRatio(aThumbRatio)
     , mThumbLength(aThumbLength)
+    , mIsAsyncDraggable(aIsAsyncDraggable)
   {}
 
   ScrollDirection mDirection;
   // The scrollbar thumb ratio is the ratio of the thumb position (in the CSS
   // pixels of the scrollframe's parent's space) to the scroll position (in the
   // CSS pixels of the scrollframe's space).
   float mThumbRatio;
   CSSCoord mThumbLength;
+  // Whether the scrollbar thumb can be dragged asynchronously.
+  bool mIsAsyncDraggable;
 
   bool operator==(const ScrollThumbData& aOther) const {
     return mDirection == aOther.mDirection &&
            mThumbRatio == aOther.mThumbRatio &&
-           mThumbLength == aOther.mThumbLength;
+           mThumbLength == aOther.mThumbLength &&
+           mIsAsyncDraggable == aOther.mIsAsyncDraggable;
   }
   bool operator!=(const ScrollThumbData& aOther) const {
     return !(*this == aOther);
   }
 };
 
 // Infrequently changing layer attributes that require no special
 // serialization work.
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -327,16 +327,31 @@ nsSliderFrame::BuildDisplayList(nsDispla
     aLists.Outlines()->AppendNewToTop(new (aBuilder)
       nsDisplayEventReceiver(aBuilder, this));
     return;
   }
   
   nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
 }
 
+static bool
+UsesCustomScrollbarMediator(nsIFrame* scrollbarBox) {
+  if (nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox)) {
+    if (nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator()) {
+      nsIScrollableFrame* scrollFrame = do_QueryFrame(mediator);
+      // The scrollbar mediator is not the scroll frame.
+      // That means this scroll frame has a custom scrollbar mediator.
+      if (!scrollFrame) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 void
 nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                            const nsRect&           aDirtyRect,
                                            const nsDisplayListSet& aLists)
 {
   // if we are too small to have a thumb don't paint it.
   nsIFrame* thumb = nsBox::GetChildXULBox(this);
 
@@ -371,16 +386,19 @@ nsSliderFrame::BuildDisplayListForChildr
       bool isHorizontal = (flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR);
       ScrollDirection scrollDirection = isHorizontal
           ? ScrollDirection::HORIZONTAL
           : ScrollDirection::VERTICAL;
       const float appUnitsPerCss = float(AppUnitsPerCSSPixel());
       CSSCoord thumbLength = NSAppUnitsToFloatPixels(
           isHorizontal ? thumbRect.width : thumbRect.height, appUnitsPerCss);
 
+      nsIFrame* scrollbarBox = GetScrollbar();
+      bool isAsyncDraggable = !UsesCustomScrollbarMediator(scrollbarBox);
+
       nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
       nsDisplayListCollection tempLists;
       nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, tempLists);
 
       // This is a bit of a hack. Collect up all descendant display items
       // and merge them into a single Content() list.
       nsDisplayList masterList;
       masterList.AppendToTop(tempLists.BorderBackground());
@@ -394,17 +412,18 @@ nsSliderFrame::BuildDisplayListForChildr
       const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR();
       DisplayListClipState::AutoSaveRestore ownLayerClipState(aBuilder);
       ownLayerClipState.ClearUpToASR(ownLayerASR);
       aLists.Content()->AppendNewToTop(new (aBuilder)
         nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR,
                           flags, scrollTargetId,
                           ScrollThumbData{scrollDirection,
                                           GetThumbRatio(),
-                                          thumbLength}));
+                                          thumbLength,
+                                          isAsyncDraggable}));
 
       return;
     }
   }
   
   nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
 }
 
@@ -1031,29 +1050,20 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEve
   }
 
   // APZ dragging requires the scrollbar to be layerized, which doesn't
   // happen for scroll info layers.
   if (ScrollFrameWillBuildScrollInfoLayer(scrollFrame)) {
     return;
   }
 
-  nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
-  if (!scrollbarFrame) {
+  // Custom scrollbar mediators are not supported in the APZ codepath.
+  if (UsesCustomScrollbarMediator(scrollbarBox)) {
     return;
   }
-  if (nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator()) {
-    nsIScrollableFrame* scrollFrame = do_QueryFrame(mediator);
-    // The scrollbar mediator is not the scroll frame.
-    // That means this scroll frame has a custom scrollbar mediator.
-    // That's not supported in the APZ codepath.
-    if (!scrollFrame) {
-      return;
-    }
-  }
 
   bool isHorizontal = IsXULHorizontal();
 
   mozilla::layers::FrameMetrics::ViewID scrollTargetId;
   bool hasID = nsLayoutUtils::FindIDFor(scrollableContent, &scrollTargetId);
   bool hasAPZView = hasID && (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
 
   if (!hasAPZView) {