Bug 951793 - Obey overscroll-behavior for swipe navigation. r=mstange
authorBotond Ballo <botond@mozilla.com>
Mon, 23 Oct 2017 18:27:24 -0400
changeset 447930 9eabd878337a76e387c899757fd9063b3d639251
parent 447929 daca6c7ab82de0df417d03ad3c33a9d67bd5b836
child 447931 ddd4a6daae74e2cb9a2e421ee65a02297e6f7f12
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs951793
milestone59.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 951793 - Obey overscroll-behavior for swipe navigation. r=mstange MozReview-Commit-ID: i2BuiAfG71
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
widget/InputData.cpp
widget/InputData.h
widget/cocoa/nsChildView.mm
widget/nsGUIEventIPC.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1193,16 +1193,19 @@ APZCTreeManager::ReceiveInputEvent(Input
             apzc,
             /* aTargetConfirmed = */ hitResult != HitDispatchToContentRegion,
             panInput, aOutInputBlockId);
 
         // Update the out-parameters so they are what the caller expects.
         apzc->GetGuid(aOutTargetGuid);
         panInput.mPanStartPoint = *untransformedStartPoint;
         panInput.mPanDisplacement = *untransformedDisplacement;
+
+        panInput.mOverscrollBehaviorAllowsSwipe =
+            apzc->OverscrollBehaviorAllowsSwipe();
       }
       break;
     } case PINCHGESTURE_INPUT: {  // note: no one currently sends these
       PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
       RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint,
                                                             &hitResult);
       if (apzc) {
         MOZ_ASSERT(hitResult != HitNothing);
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2875,16 +2875,22 @@ ParentLayerPoint AsyncPanZoomController:
   }
   if (!mY.OverscrollBehaviorAllowsHandoff()) {
     residualVelocity.y = aHandoffVelocity.y;
     aHandoffVelocity.y = 0;
   }
   return residualVelocity;
 }
 
