Bug 1193062 - Add mHandledByAPZ on PanGestureInput and ScrollWheelInput, and sync the information to the WidgetWheelEvent. r=kats
authorMarkus Stange <mstange@themasta.com>
Tue, 11 Aug 2015 18:04:55 -0400
changeset 259477 529d7e708472f0f10948f66888e9602fa4e23764
parent 259476 4aac3d312e5df5b25f2218b68f4b3dd42db8917e
child 259478 853c265bf5c5f343066f97d531809c395ec48bea
push id29279
push userryanvm@gmail.com
push dateThu, 27 Aug 2015 00:32:41 +0000
treeherdermozilla-central@c1121b67faa0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1193062
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 1193062 - Add mHandledByAPZ on PanGestureInput and ScrollWheelInput, and sync the information to the WidgetWheelEvent. r=kats
gfx/layers/apz/src/APZCTreeManager.cpp
widget/InputData.cpp
widget/InputData.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -549,16 +549,43 @@ APZCTreeManager::UpdateHitTestingTree(Tr
     gfx::TreeAutoIndent indent(mApzcTreeLog);
     next = UpdateHitTestingTree(aState, child, childLayersId,
                                 ancestorTransform, aParent, next);
   }
 
   return node;
 }
 
+// Returns whether or not a wheel event action will be (or was) performed by
+// APZ. If this returns true, the event must not perform a synchronous
+// scroll.
+//
+// Even if this returns false, all wheel events in APZ-aware widgets must
+// be sent through APZ so they are transformed correctly for TabParent.
+static bool
+WillHandleWheelEvent(WidgetWheelEvent* aEvent)
+{
+  return EventStateManager::WheelEventIsScrollAction(aEvent) &&
+         (aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE
+            || aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&
+         !EventStateManager::WheelEventNeedsDeltaMultipliers(aEvent);
+}
+
+template<typename PanGestureOrScrollWheelInput>
+static bool
+WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput)
+{
+  if (!NS_IsMainThread()) {
+    return true;
+  }
+
+  WidgetWheelEvent wheelEvent = aPanInput.ToWidgetWheelEvent(nullptr);
+  return WillHandleWheelEvent(&wheelEvent);
+}
+
 void
 APZCTreeManager::FlushApzRepaints(uint64_t aLayersId)
 {
   APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId);
   { // scope lock
     MonitorAutoLock lock(mTreeLock);
     FlushPendingRepaintRecursively(mRootNode, aLayersId);
   }
