Backed out 4 changesets (bug 1515774) for mochitest failrues at test_group_touchevents-3.html and test_touch_action.html.
authorBrindusan Cristian <cbrindusan@mozilla.com>
Wed, 30 Jan 2019 04:39:55 +0200
changeset 513907 031ad7f5577472b87d0172d54e9dcc40dbb4a842
parent 513906 1352060f32ff931796360a88d033592441f5af9a
child 513908 a43b674b5ff2bc892aa7c91db8f72f3f6163827c
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1515774
milestone67.0a1
backs out45c6f07160d9c0b7a472c68ff63d4aaa9bd00304
3d97f1e46c1ac46997eddca7353f7a6274c39849
69c8787c67d63de23bfdc058d634934d3e1601b5
8e17cc234256bc31d3fffa8889c26364e1228350
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
Backed out 4 changesets (bug 1515774) for mochitest failrues at test_group_touchevents-3.html and test_touch_action.html. Backed out changeset 45c6f07160d9 (bug 1515774) Backed out changeset 3d97f1e46c1a (bug 1515774) Backed out changeset 69c8787c67d6 (bug 1515774) Backed out changeset 8e17cc234256 (bug 1515774)
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZUtils.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/apz/src/GestureEventListener.cpp
gfx/layers/apz/src/GestureEventListener.h
gfx/layers/apz/test/gtest/InputUtils.h
layout/base/UnitTransforms.h
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
widget/InputData.cpp
widget/InputData.h
widget/android/nsWindow.cpp
widget/cocoa/nsChildView.mm
widget/nsGUIEventIPC.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1886,51 +1886,49 @@ void APZCTreeManager::SetupScrollbarDrag
 void APZCTreeManager::SynthesizePinchGestureFromMouseWheel(
     const ScrollWheelInput& aWheelInput,
     const RefPtr<AsyncPanZoomController>& aTarget) {
   MOZ_ASSERT(aTarget);
 
   ScreenPoint focusPoint = aWheelInput.mOrigin;
 
   // Compute span values based on the wheel delta.
-  ScreenCoord oldSpan = 100;
-  ScreenCoord newSpan = oldSpan + aWheelInput.mDeltaY;
+  // See the PinchGestureInput constructor called below for why
+  // it's OK to use ParentLayer coordinates for the span values.
+  ParentLayerCoord oldSpan = 100;
+  ParentLayerCoord newSpan = oldSpan + aWheelInput.mDeltaY;
 
   // There's no ambiguity as to the target for pinch gesture events.
   TargetConfirmationFlags confFlags{true};
 
   PinchGestureInput pinchStart{PinchGestureInput::PINCHGESTURE_START,
                                aWheelInput.mTime,
                                aWheelInput.mTimeStamp,
-                               ExternalPoint(0, 0),
                                focusPoint,
                                oldSpan,
                                oldSpan,
                                aWheelInput.modifiers};
   PinchGestureInput pinchScale1{PinchGestureInput::PINCHGESTURE_SCALE,
                                 aWheelInput.mTime,
                                 aWheelInput.mTimeStamp,
-                                ExternalPoint(0, 0),
                                 focusPoint,
                                 oldSpan,
                                 oldSpan,
                                 aWheelInput.modifiers};
   PinchGestureInput pinchScale2{PinchGestureInput::PINCHGESTURE_SCALE,
                                 aWheelInput.mTime,
                                 aWheelInput.mTimeStamp,
-                                ExternalPoint(0, 0),
                                 focusPoint,
                                 oldSpan,
                                 newSpan,
                                 aWheelInput.modifiers};
   PinchGestureInput pinchEnd{
       PinchGestureInput::PINCHGESTURE_END,
       aWheelInput.mTime,
       aWheelInput.mTimeStamp,
-      ExternalPoint(0, 0),
       PinchGestureInput::BothFingersLifted<ScreenPixel>(),
       newSpan,
       newSpan,
       aWheelInput.modifiers};
 
   mInputQueue->ReceiveInputEvent(aTarget, confFlags, pinchStart, nullptr);
   mInputQueue->ReceiveInputEvent(aTarget, confFlags, pinchScale1, nullptr);
   mInputQueue->ReceiveInputEvent(aTarget, confFlags, pinchScale2, nullptr);
--- a/gfx/layers/apz/src/APZUtils.h
+++ b/gfx/layers/apz/src/APZUtils.h
@@ -13,39 +13,16 @@
 #include "UnitTransforms.h"
 #include "mozilla/gfx/CompositorHitTestInfo.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/DefineEnum.h"
 #include "mozilla/EnumSet.h"
 #include "mozilla/FloatingPoint.h"
 
 namespace mozilla {
-
-struct ExternalPixel;
-
-template <>
-struct IsPixel<ExternalPixel> : TrueType {};
-
-typedef gfx::CoordTyped<ExternalPixel> ExternalCoord;
-typedef gfx::IntCoordTyped<ExternalPixel> ExternalIntCoord;
-typedef gfx::PointTyped<ExternalPixel> ExternalPoint;
-typedef gfx::IntPointTyped<ExternalPixel> ExternalIntPoint;
-typedef gfx::SizeTyped<ExternalPixel> ExternalSize;
-typedef gfx::IntSizeTyped<ExternalPixel> ExternalIntSize;
-typedef gfx::RectTyped<ExternalPixel> ExternalRect;
-typedef gfx::IntRectTyped<ExternalPixel> ExternalIntRect;
-typedef gfx::MarginTyped<ExternalPixel> ExternalMargin;
-typedef gfx::IntMarginTyped<ExternalPixel> ExternalIntMargin;
-typedef gfx::IntRegionTyped<ExternalPixel> ExternalIntRegion;
-
-typedef gfx::Matrix4x4Typed<ExternalPixel, ParentLayerPixel>
-    ExternalToParentLayerMatrix4x4;
-
-struct ExternalPixel {};
-
 namespace layers {
 
 class AsyncPanZoomController;
 
 enum CancelAnimationFlags : uint32_t {
   Default = 0x0,             /* Cancel all animations */
   ExcludeOverscroll = 0x1,   /* Don't clear overscroll */
   ScrollSnap = 0x2,          /* Snap to snap points */
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1073,30 +1073,28 @@ nsEventStatus AsyncPanZoomController::Ha
     const ScreenToParentLayerMatrix4x4& aTransformToApzc) {
   APZThreadUtils::AssertOnControllerThread();
 
   nsEventStatus rv = nsEventStatus_eIgnore;
 
   switch (aEvent.mInputType) {
     case MULTITOUCH_INPUT: {
       MultiTouchInput multiTouchInput = aEvent.AsMultiTouchInput();
+      if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
+        return rv;
+      }
+
       RefPtr<GestureEventListener> listener = GetGestureEventListener();
       if (listener) {
-        // We only care about screen coordinates in the gesture listener,
-        // so we don't bother transforming the event to parent layer coordinates
         rv = listener->HandleInputEvent(multiTouchInput);
         if (rv == nsEventStatus_eConsumeNoDefault) {
           return rv;
         }
       }
 
-      if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
-        return rv;
-      }
-
       switch (multiTouchInput.mType) {
         case MultiTouchInput::MULTITOUCH_START:
           rv = OnTouchStart(multiTouchInput);
           break;
         case MultiTouchInput::MULTITOUCH_MOVE:
           rv = OnTouchMove(multiTouchInput);
           break;
         case MultiTouchInput::MULTITOUCH_END:
@@ -1189,34 +1187,32 @@ nsEventStatus AsyncPanZoomController::Ha
 nsEventStatus AsyncPanZoomController::HandleGestureEvent(
     const InputData& aEvent) {
   APZThreadUtils::AssertOnControllerThread();
 
   nsEventStatus rv = nsEventStatus_eIgnore;
 
   switch (aEvent.mInputType) {
     case PINCHGESTURE_INPUT: {
-      PinchGestureInput pinchGestureInput = aEvent.AsPinchGestureInput();
-      pinchGestureInput.TransformToLocal(GetTransformToThis());
+      const PinchGestureInput& pinchGestureInput = aEvent.AsPinchGestureInput();
       switch (pinchGestureInput.mType) {
         case PinchGestureInput::PINCHGESTURE_START:
           rv = OnScaleBegin(pinchGestureInput);
           break;
         case PinchGestureInput::PINCHGESTURE_SCALE:
           rv = OnScale(pinchGestureInput);
           break;
         case PinchGestureInput::PINCHGESTURE_END:
           rv = OnScaleEnd(pinchGestureInput);
           break;
       }
       break;
     }
     case TAPGESTURE_INPUT: {
-      TapGestureInput tapGestureInput = aEvent.AsTapGestureInput();
-      tapGestureInput.TransformToLocal(GetTransformToThis());
+      const TapGestureInput& tapGestureInput = aEvent.AsTapGestureInput();
       switch (tapGestureInput.mType) {
         case TapGestureInput::TAPGESTURE_LONG:
           rv = OnLongPress(tapGestureInput);
           break;
         case TapGestureInput::TAPGESTURE_LONG_UP:
           rv = OnLongPressUp(tapGestureInput);
           break;
         case TapGestureInput::TAPGESTURE_UP:
@@ -1264,34 +1260,33 @@ void AsyncPanZoomController::StopAutoscr
     CancelAnimation(TriggeredExternally);
   }
 }
 
 nsEventStatus AsyncPanZoomController::OnTouchStart(
     const MultiTouchInput& aEvent) {
   APZC_LOG("%p got a touch-start in state %d\n", this, mState);
   mPanDirRestricted = false;
+  ParentLayerPoint point = GetFirstTouchPoint(aEvent);
 
   switch (mState) {
     case FLING:
     case ANIMATING_ZOOM:
     case SMOOTH_SCROLL:
     case OVERSCROLL_ANIMATION:
     case WHEEL_SCROLL:
     case KEYBOARD_SCROLL:
     case PAN_MOMENTUM:
     case AUTOSCROLL:
       MOZ_ASSERT(GetCurrentTouchBlock());
       GetCurrentTouchBlock()->GetOverscrollHandoffChain()->CancelAnimations(
           ExcludeOverscroll);
       MOZ_FALLTHROUGH;
     case SCROLLBAR_DRAG:
     case NOTHING: {
-      ParentLayerPoint point = GetFirstTouchPoint(aEvent);
-      mStartTouch = GetFirstExternalTouchPoint(aEvent);
       mX.StartTouch(point.x, aEvent.mTime);
       mY.StartTouch(point.y, aEvent.mTime);
       if (RefPtr<GeckoContentController> controller =
               GetGeckoContentController()) {
         MOZ_ASSERT(GetCurrentTouchBlock());
         controller->NotifyAPZStateChange(
             GetGuid(), APZStateChange::eStartTouch,
             GetCurrentTouchBlock()->GetOverscrollHandoffChain()->CanBePanned(
@@ -1321,44 +1316,46 @@ nsEventStatus AsyncPanZoomController::On
     case NOTHING:
     case ANIMATING_ZOOM:
       // May happen if the user double-taps and drags without lifting after the
       // second tap. Ignore the move if this happens.
       return nsEventStatus_eIgnore;
 
     case TOUCHING: {
       ScreenCoord panThreshold = GetTouchStartTolerance();
-      ExternalPoint extPoint = GetFirstExternalTouchPoint(aEvent);
+
       // We intentionally skip the UpdateWithTouchAtDevicePoint call when the
       // panThreshold is zero. This ensures more deterministic behaviour during
       // testing. If we call that, Axis::mPos gets updated to the point of this
       // touchmove event, but we "consume" the move to overcome the
       // panThreshold, so it's hard to pan a specific amount reliably from a
       // mochitest.
       if (panThreshold > 0.0f) {
         UpdateWithTouchAtDevicePoint(aEvent);
-        if (PanVector(extPoint).Length() < panThreshold) {
+        if (PanDistance() < panThreshold) {
           return nsEventStatus_eIgnore;
         }
       }
 
+      ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent);
+
       MOZ_ASSERT(GetCurrentTouchBlock());
       if (gfxPrefs::TouchActionEnabled() &&
           GetCurrentTouchBlock()->TouchActionAllowsPanningXY()) {
         // User tries to trigger a touch behavior. If allowed touch behavior is
         // vertical pan
         // + horizontal pan (touch-action value is equal to AUTO) we can return
         // ConsumeNoDefault status immediately to trigger cancel event further.
         // It should happen independent of the parent type (whether it is
         // scrolling or not).
-        StartPanning(extPoint);
+        StartPanning(touchPoint);
         return nsEventStatus_eConsumeNoDefault;
       }
 
-      return StartPanning(extPoint);
+      return StartPanning(touchPoint);
     }
 
     case PANNING:
     case PANNING_LOCKED_X:
     case PANNING_LOCKED_Y:
     case PAN_MOMENTUM:
       TrackTouch(aEvent);
       return nsEventStatus_eConsumeNoDefault;
@@ -1705,17 +1702,17 @@ nsEventStatus AsyncPanZoomController::On
     if (mZoomConstraints.mAllowZoom) {
       mPanDirRestricted = false;
       mX.StartTouch(aEvent.mLocalFocusPoint.x, aEvent.mTime);
       mY.StartTouch(aEvent.mLocalFocusPoint.y, aEvent.mTime);
       SetState(TOUCHING);
     } else {
       // If zooming isn't allowed, StartTouch() was already called
       // in OnScaleBegin().
-      StartPanning(ToExternalPoint(aEvent.mScreenOffset, aEvent.mFocusPoint));
+      StartPanning(aEvent.mLocalFocusPoint);
     }
   } else {
     // Otherwise, handle the fingers being lifted.
 
     // Some of the code paths below, like ScrollSnap() or HandleEndOfPan(),
     // may start an animation, but otherwise we want to end up in the NOTHING
     // state. To avoid state change notification churn, we use a
     // notification blocker.
@@ -2758,50 +2755,42 @@ ScreenPoint AsyncPanZoomController::ToSc
 
 // TODO: figure out a good way to check the w-coordinate is positive and return
 // the result
 ParentLayerPoint AsyncPanZoomController::ToParentLayerCoordinates(
     const ScreenPoint& aVector, const ScreenPoint& aAnchor) const {
   return TransformVector(GetTransformToThis(), aVector, aAnchor);
 }
 
-ParentLayerPoint AsyncPanZoomController::ToParentLayerCoordinates(
-    const ScreenPoint& aVector, const ExternalPoint& aAnchor) const {
-  return ToParentLayerCoordinates(
-      aVector,
-      ViewAs<ScreenPixel>(aAnchor, PixelCastJustification::ExternalIsScreen));
-}
-
-ExternalPoint AsyncPanZoomController::ToExternalPoint(
-    const ExternalPoint& aScreenOffset, const ScreenPoint& aScreenPoint) {
-  return aScreenOffset +
-         ViewAs<ExternalPixel>(aScreenPoint,
-                               PixelCastJustification::ExternalIsScreen);
-}
-
-ScreenPoint AsyncPanZoomController::PanVector(const ExternalPoint& aPos) const {
-  return ScreenPoint(fabs(aPos.x - mStartTouch.x),
-                     fabs(aPos.y - mStartTouch.y));
-}
-
 bool AsyncPanZoomController::Contains(const ScreenIntPoint& aPoint) const {
   ScreenToParentLayerMatrix4x4 transformToThis = GetTransformToThis();
   Maybe<ParentLayerIntPoint> point = UntransformBy(transformToThis, aPoint);
   if (!point) {
     return false;
   }
 
   ParentLayerIntRect cb;
   {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     GetFrameMetrics().GetCompositionBounds().ToIntRect(&cb);
   }
   return cb.Contains(*point);
 }
 
+ScreenCoord AsyncPanZoomController::PanDistance() const {
+  ParentLayerPoint panVector;
+  ParentLayerPoint panStart;
+  {
+    RecursiveMutexAutoLock lock(mRecursiveMutex);
+    panVector = ParentLayerPoint(mX.PanDistance(), mY.PanDistance());
+    panStart = PanStart();
+  }
+  return ToScreenCoordinates(panVector, panStart).Length();
+}
+
 ParentLayerPoint AsyncPanZoomController::PanStart() const {
   return ParentLayerPoint(mX.PanStart(), mY.PanStart());
 }
 
 const ParentLayerPoint AsyncPanZoomController::GetVelocityVector() const {
   return ParentLayerPoint(mX.GetVelocity(), mY.GetVelocity());
 }
 
@@ -2900,21 +2889,18 @@ void AsyncPanZoomController::HandlePanni
     SetState(PANNING);
   }
 }
 
 void AsyncPanZoomController::HandlePanningUpdate(
     const ScreenPoint& aPanDistance) {
   // If we're axis-locked, check if the user is trying to break the lock
   if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
-    ParentLayerPoint vector =
-        ToParentLayerCoordinates(aPanDistance, mStartTouch);
-
-    double angle = atan2(vector.y, vector.x);  // range [-pi, pi]
-    angle = fabs(angle);                       // range [0, pi]
+    double angle = atan2(aPanDistance.y, aPanDistance.x);  // range [-pi, pi]
+    angle = fabs(angle);                                   // range [0, pi]
 
     float breakThreshold = gfxPrefs::APZAxisBreakoutThreshold() * GetDPI();
 
     if (fabs(aPanDistance.x) > breakThreshold ||
         fabs(aPanDistance.y) > breakThreshold) {
       if (mState == PANNING_LOCKED_X) {
         if (!apz::IsCloseToHorizontal(angle,
                                       gfxPrefs::APZAxisBreakoutAngle())) {
@@ -2950,23 +2936,24 @@ void AsyncPanZoomController::HandlePinch
           focusChange.Length() > scrollLockThreshold) {
         mPinchLocked = true;
       }
     }
   }
 }
 
 nsEventStatus AsyncPanZoomController::StartPanning(
-    const ExternalPoint& aStartPoint) {
+    const ParentLayerPoint& aStartPoint) {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
-  ParentLayerPoint vector =
-      ToParentLayerCoordinates(PanVector(aStartPoint), mStartTouch);
-  double angle = atan2(vector.y, vector.x);  // range [-pi, pi]
-  angle = fabs(angle);                       // range [0, pi]
+  float dx = mX.PanDistance(aStartPoint.x);
+  float dy = mY.PanDistance(aStartPoint.y);
+
+  double angle = atan2(dy, dx);  // range [-pi, pi]
+  angle = fabs(angle);           // range [0, pi]
 
   if (gfxPrefs::TouchActionEnabled()) {
     HandlePanningWithTouchAction(angle);
   } else {
     if (GetAxisLockMode() == FREE) {
       SetState(PANNING);
     } else {
       HandlePanning(angle);
@@ -3328,44 +3315,41 @@ void AsyncPanZoomController::CallDispatc
     }
   }
 
   treeManagerLocal->DispatchScroll(this, aStartPoint, endPoint,
                                    aOverscrollHandoffState);
 }
 
 void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
-  ExternalPoint extPoint = GetFirstExternalTouchPoint(aEvent);
-  ScreenPoint panVector = PanVector(extPoint);
-  HandlePanningUpdate(panVector);
-
   ParentLayerPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
   ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent);
 
+  ScreenPoint panDistance =
+      ToScreenCoordinates(ParentLayerPoint(mX.PanDistance(touchPoint.x),
+                                           mY.PanDistance(touchPoint.y)),
+                          PanStart());
+  HandlePanningUpdate(panDistance);
+
   UpdateWithTouchAtDevicePoint(aEvent);
+
   if (prevTouchPoint != touchPoint) {
     MOZ_ASSERT(GetCurrentTouchBlock());
     OverscrollHandoffState handoffState(
-        *GetCurrentTouchBlock()->GetOverscrollHandoffChain(), panVector,
+        *GetCurrentTouchBlock()->GetOverscrollHandoffChain(), panDistance,
         ScrollSource::Touch);
     CallDispatchScroll(prevTouchPoint, touchPoint, handoffState);
   }
 }
 
 ParentLayerPoint AsyncPanZoomController::GetFirstTouchPoint(
     const MultiTouchInput& aEvent) {
   return ((SingleTouchData&)aEvent.mTouches[0]).mLocalScreenPoint;
 }
 
-ExternalPoint AsyncPanZoomController::GetFirstExternalTouchPoint(
-    const MultiTouchInput& aEvent) {
-  return ToExternalPoint(aEvent.mScreenOffset,
-                         ((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint);
-}
-
 void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation) {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
   mAnimation = aAnimation;
   mLastSampleTime = GetFrameTime();
   ScheduleComposite();
 }
 
 void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) {
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -487,35 +487,16 @@ class AsyncPanZoomController {
    * The anchor is necessary because with 3D tranforms, the location of the
    * vector can affect the result of the transform.
    * To respect the lock ordering, mRecursiveMutex must NOT be held when calling
    * this function (since this function acquires the tree lock).
    */
   ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector,
                                             const ScreenPoint& aAnchor) const;
 
-  /**
-   * Same as above, but uses an ExternalPoint as the anchor.
-   */
-  ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector,
-                                            const ExternalPoint& aAnchor) const;
-
-  /**
-   * Combines an offset defined as an external point, with a window-relative
-   * offset to give an absolute external point.
-   */
-  static ExternalPoint ToExternalPoint(const ExternalPoint& aScreenOffset,
-                                       const ScreenPoint& aScreenPoint);
-
-  /**
-   * Gets a vector where the head is the given point, and the tail is
-   * the touch start position.
-   */
-  ScreenPoint PanVector(const ExternalPoint& aPos) const;
-
   // Return whether or not a wheel event will be able to scroll in either
   // direction.
   bool CanScroll(const InputData& aEvent) const;
 
   // Return the directions in which this APZC allows handoff (as governed by
   // overscroll-behavior).
   ScrollDirections GetAllowedHandoffDirections() const;
 
@@ -738,19 +719,30 @@ class AsyncPanZoomController {
 
   /**
    * Schedules a composite, and if enough time has elapsed since the last
    * paint, a paint.
    */
   void ScheduleCompositeAndMaybeRepaint();
 
   /**
+   * Gets the displacement of the current touch since it began. That is, it is
+   * the distance between the current position and the initial position of the
+   * current touch (this only makes sense if a touch is currently happening and
+   * OnTouchMove() or the equivalent for pan gestures is being invoked).
+   * Note: It's an abuse of the 'Coord' class to use it to represent a 2D
+   *       distance, but it's the closest thing we currently have.
+   */
+  ScreenCoord PanDistance() const;
+
+  /**
    * Gets the start point of the current touch.
-   * This only makes sense if a touch is currently happening and OnTouchMove()
-   * or the equivalent for pan gestures is being invoked.
+   * Like PanDistance(), this only makes sense if a touch is currently
+   * happening and OnTouchMove() or the equivalent for pan gestures is
+   * being invoked.
    */
   ParentLayerPoint PanStart() const;
 
   /**
    * Gets a vector of the velocities of each axis.
    */
   const ParentLayerPoint GetVelocityVector() const;
 
@@ -761,27 +753,16 @@ class AsyncPanZoomController {
 
   /**
    * Gets the first touch point from a MultiTouchInput.  This gets only
    * the first one and assumes the rest are either missing or not relevant.
    */
   ParentLayerPoint GetFirstTouchPoint(const MultiTouchInput& aEvent);
 
   /**
-   * Gets the relevant point in the event
-   * (eg. first touch, or pinch focus point) of the given InputData.
-   */
-  ExternalPoint GetExternalPoint(const InputData& aEvent);
-
-  /**
-   * Gets the relevant point in the event, in external screen coordinates.
-   */
-  ExternalPoint GetFirstExternalTouchPoint(const MultiTouchInput& aEvent);
-
-  /**
    * Sets the panning state basing on the pan direction angle and current
    * touch-action value.
    */
   void HandlePanningWithTouchAction(double angle);
 
   /**
    * Sets the panning state ignoring the touch action value.
    */
@@ -794,21 +775,19 @@ class AsyncPanZoomController {
 
   /**
    * Set and update the pinch lock
    */
   void HandlePinchLocking(ScreenCoord spanDistance, ScreenPoint focusChange);
 
   /**
    * Sets up anything needed for panning. This takes us out of the "TOUCHING"
-   * state and starts actually panning us. We provide the physical pixel
-   * position of the start point so that the pan gesture is calculated
-   * regardless of if the window/GeckoView moved during the pan.
+   * state and starts actually panning us.
    */
-  nsEventStatus StartPanning(const ExternalPoint& aStartPoint);
+  nsEventStatus StartPanning(const ParentLayerPoint& aStartPoint);
 
   /**
    * Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
    * both axes and factors in the time delta from the last update.
    */
   void UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent);
 
   /**
@@ -1007,19 +986,16 @@ class AsyncPanZoomController {
   // set on the APZC instance for the root content document (i.e. the one we
   // support zooming on), and is only used if WebRender is enabled. The
   // animation id itself refers to the transform animation id that was set on
   // the stacking context in the WR display list. By changing the transform
   // associated with this id, we can adjust the scaling that WebRender applies,
   // thereby controlling the zoom.
   Maybe<uint64_t> mZoomAnimationId;
 
-  // Position on screen where user first put their finger down.
-  ExternalPoint mStartTouch;
-
   friend class Axis;
 
  public:
   /**
    * Invoke |callable|, passing |mLastContentPaintMetrics| as argument,
    * while holding the APZC lock required to access |mLastContentPaintMetrics|.
    * This allows code outside of an AsyncPanZoomController method implementation
    * to access |mLastContentPaintMetrics| without having to make a copy of it.
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -33,34 +33,34 @@ static const float PINCH_START_THRESHOLD
 /**
  * Determines how fast a one touch pinch zooms in and out. The greater the
  * value, the faster it zooms.
  */
 static const float ONE_TOUCH_PINCH_SPEED = 0.005f;
 
 static bool sLongTapEnabled = true;
 
-ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent) {
-  const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
-  const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
+ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent) {
+  const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
+  const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
   return (firstTouch + secondTouch) / 2;
 }
 
-ScreenCoord GetCurrentSpan(const MultiTouchInput& aEvent) {
-  const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
-  const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
-  ScreenPoint delta = secondTouch - firstTouch;
+ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent) {
+  const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
+  const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
+  ParentLayerPoint delta = secondTouch - firstTouch;
   return delta.Length();
 }
 
-ScreenCoord GestureEventListener::GetYSpanFromGestureStartPoint() {
+ParentLayerCoord GestureEventListener::GetYSpanFromGestureStartPoint() {
   // use the position that began the one-touch-pinch gesture rather
   // mTouchStartPosition
-  const ScreenPoint start = mOneTouchPinchStartPosition;
-  const ScreenPoint& current = mTouches[0].mScreenPoint;
+  const ParentLayerPoint start = mOneTouchPinchStartPosition;
+  const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint;
   return current.y - start.y;
 }
 
 TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch,
                                TapGestureInput::TapGestureType aType) {
   return TapGestureInput(aType, aTouch.mTime, aTouch.mTimeStamp,
                          aTouch.mTouches[0].mScreenPoint, aTouch.modifiers);
 }
@@ -152,18 +152,17 @@ int32_t GestureEventListener::GetLastTou
 void GestureEventListener::SetLongTapEnabled(bool aLongTapEnabled) {
   sLongTapEnabled = aLongTapEnabled;
 }
 
 nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
   switch (mState) {
     case GESTURE_NONE:
       SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN);
-      mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
-      mTouchStartOffset = mLastTouchInput.mScreenOffset;
+      mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
 
       if (sLongTapEnabled) {
         CreateLongTapTimeoutTask();
       }
       CreateMaxTapTimeoutTask();
       break;
     case GESTURE_FIRST_SINGLE_TOUCH_UP:
       if (SecondTapIsFar()) {
@@ -172,18 +171,17 @@ nsEventStatus GestureEventListener::Hand
         CancelLongTapTimeoutTask();
         CancelMaxTapTimeoutTask();
         mSingleTapSent = Nothing();
         SetState(GESTURE_NONE);
       } else {
         // Otherwise, reset the touch start position so that, if this turns into
         // a one-touch-pinch gesture, it uses the second tap's down position as
         // the focus, rather than the first tap's.
-        mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
-        mTouchStartOffset = mLastTouchInput.mScreenOffset;
+        mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
         SetState(GESTURE_SECOND_SINGLE_TOUCH_DOWN);
       }
       break;
     default:
       NS_WARNING("Unhandled state upon single touch start");
       SetState(GESTURE_NONE);
       break;
   }
@@ -237,21 +235,21 @@ nsEventStatus GestureEventListener::Hand
       SetState(GESTURE_NONE);
       break;
   }
 
   return rv;
 }
 
 bool GestureEventListener::MoveDistanceExceeds(ScreenCoord aThreshold) const {
-  ExternalPoint start = AsyncPanZoomController::ToExternalPoint(
-      mTouchStartOffset, mTouchStartPosition);
-  ExternalPoint end = AsyncPanZoomController::ToExternalPoint(
-      mLastTouchInput.mScreenOffset, mLastTouchInput.mTouches[0].mScreenPoint);
-  return (start - end).Length() > aThreshold;
+  const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint;
+  ParentLayerPoint delta = start - mTouchStartPosition;
+  ScreenPoint screenDelta =
+      mAsyncPanZoomController->ToScreenCoordinates(delta, start);
+  return (screenDelta.Length() > aThreshold);
 }
 
 bool GestureEventListener::MoveDistanceIsLarge() const {
   return MoveDistanceExceeds(mAsyncPanZoomController->GetTouchStartTolerance());
 }
 
 bool GestureEventListener::SecondTapIsFar() const {
   // Allow a little more room here, because the is actually lifting their finger
@@ -301,26 +299,27 @@ nsEventStatus GestureEventListener::Hand
           // If the one-touch-pinch feature is disabled, bail out of the double-
           // tap gesture instead.
           SetState(GESTURE_NONE);
           break;
         }
 
         SetState(GESTURE_ONE_TOUCH_PINCH);
 
-        ScreenCoord currentSpan = 1.0f;
-        ScreenPoint currentFocus = mTouchStartPosition;
+        ParentLayerCoord currentSpan = 1.0f;
+        ParentLayerPoint currentFocus = mTouchStartPosition;
 
         // save the position that the one-touch-pinch gesture actually begins
-        mOneTouchPinchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
+        mOneTouchPinchStartPosition =
+            mLastTouchInput.mTouches[0].mLocalScreenPoint;
 
         PinchGestureInput pinchEvent(
             PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime,
-            mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
-            currentFocus, currentSpan, currentSpan, mLastTouchInput.modifiers);
+            mLastTouchInput.mTimeStamp, currentFocus, currentSpan, currentSpan,
+            mLastTouchInput.modifiers);
 
         rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
 
         mPreviousSpan = currentSpan;
         mPreviousFocus = currentFocus;
       }
       break;
     }
@@ -328,28 +327,28 @@ nsEventStatus GestureEventListener::Hand
     case GESTURE_MULTI_TOUCH_DOWN: {
       if (mLastTouchInput.mTouches.Length() < 2) {
         NS_WARNING(
             "Wrong input: less than 2 moving points in "
             "GESTURE_MULTI_TOUCH_DOWN state");
         break;
       }
 
-      ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
-      ScreenPoint currentFocus = GetCurrentFocus(mLastTouchInput);
+      ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
+      ParentLayerPoint currentFocus = GetCurrentFocus(mLastTouchInput);
 
       mSpanChange += fabsf(currentSpan - mPreviousSpan);
       mFocusChange += (currentFocus - mPreviousFocus).Length();
       if (mSpanChange > PINCH_START_THRESHOLD ||
           mFocusChange > PINCH_START_THRESHOLD) {
         SetState(GESTURE_PINCH);
         PinchGestureInput pinchEvent(
             PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime,
-            mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
-            currentFocus, currentSpan, currentSpan, mLastTouchInput.modifiers);
+            mLastTouchInput.mTimeStamp, currentFocus, currentSpan, currentSpan,
+            mLastTouchInput.modifiers);
 
         rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
       } else {
         // Prevent APZC::OnTouchMove from processing a move event when two
         // touches are active
         rv = nsEventStatus_eConsumeNoDefault;
       }
 
@@ -362,46 +361,44 @@ nsEventStatus GestureEventListener::Hand
       if (mLastTouchInput.mTouches.Length() < 2) {
         NS_WARNING(
             "Wrong input: less than 2 moving points in GESTURE_PINCH state");
         // Prevent APZC::OnTouchMove() from handling this wrong input
         rv = nsEventStatus_eConsumeNoDefault;
         break;
       }
 
-      ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
+      ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
 
       PinchGestureInput pinchEvent(
           PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime,
-          mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
-          GetCurrentFocus(mLastTouchInput), currentSpan, mPreviousSpan,
-          mLastTouchInput.modifiers);
+          mLastTouchInput.mTimeStamp, GetCurrentFocus(mLastTouchInput),
+          currentSpan, mPreviousSpan, mLastTouchInput.modifiers);
 
       rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
       mPreviousSpan = currentSpan;
 
       break;
     }
 
     case GESTURE_ONE_TOUCH_PINCH: {
-      ScreenCoord currentSpan = GetYSpanFromGestureStartPoint();
+      ParentLayerCoord currentSpan = GetYSpanFromGestureStartPoint();
       float effectiveSpan =
           1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
-      ScreenPoint currentFocus = mTouchStartPosition;
+      ParentLayerPoint currentFocus = mTouchStartPosition;
 
       // Invert zoom.
       if (currentSpan.value < 0) {
         effectiveSpan = 1.0f / effectiveSpan;
       }
 
       PinchGestureInput pinchEvent(
           PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime,
-          mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
-          currentFocus, effectiveSpan, mPreviousSpan,
-          mLastTouchInput.modifiers);
+          mLastTouchInput.mTimeStamp, currentFocus, effectiveSpan,
+          mPreviousSpan, mLastTouchInput.modifiers);
 
       rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
       mPreviousSpan = effectiveSpan;
 
       break;
     }
 
     default:
@@ -466,40 +463,40 @@ nsEventStatus GestureEventListener::Hand
       if (mTouches.Length() < 2) {
         SetState(GESTURE_NONE);
       }
       break;
 
     case GESTURE_PINCH:
       if (mTouches.Length() < 2) {
         SetState(GESTURE_NONE);
-        ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
+        ParentLayerPoint point = PinchGestureInput::BothFingersLifted();
         if (mTouches.Length() == 1) {
           // As user still keeps one finger down the event's focus point should
           // contain meaningful data.
-          point = mTouches[0].mScreenPoint;
+          point = mTouches[0].mLocalScreenPoint;
         }
-        PinchGestureInput pinchEvent(
-            PinchGestureInput::PINCHGESTURE_END, mLastTouchInput.mTime,
-            mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset, point,
-            1.0f, 1.0f, mLastTouchInput.modifiers);
+        PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
+                                     mLastTouchInput.mTime,
+                                     mLastTouchInput.mTimeStamp, point, 1.0f,
+                                     1.0f, mLastTouchInput.modifiers);
         mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
       }
 
       rv = nsEventStatus_eConsumeNoDefault;
 
       break;
 
     case GESTURE_ONE_TOUCH_PINCH: {
       SetState(GESTURE_NONE);
-      ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
-      PinchGestureInput pinchEvent(
-          PinchGestureInput::PINCHGESTURE_END, mLastTouchInput.mTime,
-          mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset, point,
-          1.0f, 1.0f, mLastTouchInput.modifiers);
+      ParentLayerPoint point(-1, -1);
+      PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
+                                   mLastTouchInput.mTime,
+                                   mLastTouchInput.mTimeStamp, point, 1.0f,
+                                   1.0f, mLastTouchInput.modifiers);
       mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
 
       rv = nsEventStatus_eConsumeNoDefault;
 
       break;
     }
 
     default:
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -151,17 +151,17 @@ class GestureEventListener final {
   bool MoveDistanceExceeds(ScreenCoord aThreshold) const;
   bool MoveDistanceIsLarge() const;
   bool SecondTapIsFar() const;
 
   /**
    * Returns current vertical span, counting from the where the gesture first
    * began (after a brief delay detecting the gesture from first touch).
    */
-  ScreenCoord GetYSpanFromGestureStartPoint();
+  ParentLayerCoord GetYSpanFromGestureStartPoint();
 
   /**
    * Do actual state transition and reset substates.
    */
   void SetState(GestureState aState);
 
   RefPtr<AsyncPanZoomController> mAsyncPanZoomController;
 
@@ -180,27 +180,27 @@ class GestureEventListener final {
   GestureState mState;
 
   /**
    * Total change in span since we detected a pinch gesture. Only used when we
    * are in the |GESTURE_WAITING_PINCH| state and need to know how far zoomed
    * out we are compared to our original pinch span. Note that this does _not_
    * continue to be updated once we jump into the |GESTURE_PINCH| state.
    */
-  ScreenCoord mSpanChange;
+  ParentLayerCoord mSpanChange;
 
   /**
    * Previous span calculated for the purposes of setting inside a
    * PinchGestureInput.
    */
-  ScreenCoord mPreviousSpan;
+  ParentLayerCoord mPreviousSpan;
 
   /* Properties similar to mSpanChange and mPreviousSpan, but for the focus */
-  ScreenCoord mFocusChange;
-  ScreenPoint mPreviousFocus;
+  ParentLayerCoord mFocusChange;
+  ParentLayerPoint mPreviousFocus;
 
   /**
    * Cached copy of the last touch input.
    */
   MultiTouchInput mLastTouchInput;
 
   /**
    * Cached copy of the last tap gesture input.
@@ -214,34 +214,28 @@ class GestureEventListener final {
   /**
    * Position of the last touch that exceeds the GetTouchStartTolerance when
    * performing a one-touch-pinch gesture; using the mTouchStartPosition is
    * slightly inaccurate because by the time the touch position has passed
    * the threshold for the gesture, there is already a span that the zoom
    * is calculated from, instead of starting at 1.0 when the threshold gets
    * passed.
    */
-  ScreenPoint mOneTouchPinchStartPosition;
+  ParentLayerPoint mOneTouchPinchStartPosition;
 
   /**
    * Position of the last touch starting. This is only valid during an attempt
    * to determine if a touch is a tap. If a touch point moves away from
    * mTouchStartPosition to the distance greater than
    * AsyncPanZoomController::GetTouchStartTolerance() while in
    * GESTURE_FIRST_SINGLE_TOUCH_DOWN, GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN
    * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is
    * not tap.
    */
-  ScreenPoint mTouchStartPosition;
-
-  /**
-   * We store the window/GeckoView's display offset as well, so we can
-   * track the user's physical touch movements in absolute display coordinates.
-   */
-  ExternalPoint mTouchStartOffset;
+  ParentLayerPoint mTouchStartPosition;
 
   /**
    * Task used to timeout a long tap. This gets posted to the UI thread such
    * that it runs a time when a single tap happens. We cache it so that
    * we can cancel it if any other touch event happens.
    *
    * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN
    * and GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN states.
--- a/gfx/layers/apz/test/gtest/InputUtils.h
+++ b/gfx/layers/apz/test/gtest/InputUtils.h
@@ -27,18 +27,19 @@
  * APZC instances in isolation and also an entire APZ tree, while using the same
  * code to dispatch input events.
  */
 
 PinchGestureInput CreatePinchGestureInput(
     PinchGestureInput::PinchGestureType aType, const ScreenPoint& aFocus,
     float aCurrentSpan, float aPreviousSpan) {
   ParentLayerPoint localFocus(aFocus.x, aFocus.y);
-  PinchGestureInput result(aType, 0, TimeStamp(), ExternalPoint(0, 0), aFocus,
-                           aCurrentSpan, aPreviousSpan, 0);
+  PinchGestureInput result(aType, 0, TimeStamp(), localFocus, aCurrentSpan,
+                           aPreviousSpan, 0);
+  result.mFocusPoint = aFocus;
   return result;
 }
 
 template <class InputReceiver>
 void SetDefaultAllowedTouchBehavior(const RefPtr<InputReceiver>& aTarget,
                                     uint64_t aInputBlockId,
                                     int touchPoints = 1) {
   nsTArray<uint32_t> defaultBehaviors;
--- a/layout/base/UnitTransforms.h
+++ b/layout/base/UnitTransforms.h
@@ -54,18 +54,16 @@ enum class PixelCastJustification : uint
   // as an AsyncTransformMatrix. See the definitions of these matrices in
   // LayersTypes.h for details.
   MultipleAsyncTransforms,
   // We have reason to believe a layer doesn't have a local transform.
   // Should only be used if we've already checked or asserted this.
   NoTransformOnLayer,
   // LayerPixels are ImagePixels
   LayerIsImage,
-  // External pixels are the same scale as screen pixels
-  ExternalIsScreen,
 };
 
 template <class TargetUnits, class SourceUnits>
 gfx::CoordTyped<TargetUnits> ViewAs(const gfx::CoordTyped<SourceUnits>& aCoord,
                                     PixelCastJustification) {
   return gfx::CoordTyped<TargetUnits>(aCoord.value);
 }
 template <class TargetUnits, class SourceUnits>
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
@@ -34,17 +34,17 @@ public class PanZoomController extends J
     private long mLastDownTime;
 
     private SynthesizedEventState mPointerState;
 
     private ArrayList<Pair<Integer, MotionEvent>> mQueuedEvents;
 
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleMotionEvent(
-            int action, int actionIndex, long time, int metaState,  float screenX, float screenY,
+            int action, int actionIndex, long time, int metaState,
             int pointerId[], float x[], float y[], float orientation[], float pressure[],
             float toolMajor[], float toolMinor[]);
 
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleScrollEvent(
             long time, int metaState,
             float x, float y,
             float hScroll, float vScroll);
@@ -89,25 +89,18 @@ public class PanZoomController extends J
             orientation[i] = coords.orientation;
             pressure[i] = coords.pressure;
 
             // If we are converting to CSS pixels, we should adjust the radii as well.
             toolMajor[i] = coords.toolMajor;
             toolMinor[i] = coords.toolMinor;
         }
 
-        final float screenX = event.getRawX() - event.getX();
-        final float screenY = event.getRawY() - event.getY();
-
-        // Take this opportunity to update screen origin of session. This gets
-        // dispatched to the gecko thread, so we also pass the new screen x/y directly to apz.
-        mSession.onScreenOriginChanged((int)screenX, (int)screenY);
-
         return handleMotionEvent(action, event.getActionIndex(), event.getEventTime(),
-                event.getMetaState(), screenX, screenY, pointerId, x, y, orientation, pressure,
+                event.getMetaState(), pointerId, x, y, orientation, pressure,
                 toolMajor, toolMinor);
     }
 
     private boolean handleScrollEvent(MotionEvent event) {
         if (!mAttached) {
             mQueuedEvents.add(new Pair<>(EVENT_SOURCE_SCROLL, event));
             return false;
         }
--- a/widget/InputData.cpp
+++ b/widget/InputData.cpp
@@ -77,17 +77,16 @@ MultiTouchInput::MultiTouchInput()
     : InputData(MULTITOUCH_INPUT),
       mType(MULTITOUCH_START),
       mHandledByAPZ(false) {}
 
 MultiTouchInput::MultiTouchInput(const MultiTouchInput& aOther)
     : InputData(MULTITOUCH_INPUT, aOther.mTime, aOther.mTimeStamp,
                 aOther.modifiers),
       mType(aOther.mType),
-      mScreenOffset(aOther.mScreenOffset),
       mHandledByAPZ(aOther.mHandledByAPZ) {
   mTouches.AppendElements(aOther.mTouches);
 }
 
 MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
     : InputData(MULTITOUCH_INPUT, aTouchEvent.mTime, aTouchEvent.mTimeStamp,
                 aTouchEvent.mModifiers),
       mHandledByAPZ(aTouchEvent.mFlags.mHandledByAPZ) {
@@ -107,20 +106,16 @@ MultiTouchInput::MultiTouchInput(const W
     case eTouchCancel:
       mType = MULTITOUCH_CANCEL;
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
       break;
   }
 
-  mScreenOffset = ViewAs<ExternalPixel>(
-      aTouchEvent.mWidget->WidgetToScreenOffset(),
-      PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
-
   for (size_t i = 0; i < aTouchEvent.mTouches.Length(); i++) {
     const Touch* domTouch = aTouchEvent.mTouches[i];
 
     // Extract data from weird interfaces.
     int32_t identifier = domTouch->Identifier();
     int32_t radiusX = domTouch->RadiusX(CallerType::System);
     int32_t radiusY = domTouch->RadiusY(CallerType::System);
     float rotationAngle = domTouch->RotationAngle(CallerType::System);
@@ -132,16 +127,52 @@ MultiTouchInput::MultiTouchInput(const W
             domTouch->mRefPoint,
             PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
         ScreenSize(radiusX, radiusY), rotationAngle, force);
 
     mTouches.AppendElement(data);
   }
 }
 
+MultiTouchInput::MultiTouchInput(const WidgetMouseEvent& aMouseEvent)
+    : InputData(MULTITOUCH_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
+                aMouseEvent.mModifiers),
+      mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ) {
+  MOZ_ASSERT(NS_IsMainThread(),
+             "Can only copy from WidgetMouseEvent on main thread");
+  switch (aMouseEvent.mMessage) {
+    case eMouseDown:
+      mType = MULTITOUCH_START;
+      break;
+    case eMouseMove:
+      mType = MULTITOUCH_MOVE;
+      break;
+    case eMouseUp:
+      mType = MULTITOUCH_END;
+      break;
+    // The mouse pointer has been interrupted in an implementation-specific
+    // manner, such as a synchronous event or action cancelling the touch, or a
+    // touch point leaving the document window and going into a non-document
+    // area capable of handling user interactions.
+    case eMouseExitFromWidget:
+      mType = MULTITOUCH_CANCEL;
+      break;
+    default:
+      NS_WARNING("Did not assign a type to a MultiTouchInput");
+      break;
+  }
+
+  mTouches.AppendElement(SingleTouchData(
+      0,
+      ViewAs<ScreenPixel>(
+          aMouseEvent.mRefPoint,
+          PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
+      ScreenSize(1, 1), 180.0f, 1.0f));
+}
+
 void MultiTouchInput::Translate(const ScreenPoint& aTranslation) {
   const int32_t xTranslation = (int32_t)(aTranslation.x + 0.5f);
   const int32_t yTranslation = (int32_t)(aTranslation.y + 0.5f);
 
   for (auto iter = mTouches.begin(); iter != mTouches.end(); iter++) {
     iter->mScreenPoint.MoveBy(xTranslation, yTranslation);
   }
 }
@@ -510,24 +541,37 @@ ScreenPoint PanGestureInput::UserMultipl
 ParentLayerPoint PanGestureInput::UserMultipliedLocalPanDisplacement() const {
   return ParentLayerPoint(mLocalPanDisplacement.x * mUserDeltaMultiplierX,
                           mLocalPanDisplacement.y * mUserDeltaMultiplierY);
 }
 
 PinchGestureInput::PinchGestureInput()
     : InputData(PINCHGESTURE_INPUT), mType(PINCHGESTURE_START) {}
 
-PinchGestureInput::PinchGestureInput(
-    PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
-    const ExternalPoint& aScreenOffset, const ScreenPoint& aFocusPoint,
-    ScreenCoord aCurrentSpan, ScreenCoord aPreviousSpan, Modifiers aModifiers)
+PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
+                                     TimeStamp aTimeStamp,
+                                     const ScreenPoint& aFocusPoint,
+                                     ParentLayerCoord aCurrentSpan,
+                                     ParentLayerCoord aPreviousSpan,
+                                     Modifiers aModifiers)
     : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mFocusPoint(aFocusPoint),
-      mScreenOffset(aScreenOffset),
+      mCurrentSpan(aCurrentSpan),
+      mPreviousSpan(aPreviousSpan) {}
+
+PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
+                                     TimeStamp aTimeStamp,
+                                     const ParentLayerPoint& aLocalFocusPoint,
+                                     ParentLayerCoord aCurrentSpan,
+                                     ParentLayerCoord aPreviousSpan,
+                                     Modifiers aModifiers)
+    : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
+      mType(aType),
+      mLocalFocusPoint(aLocalFocusPoint),
       mCurrentSpan(aCurrentSpan),
       mPreviousSpan(aPreviousSpan) {}
 
 bool PinchGestureInput::TransformToLocal(
     const ScreenToParentLayerMatrix4x4& aTransform) {
   if (mFocusPoint == BothFingersLifted<ScreenPixel>()) {
     // Special value, no transform required.
     mLocalFocusPoint = BothFingersLifted();
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -192,34 +192,38 @@ class MultiTouchInput : public InputData
   ));
   // clang-format on
 
   MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp,
                   Modifiers aModifiers);
   MultiTouchInput();
   MultiTouchInput(const MultiTouchInput& aOther);
   explicit MultiTouchInput(const WidgetTouchEvent& aTouchEvent);
