1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_PointerEventHandler_h 8 #define mozilla_PointerEventHandler_h 9 10 #include "mozilla/EventForwards.h" 11 #include "mozilla/MouseEvents.h" 12 #include "mozilla/TouchEvents.h" 13 14 class nsIFrame; 15 class nsIContent; 16 17 namespace mozilla { 18 19 class PresShell; 20 21 class PointerCaptureInfo final { 22 public: 23 nsCOMPtr<nsIContent> mPendingContent; 24 nsCOMPtr<nsIContent> mOverrideContent; 25 PointerCaptureInfo(nsIContent * aPendingContent)26 explicit PointerCaptureInfo(nsIContent* aPendingContent) 27 : mPendingContent(aPendingContent) { 28 MOZ_COUNT_CTOR(PointerCaptureInfo); 29 } 30 MOZ_COUNTED_DTOR(PointerCaptureInfo)31 MOZ_COUNTED_DTOR(PointerCaptureInfo) 32 33 bool Empty() { return !(mPendingContent || mOverrideContent); } 34 }; 35 36 class PointerEventHandler final { 37 public: 38 // Called in nsLayoutStatics::Initialize/Shutdown to initialize pointer event 39 // related static variables. 40 static void InitializeStatics(); 41 static void ReleaseStatics(); 42 43 // Return the preference value of implicit capture. 44 static bool IsPointerEventImplicitCaptureForTouchEnabled(); 45 46 // Called in ESM::PreHandleEvent to update current active pointers in a hash 47 // table. 48 static void UpdateActivePointerState(WidgetMouseEvent* aEvent); 49 50 // Got/release pointer capture of the specified pointer by the content. 51 static void SetPointerCaptureById(uint32_t aPointerId, nsIContent* aContent); 52 static void ReleasePointerCaptureById(uint32_t aPointerId); 53 static void ReleaseAllPointerCapture(); 54 55 // Get the pointer captured info of the specified pointer. 56 static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId); 57 58 // GetPointerInfo returns true if pointer with aPointerId is situated in 59 // device, false otherwise. 60 // aActiveState is additional information, which shows state of pointer like 61 // button state for mouse. 62 static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState); 63 64 // CheckPointerCaptureState checks cases, when got/lostpointercapture events 65 // should be fired. 66 MOZ_CAN_RUN_SCRIPT 67 static void MaybeProcessPointerCapture(WidgetGUIEvent* aEvent); 68 MOZ_CAN_RUN_SCRIPT 69 static void ProcessPointerCaptureForMouse(WidgetMouseEvent* aEvent); 70 MOZ_CAN_RUN_SCRIPT 71 static void ProcessPointerCaptureForTouch(WidgetTouchEvent* aEvent); 72 MOZ_CAN_RUN_SCRIPT 73 static void CheckPointerCaptureState(WidgetPointerEvent* aEvent); 74 75 // Implicitly get and release capture of current pointer for touch. 76 static void ImplicitlyCapturePointer(nsIFrame* aFrame, WidgetEvent* aEvent); 77 MOZ_CAN_RUN_SCRIPT 78 static void ImplicitlyReleasePointerCapture(WidgetEvent* aEvent); 79 80 /** 81 * GetPointerCapturingContent returns a target content which captures the 82 * pointer. It's applied to mouse or pointer event (except mousedown and 83 * pointerdown). When capturing, return the content. Otherwise, nullptr. 84 * 85 * @param aEvent A mouse event or pointer event which may be 86 * captured. 87 * 88 * @return Target content for aEvent. 89 */ 90 static nsIContent* GetPointerCapturingContent(WidgetGUIEvent* aEvent); 91 92 static nsIContent* GetPointerCapturingContent(uint32_t aPointerId); 93 94 // Release pointer capture if captured by the specified content or it's 95 // descendant. This is called to handle the case that the pointer capturing 96 // content or it's parent is removed from the document. 97 static void ReleaseIfCaptureByDescendant(nsIContent* aContent); 98 99 /* 100 * This function handles the case when content had called preventDefault on 101 * the active pointer. In that case we have to prevent firing subsequent mouse 102 * to content. We check the flag PointerInfo::mPreventMouseEventByContent and 103 * call PreventDefault(false) to stop default behaviors and stop firing mouse 104 * events to content and chrome. 105 * 106 * note: mouse transition events are excluded 107 * note: we have to clean mPreventMouseEventByContent on pointerup for those 108 * devices support hover 109 * note: we don't suppress firing mouse events to chrome and system group 110 * handlers because they may implement default behaviors 111 */ 112 static void PreHandlePointerEventsPreventDefault( 113 WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent); 114 115 /* 116 * This function handles the preventDefault behavior of pointerdown. When user 117 * preventDefault on pointerdown, We have to mark the active pointer to 118 * prevent sebsequent mouse events (except mouse transition events) and 119 * default behaviors. 120 * 121 * We add mPreventMouseEventByContent flag in PointerInfo to represent the 122 * active pointer won't firing compatible mouse events. It's set to true when 123 * content preventDefault on pointerdown 124 */ 125 static void PostHandlePointerEventsPreventDefault( 126 WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent); 127 128 MOZ_CAN_RUN_SCRIPT 129 static void DispatchPointerFromMouseOrTouch( 130 PresShell* aShell, nsIFrame* aFrame, nsIContent* aContent, 131 WidgetGUIEvent* aEvent, bool aDontRetargetEvents, nsEventStatus* aStatus, 132 nsIContent** aTargetContent); 133 134 static void InitPointerEventFromMouse(WidgetPointerEvent* aPointerEvent, 135 WidgetMouseEvent* aMouseEvent, 136 EventMessage aMessage); 137 138 static void InitPointerEventFromTouch(WidgetPointerEvent* aPointerEvent, 139 WidgetTouchEvent* aTouchEvent, 140 mozilla::dom::Touch* aTouch, 141 bool aIsPrimary); 142 ShouldGeneratePointerEventFromMouse(WidgetGUIEvent * aEvent)143 static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) { 144 return aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp || 145 aEvent->mMessage == eMouseMove; 146 } 147 ShouldGeneratePointerEventFromTouch(WidgetGUIEvent * aEvent)148 static bool ShouldGeneratePointerEventFromTouch(WidgetGUIEvent* aEvent) { 149 return aEvent->mMessage == eTouchStart || aEvent->mMessage == eTouchMove || 150 aEvent->mMessage == eTouchEnd || aEvent->mMessage == eTouchCancel || 151 aEvent->mMessage == eTouchPointerCancel; 152 } 153 GetSpoofedPointerIdForRFP()154 static MOZ_ALWAYS_INLINE int32_t GetSpoofedPointerIdForRFP() { 155 return sSpoofedPointerId.valueOr(0); 156 } 157 158 private: 159 // GetPointerType returns pointer type like mouse, pen or touch for pointer 160 // event with pointerId. The return value must be one of 161 // MouseEvent_Binding::MOZ_SOURCE_* 162 static uint16_t GetPointerType(uint32_t aPointerId); 163 164 // GetPointerPrimaryState returns state of attribute isPrimary for pointer 165 // event with pointerId 166 static bool GetPointerPrimaryState(uint32_t aPointerId); 167 168 MOZ_CAN_RUN_SCRIPT 169 static void DispatchGotOrLostPointerCaptureEvent( 170 bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent, 171 nsIContent* aCaptureTarget); 172 173 // The cached spoofed pointer ID for fingerprinting resistance. We will use a 174 // mouse pointer id for desktop. For mobile, we should use the touch pointer 175 // id as the spoofed one, and this work will be addressed in Bug 1492775. 176 static Maybe<int32_t> sSpoofedPointerId; 177 178 // A helper function to cache the pointer id of the spoofed interface, we 179 // would only cache the pointer id once. After that, we would always stick to 180 // that pointer id for fingerprinting resistance. 181 static void MaybeCacheSpoofedPointerID(uint16_t aInputSource, 182 uint32_t aPointerId); 183 }; 184 185 } // namespace mozilla 186 187 #endif // mozilla_PointerEventHandler_h 188