2017-09-06 10:47:49 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* 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_PointerEventHandler_h
|
|
|
|
#define mozilla_PointerEventHandler_h
|
|
|
|
|
|
|
|
#include "mozilla/EventForwards.h"
|
2017-11-26 16:54:07 +03:00
|
|
|
#include "mozilla/MouseEvents.h"
|
|
|
|
#include "mozilla/TouchEvents.h"
|
2020-10-30 11:31:42 +03:00
|
|
|
#include "mozilla/WeakPtr.h"
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2020-11-23 19:21:38 +03:00
|
|
|
// XXX Avoid including this here by moving function bodies to the cpp file
|
|
|
|
#include "mozilla/dom/Document.h"
|
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
class nsIFrame;
|
|
|
|
class nsIContent;
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
class PresShell;
|
|
|
|
|
2020-10-05 18:56:52 +03:00
|
|
|
namespace dom {
|
2020-10-27 00:00:50 +03:00
|
|
|
class BrowserParent;
|
2020-10-30 11:31:42 +03:00
|
|
|
class Document;
|
2020-10-05 18:56:52 +03:00
|
|
|
class Element;
|
2020-10-27 00:00:50 +03:00
|
|
|
}; // namespace dom
|
2020-10-05 18:56:52 +03:00
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
class PointerCaptureInfo final {
|
|
|
|
public:
|
2020-10-05 18:56:52 +03:00
|
|
|
RefPtr<dom::Element> mPendingElement;
|
|
|
|
RefPtr<dom::Element> mOverrideElement;
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2020-10-05 18:56:52 +03:00
|
|
|
explicit PointerCaptureInfo(dom::Element* aPendingElement)
|
|
|
|
: mPendingElement(aPendingElement) {
|
2017-09-06 10:47:49 +03:00
|
|
|
MOZ_COUNT_CTOR(PointerCaptureInfo);
|
|
|
|
}
|
|
|
|
|
2020-02-20 14:40:14 +03:00
|
|
|
MOZ_COUNTED_DTOR(PointerCaptureInfo)
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2020-10-05 18:56:52 +03:00
|
|
|
bool Empty() { return !(mPendingElement || mOverrideElement); }
|
2017-09-06 10:47:49 +03:00
|
|
|
};
|
|
|
|
|
2020-10-30 11:31:42 +03:00
|
|
|
class PointerInfo final {
|
|
|
|
public:
|
|
|
|
uint16_t mPointerType;
|
|
|
|
bool mActiveState;
|
|
|
|
bool mPrimaryState;
|
|
|
|
bool mPreventMouseEventByContent;
|
|
|
|
WeakPtr<dom::Document> mActiveDocument;
|
|
|
|
explicit PointerInfo(bool aActiveState, uint16_t aPointerType,
|
|
|
|
bool aPrimaryState, dom::Document* aActiveDocument)
|
|
|
|
: mPointerType(aPointerType),
|
|
|
|
mActiveState(aActiveState),
|
|
|
|
mPrimaryState(aPrimaryState),
|
|
|
|
mPreventMouseEventByContent(false),
|
|
|
|
mActiveDocument(aActiveDocument) {}
|
|
|
|
};
|
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
class PointerEventHandler final {
|
|
|
|
public:
|
|
|
|
// Called in nsLayoutStatics::Initialize/Shutdown to initialize pointer event
|
|
|
|
// related static variables.
|
|
|
|
static void InitializeStatics();
|
|
|
|
static void ReleaseStatics();
|
|
|
|
|
|
|
|
// Return the preference value of implicit capture.
|
|
|
|
static bool IsPointerEventImplicitCaptureForTouchEnabled();
|
|
|
|
|
|
|
|
// Called in ESM::PreHandleEvent to update current active pointers in a hash
|
|
|
|
// table.
|
2020-10-30 11:31:42 +03:00
|
|
|
static void UpdateActivePointerState(WidgetMouseEvent* aEvent,
|
|
|
|
nsIContent* aTargetContent);
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2020-10-27 00:00:50 +03:00
|
|
|
// Request/release pointer capture of the specified pointer by the element.
|
|
|
|
static void RequestPointerCaptureById(uint32_t aPointerId,
|
|
|
|
dom::Element* aElement);
|
2017-09-06 10:47:49 +03:00
|
|
|
static void ReleasePointerCaptureById(uint32_t aPointerId);
|
2017-09-14 09:29:04 +03:00
|
|
|
static void ReleaseAllPointerCapture();
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2020-10-27 00:00:50 +03:00
|
|
|
// Set/release pointer capture of the specified pointer by the remote target.
|
|
|
|
// Should only be called in parent process.
|
|
|
|
static bool SetPointerCaptureRemoteTarget(uint32_t aPointerId,
|
|
|
|
dom::BrowserParent* aBrowserParent);
|
|
|
|
static void ReleasePointerCaptureRemoteTarget(
|
|
|
|
dom::BrowserParent* aBrowserParent);
|
|
|
|
static void ReleasePointerCaptureRemoteTarget(uint32_t aPointerId);
|
|
|
|
static void ReleaseAllPointerCaptureRemoteTarget();
|
|
|
|
|
|
|
|
// Get the pointer capturing remote target of the specified pointer.
|
|
|
|
static dom::BrowserParent* GetPointerCapturingRemoteTarget(
|
|
|
|
uint32_t aPointerId);
|
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
// Get the pointer captured info of the specified pointer.
|
|
|
|
static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId);
|
|
|
|
|
2020-10-30 11:31:42 +03:00
|
|
|
// Return the PointerInfo if the pointer with aPointerId is situated in device
|
|
|
|
// , nullptr otherwise.
|
|
|
|
static const PointerInfo* GetPointerInfo(uint32_t aPointerId);
|
2017-09-06 10:47:49 +03:00
|
|
|
|
|
|
|
// CheckPointerCaptureState checks cases, when got/lostpointercapture events
|
|
|
|
// should be fired.
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-11-26 16:54:07 +03:00
|
|
|
static void MaybeProcessPointerCapture(WidgetGUIEvent* aEvent);
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-11-26 16:54:07 +03:00
|
|
|
static void ProcessPointerCaptureForMouse(WidgetMouseEvent* aEvent);
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-11-26 16:54:07 +03:00
|
|
|
static void ProcessPointerCaptureForTouch(WidgetTouchEvent* aEvent);
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-09-06 10:47:49 +03:00
|
|
|
static void CheckPointerCaptureState(WidgetPointerEvent* aEvent);
|
|
|
|
|
2017-09-08 06:01:22 +03:00
|
|
|
// Implicitly get and release capture of current pointer for touch.
|
|
|
|
static void ImplicitlyCapturePointer(nsIFrame* aFrame, WidgetEvent* aEvent);
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-09-08 06:01:22 +03:00
|
|
|
static void ImplicitlyReleasePointerCapture(WidgetEvent* aEvent);
|
|
|
|
|
2017-09-06 12:28:28 +03:00
|
|
|
/**
|
2020-10-05 18:56:52 +03:00
|
|
|
* GetPointerCapturingContent returns a target element which captures the
|
2017-11-30 11:10:03 +03:00
|
|
|
* pointer. It's applied to mouse or pointer event (except mousedown and
|
2020-10-05 18:56:52 +03:00
|
|
|
* pointerdown). When capturing, return the element. Otherwise, nullptr.
|
2017-09-06 12:28:28 +03:00
|
|
|
*
|
|
|
|
* @param aEvent A mouse event or pointer event which may be
|
|
|
|
* captured.
|
|
|
|
*
|
2020-10-05 18:56:52 +03:00
|
|
|
* @return Target element for aEvent.
|
2017-09-06 12:28:28 +03:00
|
|
|
*/
|
2020-10-05 18:56:52 +03:00
|
|
|
static dom::Element* GetPointerCapturingElement(WidgetGUIEvent* aEvent);
|
2017-09-06 12:28:28 +03:00
|
|
|
|
2020-10-05 18:56:52 +03:00
|
|
|
static dom::Element* GetPointerCapturingElement(uint32_t aPointerId);
|
2017-09-06 10:47:49 +03:00
|
|
|
|
|
|
|
// Release pointer capture if captured by the specified content or it's
|
|
|
|
// descendant. This is called to handle the case that the pointer capturing
|
|
|
|
// content or it's parent is removed from the document.
|
|
|
|
static void ReleaseIfCaptureByDescendant(nsIContent* aContent);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function handles the case when content had called preventDefault on
|
|
|
|
* the active pointer. In that case we have to prevent firing subsequent mouse
|
|
|
|
* to content. We check the flag PointerInfo::mPreventMouseEventByContent and
|
|
|
|
* call PreventDefault(false) to stop default behaviors and stop firing mouse
|
|
|
|
* events to content and chrome.
|
|
|
|
*
|
|
|
|
* note: mouse transition events are excluded
|
|
|
|
* note: we have to clean mPreventMouseEventByContent on pointerup for those
|
|
|
|
* devices support hover
|
|
|
|
* note: we don't suppress firing mouse events to chrome and system group
|
|
|
|
* handlers because they may implement default behaviors
|
|
|
|
*/
|
|
|
|
static void PreHandlePointerEventsPreventDefault(
|
|
|
|
WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function handles the preventDefault behavior of pointerdown. When user
|
|
|
|
* preventDefault on pointerdown, We have to mark the active pointer to
|
|
|
|
* prevent sebsequent mouse events (except mouse transition events) and
|
|
|
|
* default behaviors.
|
|
|
|
*
|
|
|
|
* We add mPreventMouseEventByContent flag in PointerInfo to represent the
|
|
|
|
* active pointer won't firing compatible mouse events. It's set to true when
|
|
|
|
* content preventDefault on pointerdown
|
|
|
|
*/
|
|
|
|
static void PostHandlePointerEventsPreventDefault(
|
|
|
|
WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent);
|
|
|
|
|
2018-01-29 22:35:17 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-09-06 12:28:28 +03:00
|
|
|
static void DispatchPointerFromMouseOrTouch(
|
2017-11-26 16:54:07 +03:00
|
|
|
PresShell* aShell, nsIFrame* aFrame, nsIContent* aContent,
|
2017-09-06 12:28:28 +03:00
|
|
|
WidgetGUIEvent* aEvent, bool aDontRetargetEvents, nsEventStatus* aStatus,
|
|
|
|
nsIContent** aTargetContent);
|
2017-09-06 10:47:49 +03:00
|
|
|
|
2017-09-18 13:41:36 +03:00
|
|
|
static void InitPointerEventFromMouse(WidgetPointerEvent* aPointerEvent,
|
|
|
|
WidgetMouseEvent* aMouseEvent,
|
|
|
|
EventMessage aMessage);
|
|
|
|
|
|
|
|
static void InitPointerEventFromTouch(WidgetPointerEvent* aPointerEvent,
|
|
|
|
WidgetTouchEvent* aTouchEvent,
|
|
|
|
mozilla::dom::Touch* aTouch,
|
|
|
|
bool aIsPrimary);
|
|
|
|
|
2017-11-26 16:54:07 +03:00
|
|
|
static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) {
|
|
|
|
return aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp ||
|
2020-10-27 00:00:50 +03:00
|
|
|
aEvent->mMessage == eMouseMove ||
|
|
|
|
aEvent->mMessage == eMouseExitFromWidget;
|
2017-11-26 16:54:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool ShouldGeneratePointerEventFromTouch(WidgetGUIEvent* aEvent) {
|
|
|
|
return aEvent->mMessage == eTouchStart || aEvent->mMessage == eTouchMove ||
|
|
|
|
aEvent->mMessage == eTouchEnd || aEvent->mMessage == eTouchCancel ||
|
|
|
|
aEvent->mMessage == eTouchPointerCancel;
|
|
|
|
}
|
|
|
|
|
2018-11-20 12:54:52 +03:00
|
|
|
static MOZ_ALWAYS_INLINE int32_t GetSpoofedPointerIdForRFP() {
|
|
|
|
return sSpoofedPointerId.valueOr(0);
|
|
|
|
}
|
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
private:
|
2020-10-27 00:00:50 +03:00
|
|
|
// Set pointer capture of the specified pointer by the element.
|
|
|
|
static void SetPointerCaptureById(uint32_t aPointerId,
|
|
|
|
dom::Element* aElement);
|
|
|
|
|
2017-09-06 10:47:49 +03:00
|
|
|
// GetPointerType returns pointer type like mouse, pen or touch for pointer
|
|
|
|
// event with pointerId. The return value must be one of
|
2018-06-26 00:20:54 +03:00
|
|
|
// MouseEvent_Binding::MOZ_SOURCE_*
|
2017-09-06 10:47:49 +03:00
|
|
|
static uint16_t GetPointerType(uint32_t aPointerId);
|
|
|
|
|
|
|
|
// GetPointerPrimaryState returns state of attribute isPrimary for pointer
|
|
|
|
// event with pointerId
|
|
|
|
static bool GetPointerPrimaryState(uint32_t aPointerId);
|
|
|
|
|
2019-05-06 16:15:05 +03:00
|
|
|
MOZ_CAN_RUN_SCRIPT
|
2017-09-06 10:47:49 +03:00
|
|
|
static void DispatchGotOrLostPointerCaptureEvent(
|
|
|
|
bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent,
|
2020-10-05 18:56:52 +03:00
|
|
|
dom::Element* aCaptureTarget);
|
2018-11-20 12:54:52 +03:00
|
|
|
|
|
|
|
// The cached spoofed pointer ID for fingerprinting resistance. We will use a
|
|
|
|
// mouse pointer id for desktop. For mobile, we should use the touch pointer
|
|
|
|
// id as the spoofed one, and this work will be addressed in Bug 1492775.
|
|
|
|
static Maybe<int32_t> sSpoofedPointerId;
|
|
|
|
|
|
|
|
// A helper function to cache the pointer id of the spoofed interface, we
|
|
|
|
// would only cache the pointer id once. After that, we would always stick to
|
|
|
|
// that pointer id for fingerprinting resistance.
|
|
|
|
static void MaybeCacheSpoofedPointerID(uint16_t aInputSource,
|
|
|
|
uint32_t aPointerId);
|
2017-09-06 10:47:49 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_PointerEventHandler_h
|