@@ -586,16 +613,22 @@ APZCTreeManager::ReceiveInputEvent(Input
     case MULTITOUCH_INPUT: {
       MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
       result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
       break;
     } case SCROLLWHEEL_INPUT: {
       FlushRepaintsToClearScreenToGeckoTransform();
 
       ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
+
+      wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
+      if (!wheelInput.mHandledByAPZ) {
+        return result;
+      }
+
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(wheelInput.mOrigin,
                                                             &hitResult);
       if (apzc) {
         MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
 
         // For wheel events, the call to ReceiveInputEvent below may result in
         // scrolling, which changes the async transform. However, the event we
         // want to pass to gecko should be the pre-scroll event coordinates,
@@ -618,16 +651,21 @@ APZCTreeManager::ReceiveInputEvent(Input
         apzc->GetGuid(aOutTargetGuid);
         wheelInput.mOrigin = untransformedOrigin;
       }
       break;
     } case PANGESTURE_INPUT: {
       FlushRepaintsToClearScreenToGeckoTransform();
 
       PanGestureInput& panInput = aEvent.AsPanGestureInput();
+      panInput.mHandledByAPZ = WillHandleInput(panInput);
+      if (!panInput.mHandledByAPZ) {
+        return result;
+      }
+
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
                                                             &hitResult);
       if (apzc) {
         MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
 
         // For pan gesture events, the call to ReceiveInputEvent below may result in
         // scrolling, which changes the async transform. However, the event we
         // want to pass to gecko should be the pre-scroll event coordinates,
@@ -909,35 +947,20 @@ APZCTreeManager::ProcessWheelEvent(Widge
                          ScrollWheelInput::DeltaTypeForDeltaMode(aEvent.deltaMode),
                          origin,
                          aEvent.deltaX,
                          aEvent.deltaY);
 
   nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
   aEvent.refPoint.x = input.mOrigin.x;
   aEvent.refPoint.y = input.mOrigin.y;
-  aEvent.mFlags.mHandledByAPZ = true;
+  aEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
   return status;
 }
 
-// Returns whether or not a wheel event action will be (or was) performed by
-// APZ. If this returns true, the event must not perform a synchronous
-// scroll.
-//
-// Even if this returns false, all wheel events in APZ-aware widgets must
-// be sent through APZ so they are transformed correctly for TabParent.
-static bool
-WillHandleWheelEvent(WidgetWheelEvent* aEvent)
-{
-  return EventStateManager::WheelEventIsScrollAction(aEvent) &&
-         (aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE
-            || aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&
-         !EventStateManager::WheelEventNeedsDeltaMultipliers(aEvent);
-}
-
 nsEventStatus
 APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent,
                                    ScrollableLayerGuid* aOutTargetGuid,
                                    uint64_t* aOutInputBlockId)
 {
   // This function will be removed once metro code is modified to use the
   // InputData version of ReceiveInputEvent.
   // In general it is preferable to use the version of ReceiveInputEvent
@@ -965,22 +988,20 @@ APZCTreeManager::ReceiveInputEvent(Widge
       touchEvent.touches.SetCapacity(touchInput.mTouches.Length());
       for (size_t i = 0; i < touchInput.mTouches.Length(); i++) {
         *touchEvent.touches.AppendElement() = touchInput.mTouches[i].ToNewDOMTouch();
       }
       return result;
     }
     case eWheelEventClass: {
       WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent();
-      if (!WillHandleWheelEvent(&wheelEvent)) {
-        // Don't send through APZ if we're not scrolling or if the delta mode
-        // is not line-based.
-        return ProcessEvent(aEvent, aOutTargetGuid, aOutInputBlockId);
+      if (WillHandleWheelEvent(&wheelEvent)) {
+        return ProcessWheelEvent(wheelEvent, aOutTargetGuid, aOutInputBlockId);
       }
-      return ProcessWheelEvent(wheelEvent, aOutTargetGuid, aOutInputBlockId);
+      return ProcessEvent(aEvent, aOutTargetGuid, aOutInputBlockId);
     }
     default: {
       return ProcessEvent(aEvent, aOutTargetGuid, aOutInputBlockId);
     }
   }
 }
 
 void
--- a/widget/InputData.cpp
+++ b/widget/InputData.cpp
@@ -250,17 +250,17 @@ PanGestureInput::ToWidgetWheelEvent(nsIW
       PixelCastJustification::LayoutDeviceToScreenForUntransformedEvent));
   wheelEvent.buttons = 0;
   wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_PIXEL;
   wheelEvent.isMomentum = IsMomentum();
   wheelEvent.lineOrPageDeltaX = mLineOrPageDeltaX;
   wheelEvent.lineOrPageDeltaY = mLineOrPageDeltaY;
   wheelEvent.deltaX = mPanDisplacement.x;
   wheelEvent.deltaY = mPanDisplacement.y;
-  wheelEvent.mFlags.mHandledByAPZ = true;
+  wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
   return wheelEvent;
 }
 
 bool
 PanGestureInput::TransformToLocal(const gfx::Matrix4x4& aTransform)
 { 
   Maybe<ParentLayerPoint> panStartPoint = UntransformTo<ParentLayerPixel>(aTransform, mPanStartPoint);
   if (!panStartPoint) {
@@ -322,17 +322,17 @@ ScrollWheelInput::ToWidgetWheelEvent(nsI
       PixelCastJustification::LayoutDeviceToScreenForUntransformedEvent));
   wheelEvent.buttons = 0;
   wheelEvent.deltaMode = DeltaModeForDeltaType(mDeltaType);
   wheelEvent.isMomentum = mIsMomentum;
   wheelEvent.deltaX = mDeltaX;
   wheelEvent.deltaY = mDeltaY;
   wheelEvent.lineOrPageDeltaX = mLineOrPageDeltaX;
   wheelEvent.lineOrPageDeltaY = mLineOrPageDeltaY;
-  wheelEvent.mFlags.mHandledByAPZ = true;
+  wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
   return wheelEvent;
 }
 
 bool
 ScrollWheelInput::TransformToLocal(const gfx::Matrix4x4& aTransform)
 {
   Maybe<ParentLayerPoint> point = UntransformTo<ParentLayerPixel>(aTransform, mOrigin);
   if (!point) {
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -304,17 +304,18 @@ public:
                   const ScreenPoint& aPanStartPoint,
                   const ScreenPoint& aPanDisplacement,
                   Modifiers aModifiers)
     : InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mPanStartPoint(aPanStartPoint),
       mPanDisplacement(aPanDisplacement),
       mLineOrPageDeltaX(0),
-      mLineOrPageDeltaY(0)
+      mLineOrPageDeltaY(0),
+      mHandledByAPZ(false)
   {
   }
 
   bool IsMomentum() const;
 
   WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
 
   bool TransformToLocal(const gfx::Matrix4x4& aTransform);
@@ -328,16 +329,18 @@ public:
   // Versions of |mPanStartPoint| and |mPanDisplacement| in the local
   // coordinates of the APZC receiving the pan. These are set and used by APZ.
   ParentLayerPoint mLocalPanStartPoint;
   ParentLayerPoint mLocalPanDisplacement;
 
   // See lineOrPageDeltaX/Y on WidgetWheelEvent.
   int32_t mLineOrPageDeltaX;
   int32_t mLineOrPageDeltaY;
+
+  bool mHandledByAPZ;
 };
 
 /**
  * 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
@@ -507,30 +510,33 @@ public:
                    ScrollDeltaType aDeltaType,
                    const ScreenPoint& aOrigin,
                    double aDeltaX,
                    double aDeltaY)
    : InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers),
      mDeltaType(aDeltaType),
      mScrollMode(aScrollMode),
      mOrigin(aOrigin),
+     mHandledByAPZ(false),
      mDeltaX(aDeltaX),
      mDeltaY(aDeltaY),
      mLineOrPageDeltaX(0),
      mLineOrPageDeltaY(0),
      mIsMomentum(false)
   {}
 
   WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
   bool TransformToLocal(const gfx::Matrix4x4& aTransform);
 
   ScrollDeltaType mDeltaType;
   ScrollMode mScrollMode;
   ScreenPoint mOrigin;
 
+  bool mHandledByAPZ;
+
   // Deltas are in units corresponding to the delta type. For line deltas, they
   // are the number of line units to scroll. The number of device pixels for a
   // horizontal and vertical line unit are in FrameMetrics::mLineScrollAmount.
   // For pixel deltas, these values are in ScreenCoords.
   //
   // The horizontal (X) delta is > 0 for scrolling right and < 0 for scrolling
   // left. The vertical (Y) delta is < 0 for scrolling up and > 0 for
   // scrolling down.