Bug 1528725 - Hit-test pointer events against out-of-process iframes in WebRender mode. r=kats
authorHenri Sivonen <hsivonen@hsivonen.fi>
Wed, 27 Feb 2019 16:15:07 +0000
changeset 519351 94fb56d47147bea9bb6cd05bb20c1a9fe8ee7066
parent 519350 7faa9b2768ed41c88088b9ecd58b89fb0101a5cd
child 519352 66106f6c975168680c1e5f2a4009d40d976b9f82
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)
reviewerskats
bugs1528725
milestone67.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 1528725 - Hit-test pointer events against out-of-process iframes in WebRender mode. r=kats Differential Revision: https://phabricator.services.mozilla.com/D20470
gfx/layers/apz/public/APZInputBridge.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/src/APZInputBridge.cpp
gfx/layers/apz/test/gtest/TestEventRegions.cpp
gfx/layers/apz/test/gtest/TestHitTesting.cpp
gfx/layers/ipc/APZInputBridgeChild.cpp
gfx/layers/ipc/APZInputBridgeChild.h
gfx/layers/ipc/APZInputBridgeParent.cpp
gfx/layers/ipc/APZInputBridgeParent.h
gfx/layers/ipc/PAPZInputBridge.ipdl
--- a/gfx/layers/apz/public/APZInputBridge.h
+++ b/gfx/layers/apz/public/APZInputBridge.h
@@ -100,17 +100,18 @@ class APZInputBridge {
  protected:
   friend class APZInputBridgeParent;
 
   // Methods to help process WidgetInputEvents (or manage conversion to/from
   // InputData)
 
   virtual void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
                                      ScrollableLayerGuid* aOutTargetGuid,
-                                     uint64_t* aOutFocusSequenceNumber) = 0;
+                                     uint64_t* aOutFocusSequenceNumber,
+                                     LayersId* aOutLayersId) = 0;
 
   virtual void UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
                                       EventMessage aEventMessage) = 0;
 
   virtual ~APZInputBridge() {}
 };
 
 }  // namespace layers
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1214,18 +1214,18 @@ nsEventStatus APZCTreeManager::ReceiveIn
         // If this is the start of a drag we need to unambiguously know if it's
         // going to land on a scrollbar or not. We can't apply an untransform
         // here without knowing that, so we need to ensure the untransform is
         // a no-op.
         FlushRepaintsToClearScreenToGeckoTransform();
       }
 
       HitTestingTreeNodeAutoLock hitScrollbarNode;