+  // This conversion from WidgetMouseEvent to MultiTouchInput is needed because
+  // on the B2G emulator we can only receive mouse events, but we need to be
+  // able to pan correctly. To do this, we convert the events into a format that
+  // the panning code can handle. This code is very limited and only supports
+  // SingleTouchData. It also sends garbage for the identifier, radius, force
+  // and rotation angle.
+  explicit MultiTouchInput(const WidgetMouseEvent& aMouseEvent);
   void Translate(const ScreenPoint& aTranslation);
 
   WidgetTouchEvent ToWidgetTouchEvent(nsIWidget* aWidget) const;
   WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
 
   // Return the index into mTouches of the SingleTouchData with the given
   // identifier, or -1 if there is no such SingleTouchData.
   int32_t IndexOfTouch(int32_t aTouchIdentifier);
 
   bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
 
   // Warning, this class is serialized and sent over IPC. Any change to its
   // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   MultiTouchType mType;
   nsTArray<SingleTouchData> mTouches;
-  // The screen offset of the root widget. This can be changing along with
-  // the touch interaction, so we sstore it in the event.
-  ExternalPoint mScreenOffset;
   bool mHandledByAPZ;
 };
 
 class MouseInput : public InputData {
  protected:
   friend mozilla::layers::APZInputBridgeChild;
   friend mozilla::layers::PAPZInputBridgeParent;
 
@@ -405,20 +409,34 @@ class PinchGestureInput : public InputDa
     PinchGestureType, (
       PINCHGESTURE_START,
       PINCHGESTURE_SCALE,
       PINCHGESTURE_END
   ));
   // clang-format on
 
   // Construct a pinch gesture from a Screen point.
