Bug 1035356 - Make ReceiveInputEvent(InputData...) do in-place modifications of the event to DOM space. r=mstange r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 08 Jul 2014 14:55:52 -0400
changeset 214886 d3ec4c615ab453d56242065f8032477dd26da411
parent 214885 67001e68b078c85111a876e48f3049540de424a6
child 214887 725b7db309c3ef86c679f0ce6b690cff43ffe8cb
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, botond
bugs1035356
milestone33.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 1035356 - Make ReceiveInputEvent(InputData...) do in-place modifications of the event to DOM space. r=mstange r=botond
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
widget/InputData.h
widget/android/AndroidJNI.cpp
widget/cocoa/nsChildView.mm
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -360,76 +360,104 @@ ApplyTransform(gfx::IntPointTyped<T>* aP
 /*static*/ void
 ApplyTransform(nsIntPoint* aPoint, const gfx3DMatrix& aMatrix)
 {
   gfxPoint result = aMatrix.Transform(gfxPoint(aPoint->x, aPoint->y));
   aPoint->x = NS_lround(result.x);
   aPoint->y = NS_lround(result.y);
 }
 
+/*static*/ template<class T> void
+TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager* aApzcTm)
+{
+  gfx3DMatrix transformToApzc, transformToGecko;
+  aApzcTm->GetInputTransforms(aApzc, transformToApzc, transformToGecko);
+  ApplyTransform(aPoint, transformToApzc * transformToGecko);
+}
+
 nsEventStatus
-APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
+APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
                                    ScrollableLayerGuid* aOutTargetGuid)
 {
   nsEventStatus result = nsEventStatus_eIgnore;
   gfx3DMatrix transformToApzc;
   gfx3DMatrix transformToGecko;
   switch (aEvent.mInputType) {
     case MULTITOUCH_INPUT: {
-      MultiTouchInput touchInput = aEvent.AsMultiTouchInput();
+      MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
       result = ProcessTouchInput(touchInput, aOutTargetGuid);
       break;
     } case PANGESTURE_INPUT: {
-      const PanGestureInput& panInput = aEvent.AsPanGestureInput();
+      PanGestureInput& panInput = aEvent.AsPanGestureInput();
       bool inOverscrolledApzc = false;
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
                                                             &inOverscrolledApzc);
       if (apzc) {
         if (panInput.mType == PanGestureInput::PANGESTURE_START ||
             panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMSTART) {
           BuildOverscrollHandoffChain(apzc);
         }
-        apzc->GetGuid(aOutTargetGuid);
+
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        PanGestureInput inputForApzc(panInput);
         GetInputTransforms(apzc, transformToApzc, transformToGecko);
-        PanGestureInput inputForApzc(panInput);
         ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc);
         result = apzc->ReceiveInputEvent(inputForApzc);
+
+        // Update the out-parameters so they are what the caller expects.
+        apzc->GetGuid(aOutTargetGuid);
+        TransformScreenToGecko(&(panInput.mPanStartPoint), apzc, this);
+
         if (panInput.mType == PanGestureInput::PANGESTURE_END ||
             panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMEND) {
           ClearOverscrollHandoffChain();
         }
       }
       break;
     } case PINCHGESTURE_INPUT: {
-      const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
+      PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
       bool inOverscrolledApzc = false;
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint,
                                                             &inOverscrolledApzc);
       if (apzc) {
-        apzc->GetGuid(aOutTargetGuid);
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        PinchGestureInput inputForApzc(pinchInput);
         GetInputTransforms(apzc, transformToApzc, transformToGecko);
-        PinchGestureInput inputForApzc(pinchInput);
         ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc);
         apzc->ReceiveInputEvent(inputForApzc);
+
+        // Update the out-parameters so they are what the caller expects.
+        apzc->GetGuid(aOutTargetGuid);
+        TransformScreenToGecko(&(pinchInput.mFocusPoint), apzc, this);
       }
       result = inOverscrolledApzc ? nsEventStatus_eConsumeNoDefault
              : apzc ? nsEventStatus_eConsumeDoDefault
              : nsEventStatus_eIgnore;
       break;
     } case TAPGESTURE_INPUT: {
-      const TapGestureInput& tapInput = aEvent.AsTapGestureInput();
+      TapGestureInput& tapInput = aEvent.AsTapGestureInput();
       bool inOverscrolledApzc = false;
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint),
                                                             &inOverscrolledApzc);
       if (apzc) {
-        apzc->GetGuid(aOutTargetGuid);
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        TapGestureInput inputForApzc(tapInput);
         GetInputTransforms(apzc, transformToApzc, transformToGecko);
-        TapGestureInput inputForApzc(tapInput);
         ApplyTransform(&(inputForApzc.mPoint), transformToApzc);
         apzc->ReceiveInputEvent(inputForApzc);
+
+        // Update the out-parameters so they are what the caller expects.
+        apzc->GetGuid(aOutTargetGuid);
+        TransformScreenToGecko(&(tapInput.mPoint), apzc, this);
       }
       result = inOverscrolledApzc ? nsEventStatus_eConsumeNoDefault
              : apzc ? nsEventStatus_eConsumeDoDefault
              : nsEventStatus_eIgnore;
       break;
     }
   }
   return result;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -117,21 +117,26 @@ public:
                                    uint64_t aOriginatingLayersId,
                                    uint32_t aPaintSequenceNumber);
 
   /**
    * General handler for incoming input events. Manipulates the frame metrics
    * based on what type of input it is. For example, a PinchGestureEvent will
    * cause scaling. This should only be called externally to this class.
    *
-   * @param aEvent input event object, will not be modified
+   * This function transforms |aEvent| to have its coordinates in DOM space.
+   * This is so that the event can be passed through the DOM and content can
+   * handle them. The event may need to be converted to a WidgetInputEvent
+   * by the caller if it wants to do this.
+   *
+   * @param aEvent input event object; is modified in-place
    * @param aOutTargetGuid returns the guid of the apzc this event was
    * delivered to. May be null.
    */
