Bug 1281575 - Create IPDL protocol implementation of IAPZCTreeManager. r=kats
☠☠ backed out by b73eac8de814 ☠ ☠
authorRyan Hunt <rhunt@mozilla.com>
Wed, 20 Jul 2016 13:37:00 +0200
changeset 331059 b95ebdb96050ecd6f713f7052e28a6d705938020
parent 331058 3119db384fccddf90d5926a2e11296d9b280ae4a
child 331060 e543221ad4eeea0df25192d740a587211105f511
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1281575
milestone50.0a1
Bug 1281575 - Create IPDL protocol implementation of IAPZCTreeManager. r=kats
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/GestureEventListener.cpp
gfx/layers/ipc/APZCTreeManagerChild.cpp
gfx/layers/ipc/APZCTreeManagerChild.h
gfx/layers/ipc/APZCTreeManagerParent.cpp
gfx/layers/ipc/APZCTreeManagerParent.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/PAPZCTreeManager.ipdl
gfx/layers/moz.build
widget/InputData.h
widget/nsGUIEventIPC.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -860,16 +860,19 @@ APZCTreeManager::ReceiveInputEvent(Input
             /* aTargetConfirmed = */ hitResult != HitDispatchToContentRegion,
             tapInput, aOutInputBlockId);
 
         // Update the out-parameters so they are what the caller expects.
         apzc->GetGuid(aOutTargetGuid);
         tapInput.mPoint = *untransformedPoint;
       }
       break;
