Bug 1367765 - Factor out a SetupScrollbarDrag() helper function. r=rhunt draft
authorBotond Ballo <botond@mozilla.com>
Thu, 07 Sep 2017 00:05:28 -0400
changeset 662630 bc5c153f2b2ca09ea3253b50efbca629763305e3
parent 662474 02c78441c03d5d004e57596a130856861a30188a
child 662631 0c3bf836ebf7f1a76d91f4a11acc47c0ecca6ac8
child 663395 2e1420a9ae2b9b16c54b89a9cafa0aa9926434b2
push id79143
push userbballo@mozilla.com
push dateMon, 11 Sep 2017 21:46:42 +0000
reviewersrhunt
bugs1367765
milestone57.0a1
Bug 1367765 - Factor out a SetupScrollbarDrag() helper function. r=rhunt MozReview-Commit-ID: 9IMZRMUHpDy
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1039,71 +1039,18 @@ APZCTreeManager::ReceiveInputEvent(Input
         }
         result = mInputQueue->ReceiveInputEvent(
           apzc, targetConfirmed,
           mouseInput, aOutInputBlockId);
 
         // If we're starting an async scrollbar drag
         if (apzDragEnabled && startsDrag && hitScrollbarNode &&
             hitScrollbarNode->IsScrollThumbNode() &&
-            hitScrollbarNode->GetScrollThumbData().mIsAsyncDraggable &&
-            mInputQueue->GetCurrentDragBlock()) {
-          DragBlockState* dragBlock = mInputQueue->GetCurrentDragBlock();
-          const ScrollThumbData& thumbData = hitScrollbarNode->GetScrollThumbData();
-
-          // Record the thumb's position at the start of the drag.
-          // We snap back to this position if, during the drag, the mouse
-          // gets sufficiently far away from the scrollbar.
-          dragBlock->SetInitialThumbPos(thumbData.mThumbStart);
-
-          // Under some conditions, we can confirm the drag block right away.
-          // Otherwise, we have to wait for a main-thread confirmation.
-          if (gfxPrefs::APZDragInitiationEnabled() &&
-              // check that the scrollbar's target scroll frame is layerized
-              hitScrollbarNode->GetScrollTargetId() == apzc->GetGuid().mScrollId &&
-              !apzc->IsScrollInfoLayer()) {
-            uint64_t dragBlockId = dragBlock->GetBlockId();
-            // AsyncPanZoomController::HandleInputEvent() will call
-            // TransformToLocal() on the event, but we need its mLocalOrigin now
-            // to compute a drag start offset for the AsyncDragMetrics.
-            mouseInput.TransformToLocal(apzc->GetTransformToThis());
-            CSSCoord dragStart = apzc->ConvertScrollbarPoint(
-                mouseInput.mLocalOrigin, thumbData);
-            // ConvertScrollbarPoint() got the drag start offset relative to
-            // the scroll track. Now get it relative to the thumb.
-            // ScrollThumbData::mThumbStart stores the offset of the thumb
-            // relative to the scroll track at the time of the last paint.
-            // Since that paint, the thumb may have acquired an async transform
-            // due to async scrolling, so look that up and apply it.
-            LayerToParentLayerMatrix4x4 thumbTransform;
-            {
-              MutexAutoLock lock(mTreeLock);
-              thumbTransform = ComputeTransformForNode(hitScrollbarNode);
-            }
-            // Only consider the translation, since we do not support both
-            // zooming and scrollbar dragging on any platform.
-            CSSCoord thumbStart = thumbData.mThumbStart
-                                + ((thumbData.mDirection == ScrollDirection::HORIZONTAL)
-                                   ? thumbTransform._41 : thumbTransform._42);
-            dragStart -= thumbStart;
-
-            // Content can't prevent scrollbar dragging with preventDefault(),
-            // so we don't need to wait for a content response. It's important
-            // to do this before calling ConfirmDragBlock() since that can
-            // potentially process and consume the block.
-            dragBlock->SetContentResponse(false);
-
-            mInputQueue->ConfirmDragBlock(
-                dragBlockId, apzc,
-                AsyncDragMetrics(apzc->GetGuid().mScrollId,
-                                 apzc->GetGuid().mPresShellId,
-                                 dragBlockId,
-                                 dragStart,
-                                 thumbData.mDirection));
-          }
+            hitScrollbarNode->GetScrollThumbData().mIsAsyncDraggable) {
+          SetupScrollbarDrag(mouseInput, hitScrollbarNode.get(), apzc.get());
         }
 
         if (result == nsEventStatus_eConsumeDoDefault) {
           // This input event is part of a drag block, so whether or not it is
           // directed at a scrollbar depends on whether the drag block started
           // on a scrollbar.
           hitScrollbar = mInputQueue->IsDragOnScrollbar(hitScrollbar);
         }
@@ -1541,16 +1488,80 @@ APZCTreeManager::ProcessTouchInput(Multi
     mHitResultForInputBlock = HitNothing;
     mRetainedTouchIdentifier = -1;
   }
 
   return result;
 }
 
 void
