diff options
Diffstat (limited to 'widget/MouseEvents.h')
-rw-r--r-- | widget/MouseEvents.h | 812 |
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__ |