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