+APZCTreeManager::SetupScrollbarDrag(MouseInput& aMouseInput,
+                                    const HitTestingTreeNode* aScrollThumbNode,
+                                    AsyncPanZoomController* aApzc)
+{
+  DragBlockState* dragBlock = mInputQueue->GetCurrentDragBlock();
+  if (!dragBlock) {
+    return;
+  }
+
+  const ScrollThumbData& thumbData = aScrollThumbNode->GetScrollThumbData();
+
+  // Record the thumb's position at the start of the drag.
+  // We snap back to this position if, during the drag, the mouse
+  // gets sufficiently far away from the scrollbar.
+  dragBlock->SetInitialThumbPos(thumbData.mThumbStart);
+
+  // Under some conditions, we can confirm the drag block right away.
+  // Otherwise, we have to wait for a main-thread confirmation.
+  if (gfxPrefs::APZDragInitiationEnabled() &&
+      // check that the scrollbar's target scroll frame is layerized
+      aScrollThumbNode->GetScrollTargetId() == aApzc->GetGuid().mScrollId &&
+      !aApzc->IsScrollInfoLayer()) {
+    uint64_t dragBlockId = dragBlock->GetBlockId();
+    // AsyncPanZoomController::HandleInputEvent() will call
+    // TransformToLocal() on the event, but we need its mLocalOrigin now
+    // to compute a drag start offset for the AsyncDragMetrics.
+    aMouseInput.TransformToLocal(aApzc->GetTransformToThis());
+    CSSCoord dragStart = aApzc->ConvertScrollbarPoint(
+        aMouseInput.mLocalOrigin, thumbData);
+    // ConvertScrollbarPoint() got the drag start offset relative to
+    // the scroll track. Now get it relative to the thumb.
+    // ScrollThumbData::mThumbStart stores the offset of the thumb
+    // relative to the scroll track at the time of the last paint.
+    // Since that paint, the thumb may have acquired an async transform
+    // due to async scrolling, so look that up and apply it.
+    LayerToParentLayerMatrix4x4 thumbTransform;
+    {
+      MutexAutoLock lock(mTreeLock);
+      thumbTransform = ComputeTransformForNode(aScrollThumbNode);
+    }
+    // Only consider the translation, since we do not support both
+    // zooming and scrollbar dragging on any platform.
+    CSSCoord thumbStart = thumbData.mThumbStart
+                        + ((thumbData.mDirection == ScrollDirection::HORIZONTAL)
+                           ? thumbTransform._41 : thumbTransform._42);
+    dragStart -= thumbStart;
+
+    // Content can't prevent scrollbar dragging with preventDefault(),
+    // so we don't need to wait for a content response. It's important
+    // to do this before calling ConfirmDragBlock() since that can
+    // potentially process and consume the block.
+    dragBlock->SetContentResponse(false);
+
+    mInputQueue->ConfirmDragBlock(
+        dragBlockId, aApzc,
+        AsyncDragMetrics(aApzc->GetGuid().mScrollId,
+                         aApzc->GetGuid().mPresShellId,
+                         dragBlockId,
+                         dragStart,
+                         thumbData.mDirection));
+  }
+}
+
+void
 APZCTreeManager::UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
                                         EventMessage aEventMessage)
 {
   WheelBlockState* txn = mInputQueue->GetActiveWheelTransaction();
   if (!txn) {
     return;
   }
 
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -528,16 +528,32 @@ private:
   already_AddRefed<AsyncPanZoomController> GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
   already_AddRefed<AsyncPanZoomController> CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
   already_AddRefed<AsyncPanZoomController> GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
                                                                   nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
                                                                   HitTestResult* aOutHitResult);
   nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
                                   ScrollableLayerGuid* aOutTargetGuid,
                                   uint64_t* aOutInputBlockId);
+  /**
+   * Given a mouse-down event that hit a scroll thumb node, set up APZ
+   * dragging of the scroll thumb.
+   *
+   * Must be called after the mouse event has been sent to InputQueue.
+   *
+   * @param aMouseInput The mouse-down event.
+   * @param aScrollThumbNode Tthe scroll thumb node that was hit.
+   * @param aApzc
+   *     The APZC for the scroll frame scrolled by the scroll thumb, if that
+   *     scroll frame is layerized. (A thumb can be layerized without its
+   *     target scroll frame being layerized.) Otherwise, an enclosing APZC.
+   */
+  void SetupScrollbarDrag(MouseInput& aMouseInput,
+                          const HitTestingTreeNode* aScrollThumbNode,
+                          AsyncPanZoomController* aApzc);
   void FlushRepaintsToClearScreenToGeckoTransform();
 
   already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(TreeBuildingState& aState,
                                                            AsyncPanZoomController* aApzc,
                                                            uint64_t aLayersId);
   template<class ScrollNode>
   HitTestingTreeNode* PrepareNodeForLayer(const ScrollNode& aLayer,
                                           const FrameMetrics& aMetrics,