-      RefPtr<AsyncPanZoomController> apzc =
-          GetTargetAPZC(mouseInput.mOrigin, &hitResult, &hitScrollbarNode);
+      RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(
+          mouseInput.mOrigin, &hitResult, &aEvent.mLayersId, &hitScrollbarNode);
       bool hitScrollbar = (bool)hitScrollbarNode;
 
       // When the mouse is outside the window we still want to handle dragging
       // but we won't find an APZC. Fallback to root APZC then.
       {  // scope lock
         RecursiveMutexAutoLock lock(mTreeLock);
         if (!apzc && mRootNode) {
           apzc = mRootNode->GetApzc();
@@ -1296,24 +1296,26 @@ nsEventStatus APZCTreeManager::ReceiveIn
           aOutTargetGuid->mScrollId = ScrollableLayerGuid::NULL_SCROLL_ID;
         }
       }
       break;
     }
     case SCROLLWHEEL_INPUT: {
       FlushRepaintsToClearScreenToGeckoTransform();
 
+      // Do this before early return for Fission hit testing.
       ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
+      RefPtr<AsyncPanZoomController> apzc =
+          GetTargetAPZC(wheelInput.mOrigin, &hitResult, &aEvent.mLayersId);
+
       wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
       if (!wheelInput.mHandledByAPZ) {
         return result;
       }
 
-      RefPtr<AsyncPanZoomController> apzc =
-          GetTargetAPZC(wheelInput.mOrigin, &hitResult);
       if (apzc) {
         MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
 
         if (wheelInput.mAPZAction == APZWheelAction::PinchZoom) {
           // The mousewheel may have hit a subframe, but we want to send the
           // pinch-zoom events to the root-content APZC.
           {
             RecursiveMutexAutoLock lock(mTreeLock);
@@ -1351,34 +1353,36 @@ nsEventStatus APZCTreeManager::ReceiveIn
         apzc->GetGuid(aOutTargetGuid);
         wheelInput.mOrigin = *untransformedOrigin;
       }
       break;
     }
     case PANGESTURE_INPUT: {
       FlushRepaintsToClearScreenToGeckoTransform();
 
+      // Do this before early return for Fission hit testing.
       PanGestureInput& panInput = aEvent.AsPanGestureInput();
+      RefPtr<AsyncPanZoomController> apzc =
+          GetTargetAPZC(panInput.mPanStartPoint, &hitResult, &aEvent.mLayersId);
+
       panInput.mHandledByAPZ = WillHandleInput(panInput);
       if (!panInput.mHandledByAPZ) {
         return result;
       }
 
       // If/when we enable support for pan inputs off-main-thread, we'll need
       // to duplicate this EventStateManager code or something. See the call to
       // GetUserPrefsForWheelEvent in IAPZCTreeManager.cpp for why these fields
       // are stored separately.
       MOZ_ASSERT(NS_IsMainThread());
       WidgetWheelEvent wheelEvent = panInput.ToWidgetWheelEvent(nullptr);
       EventStateManager::GetUserPrefsForWheelEvent(
           &wheelEvent, &panInput.mUserDeltaMultiplierX,
           &panInput.mUserDeltaMultiplierY);
 
-      RefPtr<AsyncPanZoomController> apzc =
-          GetTargetAPZC(panInput.mPanStartPoint, &hitResult);
       if (apzc) {
         MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
 
         // 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, transformed into the gecko space. (pre-scroll because
         // the mouse cursor is stationary during pan gesture scrolling, unlike
@@ -1409,17 +1413,17 @@ nsEventStatus APZCTreeManager::ReceiveIn
         panInput.mOverscrollBehaviorAllowsSwipe =
             apzc->OverscrollBehaviorAllowsSwipe();
       }
       break;
     }
     case PINCHGESTURE_INPUT: {  // note: no one currently sends these
       PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
       RefPtr<AsyncPanZoomController> apzc =
-          GetTargetAPZC(pinchInput.mFocusPoint, &hitResult);
+          GetTargetAPZC(pinchInput.mFocusPoint, &hitResult, &aEvent.mLayersId);
       if (apzc) {
         MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
 
         ScreenToScreenMatrix4x4 outTransform =
             GetScreenToApzcTransform(apzc) * GetApzcToGeckoTransform(apzc);
         Maybe<ScreenPoint> untransformedFocusPoint =
             UntransformBy(outTransform, pinchInput.mFocusPoint);
 
@@ -1435,17 +1439,17 @@ nsEventStatus APZCTreeManager::ReceiveIn
         apzc->GetGuid(aOutTargetGuid);
         pinchInput.mFocusPoint = *untransformedFocusPoint;
       }
       break;
     }
     case TAPGESTURE_INPUT: {  // note: no one currently sends these
       TapGestureInput& tapInput = aEvent.AsTapGestureInput();
       RefPtr<AsyncPanZoomController> apzc =
-          GetTargetAPZC(tapInput.mPoint, &hitResult);
+          GetTargetAPZC(tapInput.mPoint, &hitResult, &aEvent.mLayersId);
       if (apzc) {
         MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
 
         ScreenToScreenMatrix4x4 outTransform =
             GetScreenToApzcTransform(apzc) * GetApzcToGeckoTransform(apzc);
         Maybe<ScreenIntPoint> untransformedPoint =
             UntransformBy(outTransform, tapInput.mPoint);
 
@@ -1586,34 +1590,35 @@ static TouchBehaviorFlags ConvertToTouch
   }
   return result;
 }
 
 already_AddRefed<AsyncPanZoomController>
 APZCTreeManager::GetTouchInputBlockAPZC(
     const MultiTouchInput& aEvent,
     nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
-    CompositorHitTestInfo* aOutHitResult,
+    CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
     HitTestingTreeNodeAutoLock* aOutHitScrollbarNode) {
   RefPtr<AsyncPanZoomController> apzc;
   if (aEvent.mTouches.Length() == 0) {
     return apzc.forget();
   }
 
   FlushRepaintsToClearScreenToGeckoTransform();
 
   CompositorHitTestInfo hitResult;
   apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, &hitResult,
+                       aEvent.mTouches.Length() == 1 ? aOutLayersId : nullptr,
                        aOutHitScrollbarNode);
   if (aOutTouchBehaviors) {
     aOutTouchBehaviors->AppendElement(ConvertToTouchBehavior(hitResult));
   }
   for (size_t i = 1; i < aEvent.mTouches.Length(); i++) {
     RefPtr<AsyncPanZoomController> apzc2 =
-        GetTargetAPZC(aEvent.mTouches[i].mScreenPoint, &hitResult);
+        GetTargetAPZC(aEvent.mTouches[i].mScreenPoint, &hitResult, nullptr);
     if (aOutTouchBehaviors) {
       aOutTouchBehaviors->AppendElement(ConvertToTouchBehavior(hitResult));
     }
     apzc = GetMultitouchTarget(apzc, apzc2);
     APZCTM_LOG("Using APZC %p as the root APZC for multi-touch\n", apzc.get());
     // A multi-touch gesture will not be a scrollbar drag, even if the
     // first touch point happened to hit a scrollbar.
     aOutHitScrollbarNode->Clear();
@@ -1647,17 +1652,18 @@ nsEventStatus APZCTreeManager::ProcessTo
       if (mRetainedTouchIdentifier == -1) {
         mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
       }
       return nsEventStatus_eConsumeNoDefault;
     }
 
     mHitResultForInputBlock = CompositorHitTestInvisibleToHit;
     mApzcForInputBlock = GetTouchInputBlockAPZC(
-        aInput, &touchBehaviors, &mHitResultForInputBlock, &hitScrollbarNode);
+        aInput, &touchBehaviors, &mHitResultForInputBlock, &aInput.mLayersId,
+        &hitScrollbarNode);
 
     // Check if this event starts a scrollbar touch-drag. The conditions
     // checked are similar to the ones we check for MOUSE_INPUT starting
     // a scrollbar mouse-drag.
     mInScrollbarTouchDrag =
         gfxPrefs::APZDragEnabled() && gfxPrefs::APZTouchDragEnabled() &&
         hitScrollbarNode && hitScrollbarNode->IsScrollThumbNode() &&
         hitScrollbarNode->GetScrollbarData().mThumbIsAsyncDraggable;
@@ -1985,27 +1991,28 @@ void APZCTreeManager::UpdateWheelTransac
       return;
     default:
       break;
   }
 }
 
 void APZCTreeManager::ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
                                             ScrollableLayerGuid* aOutTargetGuid,