-  nsEventStatus ReceiveInputEvent(const InputData& aEvent,
+  nsEventStatus ReceiveInputEvent(InputData& aEvent,
                                   ScrollableLayerGuid* aOutTargetGuid);
 
   /**
    * WidgetInputEvent handler. Transforms |aEvent| (which is assumed to be an
    * already-existing instance of an WidgetInputEvent which may be an
    * WidgetTouchEvent) to have its coordinates in DOM space. This is so that the
    * event can be passed through the DOM and content can handle them.
    *
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -38,16 +38,21 @@ class TapGestureInput;
 // from InputType (eventually probably almost as many as *Events.h has), it
 // will be more and more clear what's going on with a macro that shortens the
 // definition of the RTTI functions.
 #define INPUTDATA_AS_CHILD_TYPE(type, enumID) \
   const type& As##type() const \
   { \
     NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \
     return (const type&) *this; \
+  } \
+  type& As##type() \
+  { \
+    NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \
+    return (type&) *this; \
   }
 
 /** Base input data class. Should never be instantiated. */
 class InputData
 {
 public:
   InputType mInputType;
   // Time in milliseconds that this data is relevant to. This only really
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -871,17 +871,17 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
 {
     APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
     if (controller) {
         AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event);
-        const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
+        MultiTouchInput input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
         delete wrapper;
         if (input.mType >= 0) {
             controller->ReceiveInputEvent(input, nullptr);
         }
     }
 }
 
 NS_EXPORT void JNICALL
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -5201,69 +5201,69 @@ static int32_t RoundUp(double aDouble)
     ScrollableLayerGuid guid;
 
     // MayBegin and Cancelled are dispatched when the fingers start or stop
     // touching the touchpad before any scrolling has occurred. These events
     // can be used to control scrollbar visibility or interrupt scroll
     // animations. They are only dispatched on 10.8 or later, and only by
     // relatively modern devices.
     if (phase == NSEventPhaseMayBegin) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_MAYSTART,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_MAYSTART, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
       return;
     }
     if (phase == NSEventPhaseCancelled) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_CANCELLED,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_CANCELLED, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
       return;
     }
 
     // Legacy scroll events are dispatched by devices that do not have a
     // concept of a scroll gesture, for example by USB mice with
     // traditional mouse wheels.
     // For these kinds of scrolls, we want to surround every single scroll
     // event with a PANGESTURE_START and a PANGESTURE_END event. The APZC
     // needs to know that the real scroll gesture can end abruptly after any
     // one of these events.
     bool isLegacyScroll = (phase == NSEventPhaseNone &&
       momentumPhase == NSEventPhaseNone && delta != ScreenPoint(0, 0));
 
     if (phase == NSEventPhaseBegan || isLegacyScroll) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_START,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_START, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
     if (momentumPhase == NSEventPhaseNone && delta != ScreenPoint(0, 0)) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_PAN,
-                                                eventTime, eventTimeStamp, location,
-                                                delta, 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_PAN, eventTime,
+                               eventTimeStamp, location, delta, 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
     if (phase == NSEventPhaseEnded || isLegacyScroll) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_END,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_END, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
 
     // Any device that can dispatch momentum events supports all three momentum phases.
     if (momentumPhase == NSEventPhaseBegan) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_MOMENTUMSTART,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMSTART, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
     if (momentumPhase == NSEventPhaseChanged && delta != ScreenPoint(0, 0)) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_MOMENTUMPAN,
-                                                eventTime, eventTimeStamp, location,
-                                                delta, 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMPAN, eventTime,
+                               eventTimeStamp, location, delta, 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
     if (momentumPhase == NSEventPhaseEnded) {
-      apzctm->ReceiveInputEvent(PanGestureInput(PanGestureInput::PANGESTURE_MOMENTUMEND,
-                                                eventTime, eventTimeStamp, location,
-                                                ScreenPoint(0, 0), 0), &guid);
+      PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMEND, eventTime,
+                               eventTimeStamp, location, ScreenPoint(0, 0), 0);
+      apzctm->ReceiveInputEvent(panInput, &guid);
     }
   }
 }
 
 -(NSMenu*)menuForEvent:(NSEvent*)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;