+    } case SENTINEL_INPUT: {
+      MOZ_ASSERT_UNREACHABLE("Invalid InputType.");
+      break;
     }
   }
   return result;
 }
 
 static TouchBehaviorFlags
 ConvertToTouchBehavior(HitTestResult result)
 {
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -22,16 +22,17 @@
 
 namespace mozilla {
 class MultiTouchInput;
 
 namespace layers {
 
 class Layer;
 class AsyncPanZoomController;
+class APZCTreeManagerParent;
 class CompositorBridgeParent;
 class OverscrollHandoffChain;
 struct OverscrollHandoffState;
 struct FlingHandoffState;
 class LayerMetricsWrapper;
 class InputQueue;
 class GeckoContentController;
 class HitTestingTreeNode;
@@ -376,28 +377,30 @@ public:
   /**
    * Function used to disable LongTap gestures.
    *
    * On slow running tests, drags and touch events can be misinterpreted
    * as a long tap. This allows tests to disable long tap gesture detection.
    */
   void SetLongTapEnabled(bool aTapGestureEnabled) override;
 
+  // Methods to help process WidgetInputEvents (or manage conversion to/from InputData)
+
+  void TransformEventRefPoint(
+      LayoutDeviceIntPoint* aRefPoint,
+      ScrollableLayerGuid* aOutTargetGuid) override;
+
+  void UpdateWheelTransaction(
+      LayoutDeviceIntPoint aRefPoint,
+      EventMessage aEventMessage) override;
+
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~APZCTreeManager();
 
-  // Methods to help process WidgetInputEvents (or manage conversion to/from InputData)
-  void TransformEventRefPoint(
-      LayoutDeviceIntPoint* aRefPoint,
-      ScrollableLayerGuid* aOutTargetGuid) override;
-  void UpdateWheelTransaction(
-      LayoutDeviceIntPoint aRefPoint,
-      EventMessage aEventMessage) override;
-
   // Protected hooks for gtests subclass
   virtual AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
                                                   GeckoContentController* aController);
 public:
   // Public hooks for gtests subclass
   virtual TimeStamp GetFrameTime();
 
 public:
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -998,35 +998,35 @@ nsEventStatus AsyncPanZoomController::Ha
     }
 
     // TODO Need to implement blocks to properly handle this.
     //rv = HandleDragEvent(mouseInput, dragMetrics);
     break;
   }
   case SCROLLWHEEL_INPUT: {
     ScrollWheelInput scrollInput = aEvent.AsScrollWheelInput();
-    if (!scrollInput.TransformToLocal(aTransformToApzc)) { 
+    if (!scrollInput.TransformToLocal(aTransformToApzc)) {
       return rv;
     }
 
     rv = OnScrollWheel(scrollInput);
     break;
   }
   case PINCHGESTURE_INPUT: {
     PinchGestureInput pinchInput = aEvent.AsPinchGestureInput();
-    if (!pinchInput.TransformToLocal(aTransformToApzc)) { 
+    if (!pinchInput.TransformToLocal(aTransformToApzc)) {
       return rv;
     }
 
     rv = HandleGestureEvent(pinchInput);
     break;
   }
   case TAPGESTURE_INPUT: {
     TapGestureInput tapInput = aEvent.AsTapGestureInput();
-    if (!tapInput.TransformToLocal(aTransformToApzc)) { 
+    if (!tapInput.TransformToLocal(aTransformToApzc)) {
       return rv;
     }
 
     rv = HandleGestureEvent(tapInput);
     break;
   }
   default: NS_WARNING("Unhandled input event type"); break;
   }
@@ -1465,17 +1465,17 @@ nsEventStatus AsyncPanZoomController::On
 
 bool
 AsyncPanZoomController::ConvertToGecko(const ScreenIntPoint& aPoint, CSSPoint* aOut)
 {
   if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
     ScreenToScreenMatrix4x4 transformScreenToGecko =
         treeManagerLocal->GetScreenToApzcTransform(this)
       * treeManagerLocal->GetApzcToGeckoTransform(this);
-    
+
     Maybe<ScreenIntPoint> layoutPoint = UntransformBy(
         transformScreenToGecko, aPoint);
     if (!layoutPoint) {
       return false;
     }
 
     { // scoped lock to access mFrameMetrics
       ReentrantMonitorAutoEnter lock(mMonitor);
@@ -1771,16 +1771,21 @@ nsEventStatus AsyncPanZoomController::On
       // appunits/second
       nsPoint velocity =
         CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
 
       WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
       animation->Update(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
       break;
     }
+
+    case ScrollWheelInput::SCROLLMODE_SENTINEL: {
+      MOZ_ASSERT_UNREACHABLE("Invalid ScrollMode.");
+      break;
+    }
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 void
 AsyncPanZoomController::NotifyMozMouseScrollEvent(const nsString& aString) const
 {
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -121,16 +121,19 @@ nsEventStatus GestureEventListener::Hand
     }
 
     rv = HandleInputTouchEnd();
     break;
   case MultiTouchInput::MULTITOUCH_CANCEL:
     mTouches.Clear();
     rv = HandleInputTouchCancel();
     break;
+  case MultiTouchInput::MULTITOUCH_SENTINEL:
+    MOZ_ASSERT_UNREACHABLE("Invalid MultTouchInput.");
+    break;
   }
 
   return rv;
 }
 
 int32_t GestureEventListener::GetLastTouchIdentifier() const
 {
   if (mTouches.Length() != 1) {
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/APZCTreeManagerChild.cpp
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/APZCTreeManagerChild.h"
+
+#include "InputData.h"                  // for InputData
+
+namespace mozilla {
+namespace layers {
+
+nsEventStatus
+APZCTreeManagerChild::ReceiveInputEvent(
+    InputData& aEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  switch (aEvent.mInputType) {
+  case MULTITOUCH_INPUT: {
+    MultiTouchInput& event = aEvent.AsMultiTouchInput();
+    MultiTouchInput processedEvent;
+
+    nsEventStatus res;
+    SendReceiveMultiTouchInputEvent(event,
+                                    &res,
+                                    &processedEvent,
+                                    aOutTargetGuid,
+                                    aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  case MOUSE_INPUT: {
+    MouseInput& event = aEvent.AsMouseInput();
+    MouseInput processedEvent;
+
+    nsEventStatus res;
+    SendReceiveMouseInputEvent(event,
+                               &res,
+                               &processedEvent,
+                               aOutTargetGuid,
+                               aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  case PANGESTURE_INPUT: {
+    PanGestureInput& event = aEvent.AsPanGestureInput();
+    PanGestureInput processedEvent;
+
+    nsEventStatus res;
+    SendReceivePanGestureInputEvent(event,
+                                    &res,
+                                    &processedEvent,
+                                    aOutTargetGuid,
+                                    aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  case PINCHGESTURE_INPUT: {
+    PinchGestureInput& event = aEvent.AsPinchGestureInput();
+    PinchGestureInput processedEvent;
+
+    nsEventStatus res;
+    SendReceivePinchGestureInputEvent(event,
+                                      &res,
+                                      &processedEvent,
+                                      aOutTargetGuid,
+                                      aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  case TAPGESTURE_INPUT: {
+    TapGestureInput& event = aEvent.AsTapGestureInput();
+    TapGestureInput processedEvent;
+
+    nsEventStatus res;
+    SendReceiveTapGestureInputEvent(event,
+                                    &res,
+                                    &processedEvent,
+                                    aOutTargetGuid,
+                                    aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  case SCROLLWHEEL_INPUT: {
+    ScrollWheelInput& event = aEvent.AsScrollWheelInput();
+    ScrollWheelInput processedEvent;
+
+    nsEventStatus res;
+    SendReceiveScrollWheelInputEvent(event,
+                                     &res,
+                                     &processedEvent,
+                                     aOutTargetGuid,
+                                     aOutInputBlockId);
+
+    event = processedEvent;
+    return res;
+  }
+  default: {
+    MOZ_ASSERT_UNREACHABLE("Invalid InputData type.");
+    return nsEventStatus_eConsumeNoDefault;
+  }
+  }
+}
+
+void
+APZCTreeManagerChild::ZoomToRect(
+    const ScrollableLayerGuid& aGuid,
+    const CSSRect& aRect,
+    const uint32_t aFlags)
+{
+  SendZoomToRect(aGuid, aRect, aFlags);
+}
+
+void
+APZCTreeManagerChild::ContentReceivedInputBlock(
+    uint64_t aInputBlockId,
+    bool aPreventDefault)
+{
+  SendContentReceivedInputBlock(aInputBlockId, aPreventDefault);
+}
+
+void
+APZCTreeManagerChild::SetTargetAPZC(
+    uint64_t aInputBlockId,
+    const nsTArray<ScrollableLayerGuid>& aTargets)
+{
+  SendSetTargetAPZC(aInputBlockId, aTargets);
+}
+
+void
+APZCTreeManagerChild::UpdateZoomConstraints(
+    const ScrollableLayerGuid& aGuid,
+    const Maybe<ZoomConstraints>& aConstraints)
+{
+  SendUpdateZoomConstraints(aGuid, aConstraints);
+}
+
+void
+APZCTreeManagerChild::CancelAnimation(const ScrollableLayerGuid &aGuid)
+{
+  SendCancelAnimation(aGuid);
+}
+
+void
+APZCTreeManagerChild::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
+{
+  SendAdjustScrollForSurfaceShift(aShift);
+}
+
+void
+APZCTreeManagerChild::SetDPI(float aDpiValue)
+{
+  SendSetDPI(aDpiValue);
+}
+
+void
+APZCTreeManagerChild::SetAllowedTouchBehavior(
+    uint64_t aInputBlockId,
+    const nsTArray<TouchBehaviorFlags>& aValues)
+{
+  SendSetAllowedTouchBehavior(aInputBlockId, aValues);
+}
+
+void
+APZCTreeManagerChild::StartScrollbarDrag(
+    const ScrollableLayerGuid& aGuid,
+    const AsyncDragMetrics& aDragMetrics)
+{
+  SendStartScrollbarDrag(aGuid, aDragMetrics);
+}
+
+void
+APZCTreeManagerChild::SetLongTapEnabled(bool aTapGestureEnabled)
+{
+  SendSetLongTapEnabled(aTapGestureEnabled);
+}
+
+void
+APZCTreeManagerChild::ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY)
+{
+  SendProcessTouchVelocity(aTimestampMs, aSpeedY);
+}
+
+void
+APZCTreeManagerChild::UpdateWheelTransaction(
+    LayoutDeviceIntPoint aRefPoint,
+    EventMessage aEventMessage)
+{
+  SendUpdateWheelTransaction(aRefPoint, aEventMessage);
+}
+
+void APZCTreeManagerChild::TransformEventRefPoint(
+    LayoutDeviceIntPoint* aRefPoint,
+    ScrollableLayerGuid* aOutTargetGuid)
+{
+  SendTransformEventRefPoint(*aRefPoint, aRefPoint, aOutTargetGuid);
+}
+
+void
+APZCTreeManagerChild::OnProcessingError(
+        Result aCode,
+        const char* aReason)
+{
+  MOZ_RELEASE_ASSERT(aCode != MsgDropped);
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/APZCTreeManagerChild.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_APZCTreeManagerChild_h
+#define mozilla_layers_APZCTreeManagerChild_h
+
+#include "mozilla/layers/IAPZCTreeManager.h"
+#include "mozilla/layers/PAPZCTreeManagerChild.h"
+
+namespace mozilla {
+namespace layers {
+
+
+class APZCTreeManagerChild
+  : public IAPZCTreeManager
+  , public PAPZCTreeManagerChild
+{
+public:
+  APZCTreeManagerChild() { }
+
+  nsEventStatus
+  ReceiveInputEvent(
+          InputData& aEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  void
+  ZoomToRect(
+          const ScrollableLayerGuid& aGuid,
+          const CSSRect& aRect,
+          const uint32_t aFlags = DEFAULT_BEHAVIOR) override;
+
+  void
+  ContentReceivedInputBlock(
+          uint64_t aInputBlockId,
+          bool aPreventDefault) override;
+
+  void
+  SetTargetAPZC(
+          uint64_t aInputBlockId,
+          const nsTArray<ScrollableLayerGuid>& aTargets) override;
+
+  void
+  UpdateZoomConstraints(
+          const ScrollableLayerGuid& aGuid,
+          const Maybe<ZoomConstraints>& aConstraints) override;
+
+  void
+  CancelAnimation(const ScrollableLayerGuid &aGuid) override;
+
+  void
+  AdjustScrollForSurfaceShift(const ScreenPoint& aShift) override;
+
+  void
+  SetDPI(float aDpiValue) override;
+
+  void
+  SetAllowedTouchBehavior(
+          uint64_t aInputBlockId,
+          const nsTArray<TouchBehaviorFlags>& aValues) override;
+
+  void
+  StartScrollbarDrag(
+          const ScrollableLayerGuid& aGuid,
+          const AsyncDragMetrics& aDragMetrics) override;
+
+  void
+  SetLongTapEnabled(bool aTapGestureEnabled) override;
+
+  void
+  ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY) override;
+
+  void
+  TransformEventRefPoint(
+          LayoutDeviceIntPoint* aRefPoint,
+          ScrollableLayerGuid* aOutTargetGuid) override;
+
+  void
+  UpdateWheelTransaction(
+          LayoutDeviceIntPoint aRefPoint,
+          EventMessage aEventMessage) override;
+
+  void
+  OnProcessingError(
+          Result aCode,
+          const char* aReason) override;
+
+protected:
+
+  virtual
+  ~APZCTreeManagerChild() { }
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_APZCTreeManagerChild_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/APZCTreeManagerParent.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/APZCTreeManagerParent.h"
+
+#include "mozilla/layers/APZCTreeManager.h"
+#include "mozilla/layers/APZThreadUtils.h"
+
+namespace mozilla {
+namespace layers {
+
+APZCTreeManagerParent::APZCTreeManagerParent(RefPtr<APZCTreeManager> aAPZCTreeManager)
+  : mTreeManager(aAPZCTreeManager)
+{
+  MOZ_ASSERT(aAPZCTreeManager != nullptr);
+}
+
+bool
+APZCTreeManagerParent::RecvReceiveMultiTouchInputEvent(
+    const MultiTouchInput& aEvent,
+    nsEventStatus* aOutStatus,
+    MultiTouchInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  MultiTouchInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvReceiveMouseInputEvent(
+    const MouseInput& aEvent,
+    nsEventStatus* aOutStatus,
+    MouseInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  MouseInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvReceivePanGestureInputEvent(
+    const PanGestureInput& aEvent,
+    nsEventStatus* aOutStatus,
+    PanGestureInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  PanGestureInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvReceivePinchGestureInputEvent(
+    const PinchGestureInput& aEvent,
+    nsEventStatus* aOutStatus,
+    PinchGestureInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  PinchGestureInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvReceiveTapGestureInputEvent(
+    const TapGestureInput& aEvent,
+    nsEventStatus* aOutStatus,
+    TapGestureInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  TapGestureInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvReceiveScrollWheelInputEvent(
+    const ScrollWheelInput& aEvent,
+    nsEventStatus* aOutStatus,
+    ScrollWheelInput* aOutEvent,
+    ScrollableLayerGuid* aOutTargetGuid,
+    uint64_t* aOutInputBlockId)
+{
+  ScrollWheelInput event = aEvent;
+
+  *aOutStatus = mTreeManager->ReceiveInputEvent(
+    event,
+    aOutTargetGuid,
+    aOutInputBlockId);
+  *aOutEvent = event;
+
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvZoomToRect(
+    const ScrollableLayerGuid& aGuid,
+    const CSSRect& aRect,
+    const uint32_t& aFlags)
+{
+  mTreeManager->ZoomToRect(aGuid, aRect, aFlags);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvContentReceivedInputBlock(
+    const uint64_t& aInputBlockId,
+    const bool& aPreventDefault)
+{
+  mTreeManager->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvSetTargetAPZC(
+    const uint64_t& aInputBlockId,
+    nsTArray<ScrollableLayerGuid>&& aTargets)
+{
+  mTreeManager->SetTargetAPZC(aInputBlockId, aTargets);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvUpdateZoomConstraints(
+    const ScrollableLayerGuid& aGuid,
+    const MaybeZoomConstraints& aConstraints)
+{
+  mTreeManager->UpdateZoomConstraints(aGuid, aConstraints);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvCancelAnimation(const ScrollableLayerGuid& aGuid)
+{
+  mTreeManager->CancelAnimation(aGuid);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvAdjustScrollForSurfaceShift(const ScreenPoint& aShift)
+{
+  mTreeManager->AdjustScrollForSurfaceShift(aShift);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvSetDPI(const float& aDpiValue)
+{
+  mTreeManager->SetDPI(aDpiValue);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvSetAllowedTouchBehavior(
+    const uint64_t& aInputBlockId,
+    nsTArray<TouchBehaviorFlags>&& aValues)
+{
+  mTreeManager->SetAllowedTouchBehavior(aInputBlockId, aValues);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvStartScrollbarDrag(
+    const ScrollableLayerGuid& aGuid,
+    const AsyncDragMetrics& aDragMetrics)
+{
+  mTreeManager->StartScrollbarDrag(aGuid, aDragMetrics);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvSetLongTapEnabled(const bool& aTapGestureEnabled)
+{
+  mTreeManager->SetLongTapEnabled(aTapGestureEnabled);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvProcessTouchVelocity(
+  const uint32_t& aTimestampMs,
+  const float& aSpeedY)
+{
+  mTreeManager->ProcessTouchVelocity(aTimestampMs, aSpeedY);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvUpdateWheelTransaction(
+        const LayoutDeviceIntPoint& aRefPoint,
+        const EventMessage& aEventMessage)
+{
+  mTreeManager->UpdateWheelTransaction(aRefPoint, aEventMessage);
+  return true;
+}
+
+bool
+APZCTreeManagerParent::RecvTransformEventRefPoint(
+        const LayoutDeviceIntPoint& aRefPoint,
+        LayoutDeviceIntPoint* aOutRefPoint,
+        ScrollableLayerGuid* aOutTargetGuid)
+{
+  LayoutDeviceIntPoint refPoint = aRefPoint;
+  mTreeManager->TransformEventRefPoint(&refPoint, aOutTargetGuid);
+  *aOutRefPoint = refPoint;
+
+  return true;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/APZCTreeManagerParent.h
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_APZCTreeManagerParent_h
+#define mozilla_layers_APZCTreeManagerParent_h
+
+#include "mozilla/layers/PAPZCTreeManagerParent.h"
+
+namespace mozilla {
+namespace layers {
+
+class APZCTreeManager;
+
+class APZCTreeManagerParent
+    : public PAPZCTreeManagerParent
+{
+public:
+
+  APZCTreeManagerParent(RefPtr<APZCTreeManager> aAPZCTreeManager);
+  virtual ~APZCTreeManagerParent() { }
+
+  bool
+  RecvReceiveMultiTouchInputEvent(
+          const MultiTouchInput& aEvent,
+          nsEventStatus* aOutStatus,
+          MultiTouchInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvReceiveMouseInputEvent(
+          const MouseInput& aEvent,
+          nsEventStatus* aOutStatus,
+          MouseInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvReceivePanGestureInputEvent(
+          const PanGestureInput& aEvent,
+          nsEventStatus* aOutStatus,
+          PanGestureInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvReceivePinchGestureInputEvent(
+          const PinchGestureInput& aEvent,
+          nsEventStatus* aOutStatus,
+          PinchGestureInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvReceiveTapGestureInputEvent(
+          const TapGestureInput& aEvent,
+          nsEventStatus* aOutStatus,
+          TapGestureInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvReceiveScrollWheelInputEvent(
+          const ScrollWheelInput& aEvent,
+          nsEventStatus* aOutStatus,
+          ScrollWheelInput* aOutEvent,
+          ScrollableLayerGuid* aOutTargetGuid,
+          uint64_t* aOutInputBlockId) override;
+
+  bool
+  RecvZoomToRect(
+          const ScrollableLayerGuid& aGuid,
+          const CSSRect& aRect,
+          const uint32_t& aFlags) override;
+
+  bool
+  RecvContentReceivedInputBlock(
+          const uint64_t& aInputBlockId,
+          const bool& aPreventDefault) override;
+
+  bool
+  RecvSetTargetAPZC(
+          const uint64_t& aInputBlockId,
+          nsTArray<ScrollableLayerGuid>&& aTargets) override;
+
+  bool
+  RecvUpdateZoomConstraints(
+          const ScrollableLayerGuid& aGuid,
+          const MaybeZoomConstraints& aConstraints) override;
+
+  bool
+  RecvCancelAnimation(const ScrollableLayerGuid& aGuid) override;
+
+  bool
+  RecvAdjustScrollForSurfaceShift(const ScreenPoint& aShift) override;
+
+  bool
+  RecvSetDPI(const float& aDpiValue) override;
+
+  bool
+  RecvSetAllowedTouchBehavior(
+          const uint64_t& aInputBlockId,
+          nsTArray<TouchBehaviorFlags>&& aValues) override;
+
+  bool
+  RecvStartScrollbarDrag(
+          const ScrollableLayerGuid& aGuid,
+          const AsyncDragMetrics& aDragMetrics) override;
+
+  bool
+  RecvSetLongTapEnabled(const bool& aTapGestureEnabled) override;
+
+  bool
+  RecvProcessTouchVelocity(
+          const uint32_t& aTimestampMs,
+          const float& aSpeedY) override;
+
+  bool
+  RecvUpdateWheelTransaction(
+          const LayoutDeviceIntPoint& aRefPoint,
+          const EventMessage& aEventMessage) override;
+
+  bool
+  RecvTransformEventRefPoint(
+          const LayoutDeviceIntPoint& aRefPoint,
+          LayoutDeviceIntPoint* aOutRefPoint,
+          ScrollableLayerGuid* aOutTargetGuid) override;
+
+  void
+  ActorDestroy(ActorDestroyReason aWhy) override { }
+
+private:
+  RefPtr<APZCTreeManager> mTreeManager;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_APZCTreeManagerParent_h
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include <stddef.h>                     // for size_t
 #include "ClientLayerManager.h"         // for ClientLayerManager
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/task.h"                  // for NewRunnableMethod, etc
+#include "gfxPrefs.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/PLayerTransactionChild.h"
 #include "mozilla/layers/TextureClient.h"// for TextureClient
 #include "mozilla/layers/TextureClientPool.h"// for TextureClientPool
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
@@ -34,16 +35,17 @@
 #include "mozilla/widget/CompositorWidget.h"
 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
 # include "mozilla/widget/CompositorWidgetChild.h"
 #endif
 
 using mozilla::layers::LayerTransactionChild;
 using mozilla::dom::TabChildBase;
 using mozilla::Unused;
+using mozilla::gfx::GPUProcessManager;
 
 namespace mozilla {
 namespace layers {
 
 static StaticRefPtr<CompositorBridgeChild> sCompositorBridge;
 
 Atomic<int32_t> CompositableForwarder::sSerialCounter(0);
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/PAPZCTreeManager.ipdl
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include "mozilla/GfxMessageUtils.h";
+include "ipc/nsGUIEventIPC.h";
+
+using CSSRect from "Units.h";
+using LayoutDeviceIntPoint from "Units.h";
+using ScreenPoint from "Units.h";
+using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
+using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
+using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
+using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
+
+using nsEventStatus from "mozilla/EventForwards.h";
+using EventMessage from "mozilla/EventForwards.h";
+using class mozilla::WidgetInputEvent from "mozilla/BasicEvents.h";
+using class mozilla::WidgetMouseEventBase from "mozilla/MouseEvents.h";
+using mozilla::WidgetMouseEvent::Reason from "mozilla/MouseEvents.h";
+using class mozilla::WidgetTouchEvent from "mozilla/TouchEvents.h";
+using class mozilla::WidgetWheelEvent from "mozilla/MouseEvents.h";
+using class mozilla::InputData from "InputData.h";
+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";
+
+namespace mozilla {
+namespace layers {
+
+sync protocol PAPZCTreeManager
+{
+parent:
+
+  sync ReceiveMultiTouchInputEvent(MultiTouchInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             MultiTouchInput     aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  sync ReceiveMouseInputEvent(MouseInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             MouseInput          aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  sync ReceivePanGestureInputEvent(PanGestureInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             PanGestureInput     aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  sync ReceivePinchGestureInputEvent(PinchGestureInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             PinchGestureInput   aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  sync ReceiveTapGestureInputEvent(TapGestureInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             TapGestureInput     aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  sync ReceiveScrollWheelInputEvent(ScrollWheelInput aEvent)
+    returns (nsEventStatus       aOutStatus,
+             ScrollWheelInput    aOutEvent,
+             ScrollableLayerGuid aOutTargetGuid,
+             uint64_t            aOutInputBlockId);
+
+  async ZoomToRect(ScrollableLayerGuid aGuid, CSSRect aRect, uint32_t Flags);
+
+  async ContentReceivedInputBlock(uint64_t aInputBlockId, bool PreventDefault);
+
+  async SetTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] Targets);
+
+  async UpdateZoomConstraints(ScrollableLayerGuid aGuid, MaybeZoomConstraints aConstraints);
+
+  async CancelAnimation(ScrollableLayerGuid aGuid);
+
+  async AdjustScrollForSurfaceShift(ScreenPoint aShift);
+
+  async SetDPI(float aDpiValue);
+
+  async SetAllowedTouchBehavior(uint64_t aInputBlockId, TouchBehaviorFlags[] aValues);
+
+  async StartScrollbarDrag(ScrollableLayerGuid aGuid, AsyncDragMetrics aDragMetrics);
+
+  async SetLongTapEnabled(bool aTapGestureEnabled);
+
+  async ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY);
+
+  async UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage);
+
+  sync TransformEventRefPoint(LayoutDeviceIntPoint aRefPoint)
+    returns (LayoutDeviceIntPoint   aOutRefPoint,
+             ScrollableLayerGuid    aOutTargetGuid);
+
+  async __delete__();
+};
+
+} // namespace gfx
+} // namespace mozilla
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -149,16 +149,18 @@ EXPORTS.mozilla.layers += [
     'composite/TiledContentHost.h',
     'Compositor.h',
     'CompositorTypes.h',
     'D3D11ShareHandleImage.h',
     'D3D9SurfaceImage.h',
     'Effects.h',
     'ImageDataSerializer.h',
     'ipc/APZChild.h',
+    'ipc/APZCTreeManagerChild.h',
+    'ipc/APZCTreeManagerParent.h',
     'ipc/AsyncTransactionTracker.h',
     'ipc/CompositableForwarder.h',
     'ipc/CompositableTransactionParent.h',
     'ipc/CompositorBridgeChild.h',
     'ipc/CompositorBridgeParent.h',
     'ipc/CompositorThread.h',
     'ipc/FenceUtils.h',
     'ipc/GonkNativeHandle.h',
@@ -337,16 +339,18 @@ UNIFIED_SOURCES += [
     'Compositor.cpp',
     'CopyableCanvasLayer.cpp',
     'Effects.cpp',
     'FrameMetrics.cpp',
     'GLImages.cpp',
     'ImageDataSerializer.cpp',
     'ImageLayers.cpp',
     'ipc/APZChild.cpp',
+    'ipc/APZCTreeManagerChild.cpp',
+    'ipc/APZCTreeManagerParent.cpp',
     'ipc/AsyncTransactionTracker.cpp',
     'ipc/CompositableTransactionParent.cpp',
     'ipc/CompositorBench.cpp',
     'ipc/CompositorBridgeChild.cpp',
     'ipc/CompositorBridgeParent.cpp',
     'ipc/CompositorThread.cpp',
     'ipc/FenceUtils.cpp',
     'ipc/ImageBridgeChild.cpp',
@@ -409,16 +413,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'opengl/MacIOSurfaceTextureClientOGL.cpp',
         'opengl/MacIOSurfaceTextureHostOGL.cpp',
     ]
 
 IPDL_SOURCES = [
     'ipc/LayersMessages.ipdlh',
     'ipc/LayersSurfaces.ipdlh',
     'ipc/PAPZ.ipdl',
+    'ipc/PAPZCTreeManager.ipdl',
     'ipc/PCompositable.ipdl',
     'ipc/PCompositorBridge.ipdl',
     'ipc/PImageBridge.ipdl',
     'ipc/PImageContainer.ipdl',
     'ipc/PLayer.ipdl',
     'ipc/PLayerTransaction.ipdl',
     'ipc/PSharedBufferManager.ipdl',
     'ipc/PTexture.ipdl',
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -16,28 +16,38 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/MatrixFwd.h"
 
 template<class E> struct already_AddRefed;
 class nsIWidget;
 
 namespace mozilla {
 
+namespace layers {
+class PAPZCTreeManagerParent;
+class APZCTreeManagerChild;
+}
+
 namespace dom {
 class Touch;
 } // namespace dom
 
 enum InputType
 {
+  // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+  // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
   MULTITOUCH_INPUT,
   MOUSE_INPUT,
   PANGESTURE_INPUT,
   PINCHGESTURE_INPUT,
   TAPGESTURE_INPUT,
-  SCROLLWHEEL_INPUT
+  SCROLLWHEEL_INPUT,
+
+  // Used as an upper bound for ContiguousEnumSerializer
+  SENTINEL_INPUT,
 };
 
 class MultiTouchInput;
 class MouseInput;
 class PanGestureInput;
 class PinchGestureInput;
 class TapGestureInput;
 class ScrollWheelInput;
@@ -57,16 +67,18 @@ class ScrollWheelInput;
     MOZ_ASSERT(mInputType == enumID, "Invalid cast of InputData."); \
     return (type&) *this; \
   }
 
 /** Base input data class. Should never be instantiated. */
 class InputData
 {
 public:
+  // Warning, this class is serialized and sent over IPC. Any change to its
+  // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   InputType mInputType;
   // Time in milliseconds that this data is relevant to. This only really
   // matters when this data is used as an event. We use uint32_t instead of
   // TimeStamp because it is easier to convert from WidgetInputEvent. The time
   // is platform-specific but it in the case of B2G and Fennec it is since
   // startup.
   uint32_t mTime;
   // Set in parallel to mTime until we determine it is safe to drop
@@ -153,16 +165,19 @@ public:
   }
 
   SingleTouchData()
   {
   }
 
   already_AddRefed<dom::Touch> ToNewDOMTouch() const;
 
+  // Warning, this class is serialized and sent over IPC. Any change to its
+  // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
+
   // A unique number assigned to each SingleTouchData within a MultiTouchInput so
   // that they can be easily distinguished when handling a touch start/move/end.
   int32_t mIdentifier;
 
   // Point on the screen that the touch hit, in device pixels. They are
   // coordinates on the screen.
   ScreenIntPoint mScreenPoint;
 
@@ -193,20 +208,25 @@ public:
  *
  * Stores an array of SingleTouchData.
  */
 class MultiTouchInput : public InputData
 {
 public:
   enum MultiTouchType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
     MULTITOUCH_START,
     MULTITOUCH_MOVE,
     MULTITOUCH_END,
-    MULTITOUCH_CANCEL
+    MULTITOUCH_CANCEL,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    MULTITOUCH_SENTINEL,
   };
 
   MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp,
                   Modifiers aModifiers)
     : InputData(MULTITOUCH_INPUT, aTime, aTimeStamp, aModifiers)
     , mType(aType)
     , mHandledByAPZ(false)
   {
@@ -240,89 +260,126 @@ public:
   // 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);
 
   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;
   bool mHandledByAPZ;
 };
 
 class MouseInput : public InputData
 {
+protected:
+  friend mozilla::layers::PAPZCTreeManagerParent;
+  friend mozilla::layers::APZCTreeManagerChild;
+
+  MouseInput()
+    : InputData(MOUSE_INPUT)
+    , mType(MOUSE_NONE)
+    , mButtonType(NONE)
+    , mInputSource(0)
+    , mButtons(0)
+    , mHandledByAPZ(false)
+  {}
+
 public:
   enum MouseType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
     MOUSE_NONE,
     MOUSE_MOVE,
     MOUSE_DOWN,
     MOUSE_UP,
     MOUSE_DRAG_START,
     MOUSE_DRAG_END,
     MOUSE_WIDGET_ENTER,
     MOUSE_WIDGET_EXIT,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    MOUSE_SENTINEL,
   };
 
   enum ButtonType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
     LEFT_BUTTON,
     MIDDLE_BUTTON,
     RIGHT_BUTTON,
-    NONE
+    NONE,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    BUTTON_SENTINEL,
   };
 
   MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource, int16_t aButtons, const ScreenPoint& aPoint,
              uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers)
     : InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers)
     , mType(aType)
     , mButtonType(aButtonType)
     , mInputSource(aInputSource)
     , mButtons(aButtons)
     , mOrigin(aPoint)
     , mHandledByAPZ(false)
   {}
 
-  MouseInput()
-    : InputData(MOUSE_INPUT)
-    , mType(MOUSE_NONE)
-    , mButtonType(NONE)
-    , mInputSource(0)
-    , mButtons(0)
-    , mHandledByAPZ(false)
-  {}
-
   explicit MouseInput(const WidgetMouseEventBase& aMouseEvent);
 
   bool IsLeftButton() const { return mButtonType == LEFT_BUTTON; }
 
   bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
   WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
 
+  // Warning, this class is serialized and sent over IPC. Any change to its
+  // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   MouseType mType;
   ButtonType mButtonType;
   uint16_t mInputSource;
   int16_t mButtons;
   ScreenPoint mOrigin;
   ParentLayerPoint mLocalOrigin;
   bool mHandledByAPZ;
 };
 
 /**
  * Encapsulation class for pan events, can be used off-main-thread.
  * These events are currently only used for scrolling on desktop.
  */
 class PanGestureInput : public InputData
 {
+protected:
+  friend mozilla::layers::PAPZCTreeManagerParent;
+  friend mozilla::layers::APZCTreeManagerChild;
+
+  PanGestureInput()
+    : InputData(PANGESTURE_INPUT),
+      mLineOrPageDeltaX(0),
+      mLineOrPageDeltaY(0),
+      mUserDeltaMultiplierX(1.0),
+      mUserDeltaMultiplierY(1.0),
+      mHandledByAPZ(false),
+      mFollowedByMomentum(false),
+      mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
+  {
+  }
+
 public:
   enum PanGestureType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
+
     // MayStart: Dispatched before any actual panning has occurred but when a
     // pan gesture is probably about to start, for example when the user
     // starts touching the touchpad. Should interrupt any ongoing APZ
     // animation and can be used to trigger scrollability indicators (e.g.
     // flashing overlay scrollbars).
     PANGESTURE_MAYSTART,
 
     // Cancelled: Dispatched after MayStart when no pan gesture is going to
@@ -354,17 +411,20 @@ public:
     PANGESTURE_MOMENTUMSTART,
 
     // MomentumPan: The actual momentum motion by mPanDisplacement.
     PANGESTURE_MOMENTUMPAN,
 
     // MomentumEnd: The momentum animation has ended, for example because the
     // momentum velocity has gone below the stopping threshold, or because the
     // user has stopped the animation by putting their fingers on a touchpad.
-    PANGESTURE_MOMENTUMEND
+    PANGESTURE_MOMENTUMEND,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    PANGESTURE_SENTINEL,
   };
 
   PanGestureInput(PanGestureType aType,
                   uint32_t aTime,
                   TimeStamp aTimeStamp,
                   const ScreenPoint& aPanStartPoint,
                   const ScreenPoint& aPanDisplacement,
                   Modifiers aModifiers)
@@ -386,16 +446,18 @@ public:
 
   WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
 
   bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
 
   ScreenPoint UserMultipliedPanDisplacement() const;
   ParentLayerPoint UserMultipliedLocalPanDisplacement() const;
 
+  // Warning, this class is serialized and sent over IPC. Any change to its
+  // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   PanGestureType mType;
   ScreenPoint mPanStartPoint;
 
   // The delta. This can be non-zero on any type of event.
   ScreenPoint mPanDisplacement;
 
   // Versions of |mPanStartPoint| and |mPanDisplacement| in the local
   // coordinates of the APZC receiving the pan. These are set and used by APZ.
@@ -427,22 +489,36 @@ public:
 
 /**
  * Encapsulation class for pinch events. In general, these will be generated by
  * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
  * determining whether or not the user was trying to do a gesture.
  */
 class PinchGestureInput : public InputData
 {
+protected:
+  friend mozilla::layers::PAPZCTreeManagerParent;
+  friend mozilla::layers::APZCTreeManagerChild;
+
+  PinchGestureInput()
+    : InputData(PINCHGESTURE_INPUT)
+  {
+  }
+
 public:
   enum PinchGestureType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
     PINCHGESTURE_START,
     PINCHGESTURE_SCALE,
-    PINCHGESTURE_END
+    PINCHGESTURE_END,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    PINCHGESTURE_SENTINEL,
   };
 
   // Construct a tap gesture from a Screen point.
   // mLocalFocusPoint remains (0,0) unless it's set later.
   PinchGestureInput(PinchGestureType aType,
                     uint32_t aTime,
                     TimeStamp aTimeStamp,
                     const ScreenPoint& aFocusPoint,
@@ -471,16 +547,18 @@ public:
       mLocalFocusPoint(aLocalFocusPoint),
       mCurrentSpan(aCurrentSpan),
       mPreviousSpan(aPreviousSpan)
   {
   }
 
   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
   // screen, it is their midpoint. In the case of more than two fingers, the
   // 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
@@ -505,25 +583,39 @@ public:
 
 /**
  * Encapsulation class for tap events. In general, these will be generated by
  * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
  * determining whether or not the user was trying to do a gesture.
  */
 class TapGestureInput : public InputData
 {
+protected:
+  friend mozilla::layers::PAPZCTreeManagerParent;
+  friend mozilla::layers::APZCTreeManagerChild;
+
+  TapGestureInput()
+    : InputData(TAPGESTURE_INPUT)
+  {
+  }
+
 public:
   enum TapGestureType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
     TAPGESTURE_LONG,
     TAPGESTURE_LONG_UP,
     TAPGESTURE_UP,
     TAPGESTURE_CONFIRMED,
     TAPGESTURE_DOUBLE,
-    TAPGESTURE_CANCEL
+    TAPGESTURE_CANCEL,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    TAPGESTURE_SENTINEL,
   };
 
   // Construct a tap gesture from a Screen point.
   // mLocalPoint remains (0,0) unless it's set later.
   TapGestureInput(TapGestureType aType,
                   uint32_t aTime,
                   TimeStamp aTimeStamp,
                   const ScreenIntPoint& aPoint,
@@ -544,39 +636,63 @@ public:
     : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mLocalPoint(aLocalPoint)
   {
   }
 
   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
   TapGestureType mType;
 
   // The location of the tap in screen pixels.
   ScreenIntPoint mPoint;
 
   // The location of the tap in the local coordinates of the APZC receiving it.
   // This is set and used by APZ.
   ParentLayerPoint mLocalPoint;
 };
 
 // Encapsulation class for scroll-wheel events. These are generated by mice
 // with physical scroll wheels, and on Windows by most touchpads when using
 // scroll gestures.
 class ScrollWheelInput : public InputData
 {
+protected:
+  friend mozilla::layers::PAPZCTreeManagerParent;
+  friend mozilla::layers::APZCTreeManagerChild;
+
+  ScrollWheelInput()
+    : InputData(SCROLLWHEEL_INPUT)
+    , mHandledByAPZ(false)
+    , mLineOrPageDeltaX(0)
+    , mLineOrPageDeltaY(0)
+    , mScrollSeriesNumber(0)
+    , mUserDeltaMultiplierX(1.0)
+    , mUserDeltaMultiplierY(1.0)
+    , mMayHaveMomentum(false)
+    , mIsMomentum(false)
+  {}
+
 public:
   enum ScrollDeltaType
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
+
     // There are three kinds of scroll delta modes in Gecko: "page", "line" and
     // "pixel".
     SCROLLDELTA_LINE,
     SCROLLDELTA_PAGE,
-    SCROLLDELTA_PIXEL
+    SCROLLDELTA_PIXEL,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    SCROLLDELTA_SENTINEL,
   };
 
   static ScrollDeltaType
   DeltaTypeForDeltaMode(uint32_t aDeltaMode)
   {
     switch (aDeltaMode) {
       case nsIDOMWheelEvent::DOM_DELTA_LINE:
         return SCROLLDELTA_LINE;
@@ -603,18 +719,24 @@ public:
     default:
       MOZ_CRASH();
     }
     return nsIScrollableFrame::LINES;
   }
 
   enum ScrollMode
   {
+    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
+    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
+
     SCROLLMODE_INSTANT,
-    SCROLLMODE_SMOOTH
+    SCROLLMODE_SMOOTH,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    SCROLLMODE_SENTINEL,
   };
 
   ScrollWheelInput(uint32_t aTime,
                    TimeStamp aTimeStamp,
                    Modifiers aModifiers,
                    ScrollMode aScrollMode,
                    ScrollDeltaType aDeltaType,
                    const ScreenPoint& aOrigin,
@@ -640,16 +762,18 @@ public:
 
   explicit ScrollWheelInput(const WidgetWheelEvent& aEvent);
 
   WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
   bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
 
   bool IsCustomizedByUserPrefs() const;
 
+  // Warning, this class is serialized and sent over IPC. Any change to its
+  // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
   ScrollDeltaType mDeltaType;
   ScrollMode mScrollMode;
   ScreenPoint mOrigin;
 
   bool mHandledByAPZ;
 
   // Deltas are in units corresponding to the delta type. For line deltas, they
   // are the number of line units to scroll. The number of device pixels for a
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -9,16 +9,17 @@
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/ContentCache.h"
 #include "mozilla/GfxMessageUtils.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
+#include "InputData.h"
 
 namespace IPC
 {
 
 template<>
 struct ParamTraits<mozilla::EventMessage>
 {
   typedef mozilla::EventMessage paramType;
@@ -1025,11 +1026,319 @@ struct ParamTraits<mozilla::widget::Cand
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mPoint) &&
            ReadParam(aMsg, aIter, &aResult->mRect) &&
            ReadParam(aMsg, aIter, &aResult->mExcludeRect);
   }
 };
 
+// InputData.h
+
+template<>
+struct ParamTraits<mozilla::InputType>
+  : public ContiguousEnumSerializer<
+             mozilla::InputType,
+             mozilla::InputType::MULTITOUCH_INPUT,
+             mozilla::InputType::SENTINEL_INPUT>
+{};
+
+template<>
+struct ParamTraits<mozilla::InputData>
+{
+  typedef mozilla::InputData paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mInputType);
+    WriteParam(aMsg, aParam.mTime);
+    WriteParam(aMsg, aParam.mTimeStamp);
+    WriteParam(aMsg, aParam.modifiers);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->mInputType) &&
+           ReadParam(aMsg, aIter, &aResult->mTime) &&
+           ReadParam(aMsg, aIter, &aResult->mTimeStamp) &&
+           ReadParam(aMsg, aIter, &aResult->modifiers);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::SingleTouchData>
+{
+  typedef mozilla::SingleTouchData paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mIdentifier);
+    WriteParam(aMsg, aParam.mScreenPoint);
+    WriteParam(aMsg, aParam.mLocalScreenPoint);
+    WriteParam(aMsg, aParam.mRadius);
+    WriteParam(aMsg, aParam.mRotationAngle);
+    WriteParam(aMsg, aParam.mForce);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return (ReadParam(aMsg, aIter, &aResult->mIdentifier) &&
+            ReadParam(aMsg, aIter, &aResult->mScreenPoint) &&
+            ReadParam(aMsg, aIter, &aResult->mLocalScreenPoint) &&
+            ReadParam(aMsg, aIter, &aResult->mRadius) &&
+            ReadParam(aMsg, aIter, &aResult->mRotationAngle) &&
+            ReadParam(aMsg, aIter, &aResult->mForce));
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::MultiTouchInput::MultiTouchType>
+  : public ContiguousEnumSerializer<
+             mozilla::MultiTouchInput::MultiTouchType,
+             mozilla::MultiTouchInput::MultiTouchType::MULTITOUCH_START,
+             mozilla::MultiTouchInput::MultiTouchType::MULTITOUCH_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::MultiTouchInput>
+{
+  typedef mozilla::MultiTouchInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mType);
+    WriteParam(aMsg, aParam.mTouches);
+    WriteParam(aMsg, aParam.mHandledByAPZ);
+  }
+
+  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);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::MouseInput::MouseType>
+  : public ContiguousEnumSerializer<
+             mozilla::MouseInput::MouseType,
+             mozilla::MouseInput::MouseType::MOUSE_NONE,
+             mozilla::MouseInput::MouseType::MOUSE_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::MouseInput::ButtonType>
+  : public ContiguousEnumSerializer<
+             mozilla::MouseInput::ButtonType,
+             mozilla::MouseInput::ButtonType::LEFT_BUTTON,
+             mozilla::MouseInput::ButtonType::BUTTON_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::MouseInput>
+{
+  typedef mozilla::MouseInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mButtonType);
+    WriteParam(aMsg, aParam.mType);
+    WriteParam(aMsg, aParam.mInputSource);
+    WriteParam(aMsg, aParam.mButtons);
+    WriteParam(aMsg, aParam.mOrigin);
+    WriteParam(aMsg, aParam.mLocalOrigin);
+    WriteParam(aMsg, aParam.mHandledByAPZ);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, static_cast<mozilla::InputData*>(aResult)) &&
+           ReadParam(aMsg, aIter, &aResult->mButtonType) &&
+           ReadParam(aMsg, aIter, &aResult->mType) &&
+           ReadParam(aMsg, aIter, &aResult->mInputSource) &&
+           ReadParam(aMsg, aIter, &aResult->mButtons) &&
+           ReadParam(aMsg, aIter, &aResult->mOrigin) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalOrigin) &&
+           ReadParam(aMsg, aIter, &aResult->mHandledByAPZ);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::PanGestureInput::PanGestureType>
+  : public ContiguousEnumSerializer<
+             mozilla::PanGestureInput::PanGestureType,
+             mozilla::PanGestureInput::PanGestureType::PANGESTURE_MAYSTART,
+             mozilla::PanGestureInput::PanGestureType::PANGESTURE_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::PanGestureInput>
+{
+  typedef mozilla::PanGestureInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mType);
+    WriteParam(aMsg, aParam.mPanStartPoint);
+    WriteParam(aMsg, aParam.mPanDisplacement);
+    WriteParam(aMsg, aParam.mLocalPanStartPoint);
+    WriteParam(aMsg, aParam.mLocalPanDisplacement);
+    WriteParam(aMsg, aParam.mLineOrPageDeltaX);
+    WriteParam(aMsg, aParam.mLineOrPageDeltaY);
+    WriteParam(aMsg, aParam.mUserDeltaMultiplierX);
+    WriteParam(aMsg, aParam.mUserDeltaMultiplierY);
+    WriteParam(aMsg, aParam.mHandledByAPZ);
+    WriteParam(aMsg, aParam.mFollowedByMomentum);
+    WriteParam(aMsg, aParam.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+  }
+
+  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->mPanStartPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mPanDisplacement) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalPanStartPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalPanDisplacement) &&
+           ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaX) &&
+           ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaY) &&
+           ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierX) &&
+           ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierY) &&
+           ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
+           ReadParam(aMsg, aIter, &aResult->mFollowedByMomentum) &&
+           ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::PinchGestureInput::PinchGestureType>
+  : public ContiguousEnumSerializer<
+             mozilla::PinchGestureInput::PinchGestureType,
+             mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_START,
+             mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::PinchGestureInput>
+{
+  typedef mozilla::PinchGestureInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mType);
+    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->mFocusPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalFocusPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mCurrentSpan) &&
+           ReadParam(aMsg, aIter, &aResult->mPreviousSpan);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::TapGestureInput::TapGestureType>
+  : public ContiguousEnumSerializer<
+             mozilla::TapGestureInput::TapGestureType,
+             mozilla::TapGestureInput::TapGestureType::TAPGESTURE_LONG,
+             mozilla::TapGestureInput::TapGestureType::TAPGESTURE_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::TapGestureInput>
+{
+  typedef mozilla::TapGestureInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mType);
+    WriteParam(aMsg, aParam.mPoint);
+    WriteParam(aMsg, aParam.mLocalPoint);
+  }
+
+  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->mPoint) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalPoint);
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::ScrollWheelInput::ScrollDeltaType>
+  : public ContiguousEnumSerializer<
+             mozilla::ScrollWheelInput::ScrollDeltaType,
+             mozilla::ScrollWheelInput::ScrollDeltaType::SCROLLDELTA_LINE,
+             mozilla::ScrollWheelInput::ScrollDeltaType::SCROLLDELTA_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::ScrollWheelInput::ScrollMode>
+  : public ContiguousEnumSerializer<
+             mozilla::ScrollWheelInput::ScrollMode,
+             mozilla::ScrollWheelInput::ScrollMode::SCROLLMODE_INSTANT,
+             mozilla::ScrollWheelInput::ScrollMode::SCROLLMODE_SENTINEL>
+{};
+
+template<>
+struct ParamTraits<mozilla::ScrollWheelInput>
+{
+  typedef mozilla::ScrollWheelInput paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::InputData>(aParam));
+    WriteParam(aMsg, aParam.mDeltaType);
+    WriteParam(aMsg, aParam.mScrollMode);
+    WriteParam(aMsg, aParam.mOrigin);
+    WriteParam(aMsg, aParam.mHandledByAPZ);
+    WriteParam(aMsg, aParam.mDeltaX);
+    WriteParam(aMsg, aParam.mDeltaY);
+    WriteParam(aMsg, aParam.mLocalOrigin);
+    WriteParam(aMsg, aParam.mLineOrPageDeltaX);
+    WriteParam(aMsg, aParam.mLineOrPageDeltaY);
+    WriteParam(aMsg, aParam.mScrollSeriesNumber);
+    WriteParam(aMsg, aParam.mUserDeltaMultiplierX);
+    WriteParam(aMsg, aParam.mUserDeltaMultiplierY);
+    WriteParam(aMsg, aParam.mMayHaveMomentum);
+    WriteParam(aMsg, aParam.mIsMomentum);
+    WriteParam(aMsg, aParam.mAllowToOverrideSystemScrollSpeed);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, static_cast<mozilla::InputData*>(aResult)) &&
+           ReadParam(aMsg, aIter, &aResult->mDeltaType) &&
+           ReadParam(aMsg, aIter, &aResult->mScrollMode) &&
+           ReadParam(aMsg, aIter, &aResult->mOrigin) &&
+           ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
+           ReadParam(aMsg, aIter, &aResult->mDeltaX) &&
+           ReadParam(aMsg, aIter, &aResult->mDeltaY) &&
+           ReadParam(aMsg, aIter, &aResult->mLocalOrigin) &&
+           ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaX) &&
+           ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaY) &&
+           ReadParam(aMsg, aIter, &aResult->mScrollSeriesNumber) &&
+           ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierX) &&
+           ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierY) &&
+           ReadParam(aMsg, aIter, &aResult->mMayHaveMomentum) &&
+           ReadParam(aMsg, aIter, &aResult->mIsMomentum) &&
+           ReadParam(aMsg, aIter, &aResult->mAllowToOverrideSystemScrollSpeed);
+  }
+};
+
 } // namespace IPC
 
 #endif // nsGUIEventIPC_h__