-                                            uint64_t* aOutFocusSequenceNumber) {
+                                            uint64_t* aOutFocusSequenceNumber,
+                                            LayersId* aOutLayersId) {
   APZThreadUtils::AssertOnControllerThread();
 
   // Transform the aRefPoint.
   // If the event hits an overscrolled APZC, instruct the caller to ignore it.
   CompositorHitTestInfo hitResult = CompositorHitTestInvisibleToHit;
   PixelCastJustification LDIsScreen =
       PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent;
   ScreenIntPoint refPointAsScreen = ViewAs<ScreenPixel>(*aRefPoint, LDIsScreen);
   RefPtr<AsyncPanZoomController> apzc =
-      GetTargetAPZC(refPointAsScreen, &hitResult);
+      GetTargetAPZC(refPointAsScreen, &hitResult, aOutLayersId);
   if (apzc) {
     MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
     apzc->GetGuid(aOutTargetGuid);
     ScreenToParentLayerMatrix4x4 transformToApzc =
         GetScreenToApzcTransform(apzc);
     ParentLayerToScreenMatrix4x4 transformToGecko =
         GetApzcToGeckoTransform(apzc);
     ScreenToScreenMatrix4x4 outTransform = transformToApzc * transformToGecko;
@@ -2403,17 +2410,18 @@ ParentLayerPoint APZCTreeManager::Dispat
     currentVelocity = residualVelocity;
   }
 
   // Return any residual velocity left over after the entire handoff process.
   return finalResidualVelocity;
 }
 
 bool APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint) {
-  RefPtr<AsyncPanZoomController> target = GetTargetAPZC(aPoint, nullptr);
+  RefPtr<AsyncPanZoomController> target =
+      GetTargetAPZC(aPoint, nullptr, nullptr);
   return target != nullptr;
 }
 
 already_AddRefed<AsyncPanZoomController> APZCTreeManager::GetTargetAPZC(
     const ScrollableLayerGuid& aGuid) {
   RecursiveMutexAutoLock lock(mTreeLock);
   RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
   MOZ_ASSERT(!node || node->GetApzc());  // any node returned must have an APZC
@@ -2452,41 +2460,41 @@ already_AddRefed<HitTestingTreeNode> APZ
             }
             return matches;
           });
   return target.forget();
 }
 
 already_AddRefed<AsyncPanZoomController> APZCTreeManager::GetTargetAPZC(
     const ScreenPoint& aPoint, CompositorHitTestInfo* aOutHitResult,
-    HitTestingTreeNodeAutoLock* aOutScrollbarNode) {
+    LayersId* aOutLayersId, HitTestingTreeNodeAutoLock* aOutScrollbarNode) {
   RecursiveMutexAutoLock lock(mTreeLock);
 
   CompositorHitTestInfo hitResult;
   HitTestingTreeNode* scrollbarNode = nullptr;
   RefPtr<AsyncPanZoomController> target;
   if (gfx::gfxVars::UseWebRender()) {
-    target = GetAPZCAtPointWR(aPoint, &hitResult, &scrollbarNode);
+    target = GetAPZCAtPointWR(aPoint, &hitResult, aOutLayersId, &scrollbarNode);
   } else {
     target = GetAPZCAtPoint(mRootNode, aPoint, &hitResult, &scrollbarNode);
   }
 
   if (aOutHitResult) {
     *aOutHitResult = hitResult;
   }
   if (aOutScrollbarNode && scrollbarNode) {
     RefPtr<HitTestingTreeNode> scrollbarRef = scrollbarNode;
     aOutScrollbarNode->Initialize(lock, scrollbarRef.forget(), mTreeLock);
   }
   return target.forget();
 }
 
 already_AddRefed<AsyncPanZoomController> APZCTreeManager::GetAPZCAtPointWR(
     const ScreenPoint& aHitTestPoint, CompositorHitTestInfo* aOutHitResult,
-    HitTestingTreeNode** aOutScrollbarNode) {
+    LayersId* aOutLayersId, HitTestingTreeNode** aOutScrollbarNode) {
   MOZ_ASSERT(aOutHitResult);
   MOZ_ASSERT(aOutScrollbarNode);
 
   RefPtr<AsyncPanZoomController> result;
   RefPtr<wr::WebRenderAPI> wr = GetWebRenderAPI();
   if (!wr) {
     // If WebRender isn't running, fall back to the root APZC.
     // This is mostly for the benefit of GTests which do not
@@ -2503,16 +2511,19 @@ already_AddRefed<AsyncPanZoomController>
   gfx::CompositorHitTestInfo hitInfo;
   bool hitSomething = wr->HitTest(wr::ToWorldPoint(aHitTestPoint), pipelineId,
                                   scrollId, hitInfo);
   if (!hitSomething) {
     return result.forget();
   }
 
   LayersId layersId = wr::AsLayersId(pipelineId);
+  if (aOutLayersId) {
+    *aOutLayersId = layersId;
+  }
   result = GetTargetAPZC(layersId, scrollId);
   if (!result) {
     // It falls back to the root
     MOZ_ASSERT(scrollId == ScrollableLayerGuid::NULL_SCROLL_ID);
     result = FindRootApzcForLayersId(layersId);
     MOZ_ASSERT(result);
   }
 
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -487,17 +487,18 @@ class APZCTreeManager : public IAPZCTree
 
   APZInputBridge* InputBridge() override { return this; }
 
   // Methods to help process WidgetInputEvents (or manage conversion to/from
   // InputData)
 
   void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
                              ScrollableLayerGuid* aOutTargetGuid,
-                             uint64_t* aOutFocusSequenceNumber) override;
+                             uint64_t* aOutFocusSequenceNumber,
+                             LayersId* aOutLayersId) override;
 
   void UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
                               EventMessage aEventMessage) override;
 
   bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData);
 
   /**
    * Compute the updated shadow transform for a scroll thumb layer that
@@ -573,16 +574,17 @@ class APZCTreeManager : public IAPZCTree
      functions lock the tree of APZCs while they find the right one, and then
      return an addref'd pointer to it. This allows caller code to just use the
      target APZC without worrying about it going away. These are public for
      testing code and generally should not be used by other production code.
   */
   RefPtr<HitTestingTreeNode> GetRootNode() const;
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
       const ScreenPoint& aPoint, gfx::CompositorHitTestInfo* aOutHitResult,
