widget/MouseEvents.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_MouseEvents_h__
     7 #define mozilla_MouseEvents_h__
     9 #include <stdint.h>
    11 #include "mozilla/BasicEvents.h"
    12 #include "mozilla/MathAlgorithms.h"
    13 #include "mozilla/dom/DataTransfer.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsIDOMMouseEvent.h"
    16 #include "nsIDOMWheelEvent.h"
    18 /******************************************************************************
    19  * nsDragDropEventStatus
    20  ******************************************************************************/
    22 enum nsDragDropEventStatus
    23 {  
    24   // The event is a enter
    25   nsDragDropEventStatus_eDragEntered,
    26   // The event is exit
    27   nsDragDropEventStatus_eDragExited,
    28   // The event is drop
    29   nsDragDropEventStatus_eDrop
    30 };
    32 namespace mozilla {
    34 namespace dom {
    35   class PBrowserParent;
    36   class PBrowserChild;
    37 } // namespace dom
    39 /******************************************************************************
    40  * mozilla::WidgetPointerHelper
    41  ******************************************************************************/
    43 class WidgetPointerHelper
    44 {
    45 public:
    46   bool convertToPointer;
    47   uint32_t pointerId;
    48   uint32_t tiltX;
    49   uint32_t tiltY;
    51   WidgetPointerHelper() : convertToPointer(true), pointerId(0), tiltX(0), tiltY(0) {}
    53   void AssignPointerHelperData(const WidgetPointerHelper& aEvent)
    54   {
    55     convertToPointer = aEvent.convertToPointer;
    56     pointerId = aEvent.pointerId;
    57     tiltX = aEvent.tiltX;
    58     tiltY = aEvent.tiltY;
    59   }
    60 };
    62 /******************************************************************************
    63  * mozilla::WidgetMouseEventBase
    64  ******************************************************************************/
    66 class WidgetMouseEventBase : public WidgetInputEvent
    67 {
    68 private:
    69   friend class dom::PBrowserParent;
    70   friend class dom::PBrowserChild;
    72 protected:
    73   WidgetMouseEventBase()
    74   {
    75   }
    77   WidgetMouseEventBase(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
    78                        nsEventStructType aStructType) :
    79     WidgetInputEvent(aIsTrusted, aMessage, aWidget, aStructType),
    80     button(0), buttons(0), pressure(0),
    81     inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
    82  {
    83  }
    85 public:
    86   virtual WidgetMouseEventBase* AsMouseEventBase() MOZ_OVERRIDE { return this; }
    88   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
    89   {
    90     MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
    91     return nullptr;
    92   }
    94   /// The possible related target
    95   nsCOMPtr<nsISupports> relatedTarget;
    97   enum buttonType
    98   {
    99     eLeftButton   = 0,
   100     eMiddleButton = 1,
   101     eRightButton  = 2
   102   };
   103   // Pressed button ID of mousedown or mouseup event.
   104   // This is set only when pressing a button causes the event.
   105   int16_t button;
   107   enum buttonsFlag {
   108     eLeftButtonFlag   = 0x01,
   109     eRightButtonFlag  = 0x02,
   110     eMiddleButtonFlag = 0x04,
   111     // typicall, "back" button being left side of 5-button
   112     // mice, see "buttons" attribute document of DOM3 Events.
   113     e4thButtonFlag    = 0x08,
   114     // typicall, "forward" button being right side of 5-button
   115     // mice, see "buttons" attribute document of DOM3 Events.
   116     e5thButtonFlag    = 0x10
   117   };
   119   // Flags of all pressed buttons at the event fired.
   120   // This is set at any mouse event, don't be confused with |button|.
   121   int16_t buttons;
   123   // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
   124   float pressure;
   126   // Possible values at nsIDOMMouseEvent
   127   uint16_t inputSource;
   129   void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
   130                                 bool aCopyTargets)
   131   {
   132     AssignInputEventData(aEvent, aCopyTargets);
   134     relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr;
   135     button = aEvent.button;
   136     buttons = aEvent.buttons;
   137     pressure = aEvent.pressure;
   138     inputSource = aEvent.inputSource;
   139   }
   141   /**
   142    * Returns true if left click event.
   143    */
   144   bool IsLeftClickEvent() const
   145   {
   146     return message == NS_MOUSE_CLICK && button == eLeftButton;
   147   }
   148 };
   150 /******************************************************************************
   151  * mozilla::WidgetMouseEvent
   152  ******************************************************************************/
   154 class WidgetMouseEvent : public WidgetMouseEventBase, public WidgetPointerHelper
   155 {
   156 private:
   157   friend class mozilla::dom::PBrowserParent;
   158   friend class mozilla::dom::PBrowserChild;
   160 public:
   161   enum reasonType
   162   {
   163     eReal,
   164     eSynthesized
   165   };
   167   enum contextType
   168   {
   169     eNormal,
   170     eContextMenuKey
   171   };
   173   enum exitType
   174   {
   175     eChild,
   176     eTopLevel
   177   };
   179 protected:
   180   WidgetMouseEvent()
   181   {
   182   }
   184   WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
   185                    nsEventStructType aStructType, reasonType aReason) :
   186     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aStructType),
   187     acceptActivation(false), ignoreRootScrollFrame(false),
   188     reason(aReason), context(eNormal), exit(eChild), clickCount(0)
   189   {
   190     switch (aMessage) {
   191       case NS_MOUSEENTER:
   192       case NS_MOUSELEAVE:
   193         mFlags.mBubbles = false;
   194         mFlags.mCancelable = false;
   195         break;
   196       default:
   197         break;
   198     }
   199   }
   201 public:
   202   virtual WidgetMouseEvent* AsMouseEvent() MOZ_OVERRIDE { return this; }
   204   WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
   205                    reasonType aReason, contextType aContext = eNormal) :
   206     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_EVENT),
   207     acceptActivation(false), ignoreRootScrollFrame(false),
   208     reason(aReason), context(aContext), exit(eChild), clickCount(0)
   209   {
   210     switch (aMessage) {
   211       case NS_MOUSEENTER:
   212       case NS_MOUSELEAVE:
   213         mFlags.mBubbles = false;
   214         mFlags.mCancelable = false;
   215         break;
   216       case NS_CONTEXTMENU:
   217         button = (context == eNormal) ? eRightButton : eLeftButton;
   218         break;
   219       default:
   220         break;
   221     }
   222   }
   224 #ifdef DEBUG
   225   virtual ~WidgetMouseEvent()
   226   {
   227     NS_WARN_IF_FALSE(message != NS_CONTEXTMENU ||
   228                      button ==
   229                        ((context == eNormal) ? eRightButton : eLeftButton),
   230                      "Wrong button set to NS_CONTEXTMENU event?");
   231   }
   232 #endif
   234   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   235   {
   236     MOZ_ASSERT(eventStructType == NS_MOUSE_EVENT,
   237                "Duplicate() must be overridden by sub class");
   238     // Not copying widget, it is a weak reference.
   239     WidgetMouseEvent* result =
   240       new WidgetMouseEvent(false, message, nullptr, reason, context);
   241     result->AssignMouseEventData(*this, true);
   242     result->mFlags = mFlags;
   243     return result;
   244   }
   246   // Special return code for MOUSE_ACTIVATE to signal.
   247   // If the target accepts activation (1), or denies it (0).
   248   bool acceptActivation;
   249   // Whether the event should ignore scroll frame bounds during dispatch.
   250   bool ignoreRootScrollFrame;
   252   reasonType reason : 4;
   253   contextType context : 4;
   254   exitType exit;
   256   /// The number of mouse clicks.
   257   uint32_t clickCount;
   259   void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets)
   260   {
   261     AssignMouseEventBaseData(aEvent, aCopyTargets);
   262     AssignPointerHelperData(aEvent);
   264     acceptActivation = aEvent.acceptActivation;
   265     ignoreRootScrollFrame = aEvent.ignoreRootScrollFrame;
   266     clickCount = aEvent.clickCount;
   267   }
   269   /**
   270    * Returns true if the event is a context menu event caused by key.
   271    */
   272   bool IsContextMenuKeyEvent() const
   273   {
   274     return message == NS_CONTEXTMENU && context == eContextMenuKey;
   275   }
   277   /**
   278    * Returns true if the event is a real mouse event.  Otherwise, i.e., it's
   279    * a synthesized event by scroll or something, returns false.
   280    */
   281   bool IsReal() const
   282   {
   283     return reason == eReal;
   284   }
   285 };
   287 /******************************************************************************
   288  * mozilla::WidgetDragEvent
   289  ******************************************************************************/
   291 class WidgetDragEvent : public WidgetMouseEvent
   292 {
   293 public:
   294   virtual WidgetDragEvent* AsDragEvent() MOZ_OVERRIDE { return this; }
   296   WidgetDragEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
   297     WidgetMouseEvent(aIsTrusted, aMessage, aWidget, NS_DRAG_EVENT, eReal),
   298     userCancelled(false), mDefaultPreventedOnContent(false)
   299   {
   300     mFlags.mCancelable =
   301       (aMessage != NS_DRAGDROP_EXIT_SYNTH &&
   302        aMessage != NS_DRAGDROP_LEAVE_SYNTH &&
   303        aMessage != NS_DRAGDROP_END);
   304   }
   306   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   307   {
   308     MOZ_ASSERT(eventStructType == NS_DRAG_EVENT,
   309                "Duplicate() must be overridden by sub class");
   310     // Not copying widget, it is a weak reference.
   311     WidgetDragEvent* result = new WidgetDragEvent(false, message, nullptr);
   312     result->AssignDragEventData(*this, true);
   313     result->mFlags = mFlags;
   314     return result;
   315   }
   317   // The dragging data.
   318   nsCOMPtr<dom::DataTransfer> dataTransfer;
   320   // If this is true, user has cancelled the drag operation.
   321   bool userCancelled;
   322   // If this is true, the drag event's preventDefault() is called on content.
   323   bool mDefaultPreventedOnContent;
   325   // XXX Not tested by test_assign_event_data.html
   326   void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets)
   327   {
   328     AssignMouseEventData(aEvent, aCopyTargets);
   330     dataTransfer = aEvent.dataTransfer;
   331     // XXX userCancelled isn't copied, is this instentionally?
   332     userCancelled = false;
   333     mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
   334   }
   335 };
   337 /******************************************************************************
   338  * mozilla::WidgetMouseScrollEvent
   339  *
   340  * This is used for legacy DOM mouse scroll events, i.e.,
   341  * DOMMouseScroll and MozMousePixelScroll event.  These events are NOT hanbled
   342  * by ESM even if widget dispatches them.  Use new WidgetWheelEvent instead.
   343  ******************************************************************************/
   345 class WidgetMouseScrollEvent : public WidgetMouseEventBase
   346 {
   347 private:
   348   WidgetMouseScrollEvent()
   349   {
   350   }
   352 public:
   353   virtual WidgetMouseScrollEvent* AsMouseScrollEvent() MOZ_OVERRIDE
   354   {
   355     return this;
   356   }
   358   WidgetMouseScrollEvent(bool aIsTrusted, uint32_t aMessage,
   359                          nsIWidget* aWidget) :
   360     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_SCROLL_EVENT),
   361     delta(0), isHorizontal(false)
   362   {
   363   }
   365   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   366   {
   367     MOZ_ASSERT(eventStructType == NS_MOUSE_SCROLL_EVENT,
   368                "Duplicate() must be overridden by sub class");
   369     // Not copying widget, it is a weak reference.
   370     WidgetMouseScrollEvent* result =
   371       new WidgetMouseScrollEvent(false, message, nullptr);
   372     result->AssignMouseScrollEventData(*this, true);
   373     result->mFlags = mFlags;
   374     return result;
   375   }
   377   // The delta value of mouse scroll event.
   378   // If the event message is NS_MOUSE_SCROLL, the value indicates scroll amount
   379   // in lines.  However, if the value is nsIDOMUIEvent::SCROLL_PAGE_UP or
   380   // nsIDOMUIEvent::SCROLL_PAGE_DOWN, the value inducates one page scroll.
   381   // If the event message is NS_MOUSE_PIXEL_SCROLL, the value indicates scroll
   382   // amount in pixels.
   383   int32_t delta;
   385   // If this is true, it may cause to scroll horizontally.
   386   // Otherwise, vertically.
   387   bool isHorizontal;
   389   void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
   390                                   bool aCopyTargets)
   391   {
   392     AssignMouseEventBaseData(aEvent, aCopyTargets);
   394     delta = aEvent.delta;
   395     isHorizontal = aEvent.isHorizontal;
   396   }
   397 };
   399 /******************************************************************************
   400  * mozilla::WidgetWheelEvent
   401  ******************************************************************************/
   403 class WidgetWheelEvent : public WidgetMouseEventBase
   404 {
   405 private:
   406   friend class mozilla::dom::PBrowserParent;
   407   friend class mozilla::dom::PBrowserChild;
   409   WidgetWheelEvent()
   410   {
   411   }
   413 public:
   414   virtual WidgetWheelEvent* AsWheelEvent() MOZ_OVERRIDE { return this; }
   416   WidgetWheelEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
   417     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT),
   418     deltaX(0.0), deltaY(0.0), deltaZ(0.0),
   419     deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
   420     customizedByUserPrefs(false), isMomentum(false), isPixelOnlyDevice(false),
   421     lineOrPageDeltaX(0), lineOrPageDeltaY(0), scrollType(SCROLL_DEFAULT),
   422     overflowDeltaX(0.0), overflowDeltaY(0.0),
   423     mViewPortIsOverscrolled(false)
   424   {
   425   }
   427   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   428   {
   429     MOZ_ASSERT(eventStructType == NS_WHEEL_EVENT,
   430                "Duplicate() must be overridden by sub class");
   431     // Not copying widget, it is a weak reference.
   432     WidgetWheelEvent* result = new WidgetWheelEvent(false, message, nullptr);
   433     result->AssignWheelEventData(*this, true);
   434     result->mFlags = mFlags;
   435     return result;
   436   }
   438   // NOTE: deltaX, deltaY and deltaZ may be customized by
   439   //       mousewheel.*.delta_multiplier_* prefs which are applied by
   440   //       EventStateManager.  So, after widget dispatches this event,
   441   //       these delta values may have different values than before.
   442   double deltaX;
   443   double deltaY;
   444   double deltaZ;
   446   // Should be one of nsIDOMWheelEvent::DOM_DELTA_*
   447   uint32_t deltaMode;
   449   // Following members are for internal use only, not for DOM event.
   451   // If the delta values are computed from prefs, this value is true.
   452   // Otherwise, i.e., they are computed from native events, false.
   453   bool customizedByUserPrefs;
   455   // true if the event is caused by momentum.
   456   bool isMomentum;
   458   // If device event handlers don't know when they should set lineOrPageDeltaX
   459   // and lineOrPageDeltaY, this is true.  Otherwise, false.
   460   // If isPixelOnlyDevice is true, ESM will generate NS_MOUSE_SCROLL events
   461   // when accumulated pixel delta values reach a line height.
   462   bool isPixelOnlyDevice;
   464   // If widget sets lineOrPageDelta, EventStateManager will dispatch
   465   // NS_MOUSE_SCROLL event for compatibility.  Note that the delta value means
   466   // pages if the deltaMode is DOM_DELTA_PAGE, otherwise, lines.
   467   int32_t lineOrPageDeltaX;
   468   int32_t lineOrPageDeltaY;
   470   // When the default action for an wheel event is moving history or zooming,
   471   // need to chose a delta value for doing it.
   472   int32_t GetPreferredIntDelta()
   473   {
   474     if (!lineOrPageDeltaX && !lineOrPageDeltaY) {
   475       return 0;
   476     }
   477     if (lineOrPageDeltaY && !lineOrPageDeltaX) {
   478       return lineOrPageDeltaY;
   479     }
   480     if (lineOrPageDeltaX && !lineOrPageDeltaY) {
   481       return lineOrPageDeltaX;
   482     }
   483     if ((lineOrPageDeltaX < 0 && lineOrPageDeltaY > 0) ||
   484         (lineOrPageDeltaX > 0 && lineOrPageDeltaY < 0)) {
   485       return 0; // We cannot guess the answer in this case.
   486     }
   487     return (Abs(lineOrPageDeltaX) > Abs(lineOrPageDeltaY)) ?
   488              lineOrPageDeltaX : lineOrPageDeltaY;
   489   }
   491   // Scroll type
   492   // The default value is SCROLL_DEFAULT, which means EventStateManager will
   493   // select preferred scroll type automatically.
   494   enum ScrollType
   495   {
   496     SCROLL_DEFAULT,
   497     SCROLL_SYNCHRONOUSLY,
   498     SCROLL_ASYNCHRONOUSELY,
   499     SCROLL_SMOOTHLY
   500   };
   501   ScrollType scrollType;
   503   // overflowed delta values for scroll, these values are set by
   504   // nsEventStateManger.  If the default action of the wheel event isn't scroll,
   505   // these values always zero.  Otherwise, remaning delta values which are
   506   // not used by scroll are set.
   507   // NOTE: deltaX, deltaY and deltaZ may be modified by EventStateManager.
   508   //       However, overflowDeltaX and overflowDeltaY indicate unused original
   509   //       delta values which are not applied the delta_multiplier prefs.
   510   //       So, if widget wanted to know the actual direction to be scrolled,
   511   //       it would need to check the deltaX and deltaY.
   512   double overflowDeltaX;
   513   double overflowDeltaY;
   515   // Whether or not the parent of the currently overscrolled frame is the
   516   // ViewPort. This is false in situations when an element on the page is being
   517   // overscrolled (such as a text field), but true when the 'page' is being
   518   // overscrolled.
   519   bool mViewPortIsOverscrolled;
   521   void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
   522   {
   523     AssignMouseEventBaseData(aEvent, aCopyTargets);
   525     deltaX = aEvent.deltaX;
   526     deltaY = aEvent.deltaY;
   527     deltaZ = aEvent.deltaZ;
   528     deltaMode = aEvent.deltaMode;
   529     customizedByUserPrefs = aEvent.customizedByUserPrefs;
   530     isMomentum = aEvent.isMomentum;
   531     isPixelOnlyDevice = aEvent.isPixelOnlyDevice;
   532     lineOrPageDeltaX = aEvent.lineOrPageDeltaX;
   533     lineOrPageDeltaY = aEvent.lineOrPageDeltaY;
   534     scrollType = aEvent.scrollType;
   535     overflowDeltaX = aEvent.overflowDeltaX;
   536     overflowDeltaY = aEvent.overflowDeltaY;
   537     mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
   538   }
   539 };
   541 /******************************************************************************
   542  * mozilla::WidgetPointerEvent
   543  ******************************************************************************/
   545 class WidgetPointerEvent : public WidgetMouseEvent
   546 {
   547   friend class mozilla::dom::PBrowserParent;
   548   friend class mozilla::dom::PBrowserChild;
   550   WidgetPointerEvent()
   551   {
   552   }
   554 public:
   555   virtual WidgetPointerEvent* AsPointerEvent() MOZ_OVERRIDE { return this; }
   557   WidgetPointerEvent(bool aIsTrusted, uint32_t aMsg, nsIWidget* w)
   558     : WidgetMouseEvent(aIsTrusted, aMsg, w, NS_POINTER_EVENT, eReal)
   559     , width(0)
   560     , height(0)
   561     , isPrimary(true)
   562   {
   563     UpdateFlags();
   564   }
   566   WidgetPointerEvent(const WidgetMouseEvent& aEvent)
   567     : WidgetMouseEvent(aEvent)
   568     , width(0)
   569     , height(0)
   570     , isPrimary(true)
   571   {
   572     eventStructType = NS_POINTER_EVENT;
   573     UpdateFlags();
   574   }
   576   void UpdateFlags()
   577   {
   578     switch (message) {
   579       case NS_POINTER_ENTER:
   580       case NS_POINTER_LEAVE:
   581         mFlags.mBubbles = false;
   582         mFlags.mCancelable = false;
   583         break;
   584       case NS_POINTER_CANCEL:
   585       case NS_POINTER_GOT_CAPTURE:
   586       case NS_POINTER_LOST_CAPTURE:
   587         mFlags.mCancelable = false;
   588         break;
   589       default:
   590         break;
   591     }
   592   }
   594   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   595   {
   596     MOZ_ASSERT(eventStructType == NS_POINTER_EVENT,
   597                "Duplicate() must be overridden by sub class");
   598     // Not copying widget, it is a weak reference.
   599     WidgetPointerEvent* result =
   600       new WidgetPointerEvent(false, message, nullptr);
   601     result->AssignPointerEventData(*this, true);
   602     result->mFlags = mFlags;
   603     return result;
   604   }
   606   uint32_t width;
   607   uint32_t height;
   608   bool isPrimary;
   610   // XXX Not tested by test_assign_event_data.html
   611   void AssignPointerEventData(const WidgetPointerEvent& aEvent,
   612                               bool aCopyTargets)
   613   {
   614     AssignMouseEventData(aEvent, aCopyTargets);
   616     width = aEvent.width;
   617     height = aEvent.height;
   618     isPrimary = aEvent.isPrimary;
   619   }
   620 };
   622 } // namespace mozilla
   624 #endif // mozilla_MouseEvents_h__

mercurial