Bug 822898 - Implement pointer events. Interface. r=smaug
authorOleg Romashin <oleg.romashin@microsoft.com>
Wed, 20 Nov 2013 13:05:39 -0800
changeset 156669 36431dbba2de7f9673b412189186a8a976f6c551
parent 156668 971c64fc4e17474dcdbebf8718cf234210ea1ef3
child 156670 25c21fd4169105b57d513439264e317595c10b51
push id25684
push usercbook@mozilla.com
push dateThu, 21 Nov 2013 13:21:05 +0000
treeherdermozilla-central@7427eede548f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs822898
milestone28.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 822898 - Implement pointer events. Interface. r=smaug
content/base/src/nsGkAtomList.h
content/events/public/nsEventNameList.h
content/events/src/PointerEvent.cpp
content/events/src/PointerEvent.h
content/events/src/moz.build
content/events/src/nsEventDispatcher.cpp
dom/interfaces/core/nsIInlineEventHandlers.idl
dom/interfaces/events/nsIDOMEvent.idl
dom/webidl/EventHandler.webidl
dom/webidl/PointerEvent.webidl
dom/webidl/moz.build
modules/libpref/src/init/all.js
widget/BasicEvents.h
widget/EventClassList.h
widget/MouseEvents.h
widget/nsGUIEventIPC.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1753,16 +1753,28 @@ GK_ATOM(onMozRotateGestureStart, "onMozR
 GK_ATOM(onMozRotateGestureUpdate, "onMozRotateGestureUpdate")
 GK_ATOM(onMozRotateGesture, "onMozRotateGesture")
 GK_ATOM(onMozTapGesture, "onMozTapGesture")
 GK_ATOM(onMozPressTapGesture, "onMozPressTapGesture")
 GK_ATOM(onMozEdgeUIStarted, "onMozEdgeUIStarted")
 GK_ATOM(onMozEdgeUICanceled, "onMozEdgeUICanceled")
 GK_ATOM(onMozEdgeUICompleted, "onMozEdgeUICompleted")
 
+// Pointer events
+GK_ATOM(onpointerdown, "onpointerdown")
+GK_ATOM(onpointermove, "onpointermove")
+GK_ATOM(onpointerup, "onpointerup")
+GK_ATOM(onpointercancel, "onpointercancel")
+GK_ATOM(onpointerover, "onpointerover")
+GK_ATOM(onpointerout, "onpointerout")
+GK_ATOM(onpointerenter, "onpointerenter")
+GK_ATOM(onpointerleave, "onpointerleave")
+GK_ATOM(ongotpointercapture, "ongotpointercapture")
+GK_ATOM(onlostpointercapture, "onlostpointercapture")
+
 // orientation support
 GK_ATOM(ondevicemotion, "ondevicemotion")
 GK_ATOM(ondeviceorientation, "ondeviceorientation")
 GK_ATOM(ondeviceproximity, "ondeviceproximity")
 GK_ATOM(onmozorientationchange, "onmozorientationchange")
 GK_ATOM(onuserproximity, "onuserproximity")
 
 // light sensor support
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -288,16 +288,58 @@ EVENT(mozfullscreenerror,
 EVENT(mozpointerlockchange,
       NS_POINTERLOCKCHANGE,
       EventNameType_HTML,
       NS_EVENT)
 EVENT(mozpointerlockerror,
       NS_POINTERLOCKERROR,
       EventNameType_HTML,
       NS_EVENT)
+
+EVENT(pointerdown,
+      NS_POINTER_DOWN,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointermove,
+      NS_POINTER_MOVE,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointerup,
+      NS_POINTER_UP,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointercancel,
+      NS_POINTER_CANCEL,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointerover,
+      NS_POINTER_OVER,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointerout,
+      NS_POINTER_OUT,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointerenter,
+      NS_POINTER_ENTER,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(pointerleave,
+      NS_POINTER_LEAVE,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(gotpointercapture,
+      NS_POINTER_GOT_CAPTURE,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+EVENT(lostpointercapture,
+      NS_POINTER_LOST_CAPTURE,
+      EventNameType_All,
+      NS_POINTER_EVENT)
+
 // Not supported yet; probably never because "wheel" is a better idea.
 // EVENT(mousewheel)
 EVENT(pause,
       NS_PAUSE,
       EventNameType_HTML,
       NS_EVENT)
 EVENT(play,
       NS_PLAY,
new file mode 100644
--- /dev/null
+++ b/content/events/src/PointerEvent.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; 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/.
+ *
+ * Portions Copyright 2013 Microsoft Open Technologies, Inc. */
+
+#include "PointerEvent.h"
+#include "mozilla/MouseEvents.h"
+#include "prtime.h"
+
+namespace mozilla {
+namespace dom {
+
+PointerEvent::PointerEvent(EventTarget* aOwner,
+                           nsPresContext* aPresContext,
+                           WidgetPointerEvent* aEvent)
+  : nsDOMMouseEvent(aOwner, aPresContext, aEvent ? aEvent : new WidgetPointerEvent(false, 0, nullptr))
+{
+  NS_ASSERTION(mEvent->eventStructType == NS_POINTER_EVENT, "event type mismatch NS_POINTER_EVENT");
+
+  WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
+  if (aEvent) {
+    mEventIsInternal = false;
+  } else {
+    mEventIsInternal = true;
+    mEvent->time = PR_Now();
+    mEvent->refPoint.x = mEvent->refPoint.y = 0;
+    mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+  }
+}
+
+static uint16_t
+ConvertStringToPointerType(const nsAString& aPointerTypeArg)
+{
+  if (aPointerTypeArg.EqualsLiteral("mouse")) {
+    return nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
+  }
+  if (aPointerTypeArg.EqualsLiteral("pen")) {
+    return nsIDOMMouseEvent::MOZ_SOURCE_PEN;
+  }
+  if (aPointerTypeArg.EqualsLiteral("touch")) {
+    return nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+  }
+
+  return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+}
+
+//static
+already_AddRefed<PointerEvent>
+PointerEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
+                          const nsAString& aType,
+                          const mozilla::dom::PointerEventInit& aParam,
+                          mozilla::ErrorResult& aRv)
+{
+  nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
+  nsRefPtr<PointerEvent> e = new PointerEvent(t, nullptr, nullptr);
+  bool trusted = e->Init(t);
+
+  aRv = e->InitMouseEvent(aType, aParam.mBubbles, aParam.mCancelable,
+                          aParam.mView, aParam.mDetail, aParam.mScreenX,
+                          aParam.mScreenY, aParam.mClientX, aParam.mClientY,
+                          aParam.mCtrlKey, aParam.mAltKey, aParam.mShiftKey,
+                          aParam.mMetaKey, aParam.mButton, aParam.mRelatedTarget);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  WidgetPointerEvent* widgetEvent = e->mEvent->AsPointerEvent();
+  widgetEvent->pointerId = aParam.mPointerId;
+  widgetEvent->width = aParam.mWidth;
+  widgetEvent->height = aParam.mHeight;
+  widgetEvent->pressure = aParam.mPressure;
+  widgetEvent->tiltX = aParam.mTiltX;
+  widgetEvent->tiltY = aParam.mTiltY;
+  widgetEvent->inputSource = ConvertStringToPointerType(aParam.mPointerType);
+  widgetEvent->isPrimary = aParam.mIsPrimary;
+  widgetEvent->buttons = aParam.mButtons;
+
+  e->SetTrusted(trusted);
+  return e.forget();
+}
+
+void
+PointerEvent::GetPointerType(nsAString& aPointerType)
+{
+  switch (mEvent->AsPointerEvent()->inputSource) {
+    case nsIDOMMouseEvent::MOZ_SOURCE_MOUSE:
+      aPointerType.AssignLiteral("mouse");
+      break;
+    case nsIDOMMouseEvent::MOZ_SOURCE_PEN:
+      aPointerType.AssignLiteral("pen");
+      break;
+    case nsIDOMMouseEvent::MOZ_SOURCE_TOUCH:
+      aPointerType.AssignLiteral("touch");
+      break;
+    case nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN:
+      aPointerType.AssignLiteral("");
+      break;
+  }
+}
+
+int32_t PointerEvent::PointerId()
+{
+  return mEvent->AsPointerEvent()->pointerId;
+}
+
+int32_t PointerEvent::Width()
+{
+  return mEvent->AsPointerEvent()->width;
+}
+
+int32_t PointerEvent::Height()
+{
+  return mEvent->AsPointerEvent()->height;
+}
+
+int32_t PointerEvent::Pressure()
+{
+  return mEvent->AsPointerEvent()->pressure;
+}
+
+int32_t PointerEvent::TiltX()
+{
+  return mEvent->AsPointerEvent()->tiltX;
+}
+
+int32_t PointerEvent::TiltY()
+{
+  return mEvent->AsPointerEvent()->tiltY;
+}
+
+bool PointerEvent::IsPrimary()
+{
+  return mEvent->AsPointerEvent()->isPrimary;
+}
+
+} // namespace dom
+} // namespace mozilla
+
+using namespace mozilla;
+
+nsresult NS_NewDOMPointerEvent(nsIDOMEvent** aInstancePtrResult,
+                               dom::EventTarget* aOwner,
+                               nsPresContext* aPresContext,
+                               WidgetPointerEvent *aEvent)
+{
+  dom::PointerEvent *it = new dom::PointerEvent(aOwner, aPresContext, aEvent);
+  return CallQueryInterface(it, aInstancePtrResult);
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/PointerEvent.h
@@ -0,0 +1,50 @@
+/* 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/.
+ *
+ * Portions Copyright 2013 Microsoft Open Technologies, Inc. */
+
+#ifndef PointerEvent_h__
+#define PointerEvent_h__
+
+#include "nsDOMMouseEvent.h"
+#include "mozilla/dom/PointerEventBinding.h"
+
+class nsPresContext;
+
+namespace mozilla {
+namespace dom {
+
+class PointerEvent : public nsDOMMouseEvent
+{
+public:
+  PointerEvent(EventTarget* aOwner,
+               nsPresContext* aPresContext,
+               WidgetPointerEvent* aEvent);
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
+  {
+    return mozilla::dom::PointerEventBinding::Wrap(aCx, aScope, this);
+  }
+
+  static already_AddRefed<PointerEvent>
+  Constructor(const GlobalObject& aGlobal,
+              const nsAString& aType,
+              const PointerEventInit& aParam,
+              mozilla::ErrorResult& aRv);
+
+  int32_t PointerId();
+  int32_t Width();
+  int32_t Height();
+  int32_t Pressure();
+  int32_t TiltX();
+  int32_t TiltY();
+  bool IsPrimary();
+  void GetPointerType(nsAString& aPointerType);
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/content/events/src/moz.build
+++ b/content/events/src/moz.build
@@ -9,16 +9,17 @@ EXPORTS += [
     'nsDOMEventTargetHelper.h',
     'nsDOMTouchEvent.h',
     'nsDOMUIEvent.h',
     'nsEventListenerManager.h',
     'nsEventStateManager.h',
 ]
 
 EXPORTS.mozilla.dom += [
+    'PointerEvent.h',
     'Touch.h',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     EXPORTS.mozilla.dom += ['SpeechRecognitionError.h']
 
 UNIFIED_SOURCES += [
     'DOMWheelEvent.cpp',
@@ -52,16 +53,17 @@ UNIFIED_SOURCES += [
     'nsDOMUIEvent.cpp',
     'nsDOMXULCommandEvent.cpp',
     'nsEventDispatcher.cpp',
     'nsEventListenerManager.cpp',
     'nsEventListenerService.cpp',
     'nsIMEStateManager.cpp',
     'nsPaintRequest.cpp',
     'nsPrivateTextRange.cpp',
+    'PointerEvent.cpp',
     'TextComposition.cpp',
     'Touch.cpp',
 ]
 
 # nsEventStateManager.cpp should be built separately because of Mac OS X headers.
 SOURCES += [
     'nsEventStateManager.cpp',
 ]
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -734,16 +734,19 @@ nsEventDispatcher::CreateEvent(mozilla::
       return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, aEvent);
 
     case NS_COMMAND_EVENT:
       return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext,
                                    aEvent->AsCommandEvent());
     case NS_SIMPLE_GESTURE_EVENT:
       return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext,
                                          aEvent->AsSimpleGestureEvent());
+    case NS_POINTER_EVENT:
+      return NS_NewDOMPointerEvent(aDOMEvent, aOwner, aPresContext,
+                                   aEvent->AsPointerEvent());
     case NS_TOUCH_EVENT:
       return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext,
                                  aEvent->AsTouchEvent());
     case NS_TRANSITION_EVENT:
       return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext,
                                       aEvent->AsTransitionEvent());
     case NS_ANIMATION_EVENT:
       return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext,
--- a/dom/interfaces/core/nsIInlineEventHandlers.idl
+++ b/dom/interfaces/core/nsIInlineEventHandlers.idl
@@ -2,17 +2,17 @@
  * 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 "domstubs.idl"
 
 %{ C++
 #include "jspubtd.h"
 %}
 
-[scriptable, uuid(22df6ed6-d094-4e45-97fc-a8eca11c390c)]
+[scriptable, uuid(6c1fcf3d-119b-4cf4-9437-b9357508976a)]
 interface nsIInlineEventHandlers : nsISupports
 {
   [implicit_jscontext] attribute jsval onabort;
   [implicit_jscontext] attribute jsval onblur;
   [implicit_jscontext] attribute jsval oncanplay;
   [implicit_jscontext] attribute jsval oncanplaythrough;
   [implicit_jscontext] attribute jsval onchange;
   [implicit_jscontext] attribute jsval onclick;
@@ -66,16 +66,27 @@ interface nsIInlineEventHandlers : nsISu
   [implicit_jscontext] attribute jsval onstalled;
   [implicit_jscontext] attribute jsval onsubmit;
   [implicit_jscontext] attribute jsval onsuspend;
   [implicit_jscontext] attribute jsval ontimeupdate;
   [implicit_jscontext] attribute jsval onvolumechange;
   [implicit_jscontext] attribute jsval onwaiting;
   [implicit_jscontext] attribute jsval onwheel;
 
+  [implicit_jscontext] attribute jsval onpointerdown;
+  [implicit_jscontext] attribute jsval onpointermove;
+  [implicit_jscontext] attribute jsval onpointerout;
+  [implicit_jscontext] attribute jsval onpointerover;
+  [implicit_jscontext] attribute jsval onpointerup;
+  [implicit_jscontext] attribute jsval onpointerenter;
+  [implicit_jscontext] attribute jsval onpointerleave;
+  [implicit_jscontext] attribute jsval ongotpointercapture;
+  [implicit_jscontext] attribute jsval onlostpointercapture;
+  [implicit_jscontext] attribute jsval onpointercancel;
+
   /**
    * Non-HTML5 event attributes
    */
   [implicit_jscontext] attribute jsval oncopy;
   [implicit_jscontext] attribute jsval oncut;
   [implicit_jscontext] attribute jsval onpaste;
   [implicit_jscontext] attribute jsval onbeforescriptexecute;
   [implicit_jscontext] attribute jsval onafterscriptexecute;  
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -367,16 +367,21 @@ NS_NewDOMTransitionEvent(nsIDOMEvent** a
                          nsPresContext* aPresContext,
                          mozilla::InternalTransitionEvent* aEvent);
 nsresult
 NS_NewDOMAnimationEvent(nsIDOMEvent** aInstancePtrResult,
                         mozilla::dom::EventTarget* aOwner,
                         nsPresContext* aPresContext,
                         mozilla::InternalAnimationEvent* aEvent);
 nsresult
+NS_NewDOMPointerEvent(nsIDOMEvent** aInstancePtrResult,
+                      mozilla::dom::EventTarget* aOwner,
+                      nsPresContext* aPresContext,
+                      mozilla::WidgetPointerEvent* aEvent);
+nsresult
 NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
                     mozilla::dom::EventTarget* aOwner,
                     nsPresContext* aPresContext,
                     mozilla::WidgetTouchEvent* aEvent);
 nsresult
 NS_NewDOMMozSettingsEvent(nsIDOMEvent** aInstancePtrResult,
                           mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
--- a/dom/webidl/EventHandler.webidl
+++ b/dom/webidl/EventHandler.webidl
@@ -83,16 +83,32 @@ interface GlobalEventHandlers {
            //(Not implemented)attribute EventHandler onsort;
            attribute EventHandler onstalled;
            attribute EventHandler onsubmit;
            attribute EventHandler onsuspend;
            attribute EventHandler ontimeupdate;
            attribute EventHandler onvolumechange;
            attribute EventHandler onwaiting;
 
+           // Pointer events handlers
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerdown;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerup;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointermove;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerout;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerover;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerenter;
+           [Pref="dom.w3c_pointer_events.enabled"]
+           attribute EventHandler onpointerleave;
+
            // Mozilla-specific handlers
            attribute EventHandler onmozfullscreenchange;
            attribute EventHandler onmozfullscreenerror;
            attribute EventHandler onmozpointerlockchange;
            attribute EventHandler onmozpointerlockerror;
 };
 
 [NoInterfaceObject]
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PointerEvent.webidl
@@ -0,0 +1,37 @@
+/* -*- Mode: IDL; tab-width: 2; 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/.
+ *
+ * For more information see nsIPointerEvent.idl.
+ *
+ * Portions Copyright 2013 Microsoft Open Technologies, Inc. */
+
+interface WindowProxy;
+
+[Pref="dom.w3c_pointer_events.enabled",
+ Constructor(DOMString type, optional PointerEventInit eventInitDict)]
+interface PointerEvent : MouseEvent
+{
+  readonly attribute long pointerId;
+  readonly attribute long width;
+  readonly attribute long height;
+  readonly attribute float pressure;
+  readonly attribute long tiltX;
+  readonly attribute long tiltY;
+  readonly attribute DOMString pointerType;
+  readonly attribute boolean isPrimary;
+};
+
+dictionary PointerEventInit : MouseEventInit
+{
+  long pointerId = 0;
+  long width = 0;
+  long height = 0;
+  float pressure = 0;
+  long tiltX = 0;
+  long tiltY = 0;
+  DOMString pointerType = "";
+  boolean isPrimary = false;
+};
+
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -249,16 +249,17 @@ WEBIDL_FILES = [
     'ParentNode.webidl',
     'Performance.webidl',
     'PerformanceNavigation.webidl',
     'PerformanceTiming.webidl',
     'PeriodicWave.webidl',
     'PhoneNumberService.webidl',
     'Plugin.webidl',
     'PluginArray.webidl',
+    'PointerEvent.webidl',
     'Position.webidl',
     'PositionError.webidl',
     'ProcessingInstruction.webidl',
     'Promise.webidl',
     'PushManager.webidl',
     'Range.webidl',
     'Rect.webidl',
     'RGBColor.webidl',
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4380,16 +4380,19 @@ pref("dom.mozSettings.enabled", false);
 pref("dom.mozPermissionSettings.enabled", false);
 
 // W3C touch events
 // 0 - disabled, 1 - enabled, 2 - autodetect (win)
 #ifdef XP_WIN
 pref("dom.w3c_touch_events.enabled", 2);
 #endif
 
+// W3C draft pointer events
+pref("dom.w3c_pointer_events.enabled", false);
+
 // enable JS dump() function.
 pref("browser.dom.window.dump.enabled", false);
 
 // SPS Profiler
 pref("profiler.enabled", false);
 pref("profiler.interval", 10);
 pref("profiler.entries", 100000);
 
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -36,16 +36,17 @@ enum nsEventStructType
   NS_QUERY_CONTENT_EVENT,            // WidgetQueryContentEvent
   NS_SELECTION_EVENT,                // WidgetSelectionEvent
 
   // MouseEvents.h
   NS_MOUSE_EVENT,                    // WidgetMouseEvent
   NS_DRAG_EVENT,                     // WidgetDragEvent
   NS_MOUSE_SCROLL_EVENT,             // WidgetMouseScrollEvent
   NS_WHEEL_EVENT,                    // WidgetWheelEvent
+  NS_POINTER_EVENT,                  // PointerEvent
 
   // TouchEvents.h
   NS_GESTURENOTIFY_EVENT,            // WidgetGestureNotifyEvent
   NS_SIMPLE_GESTURE_EVENT,           // WidgetSimpleGestureEvent
   NS_TOUCH_EVENT,                    // WidgetTouchEvent
 
   // ContentEvents.h
   NS_SCRIPT_ERROR_EVENT,             // InternalScriptErrorEvent
@@ -130,16 +131,29 @@ enum nsEventStructType
 #define NS_MOUSE_CLICK                  (NS_MOUSE_MESSAGE_START + 27)
 #define NS_MOUSE_ACTIVATE               (NS_MOUSE_MESSAGE_START + 30)
 #define NS_MOUSE_ENTER_SYNTH            (NS_MOUSE_MESSAGE_START + 31)
 #define NS_MOUSE_EXIT_SYNTH             (NS_MOUSE_MESSAGE_START + 32)
 #define NS_MOUSE_MOZHITTEST             (NS_MOUSE_MESSAGE_START + 33)
 #define NS_MOUSEENTER                   (NS_MOUSE_MESSAGE_START + 34)
 #define NS_MOUSELEAVE                   (NS_MOUSE_MESSAGE_START + 35)
 
+// Pointer spec events
+#define NS_POINTER_EVENT_START          4400
+#define NS_POINTER_MOVE                 (NS_POINTER_EVENT_START)
+#define NS_POINTER_UP                   (NS_POINTER_EVENT_START + 1)
+#define NS_POINTER_DOWN                 (NS_POINTER_EVENT_START + 2)
+#define NS_POINTER_OVER                 (NS_POINTER_EVENT_START + 22)
+#define NS_POINTER_OUT                  (NS_POINTER_EVENT_START + 23)
+#define NS_POINTER_ENTER                (NS_POINTER_EVENT_START + 24)
+#define NS_POINTER_LEAVE                (NS_POINTER_EVENT_START + 25)
+#define NS_POINTER_CANCEL               (NS_POINTER_EVENT_START + 26)
+#define NS_POINTER_GOT_CAPTURE          (NS_POINTER_EVENT_START + 27)
+#define NS_POINTER_LOST_CAPTURE         (NS_POINTER_EVENT_START + 28)
+
 #define NS_CONTEXTMENU_MESSAGE_START    500
 #define NS_CONTEXTMENU                  (NS_CONTEXTMENU_MESSAGE_START)
 
 #define NS_STREAM_EVENT_START           1100
 #define NS_LOAD                         (NS_STREAM_EVENT_START)
 #define NS_PAGE_UNLOAD                  (NS_STREAM_EVENT_START + 1)
 #define NS_HASHCHANGE                   (NS_STREAM_EVENT_START + 2)
 #define NS_IMAGE_ABORT                  (NS_STREAM_EVENT_START + 3)
--- a/widget/EventClassList.h
+++ b/widget/EventClassList.h
@@ -28,16 +28,17 @@ NS_EVENT_CLASS(Widget, QueryContentEvent
 NS_EVENT_CLASS(Widget, SelectionEvent)
 
 // MouseEvents.h
 NS_EVENT_CLASS(Widget, MouseEventBase)
 NS_EVENT_CLASS(Widget, MouseEvent)
 NS_EVENT_CLASS(Widget, DragEvent)
 NS_EVENT_CLASS(Widget, MouseScrollEvent)
 NS_EVENT_CLASS(Widget, WheelEvent)
+NS_EVENT_CLASS(Widget, PointerEvent)
 
 // TouchEvents.h
 NS_EVENT_CLASS(Widget, GestureNotifyEvent)
 NS_EVENT_CLASS(Widget, SimpleGestureEvent)
 NS_EVENT_CLASS(Widget, TouchEvent)
 
 // ContentEvents.h
 NS_EVENT_CLASS(Internal, ScriptErrorEvent)
--- a/widget/MouseEvents.h
+++ b/widget/MouseEvents.h
@@ -451,11 +451,72 @@ public:
     lineOrPageDeltaY = aEvent.lineOrPageDeltaY;
     scrollType = aEvent.scrollType;
     overflowDeltaX = aEvent.overflowDeltaX;
     overflowDeltaY = aEvent.overflowDeltaY;
     mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
   }
 };
 
+/******************************************************************************
+ * mozilla::WidgetPointerEvent
+ ******************************************************************************/
+
+class WidgetPointerEvent : public WidgetMouseEvent
+{
+  friend class mozilla::dom::PBrowserParent;
+  friend class mozilla::dom::PBrowserChild;
+
+  WidgetPointerEvent()
+  {
+  }
+
+public:
+  virtual WidgetPointerEvent* AsPointerEvent() MOZ_OVERRIDE { return this; }
+
+  WidgetPointerEvent(bool aIsTrusted, uint32_t aMsg, nsIWidget* w)
+    : WidgetMouseEvent(aIsTrusted, aMsg, w, NS_POINTER_EVENT, eReal)
+    , pointerId(0)
+    , width(0)
+    , height(0)
+    , tiltX(0)
+    , tiltY(0)
+    , isPrimary(true)
+  {
+  }
+
+  WidgetPointerEvent(const WidgetMouseEvent& aEvent)
+    : WidgetMouseEvent(aEvent)
+    , pointerId(0)
+    , width(0)
+    , height(0)
+    , tiltX(0)
+    , tiltY(0)
+    , isPrimary(true)
+  {
+    eventStructType = NS_POINTER_EVENT;
+  }
+
+  WidgetPointerEvent(bool aIsTrusted, uint32_t aMsg, nsIWidget* w,
+                     uint32_t aPointerId,
+                     uint32_t aWidth, uint32_t aHeight,
+                     uint32_t aTiltX, uint32_t aTiltY, bool aIsPrimary)
+    : WidgetMouseEvent(aIsTrusted, aMsg, w, NS_POINTER_EVENT, eReal)
+    , pointerId(aPointerId)
+    , width(aWidth)
+    , height(aHeight)
+    , tiltX(aTiltX)
+    , tiltY(aTiltY)
+    , isPrimary(aIsPrimary)
+  {
+  }
+
+  uint32_t pointerId;
+  uint32_t width;
+  uint32_t height;
+  uint32_t tiltX;
+  uint32_t tiltY;
+  bool isPrimary;
+};
+
 } // namespace mozilla
 
 #endif // mozilla_MouseEvents_h__
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -202,16 +202,46 @@ struct ParamTraits<mozilla::WidgetMouseE
     aResult->context =
       static_cast<mozilla::WidgetMouseEvent::contextType>(context);
     aResult->exit = static_cast<mozilla::WidgetMouseEvent::exitType>(exit);
     return rv;
   }
 };
 
 template<>
+struct ParamTraits<mozilla::WidgetPointerEvent>
+{
+  typedef mozilla::WidgetPointerEvent paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<mozilla::WidgetMouseEvent>(aParam));
+    WriteParam(aMsg, aParam.pointerId);
+    WriteParam(aMsg, aParam.width);
+    WriteParam(aMsg, aParam.height);
+    WriteParam(aMsg, aParam.tiltX);
+    WriteParam(aMsg, aParam.tiltY);
+    WriteParam(aMsg, aParam.isPrimary);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    bool rv =
+      ReadParam(aMsg, aIter, static_cast<mozilla::WidgetMouseEvent*>(aResult)) &&
+      ReadParam(aMsg, aIter, &aResult->pointerId) &&
+      ReadParam(aMsg, aIter, &aResult->width) &&
+      ReadParam(aMsg, aIter, &aResult->height) &&
+      ReadParam(aMsg, aIter, &aResult->tiltX) &&
+      ReadParam(aMsg, aIter, &aResult->tiltY) &&
+      ReadParam(aMsg, aIter, &aResult->isPrimary);
+    return rv;
+  }
+};
+
+template<>
 struct ParamTraits<mozilla::WidgetTouchEvent>
 {
   typedef mozilla::WidgetTouchEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<const mozilla::WidgetInputEvent&>(aParam));
     // Sigh, Touch bites us again!  We want to be able to do