+      LayersId* aOutLayersId,
       HitTestingTreeNodeAutoLock* aOutScrollbarNode = nullptr);
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
       const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId);
   ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform(
       const AsyncPanZoomController* aApzc) const;
   ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform(
       const AsyncPanZoomController* aApzc) const;
   ScreenPoint GetCurrentMousePosition() const;
@@ -622,17 +624,17 @@ class APZCTreeManager : public IAPZCTree
                                      GuidComparator aComparator);
   AsyncPanZoomController* GetTargetApzcForNode(HitTestingTreeNode* aNode);
   AsyncPanZoomController* GetAPZCAtPoint(
       HitTestingTreeNode* aNode, const ScreenPoint& aHitTestPoint,
       gfx::CompositorHitTestInfo* aOutHitResult,
       HitTestingTreeNode** aOutScrollbarNode);
   already_AddRefed<AsyncPanZoomController> GetAPZCAtPointWR(
       const ScreenPoint& aHitTestPoint,
-      gfx::CompositorHitTestInfo* aOutHitResult,
+      gfx::CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
       HitTestingTreeNode** aOutScrollbarNode);
   AsyncPanZoomController* FindRootApzcForLayersId(LayersId aLayersId) const;
   AsyncPanZoomController* FindRootContentApzcForLayersId(
       LayersId aLayersId) const;
   AsyncPanZoomController* FindRootContentOrRootApzc() const;
   already_AddRefed<AsyncPanZoomController> GetMultitouchTarget(
       AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
   already_AddRefed<AsyncPanZoomController> CommonAncestor(
@@ -653,17 +655,17 @@ class APZCTreeManager : public IAPZCTree
    *     potentially start a scrollbar drag), and a scrollbar node was hit,
    *     that scrollbar node, otherwise nullptr.
    *
    * @return The APZC that was hit.
    */
   already_AddRefed<AsyncPanZoomController> GetTouchInputBlockAPZC(
       const MultiTouchInput& aEvent,
       nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
-      gfx::CompositorHitTestInfo* aOutHitResult,
+      gfx::CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
       HitTestingTreeNodeAutoLock* aOutHitScrollbarNode);
   nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
                                   ScrollableLayerGuid* aOutTargetGuid,
                                   uint64_t* aOutInputBlockId);
   /**
    * Given a mouse-down event that hit a scroll thumb node, set up APZ
    * dragging of the scroll thumb.
    *
--- a/gfx/layers/apz/src/APZInputBridge.cpp
+++ b/gfx/layers/apz/src/APZInputBridge.cpp
@@ -74,21 +74,22 @@ nsEventStatus APZInputBridge::ReceiveInp
 
         nsEventStatus status =
             ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
 
         mouseEvent.mRefPoint.x = input.mOrigin.x;
         mouseEvent.mRefPoint.y = input.mOrigin.y;
         mouseEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
         mouseEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
+        aEvent.mLayersId = input.mLayersId;
         return status;
       }
 
       ProcessUnhandledEvent(&mouseEvent.mRefPoint, aOutTargetGuid,
-                            &aEvent.mFocusSequenceNumber);
+                            &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
       return nsEventStatus_eIgnore;
     }
     case eTouchEventClass: {
       WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
       MultiTouchInput touchInput(touchEvent);
       nsEventStatus result =
           ReceiveInputEvent(touchInput, aOutTargetGuid, aOutInputBlockId);
       // touchInput was modified in-place to possibly remove some
@@ -98,16 +99,17 @@ nsEventStatus APZInputBridge::ReceiveInp
       touchEvent.mTouches.Clear();
       touchEvent.mTouches.SetCapacity(touchInput.mTouches.Length());
       for (size_t i = 0; i < touchInput.mTouches.Length(); i++) {
         *touchEvent.mTouches.AppendElement() =
             touchInput.mTouches[i].ToNewDOMTouch();
       }
       touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ;
       touchEvent.mFocusSequenceNumber = touchInput.mFocusSequenceNumber;
+      aEvent.mLayersId = touchInput.mLayersId;
       return result;
     }
     case eWheelEventClass: {
       WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent();
 
       if (Maybe<APZWheelAction> action = ActionForWheelEvent(&wheelEvent)) {
         ScrollWheelInput::ScrollMode scrollMode =
             ScrollWheelInput::SCROLLMODE_INSTANT;
@@ -156,23 +158,25 @@ nsEventStatus APZInputBridge::ReceiveInp
               &input.mUserDeltaMultiplierY);
 
           nsEventStatus status =
               ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
           wheelEvent.mRefPoint.x = input.mOrigin.x;
           wheelEvent.mRefPoint.y = input.mOrigin.y;
           wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
           wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
+          aEvent.mLayersId = input.mLayersId;
+
           return status;
         }
       }
 
       UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
       ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid,
-                            &aEvent.mFocusSequenceNumber);
+                            &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
       return nsEventStatus_eIgnore;
     }
     case eKeyboardEventClass: {
       WidgetKeyboardEvent& keyboardEvent = *aEvent.AsKeyboardEvent();
 
       KeyboardInput input(keyboardEvent);
 
       nsEventStatus status =
@@ -180,17 +184,17 @@ nsEventStatus APZInputBridge::ReceiveInp
 
       keyboardEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
       keyboardEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
       return status;
     }
     default: {
       UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
       ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid,
-                            &aEvent.mFocusSequenceNumber);
+                            &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
       return nsEventStatus_eIgnore;
     }
   }
 
   MOZ_ASSERT_UNREACHABLE("Invalid WidgetInputEvent type.");
   return nsEventStatus_eConsumeNoDefault;
 }
 
--- a/gfx/layers/apz/test/gtest/TestEventRegions.cpp
+++ b/gfx/layers/apz/test/gtest/TestEventRegions.cpp
@@ -269,27 +269,27 @@ TEST_F(APZEventRegionsTester, Obscuratio
 
   RefPtr<TestAsyncPanZoomController> parent = ApzcOf(layers[1]);
   TestAsyncPanZoomController* child = ApzcOf(layers[2]);
 
   Pan(parent, 75, 25, PanOptions::NoFling);
 
   gfx::CompositorHitTestInfo result;
   RefPtr<AsyncPanZoomController> hit =
-      manager->GetTargetAPZC(ScreenPoint(50, 75), &result);
+      manager->GetTargetAPZC(ScreenPoint(50, 75), &result, nullptr);
   EXPECT_EQ(child, hit.get());
   EXPECT_EQ(result, CompositorHitTestFlags::eVisibleToHitTest);
 }
 
 TEST_F(APZEventRegionsTester, Bug1119497) {
   CreateBug1119497LayerTree();
 
   gfx::CompositorHitTestInfo result;
   RefPtr<AsyncPanZoomController> hit =
-      manager->GetTargetAPZC(ScreenPoint(50, 50), &result);
+      manager->GetTargetAPZC(ScreenPoint(50, 50), &result, nullptr);
   // We should hit layers[2], so |result| will be eVisibleToHitTest but there's
   // no actual APZC on layers[2], so it will be the APZC of the root layer.
   EXPECT_EQ(ApzcOf(layers[0]), hit.get());
   EXPECT_EQ(result, CompositorHitTestFlags::eVisibleToHitTest);
 }
 
 TEST_F(APZEventRegionsTester, Bug1117712) {
   CreateBug1117712LayerTree();
--- a/gfx/layers/apz/test/gtest/TestHitTesting.cpp
+++ b/gfx/layers/apz/test/gtest/TestHitTesting.cpp
@@ -12,17 +12,17 @@
 class APZHitTestingTester : public APZCTreeManagerTester {
  protected:
   ScreenToParentLayerMatrix4x4 transformToApzc;
   ParentLayerToScreenMatrix4x4 transformToGecko;
 
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
       const ScreenPoint& aPoint) {
     RefPtr<AsyncPanZoomController> hit =
-        manager->GetTargetAPZC(aPoint, nullptr);
+        manager->GetTargetAPZC(aPoint, nullptr, nullptr);
     if (hit) {
       transformToApzc = manager->GetScreenToApzcTransform(hit.get());
       transformToGecko = manager->GetApzcToGeckoTransform(hit.get());
     }
     return hit.forget();
   }
 
  protected:
--- a/gfx/layers/ipc/APZInputBridgeChild.cpp
+++ b/gfx/layers/ipc/APZInputBridgeChild.cpp
@@ -119,19 +119,19 @@ nsEventStatus APZInputBridgeChild::Recei
       MOZ_ASSERT_UNREACHABLE("Invalid InputData type.");
       return nsEventStatus_eConsumeNoDefault;
     }
   }
 }
 
 void APZInputBridgeChild::ProcessUnhandledEvent(
     LayoutDeviceIntPoint* aRefPoint, ScrollableLayerGuid* aOutTargetGuid,
-    uint64_t* aOutFocusSequenceNumber) {
+    uint64_t* aOutFocusSequenceNumber, LayersId* aOutLayersId) {
   SendProcessUnhandledEvent(*aRefPoint, aRefPoint, aOutTargetGuid,
-                            aOutFocusSequenceNumber);
+                            aOutFocusSequenceNumber, aOutLayersId);
 }
 
 void APZInputBridgeChild::UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
                                                  EventMessage aEventMessage) {
   SendUpdateWheelTransaction(aRefPoint, aEventMessage);
 }
 
 }  // namespace layers
--- a/gfx/layers/ipc/APZInputBridgeChild.h
+++ b/gfx/layers/ipc/APZInputBridgeChild.h
@@ -22,17 +22,18 @@ class APZInputBridgeChild : public PAPZI
 
   nsEventStatus ReceiveInputEvent(InputData& aEvent,
                                   ScrollableLayerGuid* aOutTargetGuid,
                                   uint64_t* aOutInputBlockId) override;
 
  protected:
   void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
                              ScrollableLayerGuid* aOutTargetGuid,
-                             uint64_t* aOutFocusSequenceNumber) override;
+                             uint64_t* aOutFocusSequenceNumber,
+                             LayersId* aOutLayersId) override;
 
   void UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
                               EventMessage aEventMessage) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual ~APZInputBridgeChild();
 
  private:
--- a/gfx/layers/ipc/APZInputBridgeParent.cpp
+++ b/gfx/layers/ipc/APZInputBridgeParent.cpp
@@ -116,20 +116,21 @@ mozilla::ipc::IPCResult APZInputBridgePa
 mozilla::ipc::IPCResult APZInputBridgeParent::RecvUpdateWheelTransaction(
     const LayoutDeviceIntPoint& aRefPoint, const EventMessage& aEventMessage) {
   mTreeManager->InputBridge()->UpdateWheelTransaction(aRefPoint, aEventMessage);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult APZInputBridgeParent::RecvProcessUnhandledEvent(
     const LayoutDeviceIntPoint& aRefPoint, LayoutDeviceIntPoint* aOutRefPoint,
-    ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutFocusSequenceNumber) {
+    ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutFocusSequenceNumber,
+    LayersId* aOutLayersId) {
   LayoutDeviceIntPoint refPoint = aRefPoint;
-  mTreeManager->InputBridge()->ProcessUnhandledEvent(&refPoint, aOutTargetGuid,
-                                                     aOutFocusSequenceNumber);
+  mTreeManager->InputBridge()->ProcessUnhandledEvent(
+      &refPoint, aOutTargetGuid, aOutFocusSequenceNumber, aOutLayersId);
   *aOutRefPoint = refPoint;
 
   return IPC_OK();
 }
 
 void APZInputBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
   // We shouldn't need it after this
   mTreeManager = nullptr;
--- a/gfx/layers/ipc/APZInputBridgeParent.h
+++ b/gfx/layers/ipc/APZInputBridgeParent.h
@@ -55,17 +55,18 @@ class APZInputBridgeParent : public PAPZ
       KeyboardInput* aOutEvent, ScrollableLayerGuid* aOutTargetGuid,
       uint64_t* aOutInputBlockId);
 
   mozilla::ipc::IPCResult RecvUpdateWheelTransaction(
       const LayoutDeviceIntPoint& aRefPoint, const EventMessage& aEventMessage);
 
   mozilla::ipc::IPCResult RecvProcessUnhandledEvent(
       const LayoutDeviceIntPoint& aRefPoint, LayoutDeviceIntPoint* aOutRefPoint,
-      ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutFocusSequenceNumber);
+      ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutFocusSequenceNumber,
+      LayersId* aOutLayersId);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
  protected:
   virtual ~APZInputBridgeParent();
 
  private:
   RefPtr<IAPZCTreeManager> mTreeManager;
--- a/gfx/layers/ipc/PAPZInputBridge.ipdl
+++ b/gfx/layers/ipc/PAPZInputBridge.ipdl
@@ -11,16 +11,18 @@ using EventMessage from "mozilla/EventFo
 using class mozilla::MultiTouchInput from "InputData.h";
 using class mozilla::MouseInput from "InputData.h";
 using class mozilla::PanGestureInput from "InputData.h";
 using class mozilla::PinchGestureInput from "InputData.h";
 using class mozilla::TapGestureInput from "InputData.h";
 using class mozilla::ScrollWheelInput from "InputData.h";
 using class mozilla::KeyboardInput from "InputData.h";
 
+using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
+
 include protocol PGPU;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * This protocol is used to send input events from the UI process to the
  * GPU process for handling by APZ. There is one instance per top-level
@@ -79,15 +81,16 @@ parent:
              ScrollableLayerGuid aOutTargetGuid,
              uint64_t            aOutInputBlockId);
 
   async UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage);
 
   sync ProcessUnhandledEvent(LayoutDeviceIntPoint aRefPoint)
     returns (LayoutDeviceIntPoint   aOutRefPoint,
              ScrollableLayerGuid    aOutTargetGuid,
-             uint64_t               aOutFocusSequenceNumber);
+             uint64_t               aOutFocusSequenceNumber,
+             LayersId               aOutLayersId);
 
   async __delete__();
 };
 
 } // namespace gfx
 } // namespace mozilla