/* 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 <stdint.h>
#include "mozilla/dom/Touch.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/RefPtr.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<RefPtr<mozilla::dom::Touch>> TouchArray;
typedef AutoTArray<RefPtr<mozilla::dom::Touch>,
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<
bool>(aCloneTouches)) {
mTouches.SetCapacity(aOther.mTouches.Length());
for (
const RefPtr<dom::Touch>& touch : aOther.mTouches) {
auto clonedTouch = MakeRefPtr<dom::Touch>(*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<uint64_t> 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_