/* 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_TouchEvents_h_ #define mozilla_TouchEvents_h_ #include #include "mozilla/MouseEvents.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/Touch.h" #include "nsTArray.h" namespace mozilla { /****************************************************************************** * mozilla::WidgetGestureNotifyEvent * * This event is the first event generated when the user touches * the screen with a finger, and it's meant to decide what kind * of action we'll use for that touch interaction. * * The event is dispatched to the layout and based on what is underneath * the initial contact point it's then decided if we should pan * (finger scrolling) or drag the target element. ******************************************************************************/ class WidgetGestureNotifyEvent final : public WidgetGUIEvent { public: NS_DEFINE_AS_EVENT_OVERRIDE(Widget, GestureNotifyEvent); WidgetGestureNotifyEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget, const WidgetEventTime* aTime = nullptr) : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eGestureNotifyEventClass, aTime), mPanDirection(ePanNone), mDisplayPanFeedback(false) {} NS_DEFINE_VIRTUAL_DESTRUCTOR_CHECKING_CLASS_VALUE(WidgetGestureNotifyEvent, eGestureNotifyEventClass, eGUIEventClass) virtual WidgetEvent* Duplicate() const override { // XXX Looks like this event is handled only in PostHandleEvent() of // EventStateManager. Therefore, it might be possible to handle this // in PreHandleEvent() and not to dispatch as a DOM event into the DOM // tree like ContentQueryEvent. Then, this event doesn't need to // support Duplicate(). MOZ_ASSERT(mClass == eGestureNotifyEventClass, "Duplicate() must be overridden by sub class"); // Not copying widget, it is a weak reference. WidgetGestureNotifyEvent* result = new WidgetGestureNotifyEvent(false, mMessage, nullptr, this); result->AssignGestureNotifyEventData(*this, true); result->mFlags = mFlags; return result; } typedef int8_t PanDirectionType; enum PanDirection : PanDirectionType { ePanNone, ePanVertical, ePanHorizontal, ePanBoth }; PanDirection mPanDirection; bool mDisplayPanFeedback; void AssignGestureNotifyEventData(const WidgetGestureNotifyEvent& aEvent, bool aCopyTargets) { AssignGUIEventData(aEvent, aCopyTargets); mPanDirection = aEvent.mPanDirection; mDisplayPanFeedback = aEvent.mDisplayPanFeedback; } }; /****************************************************************************** * mozilla::WidgetSimpleGestureEvent ******************************************************************************/ class WidgetSimpleGestureEvent final : public WidgetMouseEventBase { public: NS_DEFINE_AS_EVENT_OVERRIDE(Widget, SimpleGestureEvent); WidgetSimpleGestureEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget, const WidgetEventTime* aTime = nullptr) : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eSimpleGestureEventClass, aTime), mAllowedDirections(0), mDirection(0), mClickCount(0), mDelta(0.0) {} WidgetSimpleGestureEvent(const WidgetSimpleGestureEvent& aOther) : WidgetMouseEventBase(aOther.IsTrusted(), aOther.mMessage, aOther.mWidget, eSimpleGestureEventClass), mAllowedDirections(aOther.mAllowedDirections), mDirection(aOther.mDirection), mClickCount(0), mDelta(aOther.mDelta) {} NS_DEFINE_VIRTUAL_DESTRUCTOR_CHECKING_CLASS_VALUE(WidgetSimpleGestureEvent, eSimpleGestureEventClass, eMouseEventBaseClass) virtual WidgetEvent* Duplicate() const override { MOZ_ASSERT(mClass == eSimpleGestureEventClass, "Duplicate() must be overridden by sub class"); // Not copying widget, it is a weak reference. WidgetSimpleGestureEvent* result = new WidgetSimpleGestureEvent(false, mMessage, nullptr, this); result->AssignSimpleGestureEventData(*this, true); result->mFlags = mFlags; return result; } // See SimpleGestureEvent.webidl for values uint32_t mAllowedDirections; // See SimpleGestureEvent.webidl for values uint32_t mDirection; // The number of taps for tap events uint32_t mClickCount; // Delta for magnify and rotate events double mDelta; // XXX Not tested by test_assign_event_data.html void AssignSimpleGestureEventData(const WidgetSimpleGestureEvent& aEvent, bool aCopyTargets) { AssignMouseEventBaseData(aEvent, aCopyTargets); // mAllowedDirections isn't copied mDirection = aEvent.mDirection; mDelta = aEvent.mDelta; mClickCount = aEvent.mClickCount; } }; /****************************************************************************** * mozilla::WidgetTouchEvent ******************************************************************************/ class WidgetTouchEvent final : public WidgetInputEvent { public: typedef nsTArray> TouchArray; typedef AutoTArray, 10> AutoTouchArray; typedef AutoTouchArray::base_type TouchArrayBase; NS_DEFINE_AS_EVENT_OVERRIDE(Widget, TouchEvent); MOZ_COUNTED_DEFAULT_CTOR(WidgetTouchEvent) enum class CloneTouches : bool { No, Yes }; WidgetTouchEvent(const WidgetTouchEvent& aOther, CloneTouches aCloneTouches = CloneTouches::No) : WidgetInputEvent(aOther.IsTrusted(), aOther.mMessage, aOther.mWidget, eTouchEventClass) { MOZ_COUNT_CTOR(WidgetTouchEvent); mModifiers = aOther.mModifiers; mTimeStamp = aOther.mTimeStamp; if (static_cast(aCloneTouches)) { mTouches.SetCapacity(aOther.mTouches.Length()); for (const RefPtr& touch : aOther.mTouches) { auto clonedTouch = MakeRefPtr(*touch); mTouches.AppendElement(std::move(clonedTouch)); } } else { mTouches.AppendElements(aOther.mTouches); } mInputSource = aOther.mInputSource; mButton = aOther.mButton; mButtons = aOther.mButtons; mFlags.mCancelable = mMessage != eTouchCancel; mFlags.mHandledByAPZ = aOther.mFlags.mHandledByAPZ; } WidgetTouchEvent(WidgetTouchEvent&& aOther) : WidgetInputEvent(std::move(aOther)) { MOZ_COUNT_CTOR(WidgetTouchEvent); mModifiers = aOther.mModifiers; mTimeStamp = aOther.mTimeStamp; mTouches = std::move(aOther.mTouches); mInputSource = aOther.mInputSource; mButton = aOther.mButton; mButtons = aOther.mButtons; mFlags = aOther.mFlags; } WidgetTouchEvent& operator=(WidgetTouchEvent&&) = default; WidgetTouchEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget, const WidgetEventTime* aTime = nullptr) : WidgetInputEvent(aIsTrusted, aMessage, aWidget, eTouchEventClass, aTime) { MOZ_COUNT_CTOR(WidgetTouchEvent); mFlags.mCancelable = mMessage != eTouchCancel; } #if defined(NS_BUILD_REFCNT_LOGGING) || defined(DEBUG) virtual ~WidgetTouchEvent() { MOZ_COUNT_DTOR(WidgetTouchEvent); NS_ASSERT_EVENT_CLASS_ID(eTouchEventClass, eInputEventClass); } #endif WidgetEvent* Duplicate() const override { MOZ_ASSERT(mClass == eTouchEventClass, "Duplicate() must be overridden by sub class"); // Not copying widget, it is a weak reference. WidgetTouchEvent* result = new WidgetTouchEvent(false, mMessage, nullptr, this); result->AssignTouchEventData(*this, true); result->mFlags = mFlags; return result; } TouchArray mTouches; uint16_t mInputSource = 5; // MouseEvent_Binding::MOZ_SOURCE_TOUCH int16_t mButton = eNotPressed; int16_t mButtons = 0; /** * An optional identifier for the callback associated with this touch event. * This ID is used to reference a specific callback for a synthesized event, * if one is present. If no callback is associated, this value will be empty. */ Maybe mCallbackId; void AssignTouchEventData(const WidgetTouchEvent& aEvent, bool aCopyTargets) { AssignInputEventData(aEvent, aCopyTargets); // Assign*EventData() assume that they're called only new instance. MOZ_ASSERT(mTouches.IsEmpty()); mTouches.AppendElements(aEvent.mTouches); mInputSource = aEvent.mInputSource; // NOTE: Intentionally not copying mCallbackId, it should only be tracked by // the original event or propagated to the cross-process event. } void SetConvertToPointerRawUpdate(bool aConvert) { for (dom::Touch* const touch : mTouches) { touch->convertToPointerRawUpdate = aConvert; } } [[nodiscard]] bool CanConvertToPointerRawUpdate() const { for (const dom::Touch* const touch : mTouches) { if (touch->convertToPointerRawUpdate) { return true; } } return false; } }; } // namespace mozilla #endif // mozilla_TouchEvents_h_