Bug 1016035 - Delay the processing of a PanGestureInput block until we know whether it's a swipe. r=kats
authorMarkus Stange <mstange@themasta.com>
Wed, 12 Aug 2015 00:11:54 -0400
changeset 292583 e3ac3f09448389bb62e8052e26b07f82cc26a80e
parent 292582 5030ce0ef9b05c54f8226d75fe6373d89cb40ecd
child 292584 5eab0486d697d0c3971f499208ffd5af8e1a49a5
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1016035
milestone43.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 1016035 - Delay the processing of a PanGestureInput block until we know whether it's a swipe. r=kats
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
widget/InputData.h
widget/cocoa/nsChildView.mm
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -421,16 +421,17 @@ WheelBlockState::EndTransaction()
   mTransactionEnded = true;
 }
 
 PanGestureBlockState::PanGestureBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
                                            bool aTargetConfirmed,
                                            const PanGestureInput& aInitialEvent)
   : CancelableBlockState(aTargetApzc, aTargetConfirmed)
   , mInterrupted(false)
+  , mWaitingForContentResponse(aInitialEvent.mRequiresContentResponse)
 {
   if (aTargetConfirmed) {
     // Find the nearest APZC in the overscroll handoff chain that is scrollable.
     // If we get a content confirmation later that the apzc is different, then
     // content should have found a scrollable apzc, so we don't need to handle
     // that case.
     nsRefPtr<AsyncPanZoomController> apzc =
       mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
@@ -504,17 +505,32 @@ PanGestureBlockState::Type()
 }
 
 bool
 PanGestureBlockState::SetContentResponse(bool aPreventDefault)
 {
   if (aPreventDefault) {
     mInterrupted = true;
   }
-  return CancelableBlockState::SetContentResponse(aPreventDefault);
+  bool stateChanged = CancelableBlockState::SetContentResponse(aPreventDefault);
+  if (mWaitingForContentResponse) {
+    mWaitingForContentResponse = false;
+    stateChanged = true;
+  }
+  return stateChanged;
+}
+
+bool
+PanGestureBlockState::IsReadyForHandling() const
+{
+  if (!CancelableBlockState::IsReadyForHandling()) {
+    return false;
+  }
+  return !mWaitingForContentResponse ||
+         IsContentResponseTimerExpired();
 }
 
 bool
 PanGestureBlockState::AllowScrollHandoff() const
 {
   return false;
 }
 
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -257,16 +257,17 @@ private:
 class PanGestureBlockState : public CancelableBlockState
 {
 public:
   PanGestureBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
                        bool aTargetConfirmed,
                        const PanGestureInput& aEvent);
 
   bool SetContentResponse(bool aPreventDefault) override;
+  bool IsReadyForHandling() const override;
   bool HasEvents() const override;
   void DropEvents() override;
   void HandleEvents() override;
   bool MustStayActive() override;
   const char* Type() override;
   bool SetConfirmedTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc) override;
 
   void AddEvent(const PanGestureInput& aEvent);
@@ -280,16 +281,17 @@ public:
    */
   bool AllowScrollHandoff() const;
 
   bool WasInterrupted() const { return mInterrupted; }
 
 private:
   nsTArray<PanGestureInput> mEvents;
   bool mInterrupted;
+  bool mWaitingForContentResponse;
 };
 
 /**
  * This class represents a single touch block. A touch block is
  * a set of touch events that can be cancelled by web content via
  * touch event listeners.
  *
  * Every touch-start event creates a new touch block. In this case, the
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -305,17 +305,18 @@ public:
                   const ScreenPoint& aPanDisplacement,
                   Modifiers aModifiers)
     : InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mPanStartPoint(aPanStartPoint),
       mPanDisplacement(aPanDisplacement),
       mLineOrPageDeltaX(0),
       mLineOrPageDeltaY(0),
-      mHandledByAPZ(false)
+      mHandledByAPZ(false),
+      mRequiresContentResponse(false)
   {
   }
 
   bool IsMomentum() const;
 
   WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
 
   bool TransformToLocal(const gfx::Matrix4x4& aTransform);
@@ -331,16 +332,22 @@ public:
   ParentLayerPoint mLocalPanStartPoint;
   ParentLayerPoint mLocalPanDisplacement;
 
   // See lineOrPageDeltaX/Y on WidgetWheelEvent.
   int32_t mLineOrPageDeltaX;
   int32_t mLineOrPageDeltaY;
 
   bool mHandledByAPZ;
+
+  // If this is true, the input block started by this event 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 mRequiresContentResponse;
 };
 
 /**
  * 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
@@ -4867,16 +4867,17 @@ PanGestureTypeForEvent(NSEvent* aEvent)
   if (usePreciseDeltas && hasPhaseInformation) {
     PanGestureInput panEvent(PanGestureTypeForEvent(theEvent),
                              eventIntervalTime, eventTimeStamp,
                              position, preciseDelta, modifiers);
     panEvent.mLineOrPageDeltaX = lineOrPageDeltaX;
     panEvent.mLineOrPageDeltaY = lineOrPageDeltaY;
 
     bool canTriggerSwipe = [self shouldConsiderStartingSwipeFromEvent:theEvent];
+    panEvent.mRequiresContentResponse = canTriggerSwipe;
     mGeckoChild->DispatchAPZWheelInputEvent(panEvent, canTriggerSwipe);
   } else if (usePreciseDeltas) {
     // This is on 10.6 or old touchpads that don't have any phase information.
     ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers,
                                 ScrollWheelInput::SCROLLMODE_INSTANT,
                                 ScrollWheelInput::SCROLLDELTA_PIXEL,
                                 position,
                                 preciseDelta.x,