diff options
Diffstat (limited to 'dom/events/PointerEventHandler.h')
-rw-r--r-- | dom/events/PointerEventHandler.h | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/dom/events/PointerEventHandler.h b/dom/events/PointerEventHandler.h new file mode 100644 index 0000000000..dd0b1bea40 --- /dev/null +++ b/dom/events/PointerEventHandler.h @@ -0,0 +1,235 @@ +/* -*- 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" +#include "mozilla/MouseEvents.h" +#include "mozilla/TouchEvents.h" +#include "mozilla/WeakPtr.h" + +// XXX Avoid including this here by moving function bodies to the cpp file +#include "mozilla/dom/Document.h" +#include "mozilla/dom/Element.h" + +class nsIFrame; +class nsIContent; +class nsPresContext; + +namespace mozilla { + +class PresShell; + +namespace dom { +class BrowserParent; +class Document; +class Element; +}; // namespace dom + +class PointerCaptureInfo final { + public: + RefPtr<dom::Element> mPendingElement; + RefPtr<dom::Element> mOverrideElement; + + explicit PointerCaptureInfo(dom::Element* aPendingElement) + : mPendingElement(aPendingElement) { + MOZ_COUNT_CTOR(PointerCaptureInfo); + } + + MOZ_COUNTED_DTOR(PointerCaptureInfo) + + bool Empty() { return !(mPendingElement || mOverrideElement); } +}; + +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) {} +}; + +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. + static void UpdateActivePointerState(WidgetMouseEvent* aEvent, + nsIContent* aTargetContent = nullptr); + + // Request/release pointer capture of the specified pointer by the element. + static void RequestPointerCaptureById(uint32_t aPointerId, + dom::Element* aElement); + static void ReleasePointerCaptureById(uint32_t aPointerId); + static void ReleaseAllPointerCapture(); + + // 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); + + // Get the pointer captured info of the specified pointer. + static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId); + + // Return the PointerInfo if the pointer with aPointerId is situated in device + // , nullptr otherwise. + static const PointerInfo* GetPointerInfo(uint32_t aPointerId); + + // CheckPointerCaptureState checks cases, when got/lostpointercapture events + // should be fired. + MOZ_CAN_RUN_SCRIPT + static void MaybeProcessPointerCapture(WidgetGUIEvent* aEvent); + MOZ_CAN_RUN_SCRIPT + static void ProcessPointerCaptureForMouse(WidgetMouseEvent* aEvent); + MOZ_CAN_RUN_SCRIPT + static void ProcessPointerCaptureForTouch(WidgetTouchEvent* aEvent); + MOZ_CAN_RUN_SCRIPT + static void CheckPointerCaptureState(WidgetPointerEvent* aEvent); + + // Implicitly get and release capture of current pointer for touch. + static void ImplicitlyCapturePointer(nsIFrame* aFrame, WidgetEvent* aEvent); + MOZ_CAN_RUN_SCRIPT + static void ImplicitlyReleasePointerCapture(WidgetEvent* aEvent); + + /** + * GetPointerCapturingContent returns a target element which captures the + * pointer. It's applied to mouse or pointer event (except mousedown and + * pointerdown). When capturing, return the element. Otherwise, nullptr. + * + * @param aEvent A mouse event or pointer event which may be + * captured. + * + * @return Target element for aEvent. + */ + static dom::Element* GetPointerCapturingElement(WidgetGUIEvent* aEvent); + + static dom::Element* GetPointerCapturingElement(uint32_t aPointerId); + + // 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); + + MOZ_CAN_RUN_SCRIPT + static void DispatchPointerFromMouseOrTouch( + PresShell* aShell, nsIFrame* aFrame, nsIContent* aContent, + WidgetGUIEvent* aEvent, bool aDontRetargetEvents, nsEventStatus* aStatus, + nsIContent** aTargetContent); + + static void InitPointerEventFromMouse(WidgetPointerEvent* aPointerEvent, + WidgetMouseEvent* aMouseEvent, + EventMessage aMessage); + + static void InitPointerEventFromTouch(WidgetPointerEvent* aPointerEvent, + WidgetTouchEvent* aTouchEvent, + mozilla::dom::Touch* aTouch, + bool aIsPrimary); + + static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) { + return aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp || + aEvent->mMessage == eMouseMove || + aEvent->mMessage == eMouseExitFromWidget; + } + + static bool ShouldGeneratePointerEventFromTouch(WidgetGUIEvent* aEvent) { + return aEvent->mMessage == eTouchStart || aEvent->mMessage == eTouchMove || + aEvent->mMessage == eTouchEnd || aEvent->mMessage == eTouchCancel || + aEvent->mMessage == eTouchPointerCancel; + } + + static MOZ_ALWAYS_INLINE int32_t GetSpoofedPointerIdForRFP() { + return sSpoofedPointerId.valueOr(0); + } + + static void NotifyDestroyPresContext(nsPresContext* aPresContext); + + private: + // Set pointer capture of the specified pointer by the element. + static void SetPointerCaptureById(uint32_t aPointerId, + dom::Element* aElement); + + // GetPointerType returns pointer type like mouse, pen or touch for pointer + // event with pointerId. The return value must be one of + // MouseEvent_Binding::MOZ_SOURCE_* + static uint16_t GetPointerType(uint32_t aPointerId); + + // GetPointerPrimaryState returns state of attribute isPrimary for pointer + // event with pointerId + static bool GetPointerPrimaryState(uint32_t aPointerId); + + MOZ_CAN_RUN_SCRIPT + static void DispatchGotOrLostPointerCaptureEvent( + bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent, + dom::Element* aCaptureTarget); + + // 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); +}; + +} // namespace mozilla + +#endif // mozilla_PointerEventHandler_h |