+  // (Technically, we should take the span values in Screen pixels as well,
+  // but that would require also storing them in Screen pixels and then
+  // converting them in TransformToLocal() like the focus point. Since pinch
+  // gesture events are processed by the root content APZC, the only transform
+  // between Screen and ParentLayer pixels should be a translation, which is
+  // irrelevant to span values, so we don't bother.)
   PinchGestureInput(PinchGestureType aType, uint32_t aTime,
-                    TimeStamp aTimeStamp, const ExternalPoint& aScreenOffset,
-                    const ScreenPoint& aFocusPoint, ScreenCoord aCurrentSpan,
-                    ScreenCoord aPreviousSpan, Modifiers aModifiers);
+                    TimeStamp aTimeStamp, const ScreenPoint& aFocusPoint,
+                    ParentLayerCoord aCurrentSpan,
+                    ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
+
+  // Construct a pinch gesture from a ParentLayer point.
+  // mFocusPoint remains (0,0) unless it's set later.
+  PinchGestureInput(PinchGestureType aType, uint32_t aTime,
+                    TimeStamp aTimeStamp,
+                    const ParentLayerPoint& aLocalFocusPoint,
+                    ParentLayerCoord aCurrentSpan,
+                    ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
 
   bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
 
   // Warning, this class is serialized and sent over IPC. Any change to its
   // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   PinchGestureType mType;
 
   // Center point of the pinch gesture. That is, if there are two fingers on the
@@ -426,31 +444,27 @@ class PinchGestureInput : public InputDa
   // point is implementation-specific, but can for example be the midpoint
   // between the very first and very last touch. This is in device pixels and
   // are the coordinates on the screen of this midpoint.
   // For PINCHGESTURE_END events, this instead will hold the coordinates of
   // the remaining finger, if there is one. If there isn't one then it will
   // store |BothFingersLifted()|.
   ScreenPoint mFocusPoint;
 
-  // The screen offset of the root widget. This can be changing along with
-  // the touch interaction, so we sstore it in the event.
-  ExternalPoint mScreenOffset;
-
   // |mFocusPoint| transformed to the local coordinates of the APZC targeted
   // by the hit. This is set and used by APZ.
   ParentLayerPoint mLocalFocusPoint;
 
   // The distance between the touches responsible for the pinch gesture.
-  ScreenCoord mCurrentSpan;
+  ParentLayerCoord mCurrentSpan;
 
   // The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
   // This is only really relevant during a PINCHGESTURE_SCALE because when it is
   // of this type then there must have been a history of spans.
-  ScreenCoord mPreviousSpan;
+  ParentLayerCoord mPreviousSpan;
 
   // A special value for mFocusPoint used in PINCHGESTURE_END events to
   // indicate that both fingers have been lifted. If only one finger has
   // been lifted, the coordinates of the remaining finger are expected to
   // be stored in mFocusPoint.
   // For pinch events that were not triggered by touch gestures, the
   // value of mFocusPoint in a PINCHGESTURE_END event is always expected
   // to be this value.
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -642,18 +642,17 @@ class nsWindow::NPZCSupport final
       window->ProcessUntransformedAPZEvent(&mouseEvent, guid, blockId, status);
     });
 
     return true;
   }
 
   bool HandleMotionEvent(const PanZoomController::LocalRef& aInstance,
                          int32_t aAction, int32_t aActionIndex, int64_t aTime,
-                         int32_t aMetaState, float aScreenX, float aScreenY,
-                         jni::IntArray::Param aPointerId,
+                         int32_t aMetaState, jni::IntArray::Param aPointerId,
                          jni::FloatArray::Param aX, jni::FloatArray::Param aY,
                          jni::FloatArray::Param aOrientation,
                          jni::FloatArray::Param aPressure,
                          jni::FloatArray::Param aToolMajor,
                          jni::FloatArray::Param aToolMinor) {
     MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
 
     RefPtr<IAPZCTreeManager> controller;
@@ -693,18 +692,16 @@ class nsWindow::NPZCSupport final
         break;
       default:
         return false;
     }
 
     MultiTouchInput input(type, aTime, GetEventTimeStamp(aTime), 0);
     input.modifiers = GetModifiers(aMetaState);
     input.mTouches.SetCapacity(endIndex - startIndex);
