Bug 731878 part.2 Implement D3E MouseEvent.buttons attribute r=smaug, sr=jst
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 25 Apr 2012 12:00:01 +0900
changeset 96434 392cb8e0876ffe17d92184b020e4e6666fa9e3ee
parent 96433 ac852666763d0a4e441d82e8a448a4e51262cdd3
child 96435 4d0beaad9f761118e3dbe5a9f88dc12e5ef8e9c8
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, jst
bugs731878
milestone15.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 731878 part.2 Implement D3E MouseEvent.buttons attribute r=smaug, sr=jst
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMMouseEvent.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/events/test/test_eventctors.html
dom/interfaces/events/nsIDOMDragEvent.idl
dom/interfaces/events/nsIDOMMouseEvent.idl
dom/interfaces/events/nsIDOMMouseScrollEvent.idl
dom/interfaces/events/nsIDOMMozTouchEvent.idl
dom/interfaces/events/nsIDOMSimpleGestureEvent.idl
widget/nsGUIEvent.h
widget/nsGUIEventIPC.h
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -690,16 +690,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
         new nsMouseEvent(false, msg, nsnull, oldMouseEvent->reason);
       NS_ENSURE_TRUE(mouseEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       mouseEvent->clickCount = oldMouseEvent->clickCount;
       mouseEvent->acceptActivation = oldMouseEvent->acceptActivation;
       mouseEvent->context = oldMouseEvent->context;
       mouseEvent->relatedTarget = oldMouseEvent->relatedTarget;
       mouseEvent->button = oldMouseEvent->button;
+      mouseEvent->buttons = oldMouseEvent->buttons;
       mouseEvent->modifiers = oldMouseEvent->modifiers;
       mouseEvent->pressure = oldMouseEvent->pressure;
       mouseEvent->inputSource = oldMouseEvent->inputSource;
       newEvent = mouseEvent;
       break;
     }
     case NS_DRAG_EVENT:
     {
@@ -708,16 +709,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
         new nsDragEvent(false, msg, nsnull);
       NS_ENSURE_TRUE(dragEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       dragEvent->dataTransfer = oldDragEvent->dataTransfer;
       dragEvent->clickCount = oldDragEvent->clickCount;
       dragEvent->acceptActivation = oldDragEvent->acceptActivation;
       dragEvent->relatedTarget = oldDragEvent->relatedTarget;
       dragEvent->button = oldDragEvent->button;
+      dragEvent->buttons = oldDragEvent->buttons;
       dragEvent->modifiers = oldDragEvent->modifiers;
       static_cast<nsMouseEvent*>(dragEvent)->inputSource =
         static_cast<nsMouseEvent*>(oldDragEvent)->inputSource;
       newEvent = dragEvent;
       break;
     }
     case NS_SCRIPT_ERROR_EVENT:
     {
@@ -750,16 +752,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
       NS_ENSURE_TRUE(mouseScrollEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       nsMouseScrollEvent* oldMouseScrollEvent =
         static_cast<nsMouseScrollEvent*>(mEvent);
       mouseScrollEvent->scrollFlags = oldMouseScrollEvent->scrollFlags;
       mouseScrollEvent->delta = oldMouseScrollEvent->delta;
       mouseScrollEvent->relatedTarget = oldMouseScrollEvent->relatedTarget;
       mouseScrollEvent->button = oldMouseScrollEvent->button;
+      mouseScrollEvent->buttons = oldMouseScrollEvent->buttons;
       mouseScrollEvent->modifiers = oldMouseScrollEvent->modifiers;
       static_cast<nsMouseEvent_base*>(mouseScrollEvent)->inputSource =
         static_cast<nsMouseEvent_base*>(oldMouseScrollEvent)->inputSource;
       newEvent = mouseScrollEvent;
       break;
     }
     case NS_SCROLLPORT_EVENT:
     {
@@ -896,16 +899,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
     {
       nsMozTouchEvent* oldMozTouchEvent = static_cast<nsMozTouchEvent*>(mEvent);
       nsMozTouchEvent* mozTouchEvent =
         new nsMozTouchEvent(false, msg, nsnull,
                             static_cast<nsMozTouchEvent*>(mEvent)->streamId);
       NS_ENSURE_TRUE(mozTouchEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       mozTouchEvent->modifiers = oldMozTouchEvent->modifiers;
+      mozTouchEvent->buttons = oldMozTouchEvent->buttons;
       newEvent = mozTouchEvent;
       break;
     }
     case NS_TOUCH_EVENT:
     {
       nsTouchEvent *oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
       newEvent = new nsTouchEvent(false, oldTouchEvent);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -188,21 +188,36 @@ nsDOMMouseEvent::InitMouseEvent(const ns
 
 nsresult
 nsDOMMouseEvent::InitFromCtor(const nsAString& aType,
                               JSContext* aCx, jsval* aVal)
 {
   mozilla::dom::MouseEventInit d;
   nsresult rv = d.Init(aCx, aVal);
   NS_ENSURE_SUCCESS(rv, rv);
-  return InitMouseEvent(aType, d.bubbles, d.cancelable,
-                        d.view, d.detail, d.screenX, d.screenY,
-                        d.clientX, d.clientY, 
-                        d.ctrlKey, d.altKey, d.shiftKey, d.metaKey,
-                        d.button, d.relatedTarget);
+  rv = InitMouseEvent(aType, d.bubbles, d.cancelable,
+                      d.view, d.detail, d.screenX, d.screenY,
+                      d.clientX, d.clientY, 
+                      d.ctrlKey, d.altKey, d.shiftKey, d.metaKey,
+                      d.button, d.relatedTarget);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  switch(mEvent->eventStructType) {
+    case NS_MOUSE_EVENT:
+    case NS_MOUSE_SCROLL_EVENT:
+    case NS_DRAG_EVENT:
+    case NS_SIMPLE_GESTURE_EVENT:
+    case NS_MOZTOUCH_EVENT:
+      static_cast<nsMouseEvent_base*>(mEvent)->buttons = d.buttons;
+      break;
+    default:
+      break;
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMMouseEvent::InitNSMouseEvent(const nsAString & aType, bool aCanBubble, bool aCancelable,
                                   nsIDOMWindow *aView, PRInt32 aDetail, PRInt32 aScreenX,
                                   PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY,
                                   bool aCtrlKey, bool aAltKey, bool aShiftKey,
                                   bool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget,
@@ -236,16 +251,37 @@ nsDOMMouseEvent::GetButton(PRUint16* aBu
       NS_WARNING("Tried to get mouse button for non-mouse event!");
       *aButton = nsMouseEvent::eLeftButton;
       break;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMMouseEvent::GetButtons(PRUint16* aButtons)
+{
+  NS_ENSURE_ARG_POINTER(aButtons);
+  switch(mEvent->eventStructType)
+  {
+    case NS_MOUSE_EVENT:
+    case NS_MOUSE_SCROLL_EVENT:
+    case NS_DRAG_EVENT:
+    case NS_SIMPLE_GESTURE_EVENT:
+    case NS_MOZTOUCH_EVENT:
+      *aButtons = static_cast<nsMouseEvent_base*>(mEvent)->buttons;
+      break;
+    default:
+      MOZ_NOT_REACHED("Tried to get mouse buttons for non-mouse event!");
+      *aButtons = 0;
+      break;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMMouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
 {
   NS_ENSURE_ARG_POINTER(aRelatedTarget);
   *aRelatedTarget = nsnull;
   nsISupports* relatedTarget = nsnull;
   switch(mEvent->eventStructType)
   {
     case NS_MOUSE_EVENT:
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2004,16 +2004,17 @@ nsEventStateManager::BeginTrackingDragGe
                                   getter_AddRefs(mGestureDownContent));
 
   mGestureDownFrameOwner = inDownFrame->GetContent();
   mGestureDownShift = inDownEvent->isShift;
   mGestureDownControl = inDownEvent->isControl;
   mGestureDownAlt = inDownEvent->isAlt;
   mGestureDownMeta = inDownEvent->isMeta;
   mGestureModifiers = inDownEvent->modifiers;
+  mGestureDownButtons = inDownEvent->buttons;
 
   if (mClickHoldContextMenu) {
     // fire off a timer to track click-hold
     CreateClickHoldTimer(aPresContext, inDownFrame, inDownEvent);
   }
 }
 
 
@@ -2041,16 +2042,17 @@ nsEventStateManager::FillInEventFromGest
   // different
   nsIntPoint tmpPoint = aEvent->widget->WidgetToScreenOffset();
   aEvent->refPoint = mGestureDownPoint - tmpPoint;
   aEvent->isShift = mGestureDownShift;
   aEvent->isControl = mGestureDownControl;
   aEvent->isAlt = mGestureDownAlt;
   aEvent->isMeta = mGestureDownMeta;
   aEvent->modifiers = mGestureModifiers;
+  aEvent->buttons = mGestureDownButtons;
 }
 
 //
 // GenerateDragGesture
 //
 // If we're in the TRACKING state of the d&d gesture tracker, check the current position
 // of the mouse in relation to the old one. If we've moved a sufficient amount from
 // the mouse down, then fire off a drag gesture event.
@@ -2575,16 +2577,17 @@ nsEventStateManager::SendLineScrollEvent
   event.refPoint = aEvent->refPoint;
   event.widget = aEvent->widget;
   event.time = aEvent->time;
   event.isShift = aEvent->isShift;
   event.isControl = aEvent->isControl;
   event.isAlt = aEvent->isAlt;
   event.isMeta = aEvent->isMeta;
   event.modifiers = aEvent->modifiers;
+  event.buttons = aEvent->buttons;
   event.scrollFlags = aEvent->scrollFlags;
   event.delta = aNumLines;
   event.inputSource = static_cast<nsMouseEvent_base*>(aEvent)->inputSource;
 
   nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
 }
 
 void
@@ -2611,16 +2614,17 @@ nsEventStateManager::SendPixelScrollEven
   event.refPoint = aEvent->refPoint;
   event.widget = aEvent->widget;
   event.time = aEvent->time;
   event.isShift = aEvent->isShift;
   event.isControl = aEvent->isControl;
   event.isAlt = aEvent->isAlt;
   event.isMeta = aEvent->isMeta;
   event.modifiers = aEvent->modifiers;
+  event.buttons = aEvent->buttons;
   event.scrollFlags = aEvent->scrollFlags;
   event.inputSource = static_cast<nsMouseEvent_base*>(aEvent)->inputSource;
   event.delta = aPresContext->AppUnitsToIntCSSPixels(aEvent->delta * lineHeight);
 
   nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
 }
 
 PRInt32
@@ -3411,16 +3415,17 @@ nsEventStateManager::PostHandleEvent(nsP
           event.refPoint += mouseEvent->widget->WidgetToScreenOffset();
         }
         event.refPoint -= widget->WidgetToScreenOffset();
         event.isShift = mouseEvent->isShift;
         event.isControl = mouseEvent->isControl;
         event.isAlt = mouseEvent->isAlt;
         event.isMeta = mouseEvent->isMeta;
         event.modifiers = mouseEvent->modifiers;
+        event.buttons = mouseEvent->buttons;
         event.inputSource = mouseEvent->inputSource;
 
         nsEventStatus status = nsEventStatus_eIgnore;
         nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
         if (presShell) {
           presShell->HandleEventWithTarget(&event, mCurrentTarget,
                                            targetContent, &status);
         }
@@ -3837,16 +3842,17 @@ nsEventStateManager::DispatchMouseEvent(
   nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), aMessage, aEvent->widget,
                      nsMouseEvent::eReal);
   event.refPoint = aEvent->refPoint;
   event.isShift = ((nsMouseEvent*)aEvent)->isShift;
   event.isControl = ((nsMouseEvent*)aEvent)->isControl;
   event.isAlt = ((nsMouseEvent*)aEvent)->isAlt;
   event.isMeta = ((nsMouseEvent*)aEvent)->isMeta;
   event.modifiers = ((nsMouseEvent*)aEvent)->modifiers;
+  event.buttons = ((nsMouseEvent*)aEvent)->buttons;
   event.pluginEvent = ((nsMouseEvent*)aEvent)->pluginEvent;
   event.relatedTarget = aRelatedContent;
   event.inputSource = static_cast<nsMouseEvent*>(aEvent)->inputSource;
 
   nsWeakFrame previousTarget = mCurrentTarget;
 
   mCurrentTargetContent = aTargetContent;
 
@@ -4251,16 +4257,17 @@ nsEventStateManager::FireDragEnterOrExit
   nsEventStatus status = nsEventStatus_eIgnore;
   nsDragEvent event(NS_IS_TRUSTED_EVENT(aEvent), aMsg, aEvent->widget);
   event.refPoint = aEvent->refPoint;
   event.isShift = ((nsMouseEvent*)aEvent)->isShift;
   event.isControl = ((nsMouseEvent*)aEvent)->isControl;
   event.isAlt = ((nsMouseEvent*)aEvent)->isAlt;
   event.isMeta = ((nsMouseEvent*)aEvent)->isMeta;
   event.modifiers = ((nsMouseEvent*)aEvent)->modifiers;
+  event.buttons = ((nsMouseEvent*)aEvent)->buttons;
   event.relatedTarget = aRelatedTarget;
   event.inputSource = static_cast<nsMouseEvent*>(aEvent)->inputSource;
 
   mCurrentTargetContent = aTargetContent;
 
   if (aTargetContent != aRelatedTarget) {
     //XXX This event should still go somewhere!!
     if (aTargetContent)
@@ -4414,16 +4421,17 @@ nsEventStateManager::CheckForAndDispatch
                        nsMouseEvent::eReal);
     event.refPoint = aEvent->refPoint;
     event.clickCount = aEvent->clickCount;
     event.isShift = aEvent->isShift;
     event.isControl = aEvent->isControl;
     event.isAlt = aEvent->isAlt;
     event.isMeta = aEvent->isMeta;
     event.modifiers = aEvent->modifiers;
+    event.buttons = aEvent->buttons;
     event.time = aEvent->time;
     event.flags |= flags;
     event.button = aEvent->button;
     event.inputSource = aEvent->inputSource;
 
     nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
     if (presShell) {
       nsCOMPtr<nsIContent> mouseContent = GetEventTargetContent(aEvent);
@@ -4436,16 +4444,17 @@ nsEventStateManager::CheckForAndDispatch
                             aEvent->widget, nsMouseEvent::eReal);
         event2.refPoint = aEvent->refPoint;
         event2.clickCount = aEvent->clickCount;
         event2.isShift = aEvent->isShift;
         event2.isControl = aEvent->isControl;
         event2.isAlt = aEvent->isAlt;
         event2.isMeta = aEvent->isMeta;
         event2.modifiers = aEvent->modifiers;
+        event2.buttons = aEvent->buttons;
         event2.flags |= flags;
         event2.button = aEvent->button;
         event2.inputSource = aEvent->inputSource;
 
         ret = presShell->HandleEventWithTarget(&event2, mCurrentTarget,
                                                mouseContent, aStatus);
       }
     }
@@ -5039,16 +5048,17 @@ nsEventStateManager::DoQueryScrollTarget
     aEvent->mInput.mMouseScrollEvent->message,
     aEvent->mInput.mMouseScrollEvent->widget);
 
   msEvent.isShift = aEvent->mInput.mMouseScrollEvent->isShift;
   msEvent.isControl = aEvent->mInput.mMouseScrollEvent->isControl;
   msEvent.isAlt = aEvent->mInput.mMouseScrollEvent->isAlt;
   msEvent.isMeta = aEvent->mInput.mMouseScrollEvent->isMeta;
   msEvent.modifiers = aEvent->mInput.mMouseScrollEvent->modifiers;
+  msEvent.buttons = aEvent->mInput.mMouseScrollEvent->buttons;
 
   msEvent.scrollFlags = aEvent->mInput.mMouseScrollEvent->scrollFlags;
   msEvent.delta = ComputeWheelDeltaFor(aEvent->mInput.mMouseScrollEvent);
   msEvent.scrollOverflow = aEvent->mInput.mMouseScrollEvent->scrollOverflow;
 
   bool useSystemSettings = UseSystemScrollSettingFor(&msEvent);
 
   nsIScrollableFrame::ScrollUnit unit;
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -506,16 +506,17 @@ private:
   // an <area> of an image map this is the image. (bug 289667)
   nsCOMPtr<nsIContent> mGestureDownFrameOwner;
   // State of keys when the original gesture-down happened
   bool mGestureDownShift;
   bool mGestureDownControl;
   bool mGestureDownAlt;
   bool mGestureDownMeta;
   mozilla::widget::Modifiers mGestureModifiers;
+  PRUint16 mGestureDownButtons;
 
   nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
   nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent;
   nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
   nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent;
   nsCOMPtr<nsIContent> mLastRightMouseDownContent;
   nsCOMPtr<nsIContent> mLastRightMouseDownContentParent;
 
--- a/content/events/test/test_eventctors.html
+++ b/content/events/test/test_eventctors.html
@@ -390,30 +390,32 @@ var mouseEventProps =
   { screenY: 0 },
   { clientX: 0 },
   { clientY: 0 },
   { ctrlKey: false },
   { shiftKey: false },
   { altKey: false },
   { metaKey: false },
   { button: 0 },
+  { buttons: 0 },
   { relatedTarget: null }
 ];
 
 var testProps =
 [
   { screenX: 1 },
   { screenY: 2 },
   { clientX: 3 },
   { clientY: 4 },
   { ctrlKey: true },
   { shiftKey: true },
   { altKey: true },
   { metaKey: true },
   { button: 5 },
+  { buttons: 6 },
   { relatedTarget: window }
 ];
 
 var defaultMouseEventValues = {};
 for (var i = 0; i < mouseEventProps.length; ++i) {
   for (prop in mouseEventProps[i]) {
     ok(prop in e, "MouseEvent doesn't have property " + prop + "!");
     defaultMouseEventValues[prop] = mouseEventProps[i][prop]; 
--- a/dom/interfaces/events/nsIDOMDragEvent.idl
+++ b/dom/interfaces/events/nsIDOMDragEvent.idl
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 #include "nsIDOMMouseEvent.idl"
 
 interface nsIDOMDataTransfer;
 
-[scriptable, uuid(74fb5f01-e473-4302-93f5-6f74bdaaddf2)]
+[scriptable, uuid(54cbd977-dae1-41ae-a155-a5ee5a5c6985)]
 interface nsIDOMDragEvent : nsIDOMMouseEvent
 {
   readonly attribute nsIDOMDataTransfer dataTransfer;
 
   void initDragEvent(in DOMString typeArg,
                      in boolean canBubbleArg,
                      in boolean cancelableArg,
                      in nsIDOMWindow aView,
--- a/dom/interfaces/events/nsIDOMMouseEvent.idl
+++ b/dom/interfaces/events/nsIDOMMouseEvent.idl
@@ -43,17 +43,17 @@
 /**
  * The nsIDOMMouseEvent interface is the datatype for all mouse events
  * in the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Events/
  */
 
-[scriptable, uuid(53E29996-F851-4032-B896-8AAFBD0BDF25)]
+[scriptable, uuid(8de83489-863a-4377-8ce4-f1965c23b8c7)]
 interface nsIDOMMouseEvent : nsIDOMUIEvent
 {
   readonly attribute long               screenX;
   readonly attribute long               screenY;
 
   readonly attribute long               mozMovementX;
   readonly attribute long               mozMovementY;
 
@@ -61,16 +61,17 @@ interface nsIDOMMouseEvent : nsIDOMUIEve
   readonly attribute long               clientY;
 
   readonly attribute boolean            ctrlKey;
   readonly attribute boolean            shiftKey;
   readonly attribute boolean            altKey;
   readonly attribute boolean            metaKey;
 
   readonly attribute unsigned short     button;
+  readonly attribute unsigned short     buttons;
   readonly attribute nsIDOMEventTarget  relatedTarget;
 
   void                      initMouseEvent(in DOMString typeArg,
                                            in boolean canBubbleArg,
                                            in boolean cancelableArg,
                                            in nsIDOMWindow viewArg,
                                            in long detailArg,
                                            in long screenXArg,
@@ -123,11 +124,11 @@ dictionary MouseEventInit : UIEventInit
   long screenY;
   long clientX;
   long clientY;
   boolean ctrlKey;
   boolean shiftKey;
   boolean altKey;
   boolean metaKey;
   unsigned short button;
-  // unsigned short buttons; is not supported yet.
+  unsigned short buttons;
   nsIDOMEventTarget relatedTarget;
 };
--- a/dom/interfaces/events/nsIDOMMouseScrollEvent.idl
+++ b/dom/interfaces/events/nsIDOMMouseScrollEvent.idl
@@ -33,17 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMMouseEvent.idl"
 
-[scriptable, uuid(159f24b9-2058-40b9-b5bc-6477d192955a)]
+[scriptable, uuid(E9CF55A5-0436-4F8B-91B6-7C14115B5033)]
 interface nsIDOMMouseScrollEvent : nsIDOMMouseEvent
 {
   const long HORIZONTAL_AXIS = 1;
   const long VERTICAL_AXIS = 2;
 
   readonly attribute long axis;
 
   void                initMouseScrollEvent(in DOMString typeArg,
--- a/dom/interfaces/events/nsIDOMMozTouchEvent.idl
+++ b/dom/interfaces/events/nsIDOMMozTouchEvent.idl
@@ -35,17 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsIDOMMouseEvent.idl"
 
 
-[scriptable, uuid(268da07b-4c41-4deb-96a2-10985644e6b0)]
+[scriptable, uuid(0830197e-952c-4413-be83-a94e08f4f321)]
 interface nsIDOMMozTouchEvent : nsIDOMMouseEvent
 {
   readonly attribute unsigned long streamId;
 
   void initMozTouchEvent(in DOMString typeArg,
                          in boolean canBubbleArg,
                          in boolean cancelableArg,
                          in nsIDOMWindow viewArg,
--- a/dom/interfaces/events/nsIDOMSimpleGestureEvent.idl
+++ b/dom/interfaces/events/nsIDOMSimpleGestureEvent.idl
@@ -92,17 +92,17 @@
  * Default behavior:
  *
  * Some operating systems support default behaviors for gesture events
  * when they are not handled by the application. Consumers should
  * use event.preventDefault() to prevent default behavior when
  * consuming events.
  */
 
-[scriptable, uuid(e9bdcc53-1bc0-4cae-9eb3-b215b6be7f70)]
+[scriptable, uuid(3aa7b4e8-b7a2-4e42-963d-b6d157eac1cd)]
 interface nsIDOMSimpleGestureEvent : nsIDOMMouseEvent
 {
   /* Swipe direction constants */
   const unsigned long DIRECTION_UP = 1;
   const unsigned long DIRECTION_DOWN = 2;
   const unsigned long DIRECTION_LEFT = 4;
   const unsigned long DIRECTION_RIGHT = 8;
   
--- a/widget/nsGUIEvent.h
+++ b/widget/nsGUIEvent.h
@@ -858,24 +858,25 @@ private:
 
 public:
 
   nsMouseEvent_base()
   {
   }
 
   nsMouseEvent_base(bool isTrusted, PRUint32 msg, nsIWidget *w, PRUint8 type)
-    : nsInputEvent(isTrusted, msg, w, type), button(0), modifiers(0),
-      pressure(0), inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {}
+    : nsInputEvent(isTrusted, msg, w, type), button(0), buttons(0),
+      modifiers(0), pressure(0),
+      inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {}
 
   /// The possible related target
   nsCOMPtr<nsISupports> relatedTarget;
 
   PRInt16               button;
-
+  PRInt16               buttons;
   mozilla::widget::Modifiers modifiers;
 
   // Finger or touch pressure of event
   // ranges between 0.0 and 1.0
   float                 pressure;
 
   // Possible values at nsIDOMMouseEvent
   PRUint16              inputSource;
@@ -884,16 +885,25 @@ public:
 class nsMouseEvent : public nsMouseEvent_base
 {
 private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
 
 public:
   enum buttonType  { eLeftButton = 0, eMiddleButton = 1, eRightButton = 2 };
+  enum buttonsFlag { eLeftButtonFlag   = 0x01,
+                     eRightButtonFlag  = 0x02,
+                     eMiddleButtonFlag = 0x04,
+                     // typicall, "back" button being left side of 5-button
+                     // mice, see "buttons" attribute document of DOM3 Events.
+                     e4thButtonFlag    = 0x08,
+                     // typicall, "forward" button being right side of 5-button
+                     // mice, see "buttons" attribute document of DOM3 Events.
+                     e5thButtonFlag    = 0x10 };
   enum reasonType  { eReal, eSynthesized };
   enum contextType { eNormal, eContextMenuKey };
   enum exitType    { eChild, eTopLevel };
 
   nsMouseEvent()
   {
   }
 
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -113,25 +113,27 @@ template<>
 struct ParamTraits<nsMouseEvent_base>
 {
   typedef nsMouseEvent_base paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<nsInputEvent>(aParam));
     WriteParam(aMsg, aParam.button);
+    WriteParam(aMsg, aParam.buttons);
     WriteParam(aMsg, aParam.modifiers);
     WriteParam(aMsg, aParam.pressure);
     WriteParam(aMsg, aParam.inputSource);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, static_cast<nsInputEvent*>(aResult)) &&
            ReadParam(aMsg, aIter, &aResult->button) &&
+           ReadParam(aMsg, aIter, &aResult->buttons) &&
            ReadParam(aMsg, aIter, &aResult->modifiers) &&
            ReadParam(aMsg, aIter, &aResult->pressure) &&
            ReadParam(aMsg, aIter, &aResult->inputSource);
   }
 };
 
 template<>
 struct ParamTraits<nsMouseScrollEvent>