summaryrefslogtreecommitdiffstats
path: root/widget/MouseEvents.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/MouseEvents.h')
-rw-r--r--widget/MouseEvents.h812
1 files changed, 812 insertions, 0 deletions
diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h
new file mode 100644
index 0000000000..d29b406524
--- /dev/null
+++ b/widget/MouseEvents.h
@@ -0,0 +1,812 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_MouseEvents_h__
+#define mozilla_MouseEvents_h__
+
+#include <stdint.h>
+
+#include "mozilla/BasicEvents.h"
+#include "mozilla/EventForwards.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/dom/DataTransfer.h"
+#include "mozilla/ipc/IPCForwards.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+
+namespace dom {
+class PBrowserParent;
+class PBrowserChild;
+class PBrowserBridgeParent;
+} // namespace dom
+
+class WidgetPointerEvent;
+} // namespace mozilla
+
+namespace mozilla {
+class WidgetPointerEventHolder final {
+ public:
+ nsTArray<WidgetPointerEvent> mEvents;
+ NS_INLINE_DECL_REFCOUNTING(WidgetPointerEventHolder)
+
+ private:
+ virtual ~WidgetPointerEventHolder() = default;
+};
+
+/******************************************************************************
+ * mozilla::WidgetPointerHelper
+ ******************************************************************************/
+
+class WidgetPointerHelper {
+ public:
+ uint32_t pointerId;
+ int32_t tiltX;
+ int32_t tiltY;
+ int32_t twist;
+ float tangentialPressure;
+ bool convertToPointer;
+ RefPtr<WidgetPointerEventHolder> mCoalescedWidgetEvents;
+
+ WidgetPointerHelper()
+ : pointerId(0),
+ tiltX(0),
+ tiltY(0),
+ twist(0),
+ tangentialPressure(0),
+ convertToPointer(true) {}
+
+ WidgetPointerHelper(uint32_t aPointerId, uint32_t aTiltX, uint32_t aTiltY,
+ uint32_t aTwist = 0, float aTangentialPressure = 0)
+ : pointerId(aPointerId),
+ tiltX(aTiltX),
+ tiltY(aTiltY),
+ twist(aTwist),
+ tangentialPressure(aTangentialPressure),
+ convertToPointer(true) {}
+
+ explicit WidgetPointerHelper(const WidgetPointerHelper& aHelper) = default;
+
+ void AssignPointerHelperData(const WidgetPointerHelper& aEvent,
+ bool aCopyCoalescedEvents = false) {
+ pointerId = aEvent.pointerId;
+ tiltX = aEvent.tiltX;
+ tiltY = aEvent.tiltY;
+ twist = aEvent.twist;
+ tangentialPressure = aEvent.tangentialPressure;
+ convertToPointer = aEvent.convertToPointer;
+ if (aCopyCoalescedEvents) {
+ mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents;
+ }
+ }
+};
+
+/******************************************************************************
+ * mozilla::WidgetMouseEventBase
+ ******************************************************************************/
+
+class WidgetMouseEventBase : public WidgetInputEvent {
+ private:
+ friend class dom::PBrowserParent;
+ friend class dom::PBrowserChild;
+ friend class dom::PBrowserBridgeParent;
+ ALLOW_DEPRECATED_READPARAM
+
+ protected:
+ WidgetMouseEventBase()
+ : mPressure(0),
+ mButton(0),
+ mButtons(0),
+ mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
+ // Including MouseEventBinding.h here leads to an include loop, so
+ // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.
+
+ WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage,
+ nsIWidget* aWidget, EventClassID aEventClassID,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
+ mPressure(0),
+ mButton(0),
+ mButtons(0),
+ mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
+ // Including MouseEventBinding.h here leads to an include loop, so
+ // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.
+
+ public:
+ virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; }
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
+ }
+
+ // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
+ float mPressure;
+
+ // Pressed button ID of mousedown or mouseup event.
+ // This is set only when pressing a button causes the event.
+ int16_t mButton;
+
+ // Flags of all pressed buttons at the event fired.
+ // This is set at any mouse event, don't be confused with |mButton|.
+ int16_t mButtons;
+
+ // Possible values a in MouseEvent
+ uint16_t mInputSource;
+
+ bool IsLeftButtonPressed() const {
+ return !!(mButtons & MouseButtonsFlag::ePrimaryFlag);
+ }
+ bool IsRightButtonPressed() const {
+ return !!(mButtons & MouseButtonsFlag::eSecondaryFlag);
+ }
+ bool IsMiddleButtonPressed() const {
+ return !!(mButtons & MouseButtonsFlag::eMiddleFlag);
+ }
+ bool Is4thButtonPressed() const {
+ return !!(mButtons & MouseButtonsFlag::e4thFlag);
+ }
+ bool Is5thButtonPressed() const {
+ return !!(mButtons & MouseButtonsFlag::e5thFlag);
+ }
+
+ void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
+ bool aCopyTargets) {
+ AssignInputEventData(aEvent, aCopyTargets);
+
+ mButton = aEvent.mButton;
+ mButtons = aEvent.mButtons;
+ mPressure = aEvent.mPressure;
+ mInputSource = aEvent.mInputSource;
+ }
+
+ /**
+ * Returns true if left click event.
+ */
+ bool IsLeftClickEvent() const {
+ return mMessage == eMouseClick && mButton == MouseButton::ePrimary;
+ }
+
+ /**
+ * Returns true if this event changes a button state to "pressed".
+ */
+ [[nodiscard]] bool IsPressingButton() const {
+ MOZ_ASSERT(IsTrusted());
+ if (mClass == eMouseEventClass) {
+ return mMessage == eMouseDown;
+ }
+ if (mButton == MouseButton::eNotPressed) {
+ return false;
+ }
+ // If this is an ePointerDown event whose mButton is not "not pressed", this
+ // is a button pressing event.
+ if (mMessage == ePointerDown) {
+ return true;
+ }
+ // If 2 or more buttons are pressed at same time, they are sent with
+ // pointermove rather than pointerdown. Therefore, let's check whether
+ // mButtons contains the proper flag for the pressing button.
+ const bool buttonsContainButton = !!(
+ mButtons & MouseButtonsFlagToChange(static_cast<MouseButton>(mButton)));
+ return mMessage == ePointerMove && buttonsContainButton;
+ }
+
+ /**
+ * Returns true if this event changes a button state to "released".
+ */
+ [[nodiscard]] bool IsReleasingButton() const {
+ MOZ_ASSERT(IsTrusted());
+ if (mClass == eMouseEventClass) {
+ return mMessage == eMouseUp;
+ }
+ if (mButton == MouseButton::eNotPressed) {
+ return false;
+ }
+ // If this is an ePointerUp event whose mButton is not "not pressed", this
+ // is a button release event.
+ if (mMessage == ePointerUp) {
+ return true;
+ }
+ // If the releasing button is not the last button of pressing buttons, web
+ // apps notified by pointermove rather than pointerup. Therefore, let's
+ // check whether mButtons loses the proper flag for the releasing button.
+ const bool buttonsLoseTheButton = !(
+ mButtons & MouseButtonsFlagToChange(static_cast<MouseButton>(mButton)));
+ return mMessage == ePointerMove && buttonsLoseTheButton;
+ }
+
+ /**
+ * Returns true if the input source supports hover state like a mouse.
+ */
+ [[nodiscard]] bool InputSourceSupportsHover() const;
+};
+
+/******************************************************************************
+ * mozilla::WidgetMouseEvent
+ ******************************************************************************/
+
+class WidgetMouseEvent : public WidgetMouseEventBase,
+ public WidgetPointerHelper {
+ private:
+ friend class dom::PBrowserParent;
+ friend class dom::PBrowserChild;
+ friend class dom::PBrowserBridgeParent;
+ ALLOW_DEPRECATED_READPARAM
+
+ public:
+ typedef bool ReasonType;
+ enum Reason : ReasonType { eReal, eSynthesized };
+
+ typedef uint8_t ContextMenuTriggerType;
+ enum ContextMenuTrigger : ContextMenuTriggerType {
+ eNormal,
+ eContextMenuKey,
+ eControlClick
+ };
+
+ typedef uint8_t ExitFromType;
+ enum ExitFrom : ExitFromType {
+ ePlatformChild,
+ ePlatformTopLevel,
+ ePuppet,
+ ePuppetParentToPuppetChild
+ };
+
+ protected:
+ WidgetMouseEvent()
+ : mReason(eReal),
+ mContextMenuTrigger(eNormal),
+ mClickCount(0),
+ mIgnoreRootScrollFrame(false),
+ mClickEventPrevented(false) {}
+
+ WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
+ EventClassID aEventClassID, Reason aReason,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID,
+ aTime),
+ mReason(aReason),
+ mContextMenuTrigger(eNormal),
+ mClickCount(0),
+ mIgnoreRootScrollFrame(false),
+ mClickEventPrevented(false) {}
+
+#ifdef DEBUG
+ void AssertContextMenuEventButtonConsistency() const;
+#endif
+
+ public:
+ virtual WidgetMouseEvent* AsMouseEvent() override { return this; }
+
+ WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
+ Reason aReason,
+ ContextMenuTrigger aContextMenuTrigger = eNormal,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass,
+ aTime),
+ mReason(aReason),
+ mContextMenuTrigger(aContextMenuTrigger),
+ mClickCount(0),
+ mIgnoreRootScrollFrame(false),
+ mClickEventPrevented(false) {
+ if (aMessage == eContextMenu) {
+ mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary
+ : MouseButton::ePrimary;
+ }
+ }
+
+#ifdef DEBUG
+ virtual ~WidgetMouseEvent() { AssertContextMenuEventButtonConsistency(); }
+#endif
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_ASSERT(mClass == eMouseEventClass,
+ "Duplicate() must be overridden by sub class");
+ // Not copying widget, it is a weak reference.
+ WidgetMouseEvent* result = new WidgetMouseEvent(
+ false, mMessage, nullptr, mReason, mContextMenuTrigger, this);
+ result->AssignMouseEventData(*this, true);
+ result->mFlags = mFlags;
+ return result;
+ }
+
+ // If during mouseup handling we detect that click event might need to be
+ // dispatched, this is setup to be the target of the click event.
+ nsCOMPtr<dom::EventTarget> mClickTarget;
+
+ // mReason indicates the reason why the event is fired:
+ // - Representing mouse operation.
+ // - Synthesized for emulating mousemove event when the content under the
+ // mouse cursor is scrolled.
+ Reason mReason;
+
+ // mContextMenuTrigger is valid only when mMessage is eContextMenu.
+ // This indicates if the context menu event is caused by context menu key or
+ // other reasons (typically, a click of right mouse button).
+ ContextMenuTrigger mContextMenuTrigger;
+
+ // mExitFrom contains a value only when mMessage is eMouseExitFromWidget.
+ // This indicates if the mouse cursor exits from a top level platform widget,
+ // a child widget or a puppet widget.
+ Maybe<ExitFrom> mExitFrom;
+
+ // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp,
+ // eMouseClick or eMouseDoubleClick. The number is count of mouse clicks.
+ // Otherwise, this must be 0.
+ uint32_t mClickCount;
+
+ // Whether the event should ignore scroll frame bounds during dispatch.
+ bool mIgnoreRootScrollFrame;
+
+ // Whether the event shouldn't cause click event.
+ bool mClickEventPrevented;
+
+ void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets) {
+ AssignMouseEventBaseData(aEvent, aCopyTargets);
+ AssignPointerHelperData(aEvent, /* aCopyCoalescedEvents */ true);
+
+ mExitFrom = aEvent.mExitFrom;
+ mClickCount = aEvent.mClickCount;
+ mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
+ mClickEventPrevented = aEvent.mClickEventPrevented;
+ }
+
+ /**
+ * Returns true if the event is a context menu event caused by key.
+ */
+ bool IsContextMenuKeyEvent() const {
+ return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey;
+ }
+
+ /**
+ * Returns true if the event is a real mouse event. Otherwise, i.e., it's
+ * a synthesized event by scroll or something, returns false.
+ */
+ bool IsReal() const { return mReason == eReal; }
+
+ /**
+ * Returns true if middle click paste is enabled.
+ */
+ static bool IsMiddleClickPasteEnabled();
+};
+
+/******************************************************************************
+ * mozilla::WidgetDragEvent
+ ******************************************************************************/
+
+class WidgetDragEvent : public WidgetMouseEvent {
+ private:
+ friend class mozilla::dom::PBrowserParent;
+ friend class mozilla::dom::PBrowserChild;
+ ALLOW_DEPRECATED_READPARAM
+
+ protected:
+ WidgetDragEvent()
+ : mUserCancelled(false),
+ mDefaultPreventedOnContent(false),
+ mInHTMLEditorEventListener(false) {}
+
+ public:
+ virtual WidgetDragEvent* AsDragEvent() override { return this; }
+
+ WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal,
+ aTime),
+ mUserCancelled(false),
+ mDefaultPreventedOnContent(false),
+ mInHTMLEditorEventListener(false) {}
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_ASSERT(mClass == eDragEventClass,
+ "Duplicate() must be overridden by sub class");
+ // Not copying widget, it is a weak reference.
+ WidgetDragEvent* result =
+ new WidgetDragEvent(false, mMessage, nullptr, this);
+ result->AssignDragEventData(*this, true);
+ result->mFlags = mFlags;
+ return result;
+ }
+
+ // The dragging data.
+ nsCOMPtr<dom::DataTransfer> mDataTransfer;
+
+ // If this is true, user has cancelled the drag operation.
+ bool mUserCancelled;
+ // If this is true, the drag event's preventDefault() is called on content.
+ bool mDefaultPreventedOnContent;
+ // If this event is currently being handled by HTMLEditorEventListener.
+ bool mInHTMLEditorEventListener;
+
+ // XXX Not tested by test_assign_event_data.html
+ void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets) {
+ AssignMouseEventData(aEvent, aCopyTargets);
+
+ mDataTransfer = aEvent.mDataTransfer;
+ // XXX mUserCancelled isn't copied, is this intentionally?
+ mUserCancelled = false;
+ mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
+ // XXX mInHTMLEditorEventListener isn't copied, is this intentionally?
+ mInHTMLEditorEventListener = false;
+ }
+
+ bool CanConvertToInputData() const {
+ return mMessage == eDragStart || mMessage == eDragEnd;
+ }
+
+ /**
+ * Should be called before dispatching the DOM tree if this event is
+ * synthesized for tests because drop effect is initialized before
+ * dispatching from widget if it's not synthesized event, but synthesized
+ * events are not initialized in the path.
+ */
+ void InitDropEffectForTests();
+};
+
+/******************************************************************************
+ * mozilla::WidgetMouseScrollEvent
+ *
+ * This is used for legacy DOM mouse scroll events, i.e.,
+ * DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled
+ * by ESM even if widget dispatches them. Use new WidgetWheelEvent instead.
+ ******************************************************************************/
+
+class WidgetMouseScrollEvent : public WidgetMouseEventBase {
+ private:
+ WidgetMouseScrollEvent() : mDelta(0), mIsHorizontal(false) {}
+
+ public:
+ virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override { return this; }
+
+ WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage,
+ nsIWidget* aWidget,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
+ eMouseScrollEventClass, aTime),
+ mDelta(0),
+ mIsHorizontal(false) {}
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_ASSERT(mClass == eMouseScrollEventClass,
+ "Duplicate() must be overridden by sub class");
+ // Not copying widget, it is a weak reference.
+ WidgetMouseScrollEvent* result =
+ new WidgetMouseScrollEvent(false, mMessage, nullptr, this);
+ result->AssignMouseScrollEventData(*this, true);
+ result->mFlags = mFlags;
+ return result;
+ }
+
+ // The delta value of mouse scroll event.
+ // If the event message is eLegacyMouseLineOrPageScroll, the value indicates
+ // scroll amount in lines. However, if the value is
+ // UIEvent::SCROLL_PAGE_UP or UIEvent::SCROLL_PAGE_DOWN, the
+ // value inducates one page scroll. If the event message is
+ // eLegacyMousePixelScroll, the value indicates scroll amount in pixels.
+ int32_t mDelta;
+
+ // If this is true, it may cause to scroll horizontally.
+ // Otherwise, vertically.
+ bool mIsHorizontal;
+
+ void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
+ bool aCopyTargets) {
+ AssignMouseEventBaseData(aEvent, aCopyTargets);
+
+ mDelta = aEvent.mDelta;
+ mIsHorizontal = aEvent.mIsHorizontal;
+ }
+};
+
+/******************************************************************************
+ * mozilla::WidgetWheelEvent
+ ******************************************************************************/
+
+class WidgetWheelEvent : public WidgetMouseEventBase {
+ private:
+ friend class mozilla::dom::PBrowserParent;
+ friend class mozilla::dom::PBrowserChild;
+ ALLOW_DEPRECATED_READPARAM
+
+ WidgetWheelEvent()
+ : mDeltaX(0.0),
+ mDeltaY(0.0),
+ mDeltaZ(0.0),
+ mOverflowDeltaX(0.0),
+ mOverflowDeltaY(0.0)
+ // Including WheelEventBinding.h here leads to an include loop, so
+ // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
+ ,
+ mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
+ mLineOrPageDeltaX(0),
+ mLineOrPageDeltaY(0),
+ mScrollType(SCROLL_DEFAULT),
+ mCustomizedByUserPrefs(false),
+ mMayHaveMomentum(false),
+ mIsMomentum(false),
+ mIsNoLineOrPageDelta(false),
+ mViewPortIsOverscrolled(false),
+ mCanTriggerSwipe(false),
+ mAllowToOverrideSystemScrollSpeed(false),
+ mDeltaValuesHorizontalizedForDefaultHandler(false) {}
+
+ public:
+ virtual WidgetWheelEvent* AsWheelEvent() override { return this; }
+
+ WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass,
+ aTime),
+ mDeltaX(0.0),
+ mDeltaY(0.0),
+ mDeltaZ(0.0),
+ mOverflowDeltaX(0.0),
+ mOverflowDeltaY(0.0)
+ // Including WheelEventBinding.h here leads to an include loop, so
+ // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
+ ,
+ mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
+ mLineOrPageDeltaX(0),
+ mLineOrPageDeltaY(0),
+ mScrollType(SCROLL_DEFAULT),
+ mCustomizedByUserPrefs(false),
+ mMayHaveMomentum(false),
+ mIsMomentum(false),
+ mIsNoLineOrPageDelta(false),
+ mViewPortIsOverscrolled(false),
+ mCanTriggerSwipe(false),
+ mAllowToOverrideSystemScrollSpeed(true),
+ mDeltaValuesHorizontalizedForDefaultHandler(false) {}
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_ASSERT(mClass == eWheelEventClass,
+ "Duplicate() must be overridden by sub class");
+ // Not copying widget, it is a weak reference.
+ WidgetWheelEvent* result =
+ new WidgetWheelEvent(false, mMessage, nullptr, this);
+ result->AssignWheelEventData(*this, true);
+ result->mFlags = mFlags;
+ return result;
+ }
+
+ // Scroll gestures that start at the edge of the scrollable range can result
+ // in a swipe gesture. For the first wheel event of such a gesture, call
+ // TriggersSwipe() after the event has been processed in order to find out
+ // whether a swipe should be started.
+ bool TriggersSwipe() const {
+ return mCanTriggerSwipe && mViewPortIsOverscrolled &&
+ this->mOverflowDeltaX != 0.0;
+ }
+
+ // NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by
+ // mousewheel.*.delta_multiplier_* prefs which are applied by
+ // EventStateManager. So, after widget dispatches this event,
+ // these delta values may have different values than before.
+ double mDeltaX;
+ double mDeltaY;
+ double mDeltaZ;
+
+ // The mousewheel tick counts.
+ double mWheelTicksX = 0.0;
+ double mWheelTicksY = 0.0;
+
+ enum class DeltaModeCheckingState : uint8_t {
+ // Neither deltaMode nor the delta values have been accessed.
+ Unknown,
+ // The delta values have been accessed, without checking deltaMode first.
+ Unchecked,
+ // The deltaMode has been checked.
+ Checked,
+ };
+
+ // For compat reasons, we might expose a DOM_DELTA_LINE event as
+ // DOM_DELTA_PIXEL instead. Whether we do that depends on whether the event
+ // has been asked for the deltaMode before the deltas. If it has, we assume
+ // that the page will correctly handle DOM_DELTA_LINE. This variable tracks
+ // that state. See bug 1392460.
+ DeltaModeCheckingState mDeltaModeCheckingState =
+ DeltaModeCheckingState::Unknown;
+
+ // The amount of scrolling per line or page, without accounting for mouse
+ // wheel transactions etc.
+ //
+ // Computed by EventStateManager::DeltaAccumulator::InitLineOrPageDelta.
+ nsSize mScrollAmount;
+
+ // overflowed delta values for scroll, these values are set by
+ // EventStateManger. If the default action of the wheel event isn't scroll,
+ // these values are always zero. Otherwise, remaining delta values which are
+ // not used by scroll are set.
+ // NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager.
+ // However, mOverflowDeltaX and mOverflowDeltaY indicate unused original
+ // delta values which are not applied the delta_multiplier prefs.
+ // So, if widget wanted to know the actual direction to be scrolled,
+ // it would need to check the mDeltaX and mDeltaY.
+ double mOverflowDeltaX;
+ double mOverflowDeltaY;
+
+ // Should be one of WheelEvent_Binding::DOM_DELTA_*
+ uint32_t mDeltaMode;
+
+ // If widget sets mLineOrPageDelta, EventStateManager will dispatch
+ // eLegacyMouseLineOrPageScroll event for compatibility. Note that the delta
+ // value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines.
+ int32_t mLineOrPageDeltaX;
+ int32_t mLineOrPageDeltaY;
+
+ // When the default action for an wheel event is moving history or zooming,
+ // need to chose a delta value for doing it.
+ int32_t GetPreferredIntDelta() {
+ if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) {
+ return 0;
+ }
+ if (mLineOrPageDeltaY && !mLineOrPageDeltaX) {
+ return mLineOrPageDeltaY;
+ }
+ if (mLineOrPageDeltaX && !mLineOrPageDeltaY) {
+ return mLineOrPageDeltaX;
+ }
+ if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) ||
+ (mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) {
+ return 0; // We cannot guess the answer in this case.
+ }
+ return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY))
+ ? mLineOrPageDeltaX
+ : mLineOrPageDeltaY;
+ }
+
+ // Scroll type
+ // The default value is SCROLL_DEFAULT, which means EventStateManager will
+ // select preferred scroll type automatically.
+ enum ScrollType : uint8_t {
+ SCROLL_DEFAULT,
+ SCROLL_SYNCHRONOUSLY,
+ SCROLL_ASYNCHRONOUSLY,
+ SCROLL_SMOOTHLY
+ };
+ ScrollType mScrollType;
+
+ // If the delta values are computed from prefs, this value is true.
+ // Otherwise, i.e., they are computed from native events, false.
+ bool mCustomizedByUserPrefs;
+
+ // true if the momentum events directly tied to this event may follow it.
+ bool mMayHaveMomentum;
+ // true if the event is caused by momentum.
+ bool mIsMomentum;
+
+ // If device event handlers don't know when they should set mLineOrPageDeltaX
+ // and mLineOrPageDeltaY, this is true. Otherwise, false.
+ // If mIsNoLineOrPageDelta is true, ESM will generate
+ // eLegacyMouseLineOrPageScroll events when accumulated delta values reach
+ // a line height.
+ bool mIsNoLineOrPageDelta;
+
+ // Whether or not the parent of the currently overscrolled frame is the
+ // ViewPort. This is false in situations when an element on the page is being
+ // overscrolled (such as a text field), but true when the 'page' is being
+ // overscrolled.
+ bool mViewPortIsOverscrolled;
+
+ // The wheel event can trigger a swipe to start if it's overscrolling the
+ // viewport.
+ bool mCanTriggerSwipe;
+
+ // If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be
+ // overridden. Otherwise, the scroll speed won't be overridden even if
+ // it's enabled by the pref.
+ bool mAllowToOverrideSystemScrollSpeed;
+
+ // After the event's default action handler has adjusted its delta's values
+ // for horizontalizing a vertical wheel scroll, this variable will be set to
+ // true.
+ bool mDeltaValuesHorizontalizedForDefaultHandler;
+
+ void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets) {
+ AssignMouseEventBaseData(aEvent, aCopyTargets);
+
+ mDeltaX = aEvent.mDeltaX;
+ mDeltaY = aEvent.mDeltaY;
+ mDeltaZ = aEvent.mDeltaZ;
+ mDeltaMode = aEvent.mDeltaMode;
+ mScrollAmount = aEvent.mScrollAmount;
+ mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs;
+ mMayHaveMomentum = aEvent.mMayHaveMomentum;
+ mIsMomentum = aEvent.mIsMomentum;
+ mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
+ mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX;
+ mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY;
+ mScrollType = aEvent.mScrollType;
+ mOverflowDeltaX = aEvent.mOverflowDeltaX;
+ mOverflowDeltaY = aEvent.mOverflowDeltaY;
+ mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
+ mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
+ mAllowToOverrideSystemScrollSpeed =
+ aEvent.mAllowToOverrideSystemScrollSpeed;
+ mDeltaValuesHorizontalizedForDefaultHandler =
+ aEvent.mDeltaValuesHorizontalizedForDefaultHandler;
+ }
+
+ // System scroll speed settings may be too slow at using Gecko. In such
+ // case, we should override the scroll speed computed with system settings.
+ // Following methods return preferred delta values which are multiplied by
+ // factors specified by prefs. If system scroll speed shouldn't be
+ // overridden (e.g., this feature is disabled by pref), they return raw
+ // delta values.
+ double OverriddenDeltaX() const;
+ double OverriddenDeltaY() const;
+
+ // Compute the overridden delta value. This may be useful for suppressing
+ // too fast scroll by system scroll speed overriding when widget sets
+ // mAllowToOverrideSystemScrollSpeed.
+ static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical);
+
+ private:
+ static bool sInitialized;
+ static bool sIsSystemScrollSpeedOverrideEnabled;
+ static int32_t sOverrideFactorX;
+ static int32_t sOverrideFactorY;
+ static void Initialize();
+};
+
+/******************************************************************************
+ * mozilla::WidgetPointerEvent
+ ******************************************************************************/
+
+class WidgetPointerEvent : public WidgetMouseEvent {
+ friend class mozilla::dom::PBrowserParent;
+ friend class mozilla::dom::PBrowserChild;
+ ALLOW_DEPRECATED_READPARAM
+
+ public:
+ virtual WidgetPointerEvent* AsPointerEvent() override { return this; }
+
+ WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w,
+ const WidgetEventTime* aTime = nullptr)
+ : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal, aTime),
+ mWidth(1),
+ mHeight(1),
+ mIsPrimary(true),
+ mFromTouchEvent(false) {}
+
+ explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
+ : WidgetMouseEvent(aEvent),
+ mWidth(1),
+ mHeight(1),
+ mIsPrimary(true),
+ mFromTouchEvent(false) {
+ mClass = ePointerEventClass;
+ }
+
+ virtual WidgetEvent* Duplicate() const override {
+ MOZ_ASSERT(mClass == ePointerEventClass,
+ "Duplicate() must be overridden by sub class");
+ // Not copying widget, it is a weak reference.
+ WidgetPointerEvent* result =
+ new WidgetPointerEvent(false, mMessage, nullptr, this);
+ result->AssignPointerEventData(*this, true);
+ result->mFlags = mFlags;
+ return result;
+ }
+
+ int32_t mWidth;
+ int32_t mHeight;
+ bool mIsPrimary;
+ bool mFromTouchEvent;
+
+ // XXX Not tested by test_assign_event_data.html
+ void AssignPointerEventData(const WidgetPointerEvent& aEvent,
+ bool aCopyTargets) {
+ AssignMouseEventData(aEvent, aCopyTargets);
+
+ mWidth = aEvent.mWidth;
+ mHeight = aEvent.mHeight;
+ mIsPrimary = aEvent.mIsPrimary;
+ mFromTouchEvent = aEvent.mFromTouchEvent;
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_MouseEvents_h__