Bug 428988 - Expose mouse event pressure. r=Olli.Pettay, sr=roc.
authorOleg Romashin <romaxa@gmail.com>
Thu, 11 Dec 2008 03:04:46 -0500
changeset 22585 3a8df4d8dec4e5af5d8e3b9ca80a9ec1303c8063
parent 22584 4fa1079c75f5925aa42577daa4f7ca37d0d9c120
child 22586 a210c5c09190c595b97e445b986173d499fbf351
child 22597 f6e9542592c7b01aeca21f1d771dac815240a229
push idunknown
push userunknown
push dateunknown
reviewersOlli, roc
bugs428988
milestone1.9.2a1pre
Bug 428988 - Expose mouse event pressure. r=Olli.Pettay, sr=roc.
content/base/src/nsGenericElement.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMMouseEvent.cpp
content/events/src/nsDOMMouseEvent.h
content/events/test/Makefile.in
content/events/test/test_bug428988.html
dom/public/idl/events/Makefile.in
dom/public/idl/events/nsIDOMNSMouseEvent.idl
dom/src/base/nsDOMClassInfo.cpp
widget/public/nsGUIEvent.h
widget/src/gtk2/nsWindow.cpp
widget/src/gtk2/nsWindow.h
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3410,19 +3410,22 @@ nsGenericElement::DispatchClickEvent(nsP
   NS_PRECONDITION(aTarget, "Must have target");
   NS_PRECONDITION(aSourceEvent, "Must have source event");
   NS_PRECONDITION(aStatus, "Null out param?");
 
   nsMouseEvent event(NS_IS_TRUSTED_EVENT(aSourceEvent), NS_MOUSE_CLICK,
                      aSourceEvent->widget, nsMouseEvent::eReal);
   event.refPoint = aSourceEvent->refPoint;
   PRUint32 clickCount = 1;
+  float pressure = 0;
   if (aSourceEvent->eventStructType == NS_MOUSE_EVENT) {
     clickCount = static_cast<nsMouseEvent*>(aSourceEvent)->clickCount;
-  }
+    pressure = static_cast<nsMouseEvent*>(aSourceEvent)->pressure;
+  }
+  event.pressure = pressure;
   event.clickCount = clickCount;
   event.isShift = aSourceEvent->isShift;
   event.isControl = aSourceEvent->isControl;
   event.isAlt = aSourceEvent->isAlt;
   event.isMeta = aSourceEvent->isMeta;
 
   return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
 }
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -817,16 +817,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
         new nsMouseEvent(PR_FALSE, msg, nsnull, oldMouseEvent->reason);
       NS_ENSURE_TRUE(mouseEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = PR_TRUE;
       mouseEvent->clickCount = oldMouseEvent->clickCount;
       mouseEvent->acceptActivation = oldMouseEvent->acceptActivation;
       mouseEvent->context = oldMouseEvent->context;
       mouseEvent->relatedTarget = oldMouseEvent->relatedTarget;
       mouseEvent->button = oldMouseEvent->button;
+      mouseEvent->pressure = oldMouseEvent->pressure;
       newEvent = mouseEvent;
       break;
     }
     case NS_DRAG_EVENT:
     {
       nsDragEvent* oldDragEvent = static_cast<nsDragEvent*>(mEvent);
       nsDragEvent* dragEvent =
         new nsDragEvent(PR_FALSE, msg, nsnull);
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -88,16 +88,17 @@ nsDOMMouseEvent::~nsDOMMouseEvent()
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMMouseEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMouseEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNSMouseEvent)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(MouseEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
 
 NS_IMETHODIMP
 nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
                                 nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX, 
                                 PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY, 
                                 PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey, 
@@ -132,16 +133,34 @@ nsDOMMouseEvent::InitMouseEvent(const ns
     default:
        break;
   }
 
   return NS_OK;
 }   
 
 NS_IMETHODIMP
