diff options
Diffstat (limited to 'widget/InputData.h')
-rw-r--r-- | widget/InputData.h | 828 |
1 files changed, 828 insertions, 0 deletions
diff --git a/widget/InputData.h b/widget/InputData.h new file mode 100644 index 0000000000..4b36b58cec --- /dev/null +++ b/widget/InputData.h @@ -0,0 +1,828 @@ +/* -*- 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 InputData_h__ +#define InputData_h__ + +#include "nsDebug.h" +#include "nsPoint.h" +#include "nsTArray.h" +#include "Units.h" +#include "mozilla/ScrollTypes.h" +#include "mozilla/DefineEnum.h" +#include "mozilla/EventForwards.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/WheelHandlingHelper.h" // for WheelDeltaAdjustmentStrategy +#include "mozilla/gfx/MatrixFwd.h" +#include "mozilla/layers/APZPublicUtils.h" +#include "mozilla/layers/KeyboardScrollAction.h" +#include "mozilla/TextEvents.h" + +template <class E> +struct already_AddRefed; +class nsIWidget; + +namespace mozilla { + +namespace layers { +class APZInputBridgeChild; +class PAPZInputBridgeParent; +} // namespace layers + +namespace dom { +class Touch; +} // namespace dom + +// clang-format off +MOZ_DEFINE_ENUM( + InputType, ( + MULTITOUCH_INPUT, + MOUSE_INPUT, + PANGESTURE_INPUT, + PINCHGESTURE_INPUT, + TAPGESTURE_INPUT, + SCROLLWHEEL_INPUT, + KEYBOARD_INPUT +)); +// clang-format on + +class MultiTouchInput; +class MouseInput; +class PanGestureInput; +class PinchGestureInput; +class TapGestureInput; +class ScrollWheelInput; +class KeyboardInput; + +// This looks unnecessary now, but as we add more and more classes that derive +// from InputType (eventually probably almost as many as *Events.h has), it +// will be more and more clear what's going on with a macro that shortens the +// definition of the RTTI functions. +#define INPUTDATA_AS_CHILD_TYPE(type, enumID) \ + const type& As##type() const { \ + MOZ_ASSERT(mInputType == enumID, "Invalid cast of InputData."); \ + return (const type&)*this; \ + } \ + type& As##type() { \ + MOZ_ASSERT(mInputType == enumID, "Invalid cast of InputData."); \ + return (type&)*this; \ + } + +/** Base input data class. Should never be instantiated. */ +class InputData { + public: + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + InputType mInputType; + // Time that this data is relevant to. This only really matters when this data + // is used as an event. + TimeStamp mTimeStamp; + // The sequence number of the last potentially focus changing event handled + // by APZ. This is used to track when that event has been processed by + // content, and focus can be reconfirmed for async keyboard scrolling. + uint64_t mFocusSequenceNumber; + + // The LayersId of the content process that the corresponding WidgetEvent + // should be dispatched to. + layers::LayersId mLayersId; + + Modifiers modifiers; + + INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT) + INPUTDATA_AS_CHILD_TYPE(MouseInput, MOUSE_INPUT) + INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT) + INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT) + INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT) + INPUTDATA_AS_CHILD_TYPE(ScrollWheelInput, SCROLLWHEEL_INPUT) + INPUTDATA_AS_CHILD_TYPE(KeyboardInput, KEYBOARD_INPUT) + + virtual ~InputData(); + explicit InputData(InputType aInputType); + + protected: + InputData(InputType aInputType, TimeStamp aTimeStamp, Modifiers aModifiers); +}; + +/** + * Data container for a single touch input. Similar to dom::Touch, but used in + * off-main-thread situations. This is more for just storing touch data, whereas + * dom::Touch is more useful for dispatching through the DOM (which can only + * happen on the main thread). dom::Touch also bears the problem of storing + * pointers to nsIWidget instances which can only be used on the main thread, + * so if instead we used dom::Touch and ever set these pointers + * off-main-thread, Bad Things Can Happen(tm). + * + * Note that this doesn't inherit from InputData because this itself is not an + * event. It is only a container/struct that should have any number of instances + * within a MultiTouchInput. + * + * fixme/bug 775746: Make dom::Touch inherit from this class. + */ +class SingleTouchData { + public: + // Construct a SingleTouchData from a Screen point. + // mLocalScreenPoint remains (0,0) unless it's set later. + SingleTouchData(int32_t aIdentifier, ScreenIntPoint aScreenPoint, + ScreenSize aRadius, float aRotationAngle, float aForce); + + // Construct a SingleTouchData from a ParentLayer point. + // mScreenPoint remains (0,0) unless it's set later. + // Note: if APZ starts using the radius for anything, we should add a local + // version of that too, and have this constructor take it as a + // ParentLayerSize. + SingleTouchData(int32_t aIdentifier, ParentLayerPoint aLocalScreenPoint, + ScreenSize aRadius, float aRotationAngle, float aForce); + + SingleTouchData(); + + already_AddRefed<dom::Touch> ToNewDOMTouch() const; + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + + // Historical data of this touch, which was coalesced into this event. + // Touch event coalescing can happen at the system level when the touch + // screen's sampling frequency is higher than the vsync rate, or when the + // UI thread is busy. When multiple "samples" of touch data are coalesced into + // one touch event, the touch event's regular position information is the + // information from the last sample. And the previous, "coalesced-away" + // samples are stored in mHistoricalData. + + struct HistoricalTouchData { + // The timestamp at which the information in this "sample" was originally + // sampled. + TimeStamp mTimeStamp; + + // The touch data of this historical sample. + ScreenIntPoint mScreenPoint; + ParentLayerPoint mLocalScreenPoint; + ScreenSize mRadius; + float mRotationAngle = 0.0f; + float mForce = 0.0f; + }; + CopyableTArray<HistoricalTouchData> mHistoricalData; + + // A unique number assigned to each SingleTouchData within a MultiTouchInput + // so that they can be easily distinguished when handling a touch + // start/move/end. + int32_t mIdentifier; + + // Point on the screen that the touch hit, in device pixels. They are + // coordinates on the screen. + ScreenIntPoint mScreenPoint; + + // |mScreenPoint| transformed to the local coordinates of the APZC targeted + // by the hit. This is set and used by APZ. + ParentLayerPoint mLocalScreenPoint; + + // Radius that the touch covers, i.e. if you're using your thumb it will + // probably be larger than using your pinky, even with the same force. + // Radius can be different along x and y. For example, if you press down with + // your entire finger vertically, the y radius will be much larger than the x + // radius. + ScreenSize mRadius; + + float mRotationAngle; + + // How hard the screen is being pressed. + float mForce; + + int32_t mTiltX = 0; + int32_t mTiltY = 0; + int32_t mTwist = 0; +}; + +/** + * Similar to WidgetTouchEvent, but for use off-main-thread. Also only stores a + * screen touch point instead of the many different coordinate spaces + * WidgetTouchEvent stores its touch point in. This includes a way to initialize + * itself from a WidgetTouchEvent by copying all relevant data over. Note that + * this copying from WidgetTouchEvent functionality can only be used on the main + * thread. + * + * Stores an array of SingleTouchData. + */ +class MultiTouchInput : public InputData { + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + MultiTouchType, ( + MULTITOUCH_START, + MULTITOUCH_MOVE, + MULTITOUCH_END, + MULTITOUCH_CANCEL + )); + // clang-format on + + MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp, + Modifiers aModifiers); + MultiTouchInput(); + MultiTouchInput(MultiTouchInput&&) = default; + MultiTouchInput(const MultiTouchInput&) = default; + explicit MultiTouchInput(const WidgetTouchEvent& aTouchEvent); + + MultiTouchInput& operator=(MultiTouchInput&&) = default; + MultiTouchInput& operator=(const MultiTouchInput&) = default; + + void Translate(const ScreenPoint& aTranslation); + + WidgetTouchEvent ToWidgetEvent( + nsIWidget* aWidget, + uint16_t aInputSource = + /* MouseEvent_Binding::MOZ_SOURCE_TOUCH = */ 5) const; + + // Return the index into mTouches of the SingleTouchData with the given + // identifier, or -1 if there is no such SingleTouchData. + int32_t IndexOfTouch(int32_t aTouchIdentifier); + + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + MultiTouchType mType; + CopyableTArray<SingleTouchData> mTouches; + // The screen offset of the root widget. This can be changing along with + // the touch interaction, so we sstore it in the event. + ExternalPoint mScreenOffset; + bool mHandledByAPZ; + // These button fields match to the corresponding fields in + // WidgetMouseEventBase, except mButton defaults to -1 to follow PointerEvent. + int16_t mButton = eNotPressed; + int16_t mButtons = 0; +}; + +class MouseInput : public InputData { + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + MouseInput(); + + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + MouseType, ( + MOUSE_NONE, + MOUSE_MOVE, + MOUSE_DOWN, + MOUSE_UP, + MOUSE_DRAG_START, + MOUSE_DRAG_END, + MOUSE_WIDGET_ENTER, + MOUSE_WIDGET_EXIT, + MOUSE_HITTEST, + MOUSE_EXPLORE_BY_TOUCH + )); + + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + ButtonType, ( + PRIMARY_BUTTON, + MIDDLE_BUTTON, + SECONDARY_BUTTON, + NONE + )); + // clang-format on + + MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource, + int16_t aButtons, const ScreenPoint& aPoint, TimeStamp aTimeStamp, + Modifiers aModifiers); + explicit MouseInput(const WidgetMouseEventBase& aMouseEvent); + + bool IsLeftButton() const; + + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + WidgetMouseEvent ToWidgetEvent(nsIWidget* aWidget) const; + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + MouseType mType; + ButtonType mButtonType; + uint16_t mInputSource; + int16_t mButtons; + ScreenPoint mOrigin; + ParentLayerPoint mLocalOrigin; + bool mHandledByAPZ; + /** + * If click event should not be fired in the content after the "mousedown" + * event or following "mouseup", set to true. + */ + bool mPreventClickEvent; +}; + +/** + * Encapsulation class for pan events, can be used off-main-thread. + * These events are currently only used for scrolling on desktop. + */ +class PanGestureInput : public InputData { + friend struct IPC::ParamTraits<PanGestureInput>; + + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + PanGestureInput(); + + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + PanGestureType, ( + // MayStart: Dispatched before any actual panning has occurred but when a + // pan gesture is probably about to start, for example when the user + // starts touching the touchpad. Should interrupt any ongoing APZ + // animation and can be used to trigger scrollability indicators (e.g. + // flashing overlay scrollbars). + PANGESTURE_MAYSTART, + + // Cancelled: Dispatched after MayStart when no pan gesture is going to + // happen after all, for example when the user lifts their fingers from a + // touchpad without having done any scrolling. + PANGESTURE_CANCELLED, + + // Start: A pan gesture is starting. + // For devices that do not support the MayStart event type, this event can + // be used to interrupt ongoing APZ animations. + PANGESTURE_START, + + // Pan: The actual pan motion by mPanDisplacement. + PANGESTURE_PAN, + + // End: The pan gesture has ended, for example because the user has lifted + // their fingers from a touchpad after scrolling. + // Any potential momentum events fire after this event. + PANGESTURE_END, + + // The following momentum event types are used in order to control the pan + // momentum animation. Using these instead of our own animation ensures + // that the animation curve is OS native and that the animation stops + // reliably if it is cancelled by the user. + + // MomentumStart: Dispatched between the End event of the actual + // user-controlled pan, and the first MomentumPan event of the momentum + // animation. + PANGESTURE_MOMENTUMSTART, + + // MomentumPan: The actual momentum motion by mPanDisplacement. + PANGESTURE_MOMENTUMPAN, + + // MomentumEnd: The momentum animation has ended, for example because the + // momentum velocity has gone below the stopping threshold, or because the + // user has stopped the animation by putting their fingers on a touchpad. + PANGESTURE_MOMENTUMEND, + + // Interrupted:: A pan gesture started being handled by an APZC but + // subsequent pan events might have been consumed by other operations + // which haven't been handled by the APZC (e.g. full zoom). + PANGESTURE_INTERRUPTED + )); + + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + PanDeltaType, ( + // There are three kinds of scroll delta modes in Gecko: "page", "line" + // and "pixel". Touchpad pan gestures only support "page" and "pixel". + // + // NOTE: PANDELTA_PAGE currently replicates Gtk behavior + // (see AsyncPanZoomController::OnPan). + PANDELTA_PAGE, + PANDELTA_PIXEL + )); + // clang-format on + + PanGestureInput(PanGestureType aType, TimeStamp aTimeStamp, + const ScreenPoint& aPanStartPoint, + const ScreenPoint& aPanDisplacement, Modifiers aModifiers); + + enum class IsEligibleForSwipe : bool { No, Yes }; + PanGestureInput(PanGestureType aType, TimeStamp aTimeStamp, + const ScreenPoint& aPanStartPoint, + const ScreenPoint& aPanDisplacement, Modifiers aModifiers, + IsEligibleForSwipe aIsEligibleForSwipe); + + void SetLineOrPageDeltas(int32_t aLineOrPageDeltaX, + int32_t aLineOrPageDeltaY); + + bool IsMomentum() const; + + WidgetWheelEvent ToWidgetEvent(nsIWidget* aWidget) const; + + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + + ScreenPoint UserMultipliedPanDisplacement() const; + ParentLayerPoint UserMultipliedLocalPanDisplacement() const; + + void SetHandledByAPZ(bool aHandled) { mHandledByAPZ = aHandled; } + void SetOverscrollBehaviorAllowsSwipe(bool aAllows) { + mOverscrollBehaviorAllowsSwipe = aAllows; + } + void SetSimulateMomentum(bool aSimulate) { mSimulateMomentum = aSimulate; } + void SetIsNoLineOrPageDelta(bool aIsNoLineOrPageDelta) { + mIsNoLineOrPageDelta = aIsNoLineOrPageDelta; + } + + // Returns true if this pan gesture event is elligible for browser swipe + // gesture considering the overscroll-behavior property of the target + // scroll container. + bool AllowsSwipe() const { + MOZ_ASSERT(mHandledByAPZ); + return mMayTriggerSwipe && mOverscrollBehaviorAllowsSwipe; + } + + // Similar to above AllowsSwipe() but this doesn't care the + // overscroll-behavior property, this function should be only used for cases + // where APZ isn't involved. + bool MayTriggerSwipe() const { return mMayTriggerSwipe; } + bool RequiresContentResponseIfCannotScrollHorizontallyInStartDirection(); + + static gfx::IntPoint GetIntegerDeltaForEvent(bool aIsStart, float x, float y); + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + PanGestureType mType; + ScreenPoint mPanStartPoint; + + // The delta. This can be non-zero on any type of event. + ScreenPoint mPanDisplacement; + + // Versions of |mPanStartPoint| and |mPanDisplacement| in the local + // coordinates of the APZC receiving the pan. These are set and used by APZ. + ParentLayerPoint mLocalPanStartPoint; + ParentLayerPoint mLocalPanDisplacement; + + // See lineOrPageDeltaX/Y on WidgetWheelEvent. + int32_t mLineOrPageDeltaX; + int32_t mLineOrPageDeltaY; + + // User-set delta multipliers. + double mUserDeltaMultiplierX; + double mUserDeltaMultiplierY; + + PanDeltaType mDeltaType = PANDELTA_PIXEL; + + bool mHandledByAPZ : 1; + + // This is used by APZ to communicate to widget code whether the + // overscroll-behavior of the scroll frame handling this swipe allows + // non-local overscroll behaviors in the horizontal direction (such as + // swipe navigation). + bool mOverscrollBehaviorAllowsSwipe : 1; + + // true if APZ should do a fling animation after this pan ends, like + // it would with touchscreens. (For platforms that don't emit momentum + // events.) + bool mSimulateMomentum : 1; + + // true if the creator of this object does not set the mLineOrPageDeltaX/Y + // fields and when/if WidgetWheelEvent's are generated from this object wants + // the corresponding mLineOrPageDeltaX/Y fields in the WidgetWheelEvent to be + // automatically calculated (upon event dispatch by the EventStateManager + // code). + bool mIsNoLineOrPageDelta : 1; + + private: + // If this is true, and this event started a new input block that couldn't + // find a scrollable target which is scrollable in the horizontal component + // of the scroll start direction, then this input block needs to be put on + // hold until a content response has arrived, even if the block has a + // confirmed target. + // This is used by events that can result in a swipe instead of a scroll. + bool mMayTriggerSwipe : 1; + void SetMayTriggerSwipe(bool aValue) { mMayTriggerSwipe = aValue; } +}; + +/** + * Encapsulation class for pinch events. In general, these will be generated by + * a gesture listener by looking at SingleTouchData/MultiTouchInput instances + * and determining whether or not the user was trying to do a gesture. + */ +class PinchGestureInput : public InputData { + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + PinchGestureInput(); + + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + PinchGestureType, ( + PINCHGESTURE_START, + PINCHGESTURE_SCALE, + // The FINGERLIFTED state is used when a touch-based pinch gesture is + // terminated by lifting one of the two fingers. The position of the + // finger that's still down is populated as the focus point. + PINCHGESTURE_FINGERLIFTED, + // The END state is used when the pinch gesture is completely terminated. + // In this state, the focus point should not be relied upon for having + // meaningful data. + PINCHGESTURE_END + )); + + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + PinchGestureSource, ( + UNKNOWN, // Default initialization value. Should never actually be used. + TOUCH, // From two-finger pinch gesture + ONE_TOUCH, // From one-finger pinch gesture + TRACKPAD, // From trackpad pinch gesture + MOUSEWHEEL // Synthesized from modifier+mousewheel + + // If adding more items here, increase n_values for the + // APZ_ZOOM_PINCHSOURCE Telemetry metric. + )); + // clang-format on + + // Construct a pinch gesture from a Screen point. + PinchGestureInput(PinchGestureType aType, PinchGestureSource aSource, + TimeStamp aTimeStamp, const ExternalPoint& aScreenOffset, + const ScreenPoint& aFocusPoint, ScreenCoord aCurrentSpan, + ScreenCoord aPreviousSpan, Modifiers aModifiers); + + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + + WidgetWheelEvent ToWidgetEvent(nsIWidget* aWidget) const; + + double ComputeDeltaY(nsIWidget* aWidget) const; + + // Set mLineOrPageDeltaY based on ComputeDeltaY(). + // Return false if the caller should drop this event to ensure + // that preventDefault() is respected. (More specifically, this will be + // true for event types other than PINCHGESTURE_END if the computed + // mLineOrPageDeltaY is zero. In such cases, the resulting DOMMouseScroll + // event will not be dispatched, which is a problem if the page is relying + // on DOMMouseScroll to prevent browser zooming). + // Note that even if the function returns false, the delta from the event + // is accumulated and available to be sent in a later event. + bool SetLineOrPageDeltaY(nsIWidget* aWidget); + + static gfx::IntPoint GetIntegerDeltaForEvent(bool aIsStart, float x, float y); + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + PinchGestureType mType; + + // Some indication of the input device that generated this pinch gesture. + PinchGestureSource mSource; + + // Center point of the pinch gesture. That is, if there are two fingers on the + // screen, it is their midpoint. In the case of more than two fingers, the + // point is implementation-specific, but can for example be the midpoint + // between the very first and very last touch. This is in device pixels and + // are the coordinates on the screen of this midpoint. + // For PINCHGESTURE_END events, this may hold the last known focus point or + // just be empty; in any case for END events it should not be relied upon. + // For PINCHGESTURE_FINGERLIFTED events, this holds the point of the finger + // that is still down. + ScreenPoint mFocusPoint; + + // The screen offset of the root widget. This can be changing along with + // the touch interaction, so we sstore it in the event. + ExternalPoint mScreenOffset; + + // |mFocusPoint| transformed to the local coordinates of the APZC targeted + // by the hit. This is set and used by APZ. + ParentLayerPoint mLocalFocusPoint; + + // The distance between the touches responsible for the pinch gesture. + ScreenCoord mCurrentSpan; + + // The previous |mCurrentSpan| in the PinchGestureInput preceding this one. + // This is only really relevant during a PINCHGESTURE_SCALE because when it is + // of this type then there must have been a history of spans. + ScreenCoord mPreviousSpan; + + // We accumulate (via GetIntegerDeltaForEvent) the deltaY that would be + // computed by ToWidgetEvent, and then whenever we get a whole integer + // value we put it in mLineOrPageDeltaY. Since we only ever use deltaY we + // don't need a mLineOrPageDeltaX. This field is used to dispatch legacy mouse + // events which are only dispatched when the corresponding field on + // WidgetWheelEvent is non-zero. + int32_t mLineOrPageDeltaY; + + bool mHandledByAPZ; +}; + +/** + * Encapsulation class for tap events. In general, these will be generated by + * a gesture listener by looking at SingleTouchData/MultiTouchInput instances + * and determining whether or not the user was trying to do a gesture. + */ +class TapGestureInput : public InputData { + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + TapGestureInput(); + + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + TapGestureType, ( + TAPGESTURE_LONG, + TAPGESTURE_LONG_UP, + TAPGESTURE_UP, + TAPGESTURE_CONFIRMED, + TAPGESTURE_DOUBLE, + TAPGESTURE_SECOND, // See GeckoContentController::TapType::eSecondTap + TAPGESTURE_CANCEL + )); + // clang-format on + + // Construct a tap gesture from a Screen point. + // mLocalPoint remains (0,0) unless it's set later. + TapGestureInput(TapGestureType aType, TimeStamp aTimeStamp, + const ScreenIntPoint& aPoint, Modifiers aModifiers); + + // Construct a tap gesture from a ParentLayer point. + // mPoint remains (0,0) unless it's set later. + TapGestureInput(TapGestureType aType, TimeStamp aTimeStamp, + const ParentLayerPoint& aLocalPoint, Modifiers aModifiers); + + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + + WidgetSimpleGestureEvent ToWidgetEvent(nsIWidget* aWidget) const; + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + TapGestureType mType; + + // The location of the tap in screen pixels. + ScreenIntPoint mPoint; + + // The location of the tap in the local coordinates of the APZC receiving it. + // This is set and used by APZ. + ParentLayerPoint mLocalPoint; +}; + +// Encapsulation class for scroll-wheel events. These are generated by mice +// with physical scroll wheels, and on Windows by most touchpads when using +// scroll gestures. +class ScrollWheelInput : public InputData { + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + typedef mozilla::layers::APZWheelAction APZWheelAction; + + ScrollWheelInput(); + + public: + // clang-format off + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + ScrollDeltaType, ( + // There are three kinds of scroll delta modes in Gecko: "page", "line" + // and "pixel". + SCROLLDELTA_LINE, + SCROLLDELTA_PAGE, + SCROLLDELTA_PIXEL + )); + + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE( + ScrollMode, ( + SCROLLMODE_INSTANT, + SCROLLMODE_SMOOTH + ) + ); + // clang-format on + + ScrollWheelInput(TimeStamp aTimeStamp, Modifiers aModifiers, + ScrollMode aScrollMode, ScrollDeltaType aDeltaType, + const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY, + bool aAllowToOverrideSystemScrollSpeed, + WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy); + explicit ScrollWheelInput(const WidgetWheelEvent& aEvent); + + static ScrollDeltaType DeltaTypeForDeltaMode(uint32_t aDeltaMode); + static uint32_t DeltaModeForDeltaType(ScrollDeltaType aDeltaType); + static mozilla::ScrollUnit ScrollUnitForDeltaType(ScrollDeltaType aDeltaType); + + WidgetWheelEvent ToWidgetEvent(nsIWidget* aWidget) const; + bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform); + + bool IsCustomizedByUserPrefs() const; + + // The following two functions are for auto-dir scrolling. For detailed + // information on auto-dir, @see mozilla::WheelDeltaAdjustmentStrategy + bool IsAutoDir(bool aForce = false) const { + if (aForce) { + return true; + } + + switch (mWheelDeltaAdjustmentStrategy) { + case WheelDeltaAdjustmentStrategy::eAutoDir: + case WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour: + return true; + default: + // Prevent compilation errors generated by -Werror=switch + break; + } + return false; + } + // Indicates which element this scroll honours if it's an auto-dir scroll. + // If true, honour the root element; otherwise, honour the currently scrolling + // target. + // Note that if IsAutoDir() returns false, then this function also returns + // false, but false in this case is meaningless as IsAutoDir() indicates it's + // not an auto-dir scroll. + // For detailed information on auto-dir, + // @see mozilla::WheelDeltaAdjustmentStrategy + bool HonoursRoot(bool aForce = false) const { + return WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour == + mWheelDeltaAdjustmentStrategy || + aForce; + } + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + ScrollDeltaType mDeltaType; + ScrollMode mScrollMode; + ScreenPoint mOrigin; + + bool mHandledByAPZ; + + // Deltas are in units corresponding to the delta type. For line deltas, they + // are the number of line units to scroll. The number of device pixels for a + // horizontal and vertical line unit are in FrameMetrics::mLineScrollAmount. + // For pixel deltas, these values are in ScreenCoords. + // + // The horizontal (X) delta is > 0 for scrolling right and < 0 for scrolling + // left. The vertical (Y) delta is < 0 for scrolling up and > 0 for + // scrolling down. + double mDeltaX; + double mDeltaY; + + // The number of scroll wheel ticks. + double mWheelTicksX = 0.0; + double mWheelTicksY = 0.0; + + // The location of the scroll in local coordinates. This is set and used by + // APZ. + ParentLayerPoint mLocalOrigin; + + // See lineOrPageDeltaX/Y on WidgetWheelEvent. + int32_t mLineOrPageDeltaX; + int32_t mLineOrPageDeltaY; + + // Indicates the order in which this event was added to a transaction. The + // first event is 1; if not a member of a transaction, this is 0. + uint32_t mScrollSeriesNumber; + + // User-set delta multipliers. + double mUserDeltaMultiplierX; + double mUserDeltaMultiplierY; + + bool mMayHaveMomentum; + bool mIsMomentum; + bool mAllowToOverrideSystemScrollSpeed; + + // Sometimes a wheel event input's wheel delta should be adjusted. This member + // specifies how to adjust the wheel delta. + WheelDeltaAdjustmentStrategy mWheelDeltaAdjustmentStrategy; + + APZWheelAction mAPZAction; +}; + +class KeyboardInput : public InputData { + public: + typedef mozilla::layers::KeyboardScrollAction KeyboardScrollAction; + + // Note that if you change the first member in this enum(I.e. KEY_DOWN) to one + // other member, don't forget to update the minimum value in + // ContiguousEnumSerializer for KeyboardEventType in widget/nsGUIEventIPC + // accordingly. + enum KeyboardEventType { + KEY_DOWN, + KEY_PRESS, + KEY_UP, + // Any other key event such as eAccessKeyNotFound + KEY_OTHER, + + // Used as an upper bound for ContiguousEnumSerializer + KEY_SENTINEL, + }; + + explicit KeyboardInput(const WidgetKeyboardEvent& aEvent); + + // Warning, this class is serialized and sent over IPC. Any change to its + // fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h + + KeyboardEventType mType; + uint32_t mKeyCode; + uint32_t mCharCode; + CopyableTArray<ShortcutKeyCandidate> mShortcutCandidates; + + bool mHandledByAPZ; + + // The scroll action to perform on a layer for this keyboard input. This is + // only used in APZ and is NOT serialized over IPC. + KeyboardScrollAction mAction; + + protected: + friend mozilla::layers::APZInputBridgeChild; + friend mozilla::layers::PAPZInputBridgeParent; + + KeyboardInput(); +}; + +} // namespace mozilla + +#endif // InputData_h__ |