Backed out changeset 48baafc34055 (bug 1789166) for causing mochitests failures....
[gecko.git] / widget / MouseEvents.h
blob3d469853bbd30c433ee7b6d2be7175caa568196e
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/EventForwards.h"
13 #include "mozilla/MathAlgorithms.h"
14 #include "mozilla/dom/DataTransfer.h"
15 #include "mozilla/ipc/IPCForwards.h"
16 #include "nsCOMPtr.h"
18 namespace mozilla {
20 namespace dom {
21 class PBrowserParent;
22 class PBrowserChild;
23 class PBrowserBridgeParent;
24 } // namespace dom
26 class WidgetPointerEvent;
27 } // namespace mozilla
29 namespace mozilla {
30 class WidgetPointerEventHolder final {
31 public:
32 nsTArray<WidgetPointerEvent> mEvents;
33 NS_INLINE_DECL_REFCOUNTING(WidgetPointerEventHolder)
35 private:
36 virtual ~WidgetPointerEventHolder() = default;
39 /******************************************************************************
40 * mozilla::WidgetPointerHelper
41 ******************************************************************************/
43 class WidgetPointerHelper {
44 public:
45 uint32_t pointerId;
46 int32_t tiltX;
47 int32_t tiltY;
48 int32_t twist;
49 float tangentialPressure;
50 bool convertToPointer;
51 RefPtr<WidgetPointerEventHolder> mCoalescedWidgetEvents;
53 WidgetPointerHelper()
54 : pointerId(0),
55 tiltX(0),
56 tiltY(0),
57 twist(0),
58 tangentialPressure(0),
59 convertToPointer(true) {}
61 WidgetPointerHelper(uint32_t aPointerId, uint32_t aTiltX, uint32_t aTiltY,
62 uint32_t aTwist = 0, float aTangentialPressure = 0)
63 : pointerId(aPointerId),
64 tiltX(aTiltX),
65 tiltY(aTiltY),
66 twist(aTwist),
67 tangentialPressure(aTangentialPressure),
68 convertToPointer(true) {}
70 explicit WidgetPointerHelper(const WidgetPointerHelper& aHelper) = default;
72 void AssignPointerHelperData(const WidgetPointerHelper& aEvent,
73 bool aCopyCoalescedEvents = false) {
74 pointerId = aEvent.pointerId;
75 tiltX = aEvent.tiltX;
76 tiltY = aEvent.tiltY;
77 twist = aEvent.twist;
78 tangentialPressure = aEvent.tangentialPressure;
79 convertToPointer = aEvent.convertToPointer;
80 if (aCopyCoalescedEvents) {
81 mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents;
86 /******************************************************************************
87 * mozilla::WidgetMouseEventBase
88 ******************************************************************************/
90 class WidgetMouseEventBase : public WidgetInputEvent {
91 private:
92 friend class dom::PBrowserParent;
93 friend class dom::PBrowserChild;
94 friend class dom::PBrowserBridgeParent;
95 ALLOW_DEPRECATED_READPARAM
97 protected:
98 WidgetMouseEventBase()
99 : mPressure(0),
100 mButton(0),
101 mButtons(0),
102 mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
103 // Including MouseEventBinding.h here leads to an include loop, so
104 // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.
106 WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage,
107 nsIWidget* aWidget, EventClassID aEventClassID,
108 const WidgetEventTime* aTime = nullptr)
109 : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
110 mPressure(0),
111 mButton(0),
112 mButtons(0),
113 mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
114 // Including MouseEventBinding.h here leads to an include loop, so
115 // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.
117 public:
118 virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; }
120 virtual WidgetEvent* Duplicate() const override {
121 MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
124 // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
125 float mPressure;
127 // Pressed button ID of mousedown or mouseup event.
128 // This is set only when pressing a button causes the event.
129 int16_t mButton;
131 // Flags of all pressed buttons at the event fired.
132 // This is set at any mouse event, don't be confused with |mButton|.
133 int16_t mButtons;
135 // Possible values a in MouseEvent
136 uint16_t mInputSource;
138 bool IsLeftButtonPressed() const {
139 return !!(mButtons & MouseButtonsFlag::ePrimaryFlag);
141 bool IsRightButtonPressed() const {
142 return !!(mButtons & MouseButtonsFlag::eSecondaryFlag);
144 bool IsMiddleButtonPressed() const {
145 return !!(mButtons & MouseButtonsFlag::eMiddleFlag);
147 bool Is4thButtonPressed() const {
148 return !!(mButtons & MouseButtonsFlag::e4thFlag);
150 bool Is5thButtonPressed() const {
151 return !!(mButtons & MouseButtonsFlag::e5thFlag);
154 void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
155 bool aCopyTargets) {
156 AssignInputEventData(aEvent, aCopyTargets);
158 mButton = aEvent.mButton;
159 mButtons = aEvent.mButtons;
160 mPressure = aEvent.mPressure;
161 mInputSource = aEvent.mInputSource;
165 * Returns true if left click event.
167 bool IsLeftClickEvent() const {
168 return mMessage == ePointerClick && mButton == MouseButton::ePrimary;
172 * Returns true if this event changes a button state to "pressed".
174 [[nodiscard]] bool IsPressingButton() const {
175 MOZ_ASSERT(IsTrusted());
176 if (mClass == eMouseEventClass) {
177 return mMessage == eMouseDown;
179 if (mButton == MouseButton::eNotPressed) {
180 return false;
182 // If this is an ePointerDown event whose mButton is not "not pressed", this
183 // is a button pressing event.
184 if (mMessage == ePointerDown) {
185 return true;
187 // If 2 or more buttons are pressed at same time, they are sent with
188 // pointermove rather than pointerdown. Therefore, let's check whether
189 // mButtons contains the proper flag for the pressing button.
190 const bool buttonsContainButton = !!(
191 mButtons & MouseButtonsFlagToChange(static_cast<MouseButton>(mButton)));
192 return mMessage == ePointerMove && buttonsContainButton;
196 * Returns true if this event changes a button state to "released".
198 [[nodiscard]] bool IsReleasingButton() const {
199 MOZ_ASSERT(IsTrusted());
200 if (mClass == eMouseEventClass) {
201 return mMessage == eMouseUp;
203 if (mButton == MouseButton::eNotPressed) {
204 return false;
206 // If this is an ePointerUp event whose mButton is not "not pressed", this
207 // is a button release event.
208 if (mMessage == ePointerUp) {
209 return true;
211 // If the releasing button is not the last button of pressing buttons, web
212 // apps notified by pointermove rather than pointerup. Therefore, let's
213 // check whether mButtons loses the proper flag for the releasing button.
214 const bool buttonsLoseTheButton = !(
215 mButtons & MouseButtonsFlagToChange(static_cast<MouseButton>(mButton)));
216 return mMessage == ePointerMove && buttonsLoseTheButton;
220 * Returns true if the input source supports hover state like a mouse.
222 [[nodiscard]] bool InputSourceSupportsHover() const;
225 /******************************************************************************
226 * mozilla::WidgetMouseEvent
227 ******************************************************************************/
229 class WidgetMouseEvent : public WidgetMouseEventBase,
230 public WidgetPointerHelper {
231 private:
232 friend class dom::PBrowserParent;
233 friend class dom::PBrowserChild;
234 friend class dom::PBrowserBridgeParent;
235 ALLOW_DEPRECATED_READPARAM
237 public:
238 typedef bool ReasonType;
239 enum Reason : ReasonType { eReal, eSynthesized };
241 typedef uint8_t ContextMenuTriggerType;
242 enum ContextMenuTrigger : ContextMenuTriggerType {
243 eNormal,
244 eContextMenuKey,
245 eControlClick
248 typedef uint8_t ExitFromType;
249 enum ExitFrom : ExitFromType {
250 ePlatformChild,
251 ePlatformTopLevel,
252 ePuppet,
253 ePuppetParentToPuppetChild
256 protected:
257 WidgetMouseEvent() = default;
259 WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
260 EventClassID aEventClassID, Reason aReason,
261 ContextMenuTrigger aContextMenuTrigger,
262 const WidgetEventTime* aTime = nullptr)
263 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID,
264 aTime),
265 mReason(aReason),
266 mContextMenuTrigger(aContextMenuTrigger) {}
268 #ifdef DEBUG
269 void AssertContextMenuEventButtonConsistency() const;
270 #endif
272 public:
273 virtual WidgetMouseEvent* AsMouseEvent() override { return this; }
275 WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
276 Reason aReason = eReal,
277 ContextMenuTrigger aContextMenuTrigger = eNormal,
278 const WidgetEventTime* aTime = nullptr)
279 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass,
280 aTime),
281 mReason(aReason),
282 mContextMenuTrigger(aContextMenuTrigger) {
283 MOZ_ASSERT_IF(aIsTrusted, !IsPointerEventMessage(mMessage));
284 if (aMessage == eContextMenu) {
285 mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary
286 : MouseButton::ePrimary;
290 #ifdef DEBUG
291 virtual ~WidgetMouseEvent() { AssertContextMenuEventButtonConsistency(); }
292 #endif
294 virtual WidgetEvent* Duplicate() const override {
295 MOZ_ASSERT(mClass == eMouseEventClass,
296 "Duplicate() must be overridden by sub class");
297 // Not copying widget, it is a weak reference.
298 WidgetMouseEvent* result = new WidgetMouseEvent(
299 false, mMessage, nullptr, mReason, mContextMenuTrigger, this);
300 result->AssignMouseEventData(*this, true);
301 result->mFlags = mFlags;
302 return result;
305 // If during mouseup handling we detect that click event might need to be
306 // dispatched, this is setup to be the target of the click event.
307 nsCOMPtr<dom::EventTarget> mClickTarget;
309 // mReason indicates the reason why the event is fired:
310 // - Representing mouse operation.
311 // - Synthesized for emulating mousemove event when the content under the
312 // mouse cursor is scrolled.
313 Reason mReason = eReal;
315 // mContextMenuTrigger is valid only when mMessage is eContextMenu.
316 // This indicates if the context menu event is caused by context menu key or
317 // other reasons (typically, a click of right mouse button).
318 ContextMenuTrigger mContextMenuTrigger = eNormal;
320 // mExitFrom contains a value only when mMessage is eMouseExitFromWidget.
321 // This indicates if the mouse cursor exits from a top level platform widget,
322 // a child widget or a puppet widget.
323 Maybe<ExitFrom> mExitFrom;
325 // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp,
326 // ePointerClick or eMouseDoubleClick. The number is count of mouse clicks.
327 // Otherwise, this must be 0.
328 uint32_t mClickCount = 0;
330 // Whether the event should ignore scroll frame bounds during dispatch.
331 bool mIgnoreRootScrollFrame = false;
333 // Whether the event shouldn't cause click event.
334 bool mClickEventPrevented = false;
336 void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets) {
337 AssignMouseEventBaseData(aEvent, aCopyTargets);
338 AssignPointerHelperData(aEvent, /* aCopyCoalescedEvents */ true);
340 mReason = aEvent.mReason;
341 mContextMenuTrigger = aEvent.mContextMenuTrigger;
342 mExitFrom = aEvent.mExitFrom;
343 mClickCount = aEvent.mClickCount;
344 mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
345 mClickEventPrevented = aEvent.mClickEventPrevented;
349 * Returns true if the event is a context menu event caused by key.
351 bool IsContextMenuKeyEvent() const {
352 return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey;
356 * Returns true if the event is a real mouse event. Otherwise, i.e., it's
357 * a synthesized event by scroll or something, returns false.
359 bool IsReal() const { return mReason == eReal; }
362 * Returns true if middle click paste is enabled.
364 static bool IsMiddleClickPasteEnabled();
367 /******************************************************************************
368 * mozilla::WidgetDragEvent
369 ******************************************************************************/
371 class WidgetDragEvent : public WidgetMouseEvent {
372 private:
373 friend class mozilla::dom::PBrowserParent;
374 friend class mozilla::dom::PBrowserChild;
375 ALLOW_DEPRECATED_READPARAM
377 protected:
378 WidgetDragEvent()
379 : mUserCancelled(false),
380 mDefaultPreventedOnContent(false),
381 mInHTMLEditorEventListener(false) {}
383 public:
384 virtual WidgetDragEvent* AsDragEvent() override { return this; }
386 WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
387 const WidgetEventTime* aTime = nullptr)
388 : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal,
389 eNormal, aTime),
390 mUserCancelled(false),
391 mDefaultPreventedOnContent(false),
392 mInHTMLEditorEventListener(false) {}
394 virtual WidgetEvent* Duplicate() const override {
395 MOZ_ASSERT(mClass == eDragEventClass,
396 "Duplicate() must be overridden by sub class");
397 // Not copying widget, it is a weak reference.
398 WidgetDragEvent* result =
399 new WidgetDragEvent(false, mMessage, nullptr, this);
400 result->AssignDragEventData(*this, true);
401 result->mFlags = mFlags;
402 return result;
405 // The dragging data.
406 nsCOMPtr<dom::DataTransfer> mDataTransfer;
408 // If this is true, user has cancelled the drag operation.
409 bool mUserCancelled;
410 // If this is true, the drag event's preventDefault() is called on content.
411 bool mDefaultPreventedOnContent;
412 // If this event is currently being handled by HTMLEditorEventListener.
413 bool mInHTMLEditorEventListener;
415 // XXX Not tested by test_assign_event_data.html
416 void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets) {
417 AssignMouseEventData(aEvent, aCopyTargets);
419 mDataTransfer = aEvent.mDataTransfer;
420 // XXX mUserCancelled isn't copied, is this intentionally?
421 mUserCancelled = false;
422 mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
423 // XXX mInHTMLEditorEventListener isn't copied, is this intentionally?
424 mInHTMLEditorEventListener = false;
427 bool CanConvertToInputData() const {
428 return mMessage == eDragStart || mMessage == eDragEnd;
432 * Should be called before dispatching the DOM tree if this event is
433 * synthesized for tests because drop effect is initialized before
434 * dispatching from widget if it's not synthesized event, but synthesized
435 * events are not initialized in the path.
437 void InitDropEffectForTests();
440 /******************************************************************************
441 * mozilla::WidgetMouseScrollEvent
443 * This is used for legacy DOM mouse scroll events, i.e.,
444 * DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled
445 * by ESM even if widget dispatches them. Use new WidgetWheelEvent instead.
446 ******************************************************************************/
448 class WidgetMouseScrollEvent : public WidgetMouseEventBase {
449 private:
450 WidgetMouseScrollEvent() : mDelta(0), mIsHorizontal(false) {}
452 public:
453 virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override { return this; }
455 WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage,
456 nsIWidget* aWidget,
457 const WidgetEventTime* aTime = nullptr)
458 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
459 eMouseScrollEventClass, aTime),
460 mDelta(0),
461 mIsHorizontal(false) {}
463 virtual WidgetEvent* Duplicate() const override {
464 MOZ_ASSERT(mClass == eMouseScrollEventClass,
465 "Duplicate() must be overridden by sub class");
466 // Not copying widget, it is a weak reference.
467 WidgetMouseScrollEvent* result =
468 new WidgetMouseScrollEvent(false, mMessage, nullptr, this);
469 result->AssignMouseScrollEventData(*this, true);
470 result->mFlags = mFlags;
471 return result;
474 // The delta value of mouse scroll event.
475 // If the event message is eLegacyMouseLineOrPageScroll, the value indicates
476 // scroll amount in lines. However, if the value is
477 // UIEvent::SCROLL_PAGE_UP or UIEvent::SCROLL_PAGE_DOWN, the
478 // value inducates one page scroll. If the event message is
479 // eLegacyMousePixelScroll, the value indicates scroll amount in pixels.
480 int32_t mDelta;
482 // If this is true, it may cause to scroll horizontally.
483 // Otherwise, vertically.
484 bool mIsHorizontal;
486 void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
487 bool aCopyTargets) {
488 AssignMouseEventBaseData(aEvent, aCopyTargets);
490 mDelta = aEvent.mDelta;
491 mIsHorizontal = aEvent.mIsHorizontal;
495 /******************************************************************************
496 * mozilla::WidgetWheelEvent
497 ******************************************************************************/
499 class WidgetWheelEvent : public WidgetMouseEventBase {
500 private:
501 friend class mozilla::dom::PBrowserParent;
502 friend class mozilla::dom::PBrowserChild;
503 ALLOW_DEPRECATED_READPARAM
505 WidgetWheelEvent()
506 : mDeltaX(0.0),
507 mDeltaY(0.0),
508 mDeltaZ(0.0),
509 mOverflowDeltaX(0.0),
510 mOverflowDeltaY(0.0)
511 // Including WheelEventBinding.h here leads to an include loop, so
512 // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
514 mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
515 mLineOrPageDeltaX(0),
516 mLineOrPageDeltaY(0),
517 mScrollType(SCROLL_DEFAULT),
518 mCustomizedByUserPrefs(false),
519 mMayHaveMomentum(false),
520 mIsMomentum(false),
521 mIsNoLineOrPageDelta(false),
522 mViewPortIsOverscrolled(false),
523 mCanTriggerSwipe(false),
524 mAllowToOverrideSystemScrollSpeed(false),
525 mDeltaValuesHorizontalizedForDefaultHandler(false) {}
527 public:
528 virtual WidgetWheelEvent* AsWheelEvent() override { return this; }
530 WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
531 const WidgetEventTime* aTime = nullptr)
532 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass,
533 aTime),
534 mDeltaX(0.0),
535 mDeltaY(0.0),
536 mDeltaZ(0.0),
537 mOverflowDeltaX(0.0),
538 mOverflowDeltaY(0.0)
539 // Including WheelEventBinding.h here leads to an include loop, so
540 // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
542 mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
543 mLineOrPageDeltaX(0),
544 mLineOrPageDeltaY(0),
545 mScrollType(SCROLL_DEFAULT),
546 mCustomizedByUserPrefs(false),
547 mMayHaveMomentum(false),
548 mIsMomentum(false),
549 mIsNoLineOrPageDelta(false),
550 mViewPortIsOverscrolled(false),
551 mCanTriggerSwipe(false),
552 mAllowToOverrideSystemScrollSpeed(true),
553 mDeltaValuesHorizontalizedForDefaultHandler(false) {}
555 virtual WidgetEvent* Duplicate() const override {
556 MOZ_ASSERT(mClass == eWheelEventClass,
557 "Duplicate() must be overridden by sub class");
558 // Not copying widget, it is a weak reference.
559 WidgetWheelEvent* result =
560 new WidgetWheelEvent(false, mMessage, nullptr, this);
561 result->AssignWheelEventData(*this, true);
562 result->mFlags = mFlags;
563 return result;
566 // Scroll gestures that start at the edge of the scrollable range can result
567 // in a swipe gesture. For the first wheel event of such a gesture, call
568 // TriggersSwipe() after the event has been processed in order to find out
569 // whether a swipe should be started.
570 bool TriggersSwipe() const {
571 return mCanTriggerSwipe && mViewPortIsOverscrolled &&
572 this->mOverflowDeltaX != 0.0;
575 // NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by
576 // mousewheel.*.delta_multiplier_* prefs which are applied by
577 // EventStateManager. So, after widget dispatches this event,
578 // these delta values may have different values than before.
579 double mDeltaX;
580 double mDeltaY;
581 double mDeltaZ;
583 // The mousewheel tick counts.
584 double mWheelTicksX = 0.0;
585 double mWheelTicksY = 0.0;
587 enum class DeltaModeCheckingState : uint8_t {
588 // Neither deltaMode nor the delta values have been accessed.
589 Unknown,
590 // The delta values have been accessed, without checking deltaMode first.
591 Unchecked,
592 // The deltaMode has been checked.
593 Checked,
596 // For compat reasons, we might expose a DOM_DELTA_LINE event as
597 // DOM_DELTA_PIXEL instead. Whether we do that depends on whether the event
598 // has been asked for the deltaMode before the deltas. If it has, we assume
599 // that the page will correctly handle DOM_DELTA_LINE. This variable tracks
600 // that state. See bug 1392460.
601 DeltaModeCheckingState mDeltaModeCheckingState =
602 DeltaModeCheckingState::Unknown;
604 // The amount of scrolling per line or page, without accounting for mouse
605 // wheel transactions etc.
607 // Computed by EventStateManager::DeltaAccumulator::InitLineOrPageDelta.
608 nsSize mScrollAmount;
610 // overflowed delta values for scroll, these values are set by
611 // EventStateManger. If the default action of the wheel event isn't scroll,
612 // these values are always zero. Otherwise, remaining delta values which are
613 // not used by scroll are set.
614 // NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager.
615 // However, mOverflowDeltaX and mOverflowDeltaY indicate unused original
616 // delta values which are not applied the delta_multiplier prefs.
617 // So, if widget wanted to know the actual direction to be scrolled,
618 // it would need to check the mDeltaX and mDeltaY.
619 double mOverflowDeltaX;
620 double mOverflowDeltaY;
622 // Should be one of WheelEvent_Binding::DOM_DELTA_*
623 uint32_t mDeltaMode;
625 // If widget sets mLineOrPageDelta, EventStateManager will dispatch
626 // eLegacyMouseLineOrPageScroll event for compatibility. Note that the delta
627 // value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines.
628 int32_t mLineOrPageDeltaX;
629 int32_t mLineOrPageDeltaY;
631 // When the default action for an wheel event is moving history or zooming,
632 // need to chose a delta value for doing it.
633 int32_t GetPreferredIntDelta() {
634 if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) {
635 return 0;
637 if (mLineOrPageDeltaY && !mLineOrPageDeltaX) {
638 return mLineOrPageDeltaY;
640 if (mLineOrPageDeltaX && !mLineOrPageDeltaY) {
641 return mLineOrPageDeltaX;
643 if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) ||
644 (mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) {
645 return 0; // We cannot guess the answer in this case.
647 return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY))
648 ? mLineOrPageDeltaX
649 : mLineOrPageDeltaY;
652 // Scroll type
653 // The default value is SCROLL_DEFAULT, which means EventStateManager will
654 // select preferred scroll type automatically.
655 enum ScrollType : uint8_t {
656 SCROLL_DEFAULT,
657 SCROLL_SYNCHRONOUSLY,
658 SCROLL_ASYNCHRONOUSLY,
659 SCROLL_SMOOTHLY
661 ScrollType mScrollType;
663 // If the delta values are computed from prefs, this value is true.
664 // Otherwise, i.e., they are computed from native events, false.
665 bool mCustomizedByUserPrefs;
667 // true if the momentum events directly tied to this event may follow it.
668 bool mMayHaveMomentum;
669 // true if the event is caused by momentum.
670 bool mIsMomentum;
672 // If device event handlers don't know when they should set mLineOrPageDeltaX
673 // and mLineOrPageDeltaY, this is true. Otherwise, false.
674 // If mIsNoLineOrPageDelta is true, ESM will generate
675 // eLegacyMouseLineOrPageScroll events when accumulated delta values reach
676 // a line height.
677 bool mIsNoLineOrPageDelta;
679 // Whether or not the parent of the currently overscrolled frame is the
680 // ViewPort. This is false in situations when an element on the page is being
681 // overscrolled (such as a text field), but true when the 'page' is being
682 // overscrolled.
683 bool mViewPortIsOverscrolled;
685 // The wheel event can trigger a swipe to start if it's overscrolling the
686 // viewport.
687 bool mCanTriggerSwipe;
689 // If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be
690 // overridden. Otherwise, the scroll speed won't be overridden even if
691 // it's enabled by the pref.
692 bool mAllowToOverrideSystemScrollSpeed;
694 // After the event's default action handler has adjusted its delta's values
695 // for horizontalizing a vertical wheel scroll, this variable will be set to
696 // true.
697 bool mDeltaValuesHorizontalizedForDefaultHandler;
699 void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets) {
700 AssignMouseEventBaseData(aEvent, aCopyTargets);
702 mDeltaX = aEvent.mDeltaX;
703 mDeltaY = aEvent.mDeltaY;
704 mDeltaZ = aEvent.mDeltaZ;
705 mDeltaMode = aEvent.mDeltaMode;
706 mScrollAmount = aEvent.mScrollAmount;
707 mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs;
708 mMayHaveMomentum = aEvent.mMayHaveMomentum;
709 mIsMomentum = aEvent.mIsMomentum;
710 mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
711 mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX;
712 mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY;
713 mScrollType = aEvent.mScrollType;
714 mOverflowDeltaX = aEvent.mOverflowDeltaX;
715 mOverflowDeltaY = aEvent.mOverflowDeltaY;
716 mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
717 mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
718 mAllowToOverrideSystemScrollSpeed =
719 aEvent.mAllowToOverrideSystemScrollSpeed;
720 mDeltaValuesHorizontalizedForDefaultHandler =
721 aEvent.mDeltaValuesHorizontalizedForDefaultHandler;
724 // System scroll speed settings may be too slow at using Gecko. In such
725 // case, we should override the scroll speed computed with system settings.
726 // Following methods return preferred delta values which are multiplied by
727 // factors specified by prefs. If system scroll speed shouldn't be
728 // overridden (e.g., this feature is disabled by pref), they return raw
729 // delta values.
730 double OverriddenDeltaX() const;
731 double OverriddenDeltaY() const;
733 // Compute the overridden delta value. This may be useful for suppressing
734 // too fast scroll by system scroll speed overriding when widget sets
735 // mAllowToOverrideSystemScrollSpeed.
736 static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical);
738 private:
739 static bool sInitialized;
740 static bool sIsSystemScrollSpeedOverrideEnabled;
741 static int32_t sOverrideFactorX;
742 static int32_t sOverrideFactorY;
743 static void Initialize();
746 /******************************************************************************
747 * mozilla::WidgetPointerEvent
748 ******************************************************************************/
750 class WidgetPointerEvent : public WidgetMouseEvent {
751 friend class mozilla::dom::PBrowserParent;
752 friend class mozilla::dom::PBrowserChild;
753 ALLOW_DEPRECATED_READPARAM
755 WidgetPointerEvent() = default;
757 public:
758 virtual WidgetPointerEvent* AsPointerEvent() override { return this; }
760 WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w,
761 const WidgetEventTime* aTime)
762 : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal,
763 eNormal, aTime) {
764 if (aMsg == eContextMenu) {
765 mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary
766 : MouseButton::ePrimary;
770 WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w,
771 ContextMenuTrigger aContextMenuTrigger = eNormal,
772 const WidgetEventTime* aTime = nullptr)
773 : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal,
774 aContextMenuTrigger, aTime) {
775 if (aMsg == eContextMenu) {
776 mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary
777 : MouseButton::ePrimary;
781 explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
782 : WidgetMouseEvent(aEvent) {
783 mClass = ePointerEventClass;
786 virtual WidgetEvent* Duplicate() const override {
787 MOZ_ASSERT(mClass == ePointerEventClass,
788 "Duplicate() must be overridden by sub class");
789 // Not copying widget, it is a weak reference.
790 WidgetPointerEvent* result = new WidgetPointerEvent(
791 false, mMessage, nullptr, mContextMenuTrigger, this);
792 result->AssignPointerEventData(*this, true);
793 result->mFlags = mFlags;
794 return result;
797 int32_t mWidth = 1;
798 int32_t mHeight = 1;
799 bool mIsPrimary = true;
800 bool mFromTouchEvent = false;
802 // XXX Not tested by test_assign_event_data.html
803 void AssignPointerEventData(const WidgetPointerEvent& aEvent,
804 bool aCopyTargets) {
805 AssignMouseEventData(aEvent, aCopyTargets);
807 mWidth = aEvent.mWidth;
808 mHeight = aEvent.mHeight;
809 mIsPrimary = aEvent.mIsPrimary;
810 mFromTouchEvent = aEvent.mFromTouchEvent;
814 } // namespace mozilla
816 #endif // mozilla_MouseEvents_h__