+nsDOMMouseEvent::InitNSMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
+                                  nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX,
+                                  PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY,
+                                  PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey,
+                                  PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget,
+                                  float aPressure)
+{
+  nsresult rv = nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
+                                                aView, aDetail, aScreenX, aScreenY,
+                                                aClientX, aClientY, aCtrlKey, aAltKey, aShiftKey,
+                                                aMetaKey, aButton, aRelatedTarget);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  static_cast<nsMouseEvent_base*>(mEvent)->pressure = aPressure;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMMouseEvent::GetButton(PRUint16* aButton)
 {
   NS_ENSURE_ARG_POINTER(aButton);
   switch(mEvent->eventStructType)
   {
     case NS_MOUSE_EVENT:
     case NS_MOUSE_SCROLL_EVENT:
       *aButton = static_cast<nsMouseEvent_base*>(mEvent)->button;
@@ -244,16 +263,24 @@ nsDOMMouseEvent::GetWhich(PRUint32* aWhi
 {
   NS_ENSURE_ARG_POINTER(aWhich);
   PRUint16 button;
   (void) GetButton(&button);
   *aWhich = button + 1;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMMouseEvent::GetMozPressure(float* aPressure)
+{
+  NS_ENSURE_ARG_POINTER(aPressure);
+  *aPressure = static_cast<nsMouseEvent_base*>(mEvent)->pressure;
+  return NS_OK;
+}
+
 nsresult NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult,
                              nsPresContext* aPresContext,
                              nsInputEvent *aEvent) 
 {
   nsDOMMouseEvent* it = new nsDOMMouseEvent(aPresContext, aEvent);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/events/src/nsDOMMouseEvent.h
+++ b/content/events/src/nsDOMMouseEvent.h
@@ -36,33 +36,37 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsDOMMouseEvent_h__
 #define nsDOMMouseEvent_h__
 
 #include "nsIDOMMouseEvent.h"
 #include "nsDOMUIEvent.h"
+#include "nsIDOMNSMouseEvent.h"
 
 class nsIContent;
 class nsIScrollableView;
 class nsEvent;
 
-class nsDOMMouseEvent : public nsIDOMMouseEvent,
-                        public nsDOMUIEvent
+class nsDOMMouseEvent : public nsDOMUIEvent,
+                        public nsIDOMNSMouseEvent
 {
 public:
   nsDOMMouseEvent(nsPresContext* aPresContext, nsInputEvent* aEvent);
   virtual ~nsDOMMouseEvent();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMMouseEvent Interface
   NS_DECL_NSIDOMMOUSEEVENT
-  
+
+  // nsIDOMNSMouseEvent Interface
+  NS_DECL_NSIDOMNSMOUSEEVENT
+
   // Forward to base class
   NS_FORWARD_TO_NSDOMUIEVENT
 
   // Specific implementation for a mouse event.
   NS_IMETHOD GetWhich(PRUint32 *aWhich);
 };
 
 #define NS_FORWARD_TO_NSDOMMOUSEEVENT         \
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -59,16 +59,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug402089.html \
 		test_bug405632.html \
 		test_bug409604.html \
 		test_bug412567.html \
 		test_bug443985.html \
 		test_bug447736.html \
 		test_bug456273.html \
 		test_bug457672.html \
+		test_bug428988.html \
 		bug457672.html \
 		test_draggableprop.html \
 		test_dragstart.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_bug415498.xul \
 		bug415498-doc1.html \
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug428988.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=428988
+-->
+<head>
+  <title>Test for Bug 428988</title>
+  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428988">Mozilla Bug 428988</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 428988 **/
+
+function listenerForClick(evt) {
+  is(Math.round(evt.mozPressure*100), 56, "Wrong .mozPressure");
+}
+
+function doTest() {
+  var target = document.getElementById("testTarget");
+  target.addEventListener("click", listenerForClick, true);
+  var me = document.createEvent("MouseEvent");
+  me.initNSMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
+                      false, false, false, false, 0, null, 0.56);
+  target.dispatchEvent(me);
+  target.removeEventListener("click", listenerForClick, true);
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+
+</script>
+</pre>
+<span id="testTarget" style="border: 1px solid black;">testTarget</span>
+</body>
+</html>
--- a/dom/public/idl/events/Makefile.in
+++ b/dom/public/idl/events/Makefile.in
@@ -72,11 +72,12 @@ XPIDLSRCS =					\
 	nsIDOMBeforeUnloadEvent.idl		\
 	nsIDOMNSEventTarget.idl			\
 	nsIDOMSmartCardEvent.idl                \
 	nsIDOMPageTransitionEvent.idl		\
 	nsIDOMCommandEvent.idl			\
 	nsIDOMMessageEvent.idl			\
 	nsIDOMNotifyPaintEvent.idl              \
 	nsIDOMSimpleGestureEvent.idl		\
+	nsIDOMNSMouseEvent.idl			\
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/public/idl/events/nsIDOMNSMouseEvent.idl
@@ -0,0 +1,69 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * 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"
+
+/**
+ * The nsIDOMNSMouseEvent interface extends nsIDOMMouseEvent
+ * by providing various information related to the mouse event.
+ */
+
+[scriptable, uuid(1b8e528d-7dca-44ee-8ee6-c44594ebcef1)]
+interface nsIDOMNSMouseEvent : nsIDOMMouseEvent
+{
+  // Finger or touch pressure event value
+  // ranges between 0.0 and 1.0
+  readonly attribute float mozPressure;
+
+  void                initNSMouseEvent(in DOMString typeArg,
+                                       in boolean canBubbleArg,
+                                       in boolean cancelableArg,
+                                       in nsIDOMAbstractView viewArg,
+                                       in long detailArg,
+                                       in long screenXArg,
+                                       in long screenYArg,
+                                       in long clientXArg,
+                                       in long clientYArg,
+                                       in boolean ctrlKeyArg,
+                                       in boolean altKeyArg,
+                                       in boolean shiftKeyArg,
+                                       in boolean metaKeyArg,
+                                       in unsigned short buttonArg,
+                                       in nsIDOMEventTarget relatedTargetArg,
+                                       in float pressure);
+};
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -460,16 +460,18 @@
 #include "nsDOMWorker.h"
 
 #include "nsDOMFile.h"
 #include "nsIDOMFileException.h"
 
 // Simple gestures include
 #include "nsIDOMSimpleGestureEvent.h"
 
+#include "nsIDOMNSMouseEvent.h"
+
 static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
 //       are defined in nsIDOMClassInfo.h.
@@ -2144,27 +2146,30 @@ nsDOMClassInfo::Init()
   
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(KeyboardEvent, nsIDOMKeyEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMKeyEvent)
     DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MouseEvent, nsIDOMMouseEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMouseEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSMouseEvent)
     DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MouseScrollEvent, nsIDOMMouseScrollEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMouseScrollEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMouseEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSMouseEvent)
     DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DragEvent, nsIDOMDragEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDragEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSMouseEvent)
     DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
     DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -674,22 +674,26 @@ public:
 /**
  * Mouse event
  */
 
 class nsMouseEvent_base : public nsInputEvent
 {
 public:
   nsMouseEvent_base(PRBool isTrusted, PRUint32 msg, nsIWidget *w, PRUint8 type)
-  : nsInputEvent(isTrusted, msg, w, type), button(0) {}
+  : nsInputEvent(isTrusted, msg, w, type), button(0), pressure(0) {}
 
   /// The possible related target
   nsCOMPtr<nsISupports> relatedTarget;
 
   PRInt16               button;
+
+  // Finger or touch pressure of event
+  // ranges between 0.0 and 1.0
+  float                 pressure;
 };
 
 class nsMouseEvent : public nsMouseEvent_base
 {
 public:
   enum buttonType  { eLeftButton = 0, eMiddleButton = 1, eRightButton = 2 };
   enum reasonType  { eReal, eSynthesized };
   enum contextType { eNormal, eContextMenuKey };
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -393,16 +393,17 @@ nsWindow::nsWindow()
     if (mLastDragMotionWindow == this)
         mLastDragMotionWindow = NULL;
     mDragMotionWidget = 0;
     mDragMotionContext = 0;
     mDragMotionX = 0;
     mDragMotionY = 0;
     mDragMotionTime = 0;
     mDragMotionTimerID = 0;
+    mLastMotionPressure = 0;
 
 #ifdef USE_XIM
     mIMEData = nsnull;
 #endif
 
 #ifdef ACCESSIBILITY
     mRootAccessible  = nsnull;
 #endif
@@ -2529,16 +2530,25 @@ nsWindow::OnMotionNotifyEvent(GtkWidget 
 
 
     // when we receive this, it must be that the gtk dragging is over,
     // it is dropped either in or out of mozilla, clear the flag
     sIsDraggingOutOf = PR_FALSE;
 
     nsMouseEvent event(PR_TRUE, NS_MOUSE_MOVE, this, nsMouseEvent::eReal);
 
+    // should we move this into !synthEvent?
+    gdouble pressure = 0;
+    gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+    // Sometime gdk generate 0 pressure value between normal values
+    // We have to ignore that and use last valid value
+    if (pressure)
+      mLastMotionPressure = pressure;
+    event.pressure = mLastMotionPressure;
+
     nsRect windowRect;
     ScreenToWidget(nsRect(nscoord(cursorX), nscoord(cursorY), 1, 1), windowRect);
 
     event.refPoint.x = windowRect.x;
     event.refPoint.y = windowRect.y;
 
     event.isShift   = (aEvent->state & GDK_SHIFT_MASK)
         ? PR_TRUE : PR_FALSE;
@@ -2582,16 +2592,24 @@ nsWindow::OnMotionNotifyEvent(GtkWidget 
     if (gPluginFocusWindow && gPluginFocusWindow != this) {
         nsRefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
         gPluginFocusWindow->LoseNonXEmbedPluginFocus();
     }
 #endif /* MOZ_X11 */
 
     nsMouseEvent event(PR_TRUE, NS_MOUSE_MOVE, this, nsMouseEvent::eReal);
 
+    gdouble pressure = 0;
+    gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+    // Sometime gdk generate 0 pressure value between normal values
+    // We have to ignore that and use last valid value
+    if (pressure)
+      mLastMotionPressure = pressure;
+    event.pressure = mLastMotionPressure;
+
     if (synthEvent) {
 #ifdef MOZ_X11
         event.refPoint.x = nscoord(xevent.xmotion.x);
         event.refPoint.y = nscoord(xevent.xmotion.y);
 
         event.isShift   = (xevent.xmotion.state & GDK_SHIFT_MASK)
             ? PR_TRUE : PR_FALSE;
         event.isControl = (xevent.xmotion.state & GDK_CONTROL_MASK)
@@ -2710,32 +2728,37 @@ nsWindow::OnButtonPressEvent(GtkWidget *
         DispatchActivateEvent();
     }
 
     PRBool rolledUp = check_for_rollup(aEvent->window, aEvent->x_root,
                                        aEvent->y_root, PR_FALSE);
     if (gConsumeRollupEvent && rolledUp)
             return;
 
+    gdouble pressure = 0;
+    gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+    mLastMotionPressure = pressure;
+
     PRUint16 domButton;
     switch (aEvent->button) {
     case 1:
         domButton = nsMouseEvent::eLeftButton;
         break;
     case 2:
         domButton = nsMouseEvent::eMiddleButton;
         break;
     case 3:
         domButton = nsMouseEvent::eRightButton;
         break;
     // These are mapped to horizontal scroll
     case 6:
     case 7:
         {
             nsMouseScrollEvent event(PR_TRUE, NS_MOUSE_SCROLL, this);
+            event.pressure = mLastMotionPressure;
             event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
             event.refPoint.x = nscoord(aEvent->x);
             event.refPoint.y = nscoord(aEvent->y);
             event.delta = (aEvent->button == 6) ? -2 : 2;
 
             event.isShift   = (aEvent->state & GDK_SHIFT_MASK) != 0;
             event.isControl = (aEvent->state & GDK_CONTROL_MASK) != 0;
             event.isAlt     = (aEvent->state & GDK_MOD1_MASK) != 0;
@@ -2756,25 +2779,27 @@ nsWindow::OnButtonPressEvent(GtkWidget *
         return;
     default:
         return;
     }
 
     nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_DOWN, this, nsMouseEvent::eReal);
     event.button = domButton;
     InitButtonEvent(event, aEvent);
+    event.pressure = mLastMotionPressure;
 
     DispatchEvent(&event, status);
 
     // right menu click on linux should also pop up a context menu
     if (domButton == nsMouseEvent::eRightButton &&
         NS_LIKELY(!mIsDestroyed)) {
         nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
                                       nsMouseEvent::eReal);
         InitButtonEvent(contextMenuEvent, aEvent);
+        contextMenuEvent.pressure = mLastMotionPressure;
         DispatchEvent(&contextMenuEvent, status);
     }
 }
 
 void
 nsWindow::OnButtonReleaseEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
 {
     PRUint16 domButton;
@@ -2792,19 +2817,23 @@ nsWindow::OnButtonReleaseEvent(GtkWidget
         break;
     default:
         return;
     }
 
     nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_UP, this, nsMouseEvent::eReal);
     event.button = domButton;
     InitButtonEvent(event, aEvent);
+    gdouble pressure = 0;
+    gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+    event.pressure = pressure ? pressure : mLastMotionPressure;
 
     nsEventStatus status;
     DispatchEvent(&event, status);
+    mLastMotionPressure = pressure;
 }
 
 void
 nsWindow::OnContainerFocusInEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
 {
     LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
     // Return if someone has blocked events for this widget.  This will
     // happen if someone has called gtk_widget_grab_focus() from
--- a/widget/src/gtk2/nsWindow.h
+++ b/widget/src/gtk2/nsWindow.h
@@ -545,16 +545,17 @@ private:
     // repeatedly
     GtkWidget         *mDragMotionWidget;
     GdkDragContext    *mDragMotionContext;
     gint               mDragMotionX;
     gint               mDragMotionY;
     guint              mDragMotionTime;
     guint              mDragMotionTimerID;
     nsCOMPtr<nsITimer> mDragLeaveTimer;
+    float              mLastMotionPressure;
 
     static PRBool      sIsDraggingOutOf;
     // drag in progress
     static PRBool DragInProgress(void);
 
     void         ResetDragMotionTimer     (GtkWidget      *aWidget,
                                            GdkDragContext *aDragContext,
                                            gint           aX,