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 93728 392cb8e0876ffe17d92184b020e4e6666fa9e3ee
parent 93727 ac852666763d0a4e441d82e8a448a4e51262cdd3
child 93729 4d0beaad9f761118e3dbe5a9f88dc12e5ef8e9c8
push idunknown
push userunknown
push dateunknown
reviewerssmaug, jst
bugs731878
milestone15.0a1
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>