-    input.mScreenOffset =
-        ExternalIntPoint(int32_t(floorf(aScreenX)), int32_t(floorf(aScreenY)));
 
     nsTArray<float> x(aX->GetElements());
     nsTArray<float> y(aY->GetElements());
     nsTArray<float> orientation(aOrientation->GetElements());
     nsTArray<float> pressure(aPressure->GetElements());
     nsTArray<float> toolMajor(aToolMajor->GetElements());
     nsTArray<float> toolMinor(aToolMinor->GetElements());
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -3653,19 +3653,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
     return;
   }
 
   if (gfxPrefs::APZAllowZooming()) {
     NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(anEvent, [self window]);
     ScreenPoint position =
         ViewAs<ScreenPixel>([self convertWindowCoordinatesRoundDown:locationInWindow],
                             PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
-    ExternalPoint screenOffset =
-        ViewAs<ExternalPixel>(mGeckoChild->WidgetToScreenOffset(),
-                              PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
 
     PRIntervalTime eventIntervalTime = PR_IntervalNow();
     TimeStamp eventTimeStamp = nsCocoaUtils::GetEventTimeStamp([anEvent timestamp]);
     NSEventPhase eventPhase = [anEvent phase];
     PinchGestureInput::PinchGestureType pinchGestureType;
 
     switch (eventPhase) {
       case NSEventPhaseBegan: {
@@ -3684,17 +3681,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
         NS_WARNING("Unexpected phase for pinch gesture event.");
         return;
       }
     }
 
     PinchGestureInput event{pinchGestureType,
                             eventIntervalTime,
                             eventTimeStamp,
-                            screenOffset,
                             position,
                             100.0,
                             100.0 * (1.0 - [anEvent magnification]),
                             nsCocoaUtils::ModifiersForEvent(anEvent)};
 
     if (pinchGestureType == PinchGestureInput::PINCHGESTURE_END) {
       event.mFocusPoint = PinchGestureInput::BothFingersLifted<ScreenPixel>();
     }
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -1139,26 +1139,24 @@ template <>
 struct ParamTraits<mozilla::MultiTouchInput> {
   typedef mozilla::MultiTouchInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam) {
     WriteParam(aMsg, static_cast<const mozilla::InputData&>(aParam));
     WriteParam(aMsg, aParam.mType);
     WriteParam(aMsg, aParam.mTouches);
     WriteParam(aMsg, aParam.mHandledByAPZ);
-    WriteParam(aMsg, aParam.mScreenOffset);
   }
 
   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->mTouches) &&
-           ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
-           ReadParam(aMsg, aIter, &aResult->mScreenOffset);
+           ReadParam(aMsg, aIter, &aResult->mHandledByAPZ);
   }
 };
 
 template <>
 struct ParamTraits<mozilla::MouseInput::MouseType>
     : public ContiguousEnumSerializerInclusive<
           mozilla::MouseInput::MouseType,
           mozilla::MouseInput::MouseType::MOUSE_NONE,
@@ -1261,28 +1259,26 @@ struct ParamTraits<mozilla::PinchGesture
 
 template <>
 struct ParamTraits<mozilla::PinchGestureInput> {
   typedef mozilla::PinchGestureInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam) {
     WriteParam(aMsg, static_cast<const mozilla::InputData&>(aParam));
     WriteParam(aMsg, aParam.mType);
-    WriteParam(aMsg, aParam.mScreenOffset);
     WriteParam(aMsg, aParam.mFocusPoint);
     WriteParam(aMsg, aParam.mLocalFocusPoint);
     WriteParam(aMsg, aParam.mCurrentSpan);
     WriteParam(aMsg, aParam.mPreviousSpan);
   }
 
   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->mScreenOffset) &&
            ReadParam(aMsg, aIter, &aResult->mFocusPoint) &&
            ReadParam(aMsg, aIter, &aResult->mLocalFocusPoint) &&
            ReadParam(aMsg, aIter, &aResult->mCurrentSpan) &&
            ReadParam(aMsg, aIter, &aResult->mPreviousSpan);
   }
 };
 
 template <>