Bug 1281575 - Create IPDL protocol implementation of IAPZCTreeManager. r=kats
authorRyan Hunt <rhunt@mozilla.com>
Wed, 20 Jul 2016 13:37:00 +0200
changeset 346203 0055f23a1374324df40c85c27b4ac417de6e2cc2
parent 346202 02f12f2a1fbfadbae78864cd754cf3f721f6abcb
child 346204 ab54bfc55266aaadc00567341bf494e907b0e4d7
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1281575
milestone50.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 1281575 - Create IPDL protocol implementation of IAPZCTreeManager. r=kats MozReview-Commit-ID: BEgcbidyLjm
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:
+
+  explicit 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__