+bool AsyncPanZoomController::OverscrollBehaviorAllowsSwipe() const
+{
+  RecursiveMutexAutoLock lock(mRecursiveMutex);
+  // Swipe navigation is a "non-local" overscroll behavior like handoff.
+  return mX.OverscrollBehaviorAllowsHandoff();
+}
 
 void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
                                                    const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                                                    const RefPtr<const AsyncPanZoomController>& aScrolledApzc) {
   APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
   if (treeManagerLocal) {
     const FlingHandoffState handoffState{aVelocity,
                                          aOverscrollHandoffChain,
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -437,16 +437,18 @@ public:
    * to CSS coordinates relative to the beginning of the scroll track.
    * Only the component in the direction of scrolling is returned.
    */
   CSSCoord ConvertScrollbarPoint(const ParentLayerPoint& aScrollbarPoint,
                                  const ScrollThumbData& aThumbData) const;
 
   void NotifyMozMouseScrollEvent(const nsString& aString) const;
 
+  bool OverscrollBehaviorAllowsSwipe() const;
+
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~AsyncPanZoomController();
 
   // Returns the cached current frame time.
   TimeStamp GetFrameTime() const;
 
   /**
--- a/widget/InputData.cpp
+++ b/widget/InputData.cpp
@@ -485,16 +485,17 @@ PanGestureInput::PanGestureInput()
   : InputData(PANGESTURE_INPUT)
   , mLineOrPageDeltaX(0)
   , mLineOrPageDeltaY(0)
   , mUserDeltaMultiplierX(1.0)
   , mUserDeltaMultiplierY(1.0)
   , mHandledByAPZ(false)
   , mFollowedByMomentum(false)
   , mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
+  , mOverscrollBehaviorAllowsSwipe(false)
 {
 }
 
 PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
                                  TimeStamp aTimeStamp,
                                  const ScreenPoint& aPanStartPoint,
                                  const ScreenPoint& aPanDisplacement,
                                  Modifiers aModifiers)
@@ -504,16 +505,17 @@ PanGestureInput::PanGestureInput(PanGest
   , mPanDisplacement(aPanDisplacement)
   , mLineOrPageDeltaX(0)
   , mLineOrPageDeltaY(0)
   , mUserDeltaMultiplierX(1.0)
   , mUserDeltaMultiplierY(1.0)
   , mHandledByAPZ(false)
   , mFollowedByMomentum(false)
   , mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
+  , mOverscrollBehaviorAllowsSwipe(false)
 {
 }
 
 bool
 PanGestureInput::IsMomentum() const
 {
   switch (mType) {
     case PanGestureInput::PANGESTURE_MOMENTUMSTART:
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -380,16 +380,24 @@ public:
 
   // If this is true, and this event started a new input block that couldn't
   // find a scrollable target which is scrollable in the horizontal component
   // of the scroll start direction, then this input block needs to be put on
   // hold until a content response has arrived, even if the block has a
   // confirmed target.
   // This is used by events that can result in a swipe instead of a scroll.
   bool mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection;
+
+  // This is used by APZ to communicate to the macOS widget code whether
+  // the overscroll-behavior of the scroll frame handling this swipe allows
+  // non-local overscroll behaviors in the horizontal direction (such as
+  // swipe navigation).
+  bool mOverscrollBehaviorAllowsSwipe;
+
+  // XXX: If adding any more bools, switch to using bitfields instead.
 };
 
 /**
  * Encapsulation class for pinch events. In general, these will be generated by
  * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
  * determining whether or not the user was trying to do a gesture.
  */
 class PinchGestureInput : public InputData
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2918,17 +2918,17 @@ nsChildView::DispatchAPZWheelInputEvent(
         result = mAPZC->ReceiveInputEvent(aEvent, &guid, &inputBlockId);
         if (result == nsEventStatus_eConsumeNoDefault) {
           return;
         }
 
         PanGestureInput& panInput = aEvent.AsPanGestureInput();
 
         event = panInput.ToWidgetWheelEvent(this);
-        if (aCanTriggerSwipe) {
+        if (aCanTriggerSwipe && panInput.mOverscrollBehaviorAllowsSwipe) {
           SwipeInfo swipeInfo = SendMayStartSwipe(panInput);
           event.mCanTriggerSwipe = swipeInfo.wantsSwipe;
           if (swipeInfo.wantsSwipe) {
             if (result == nsEventStatus_eIgnore) {
               // APZ has determined and that scrolling horizontally in the
               // requested direction is impossible, so it didn't do any
               // scrolling for the event.
               // We know now that MayStartSwipe wants a swipe, so we can start
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -1220,33 +1220,35 @@ struct ParamTraits<mozilla::PanGestureIn
     WriteParam(aMsg, aParam.mLocalPanDisplacement);
     WriteParam(aMsg, aParam.mLineOrPageDeltaX);
     WriteParam(aMsg, aParam.mLineOrPageDeltaY);
     WriteParam(aMsg, aParam.mUserDeltaMultiplierX);
     WriteParam(aMsg, aParam.mUserDeltaMultiplierY);
     WriteParam(aMsg, aParam.mHandledByAPZ);
     WriteParam(aMsg, aParam.mFollowedByMomentum);
     WriteParam(aMsg, aParam.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+    WriteParam(aMsg, aParam.mOverscrollBehaviorAllowsSwipe);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, static_cast<mozilla::InputData*>(aResult)) &&
            ReadParam(aMsg, aIter, &aResult->mType) &&
            ReadParam(aMsg, aIter, &aResult->mPanStartPoint) &&
            ReadParam(aMsg, aIter, &aResult->mPanDisplacement) &&
            ReadParam(aMsg, aIter, &aResult->mLocalPanStartPoint) &&
            ReadParam(aMsg, aIter, &aResult->mLocalPanDisplacement) &&
            ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaX) &&
            ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaY) &&
            ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierX) &&
            ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierY) &&
            ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
            ReadParam(aMsg, aIter, &aResult->mFollowedByMomentum) &&
-           ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+           ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection) &&
+           ReadParam(aMsg, aIter, &aResult->mOverscrollBehaviorAllowsSwipe);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::PinchGestureInput::PinchGestureType>
   : public ContiguousEnumSerializerInclusive<
              mozilla::PinchGestureInput::PinchGestureType,
              mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_START,