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/. */
5 
6 #ifndef mozilla_MouseEvents_h__
7 #define mozilla_MouseEvents_h__
8 
9 #include <stdint.h>
10 
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"
17 
18 /******************************************************************************
19  * nsDragDropEventStatus
20  ******************************************************************************/
21 
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 };
31 
32 namespace mozilla {
33 
34 namespace dom {
35   class PBrowserParent;
36   class PBrowserChild;
37 } // namespace dom
38 
39 /******************************************************************************
40  * mozilla::WidgetPointerHelper
41  ******************************************************************************/
42 
43 class WidgetPointerHelper
44 {
45 public:
46   bool convertToPointer;
47   uint32_t pointerId;
48   uint32_t tiltX;
49   uint32_t tiltY;
50   bool retargetedByPointerCapture;
51 
WidgetPointerHelper()52   WidgetPointerHelper() : convertToPointer(true), pointerId(0), tiltX(0), tiltY(0),
53                           retargetedByPointerCapture(false) {}
54 
AssignPointerHelperData(const WidgetPointerHelper & aEvent)55   void AssignPointerHelperData(const WidgetPointerHelper& aEvent)
56   {
57     convertToPointer = aEvent.convertToPointer;
58     pointerId = aEvent.pointerId;
59     tiltX = aEvent.tiltX;
60     tiltY = aEvent.tiltY;
61     retargetedByPointerCapture = aEvent.retargetedByPointerCapture;
62   }
63 };
64 
65 /******************************************************************************
66  * mozilla::WidgetMouseEventBase
67  ******************************************************************************/
68 
69 class WidgetMouseEventBase : public WidgetInputEvent
70 {
71 private:
72   friend class dom::PBrowserParent;
73   friend class dom::PBrowserChild;
74 
75 protected:
WidgetMouseEventBase()76   WidgetMouseEventBase()
77     : button(0)
78     , buttons(0)
79     , pressure(0)
80     , hitCluster(false)
81     , inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
82   {
83   }
84 
WidgetMouseEventBase(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget,EventClassID aEventClassID)85   WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage,
86                        nsIWidget* aWidget, EventClassID aEventClassID)
87     : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
88     , button(0)
89     , buttons(0)
90     , pressure(0)
91     , hitCluster(false)
92     , inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
93  {
94  }
95 
96 public:
AsMouseEventBase()97   virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; }
98 
Duplicate()99   virtual WidgetEvent* Duplicate() const override
100   {
101     MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
102   }
103 
104   /// The possible related target
105   nsCOMPtr<nsISupports> relatedTarget;
106 
107   enum buttonType
108   {
109     eLeftButton   = 0,
110     eMiddleButton = 1,
111     eRightButton  = 2
112   };
113   // Pressed button ID of mousedown or mouseup event.
114   // This is set only when pressing a button causes the event.
115   int16_t button;
116 
117   enum buttonsFlag {
118     eNoButtonFlag     = 0x00,
119     eLeftButtonFlag   = 0x01,
120     eRightButtonFlag  = 0x02,
121     eMiddleButtonFlag = 0x04,
122     // typicall, "back" button being left side of 5-button
123     // mice, see "buttons" attribute document of DOM3 Events.
124     e4thButtonFlag    = 0x08,
125     // typicall, "forward" button being right side of 5-button
126     // mice, see "buttons" attribute document of DOM3 Events.
127     e5thButtonFlag    = 0x10
128   };
129 
130   // Flags of all pressed buttons at the event fired.
131   // This is set at any mouse event, don't be confused with |button|.
132   int16_t buttons;
133 
134   // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
135   float pressure;
136   // Touch near a cluster of links (true)
137   bool hitCluster;
138 
139   // Possible values at nsIDOMMouseEvent
140   uint16_t inputSource;
141 
142   // ID of the canvas HitRegion
143   nsString region;
144 
IsLeftButtonPressed()145   bool IsLeftButtonPressed() const { return !!(buttons & eLeftButtonFlag); }
IsRightButtonPressed()146   bool IsRightButtonPressed() const { return !!(buttons & eRightButtonFlag); }
IsMiddleButtonPressed()147   bool IsMiddleButtonPressed() const { return !!(buttons & eMiddleButtonFlag); }
Is4thButtonPressed()148   bool Is4thButtonPressed() const { return !!(buttons & e4thButtonFlag); }
Is5thButtonPressed()149   bool Is5thButtonPressed() const { return !!(buttons & e5thButtonFlag); }
150 
AssignMouseEventBaseData(const WidgetMouseEventBase & aEvent,bool aCopyTargets)151   void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
152                                 bool aCopyTargets)
153   {
154     AssignInputEventData(aEvent, aCopyTargets);
155 
156     relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr;
157     button = aEvent.button;
158     buttons = aEvent.buttons;
159     pressure = aEvent.pressure;
160     hitCluster = aEvent.hitCluster;
161     inputSource = aEvent.inputSource;
162   }
163 
164   /**
165    * Returns true if left click event.
166    */
IsLeftClickEvent()167   bool IsLeftClickEvent() const
168   {
169     return mMessage == eMouseClick && button == eLeftButton;
170   }
171 };
172 
173 /******************************************************************************
174  * mozilla::WidgetMouseEvent
175  ******************************************************************************/
176 
177 class WidgetMouseEvent : public WidgetMouseEventBase
178                        , public WidgetPointerHelper
179 {
180 private:
181   friend class dom::PBrowserParent;
182   friend class dom::PBrowserChild;
183 
184 public:
185   typedef bool ReasonType;
186   enum Reason : ReasonType
187   {
188     eReal,
189     eSynthesized
190   };
191 
192   typedef bool ContextMenuTriggerType;
193   enum ContextMenuTrigger : ContextMenuTriggerType
194   {
195     eNormal,
196     eContextMenuKey
197   };
198 
199   typedef bool ExitFromType;
200   enum ExitFrom : ExitFromType
201   {
202     eChild,
203     eTopLevel
204   };
205 
206 protected:
WidgetMouseEvent()207   WidgetMouseEvent()
208     : mReason(eReal)
209     , mContextMenuTrigger(eNormal)
210     , mExitFrom(eChild)
211     , mIgnoreRootScrollFrame(false)
212     , mClickCount(0)
213   {
214   }
215 
WidgetMouseEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget,EventClassID aEventClassID,Reason aReason)216   WidgetMouseEvent(bool aIsTrusted,
217                    EventMessage aMessage,
218                    nsIWidget* aWidget,
219                    EventClassID aEventClassID,
220                    Reason aReason)
221     : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID)
222     , mReason(aReason)
223     , mContextMenuTrigger(eNormal)
224     , mExitFrom(eChild)
225     , mIgnoreRootScrollFrame(false)
226     , mClickCount(0)
227   {
228   }
229 
230 public:
AsMouseEvent()231   virtual WidgetMouseEvent* AsMouseEvent() override { return this; }
232 
233   WidgetMouseEvent(bool aIsTrusted,
234                    EventMessage aMessage,
235                    nsIWidget* aWidget,
236                    Reason aReason,
237                    ContextMenuTrigger aContextMenuTrigger = eNormal)
WidgetMouseEventBase(aIsTrusted,aMessage,aWidget,eMouseEventClass)238     : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass)
239     , mReason(aReason)
240     , mContextMenuTrigger(aContextMenuTrigger)
241     , mExitFrom(eChild)
242     , mIgnoreRootScrollFrame(false)
243     , mClickCount(0)
244   {
245     if (aMessage == eContextMenu) {
246       button = (mContextMenuTrigger == eNormal) ? eRightButton : eLeftButton;
247     }
248   }
249 
250 #ifdef DEBUG
~WidgetMouseEvent()251   virtual ~WidgetMouseEvent()
252   {
253     NS_WARNING_ASSERTION(
254       mMessage != eContextMenu ||
255       button == ((mContextMenuTrigger == eNormal) ? eRightButton : eLeftButton),
256       "Wrong button set to eContextMenu event?");
257   }
258 #endif
259 
Duplicate()260   virtual WidgetEvent* Duplicate() const override
261   {
262     MOZ_ASSERT(mClass == eMouseEventClass,
263                "Duplicate() must be overridden by sub class");
264     // Not copying widget, it is a weak reference.
265     WidgetMouseEvent* result =
266       new WidgetMouseEvent(false, mMessage, nullptr,
267                            mReason, mContextMenuTrigger);
268     result->AssignMouseEventData(*this, true);
269     result->mFlags = mFlags;
270     return result;
271   }
272 
273   // mReason indicates the reason why the event is fired:
274   // - Representing mouse operation.
275   // - Synthesized for emulating mousemove event when the content under the
276   //   mouse cursor is scrolled.
277   Reason mReason;
278 
279   // mContextMenuTrigger is valid only when mMessage is eContextMenu.
280   // This indicates if the context menu event is caused by context menu key or
281   // other reasons (typically, a click of right mouse button).
282   ContextMenuTrigger mContextMenuTrigger;
283 
284   // mExitFrom is valid only when mMessage is eMouseExitFromWidget.
285   // This indicates if the mouse cursor exits from a top level widget or
286   // a child widget.
287   ExitFrom mExitFrom;
288 
289   // Whether the event should ignore scroll frame bounds during dispatch.
290   bool mIgnoreRootScrollFrame;
291 
292   // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp,
293   // eMouseClick or eMouseDoubleClick. The number is count of mouse clicks.
294   // Otherwise, this must be 0.
295   uint32_t mClickCount;
296 
AssignMouseEventData(const WidgetMouseEvent & aEvent,bool aCopyTargets)297   void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets)
298   {
299     AssignMouseEventBaseData(aEvent, aCopyTargets);
300     AssignPointerHelperData(aEvent);
301 
302     mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
303     mClickCount = aEvent.mClickCount;
304   }
305 
306   /**
307    * Returns true if the event is a context menu event caused by key.
308    */
IsContextMenuKeyEvent()309   bool IsContextMenuKeyEvent() const
310   {
311     return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey;
312   }
313 
314   /**
315    * Returns true if the event is a real mouse event.  Otherwise, i.e., it's
316    * a synthesized event by scroll or something, returns false.
317    */
IsReal()318   bool IsReal() const
319   {
320     return mReason == eReal;
321   }
322 };
323 
324 /******************************************************************************
325  * mozilla::WidgetDragEvent
326  ******************************************************************************/
327 
328 class WidgetDragEvent : public WidgetMouseEvent
329 {
330 private:
331   friend class mozilla::dom::PBrowserParent;
332   friend class mozilla::dom::PBrowserChild;
333 protected:
WidgetDragEvent()334   WidgetDragEvent()
335     : mUserCancelled(false)
336     , mDefaultPreventedOnContent(false)
337   {
338   }
339 public:
AsDragEvent()340   virtual WidgetDragEvent* AsDragEvent() override { return this; }
341 
WidgetDragEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)342   WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
343     : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal)
344     , mUserCancelled(false)
345     , mDefaultPreventedOnContent(false)
346   {
347   }
348 
Duplicate()349   virtual WidgetEvent* Duplicate() const override
350   {
351     MOZ_ASSERT(mClass == eDragEventClass,
352                "Duplicate() must be overridden by sub class");
353     // Not copying widget, it is a weak reference.
354     WidgetDragEvent* result = new WidgetDragEvent(false, mMessage, nullptr);
355     result->AssignDragEventData(*this, true);
356     result->mFlags = mFlags;
357     return result;
358   }
359 
360   // The dragging data.
361   nsCOMPtr<dom::DataTransfer> mDataTransfer;
362 
363   // If this is true, user has cancelled the drag operation.
364   bool mUserCancelled;
365   // If this is true, the drag event's preventDefault() is called on content.
366   bool mDefaultPreventedOnContent;
367 
368   // XXX Not tested by test_assign_event_data.html
AssignDragEventData(const WidgetDragEvent & aEvent,bool aCopyTargets)369   void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets)
370   {
371     AssignMouseEventData(aEvent, aCopyTargets);
372 
373     mDataTransfer = aEvent.mDataTransfer;
374     // XXX mUserCancelled isn't copied, is this intentionally?
375     mUserCancelled = false;
376     mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
377   }
378 };
379 
380 /******************************************************************************
381  * mozilla::WidgetMouseScrollEvent
382  *
383  * This is used for legacy DOM mouse scroll events, i.e.,
384  * DOMMouseScroll and MozMousePixelScroll event.  These events are NOT hanbled
385  * by ESM even if widget dispatches them.  Use new WidgetWheelEvent instead.
386  ******************************************************************************/
387 
388 class WidgetMouseScrollEvent : public WidgetMouseEventBase
389 {
390 private:
WidgetMouseScrollEvent()391   WidgetMouseScrollEvent()
392     : mDelta(0)
393     , mIsHorizontal(false)
394   {
395   }
396 
397 public:
AsMouseScrollEvent()398   virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override
399   {
400     return this;
401   }
402 
WidgetMouseScrollEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)403   WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage,
404                          nsIWidget* aWidget)
405     : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
406                            eMouseScrollEventClass)
407     , mDelta(0)
408     , mIsHorizontal(false)
409   {
410   }
411 
Duplicate()412   virtual WidgetEvent* Duplicate() const override
413   {
414     MOZ_ASSERT(mClass == eMouseScrollEventClass,
415                "Duplicate() must be overridden by sub class");
416     // Not copying widget, it is a weak reference.
417     WidgetMouseScrollEvent* result =
418       new WidgetMouseScrollEvent(false, mMessage, nullptr);
419     result->AssignMouseScrollEventData(*this, true);
420     result->mFlags = mFlags;
421     return result;
422   }
423 
424   // The delta value of mouse scroll event.
425   // If the event message is eLegacyMouseLineOrPageScroll, the value indicates
426   // scroll amount in lines.  However, if the value is
427   // nsIDOMUIEvent::SCROLL_PAGE_UP or nsIDOMUIEvent::SCROLL_PAGE_DOWN, the
428   // value inducates one page scroll.  If the event message is
429   // eLegacyMousePixelScroll, the value indicates scroll amount in pixels.
430   int32_t mDelta;
431 
432   // If this is true, it may cause to scroll horizontally.
433   // Otherwise, vertically.
434   bool mIsHorizontal;
435 
AssignMouseScrollEventData(const WidgetMouseScrollEvent & aEvent,bool aCopyTargets)436   void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
437                                   bool aCopyTargets)
438   {
439     AssignMouseEventBaseData(aEvent, aCopyTargets);
440 
441     mDelta = aEvent.mDelta;
442     mIsHorizontal = aEvent.mIsHorizontal;
443   }
444 };
445 
446 /******************************************************************************
447  * mozilla::WidgetWheelEvent
448  ******************************************************************************/
449 
450 class WidgetWheelEvent : public WidgetMouseEventBase
451 {
452 private:
453   friend class mozilla::dom::PBrowserParent;
454   friend class mozilla::dom::PBrowserChild;
455 
WidgetWheelEvent()456   WidgetWheelEvent()
457     : mDeltaX(0.0)
458     , mDeltaY(0.0)
459     , mDeltaZ(0.0)
460     , mOverflowDeltaX(0.0)
461     , mOverflowDeltaY(0.0)
462     , mDeltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL)
463     , mLineOrPageDeltaX(0)
464     , mLineOrPageDeltaY(0)
465     , mScrollType(SCROLL_DEFAULT)
466     , mCustomizedByUserPrefs(false)
467     , mIsMomentum(false)
468     , mIsNoLineOrPageDelta(false)
469     , mViewPortIsOverscrolled(false)
470     , mCanTriggerSwipe(false)
471     , mAllowToOverrideSystemScrollSpeed(false)
472   {
473   }
474 
475 public:
AsWheelEvent()476   virtual WidgetWheelEvent* AsWheelEvent() override { return this; }
477 
WidgetWheelEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)478   WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
479     : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass)
480     , mDeltaX(0.0)
481     , mDeltaY(0.0)
482     , mDeltaZ(0.0)
483     , mOverflowDeltaX(0.0)
484     , mOverflowDeltaY(0.0)
485     , mDeltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL)
486     , mLineOrPageDeltaX(0)
487     , mLineOrPageDeltaY(0)
488     , mScrollType(SCROLL_DEFAULT)
489     , mCustomizedByUserPrefs(false)
490     , mMayHaveMomentum(false)
491     , mIsMomentum(false)
492     , mIsNoLineOrPageDelta(false)
493     , mViewPortIsOverscrolled(false)
494     , mCanTriggerSwipe(false)
495     , mAllowToOverrideSystemScrollSpeed(true)
496   {
497   }
498 
Duplicate()499   virtual WidgetEvent* Duplicate() const override
500   {
501     MOZ_ASSERT(mClass == eWheelEventClass,
502                "Duplicate() must be overridden by sub class");
503     // Not copying widget, it is a weak reference.
504     WidgetWheelEvent* result = new WidgetWheelEvent(false, mMessage, nullptr);
505     result->AssignWheelEventData(*this, true);
506     result->mFlags = mFlags;
507     return result;
508   }
509 
510   // On OS X, scroll gestures that start at the edge of the scrollable range
511   // can result in a swipe gesture. For the first wheel event of such a
512   // gesture, call TriggersSwipe() after the event has been processed
513   // in order to find out whether a swipe should be started.
TriggersSwipe()514   bool TriggersSwipe() const
515   {
516     return mCanTriggerSwipe && mViewPortIsOverscrolled &&
517            this->mOverflowDeltaX != 0.0;
518   }
519 
520   // NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by
521   //       mousewheel.*.delta_multiplier_* prefs which are applied by
522   //       EventStateManager.  So, after widget dispatches this event,
523   //       these delta values may have different values than before.
524   double mDeltaX;
525   double mDeltaY;
526   double mDeltaZ;
527 
528   // overflowed delta values for scroll, these values are set by
529   // nsEventStateManger.  If the default action of the wheel event isn't scroll,
530   // these values always zero.  Otherwise, remaning delta values which are
531   // not used by scroll are set.
532   // NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager.
533   //       However, mOverflowDeltaX and mOverflowDeltaY indicate unused original
534   //       delta values which are not applied the delta_multiplier prefs.
535   //       So, if widget wanted to know the actual direction to be scrolled,
536   //       it would need to check the mDeltaX and mDeltaY.
537   double mOverflowDeltaX;
538   double mOverflowDeltaY;
539 
540   // Should be one of nsIDOMWheelEvent::DOM_DELTA_*
541   uint32_t mDeltaMode;
542 
543   // If widget sets mLineOrPageDelta, EventStateManager will dispatch
544   // eLegacyMouseLineOrPageScroll event for compatibility.  Note that the delta
545   // value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines.
546   int32_t mLineOrPageDeltaX;
547   int32_t mLineOrPageDeltaY;
548 
549   // When the default action for an wheel event is moving history or zooming,
550   // need to chose a delta value for doing it.
GetPreferredIntDelta()551   int32_t GetPreferredIntDelta()
552   {
553     if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) {
554       return 0;
555     }
556     if (mLineOrPageDeltaY && !mLineOrPageDeltaX) {
557       return mLineOrPageDeltaY;
558     }
559     if (mLineOrPageDeltaX && !mLineOrPageDeltaY) {
560       return mLineOrPageDeltaX;
561     }
562     if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) ||
563         (mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) {
564       return 0; // We cannot guess the answer in this case.
565     }
566     return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY)) ?
567              mLineOrPageDeltaX : mLineOrPageDeltaY;
568   }
569 
570   // Scroll type
571   // The default value is SCROLL_DEFAULT, which means EventStateManager will
572   // select preferred scroll type automatically.
573   enum ScrollType : uint8_t
574   {
575     SCROLL_DEFAULT,
576     SCROLL_SYNCHRONOUSLY,
577     SCROLL_ASYNCHRONOUSELY,
578     SCROLL_SMOOTHLY
579   };
580   ScrollType mScrollType;
581 
582   // If the delta values are computed from prefs, this value is true.
583   // Otherwise, i.e., they are computed from native events, false.
584   bool mCustomizedByUserPrefs;
585 
586   // true if the momentum events directly tied to this event may follow it.
587   bool mMayHaveMomentum;
588   // true if the event is caused by momentum.
589   bool mIsMomentum;
590 
591   // If device event handlers don't know when they should set mLineOrPageDeltaX
592   // and mLineOrPageDeltaY, this is true.  Otherwise, false.
593   // If mIsNoLineOrPageDelta is true, ESM will generate
594   // eLegacyMouseLineOrPageScroll events when accumulated delta values reach
595   // a line height.
596   bool mIsNoLineOrPageDelta;
597 
598   // Whether or not the parent of the currently overscrolled frame is the
599   // ViewPort. This is false in situations when an element on the page is being
600   // overscrolled (such as a text field), but true when the 'page' is being
601   // overscrolled.
602   bool mViewPortIsOverscrolled;
603 
604   // The wheel event can trigger a swipe to start if it's overscrolling the
605   // viewport.
606   bool mCanTriggerSwipe;
607 
608   // If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be
609   // overridden.  Otherwise, the scroll speed won't be overridden even if
610   // it's enabled by the pref.
611   bool mAllowToOverrideSystemScrollSpeed;
612 
AssignWheelEventData(const WidgetWheelEvent & aEvent,bool aCopyTargets)613   void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
614   {
615     AssignMouseEventBaseData(aEvent, aCopyTargets);
616 
617     mDeltaX = aEvent.mDeltaX;
618     mDeltaY = aEvent.mDeltaY;
619     mDeltaZ = aEvent.mDeltaZ;
620     mDeltaMode = aEvent.mDeltaMode;
621     mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs;
622     mMayHaveMomentum = aEvent.mMayHaveMomentum;
623     mIsMomentum = aEvent.mIsMomentum;
624     mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
625     mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX;
626     mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY;
627     mScrollType = aEvent.mScrollType;
628     mOverflowDeltaX = aEvent.mOverflowDeltaX;
629     mOverflowDeltaY = aEvent.mOverflowDeltaY;
630     mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
631     mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
632     mAllowToOverrideSystemScrollSpeed =
633       aEvent.mAllowToOverrideSystemScrollSpeed;
634   }
635 
636   // System scroll speed settings may be too slow at using Gecko.  In such
637   // case, we should override the scroll speed computed with system settings.
638   // Following methods return preferred delta values which are multiplied by
639   // factors specified by prefs.  If system scroll speed shouldn't be
640   // overridden (e.g., this feature is disabled by pref), they return raw
641   // delta values.
642   double OverriddenDeltaX() const;
643   double OverriddenDeltaY() const;
644 
645   // Compute the overridden delta value.  This may be useful for suppressing
646   // too fast scroll by system scroll speed overriding when widget sets
647   // mAllowToOverrideSystemScrollSpeed.
648   static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical);
649 
650 private:
651   static bool sInitialized;
652   static bool sIsSystemScrollSpeedOverrideEnabled;
653   static int32_t sOverrideFactorX;
654   static int32_t sOverrideFactorY;
655   static void Initialize();
656 };
657 
658 /******************************************************************************
659  * mozilla::WidgetPointerEvent
660  ******************************************************************************/
661 
662 class WidgetPointerEvent : public WidgetMouseEvent
663 {
664   friend class mozilla::dom::PBrowserParent;
665   friend class mozilla::dom::PBrowserChild;
666 
WidgetPointerEvent()667   WidgetPointerEvent()
668     : mWidth(1)
669     , mHeight(1)
670     , mIsPrimary(true)
671   {
672   }
673 
674 public:
AsPointerEvent()675   virtual WidgetPointerEvent* AsPointerEvent() override { return this; }
676 
WidgetPointerEvent(bool aIsTrusted,EventMessage aMsg,nsIWidget * w)677   WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w)
678     : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal)
679     , mWidth(1)
680     , mHeight(1)
681     , mIsPrimary(true)
682   {
683   }
684 
WidgetPointerEvent(const WidgetMouseEvent & aEvent)685   explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
686     : WidgetMouseEvent(aEvent)
687     , mWidth(1)
688     , mHeight(1)
689     , mIsPrimary(true)
690   {
691     mClass = ePointerEventClass;
692   }
693 
Duplicate()694   virtual WidgetEvent* Duplicate() const override
695   {
696     MOZ_ASSERT(mClass == ePointerEventClass,
697                "Duplicate() must be overridden by sub class");
698     // Not copying widget, it is a weak reference.
699     WidgetPointerEvent* result =
700       new WidgetPointerEvent(false, mMessage, nullptr);
701     result->AssignPointerEventData(*this, true);
702     result->mFlags = mFlags;
703     return result;
704   }
705 
706   uint32_t mWidth;
707   uint32_t mHeight;
708   bool mIsPrimary;
709 
710   // XXX Not tested by test_assign_event_data.html
AssignPointerEventData(const WidgetPointerEvent & aEvent,bool aCopyTargets)711   void AssignPointerEventData(const WidgetPointerEvent& aEvent,
712                               bool aCopyTargets)
713   {
714     AssignMouseEventData(aEvent, aCopyTargets);
715 
716     mWidth = aEvent.mWidth;
717     mHeight = aEvent.mHeight;
718     mIsPrimary = aEvent.mIsPrimary;
719   }
720 };
721 
722 } // namespace mozilla
723 
724 #endif // mozilla_MouseEvents_h__
725