PointerEventHandler.h (28401B)
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 "LayoutConstants.h" 11 #include "mozilla/EventForwards.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/MouseEvents.h" 14 #include "mozilla/StaticPtr.h" 15 #include "mozilla/TouchEvents.h" 16 #include "mozilla/WeakPtr.h" 17 18 // XXX Avoid including this here by moving function bodies to the cpp file 19 #include "mozilla/dom/Document.h" 20 #include "mozilla/dom/Element.h" 21 #include "mozilla/layers/InputAPZContext.h" 22 23 class AutoWeakFrame; 24 class nsIFrame; 25 class nsIContent; 26 class nsPresContext; 27 28 namespace mozilla { 29 30 class PresShell; 31 32 namespace dom { 33 class BrowserParent; 34 class Document; 35 class Element; 36 }; // namespace dom 37 38 class PointerCaptureInfo final { 39 public: 40 RefPtr<dom::Element> mPendingElement; 41 RefPtr<dom::Element> mOverrideElement; 42 43 explicit PointerCaptureInfo(dom::Element* aPendingElement) 44 : mPendingElement(aPendingElement) { 45 MOZ_COUNT_CTOR(PointerCaptureInfo); 46 } 47 48 MOZ_COUNTED_DTOR(PointerCaptureInfo) 49 50 bool Empty() { return !(mPendingElement || mOverrideElement); } 51 }; 52 53 /** 54 * PointerInfo stores the pointer's information and its last state (position, 55 * buttons, etc). 56 */ 57 struct PointerInfo final { 58 using Document = dom::Document; 59 enum class Active : bool { No, Yes }; 60 enum class Primary : bool { No, Yes }; 61 enum class FromTouchEvent : bool { No, Yes }; 62 enum class SynthesizeForTests : bool { No, Yes }; 63 PointerInfo() 64 : mIsActive(false), 65 mIsPrimary(false), 66 mFromTouchEvent(false), 67 mPreventMouseEventByContent(false), 68 mIsSynthesizedForTests(false) {} 69 PointerInfo(const PointerInfo&) = default; 70 explicit PointerInfo( 71 Active aActiveState, uint16_t aInputSource, Primary aPrimaryState, 72 FromTouchEvent aFromTouchEvent, Document* aActiveDocument, 73 const PointerInfo* aLastPointerInfo = nullptr, 74 SynthesizeForTests aIsSynthesizedForTests = SynthesizeForTests::No) 75 : mActiveDocument(aActiveDocument), 76 mInputSource(aInputSource), 77 mIsActive(static_cast<bool>(aActiveState)), 78 mIsPrimary(static_cast<bool>(aPrimaryState)), 79 mFromTouchEvent(static_cast<bool>(aFromTouchEvent)), 80 mPreventMouseEventByContent(false), 81 mIsSynthesizedForTests(static_cast<bool>(aIsSynthesizedForTests)) { 82 if (aLastPointerInfo) { 83 TakeOverLastState(*aLastPointerInfo); 84 } 85 } 86 explicit PointerInfo(Active aActiveState, 87 const WidgetPointerEvent& aPointerEvent, 88 Document* aActiveDocument, 89 const PointerInfo* aLastPointerInfo = nullptr) 90 : mActiveDocument(aActiveDocument), 91 mInputSource(aPointerEvent.mInputSource), 92 mIsActive(static_cast<bool>(aActiveState)), 93 mIsPrimary(aPointerEvent.mIsPrimary), 94 mFromTouchEvent(aPointerEvent.mFromTouchEvent), 95 mPreventMouseEventByContent(false), 96 mIsSynthesizedForTests(aPointerEvent.mFlags.mIsSynthesizedForTests) { 97 if (aLastPointerInfo) { 98 TakeOverLastState(*aLastPointerInfo); 99 } 100 } 101 102 [[nodiscard]] bool InputSourceSupportsHover() const { 103 return WidgetMouseEventBase::InputSourceSupportsHover(mInputSource); 104 } 105 106 [[nodiscard]] bool HasLastState() const { 107 return mLastRefPointInRootDoc != 108 nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); 109 } 110 111 /** 112 * Make this store the last pointer state such as the position, buttons, etc, 113 * which should be used at dispatching a synthetic mouse/pointer move. 114 */ 115 void RecordLastState(const nsPoint& aRefPointInRootDoc, 116 const WidgetMouseEvent& aMouseOrPointerEvent) { 117 MOZ_ASSERT_IF(aMouseOrPointerEvent.mMessage == eMouseMove || 118 aMouseOrPointerEvent.mMessage == ePointerMove, 119 aMouseOrPointerEvent.IsReal()); 120 121 mLastRefPointInRootDoc = aRefPointInRootDoc; 122 mLastTargetGuid = layers::InputAPZContext::GetTargetLayerGuid(); 123 // FIXME: DragEvent may not be initialized with the proper state. So, 124 // ignore the details of drag events for now. 125 if (aMouseOrPointerEvent.mClass != eDragEventClass) { 126 mLastTiltX = aMouseOrPointerEvent.tiltX; 127 mLastTiltY = aMouseOrPointerEvent.tiltY; 128 mLastButtons = aMouseOrPointerEvent.mButtons; 129 mLastPressure = aMouseOrPointerEvent.mPressure; 130 } 131 } 132 133 /** 134 * Take over the last pointer state from older PointerInfo. 135 */ 136 void TakeOverLastState(const PointerInfo& aPointerInfo) { 137 mLastRefPointInRootDoc = aPointerInfo.mLastRefPointInRootDoc; 138 mLastTargetGuid = aPointerInfo.mLastTargetGuid; 139 mLastTiltX = aPointerInfo.mLastTiltX; 140 mLastTiltY = aPointerInfo.mLastTiltY; 141 mLastButtons = aPointerInfo.mLastButtons; 142 mLastPressure = aPointerInfo.mLastPressure; 143 } 144 145 /** 146 * Clear the last pointer state to stop dispatching synthesized mouse/pointer 147 * move at the position. 148 */ 149 void ClearLastState() { 150 mLastRefPointInRootDoc = 151 nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); 152 mLastTargetGuid = layers::ScrollableLayerGuid(); 153 mLastTiltX = 0; 154 mLastTiltY = 0; 155 mLastButtons = 0; 156 mLastPressure = 0.0f; 157 } 158 159 [[nodiscard]] bool EqualsBasicPointerData(const PointerInfo& aOther) const { 160 return mInputSource == aOther.mInputSource && 161 mIsActive == aOther.mIsActive && mIsPrimary == aOther.mIsPrimary && 162 mFromTouchEvent == aOther.mFromTouchEvent && 163 mIsSynthesizedForTests == aOther.mIsSynthesizedForTests; 164 } 165 166 // mLastRefPointInRootDoc stores the event point relative to the root 167 // PresShell. So, it's different from the WidgetEvent::mRefPoint. 168 nsPoint mLastRefPointInRootDoc = 169 nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); 170 layers::ScrollableLayerGuid mLastTargetGuid; 171 WeakPtr<Document> mActiveDocument; 172 // mInputSource indicates which input source caused the last event. E.g., 173 // if the last event is a compatibility mouse event, the input source is 174 // "touch". 175 uint16_t mInputSource = 0; 176 int32_t mLastTiltX = 0; 177 int32_t mLastTiltY = 0; 178 int16_t mLastButtons = 0; 179 float mLastPressure = 0.0f; 180 bool mIsActive : 1; 181 bool mIsPrimary : 1; 182 // mFromTouchEvent is set to true if the last event is a touch event or a 183 // pointer event caused by a touch event. If the last event is a 184 // compatibility mouse event, this is set to false even though the input 185 // source is "touch". 186 bool mFromTouchEvent : 1; 187 bool mPreventMouseEventByContent : 1; 188 // Set to true if the pointer is activated only by synthesized mouse events. 189 bool mIsSynthesizedForTests : 1; 190 }; 191 192 class PointerEventHandler final { 193 public: 194 // Called in nsLayoutStatics::Initialize/Shutdown to initialize pointer event 195 // related static variables. 196 static void InitializeStatics(); 197 static void ReleaseStatics(); 198 199 // Return the preference value of implicit capture. 200 static bool IsPointerEventImplicitCaptureForTouchEnabled(); 201 202 /** 203 * Dispatch a pointer event on aTargetWeakFrame if and only if the frame is 204 * available or aTargetContent if the target content does not have a frame. 205 * 206 * This follows the steps of "fire a pointer event" definition. 207 * https://w3c.github.io/pointerevents/#dfn-fire-a-pointer-event 208 * 209 * @param aPointerEventMessage The event message which you want to dispatch a 210 * pointer event. 211 * @param aMouseOrPointerEvent The source event which caused the dispatching 212 * pointer event. Must be a mouse or pointer event. 213 * @param aTargetWeakFrame If target frame is available, this should be set to 214 * non-nullptr. 215 * @param aTargetContent If target frame is not available for the content 216 * node, set this to the proper target node. 217 * @param aStatus [optional, out] The dispatched event status. 218 */ 219 MOZ_CAN_RUN_SCRIPT static nsresult DispatchPointerEventWithTarget( 220 EventMessage aPointerEventMessage, 221 const WidgetMouseEvent& aMouseOrPointerEvent, 222 const AutoWeakFrame& aTargetWeakFrame, nsIContent* aTargetContent, 223 nsEventStatus* aStatus = nullptr); 224 225 /** 226 * Dispatch a pointer event on aTargetWeakFrame if and only if the frame is 227 * available or aTargetContent if the target content does not have a frame. 228 * 229 * This follows the steps of "fire a pointer event" definition. 230 * https://w3c.github.io/pointerevents/#dfn-fire-a-pointer-event 231 * 232 * @param aPointerEventMessage The event message which you want to dispatch a 233 * pointer event. 234 * @param aTouchEvent The source touch event which caused the dispatching 235 * pointer event. 236 * @param aTouchIndex The source touch index in aTouchEvent. 237 * @param aTargetWeakFrame If target frame is available, this should be set to 238 * non-nullptr. 239 * @param aTargetContent If target frame is not available for the content 240 * node, set this to the proper target node. 241 * @param aStatus [optional, in/out] The dispatched event status. 242 */ 243 MOZ_CAN_RUN_SCRIPT static nsresult DispatchPointerEventWithTarget( 244 EventMessage aPointerEventMessage, const WidgetTouchEvent& aTouchEvent, 245 size_t aTouchIndex, const AutoWeakFrame& aTargetWeakFrame, 246 nsIContent* aTargetContent, nsEventStatus* aStatus = nullptr); 247 248 /** 249 * Dispatch a pointer event on aTargetWeakFrame if and only if the frame is 250 * available or aTargetContent if the target content does not have a frame. 251 * 252 * This follows the steps of "fire a pointer event" definition. 253 * https://w3c.github.io/pointerevents/#dfn-fire-a-pointer-event 254 * 255 * @param aPointerEvent The pointer event which should be dispatched. 256 * @param aTouchIndex The source touch index in aTouchEvent. 257 * @param aTargetWeakFrame If target frame is available, this should be set to 258 * non-nullptr. 259 * @param aTargetContent If target frame is not available for the content 260 * node, set this to the proper target node. 261 * @param aStatus [optional, in/out] The dispatched event status. 262 */ 263 MOZ_CAN_RUN_SCRIPT static nsresult DispatchPointerEventWithTarget( 264 WidgetPointerEvent& aPointerEvent, const AutoWeakFrame& aTargetWeakFrame, 265 nsIContent* aTargetContent, nsEventStatus* aStatus = nullptr); 266 267 /** 268 * Return true if click/auxclick/contextmenu event should be fired on 269 * an element which was capturing the pointer at dispatching ePointerUp. 270 * 271 * @param aSourceEvent [Optional] The source event which causes the 272 * `click`, `auxclick` or `contextmenu` event. I.e., 273 * must be one of `mouseup`, `pointerup` or `touchend`. 274 * If specifying nullptr, this method checks only 275 * whether the behavior is enabled. 276 */ 277 [[nodiscard]] static bool ShouldDispatchClickEventOnCapturingElement( 278 const WidgetGUIEvent* aSourceEvent = nullptr); 279 280 // Called in ESM::PreHandleEvent to update current active pointers in a hash 281 // table. 282 static void UpdatePointerActiveState(WidgetMouseEvent* aEvent, 283 nsIContent* aTargetContent = nullptr); 284 285 /** 286 * Called when PresShell starts handling a mouse or subclass event. This will 287 * set PointerInfo for synthesizing pointer move at the position later. 288 * 289 * @param aRefPointInRootPresShell The event location in the root 290 * PresShell. 291 * @param aMouseEvent The event which will be handled. 292 */ 293 static void RecordPointerState(const nsPoint& aRefPointInRootPresShell, 294 const WidgetMouseEvent& aMouseEvent); 295 296 /** 297 * Called when PresShell starts handling a mouse event. The data will be used 298 * for synthesizing eMouseMove to dispatch mouse boundary events and updates 299 * `:hover` state. 300 * 301 * @param aRootPresShell Must be the root PresShell of the PresShell 302 * which starts handling the event. 303 * @param aMouseEvent The mouse event which the PresShell starts 304 * handling. 305 */ 306 static void RecordMouseState(PresShell& aRootPresShell, 307 const WidgetMouseEvent& aMouseEvent); 308 309 /** 310 * Called when PresShell dispatches a mouse event to the DOM. 311 */ 312 static void RecordMouseButtons(const WidgetMouseEvent& aMouseEvent) { 313 // Buttons of mouse should be shared even if there are multiple mouse 314 // pointers which has different pointerIds for the backward compatibility. 315 // Thus, here does not check sLastMousePresShell nor pointerId. 316 if (sLastMouseInfo) { 317 sLastMouseInfo->mLastButtons = aMouseEvent.mButtons; 318 } 319 } 320 321 /** 322 * Called when PresShell starts handling a mouse event or something which 323 * should make aRootPresShell should never dispatch synthetic eMouseMove 324 * events. 325 * 326 * @param aRootPresShell Must be the root PresShell of the PresShell 327 * which starts handling the event. 328 * @param aMouseEvent The mouse event which the PresShell starts 329 * handling. 330 */ 331 static void ClearMouseState(PresShell& aRootPresShell, 332 const WidgetMouseEvent& aMouseEvent); 333 334 // Request/release pointer capture of the specified pointer by the element. 335 static void RequestPointerCaptureById(uint32_t aPointerId, 336 dom::Element* aElement); 337 static void ReleasePointerCaptureById(uint32_t aPointerId); 338 static void ReleaseAllPointerCapture(); 339 340 // Set/release pointer capture of the specified pointer by the remote target. 341 // Should only be called in parent process. 342 static bool SetPointerCaptureRemoteTarget(uint32_t aPointerId, 343 dom::BrowserParent* aBrowserParent); 344 static void ReleasePointerCaptureRemoteTarget( 345 dom::BrowserParent* aBrowserParent); 346 static void ReleasePointerCaptureRemoteTarget(uint32_t aPointerId); 347 static void ReleaseAllPointerCaptureRemoteTarget(); 348 349 // Get the pointer capturing remote target of the specified pointer. 350 static dom::BrowserParent* GetPointerCapturingRemoteTarget( 351 uint32_t aPointerId); 352 353 // Get the pointer captured info of the specified pointer. 354 static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId); 355 356 // Return the PointerInfo if the pointer with aPointerId is situated in 357 // device, nullptr otherwise. 358 // Note that the result may be activated only by synthesized events for test. 359 // If you don't want it, check PointerInfo::mIsSynthesizedForTests. 360 static const PointerInfo* GetPointerInfo(uint32_t aPointerId); 361 362 /** 363 * Return the PointeInfo which stores the last mouse event state which should 364 * be used for dispatching a synthetic eMouseMove. 365 * 366 * @param aRootPresShell [optional] If specified, return non-nullptr if 367 * and only if the last mouse info was set by 368 * aRootPresShell. Otherwise, return the last 369 * mouse info which was set by any PresShell. 370 */ 371 [[nodiscard]] static const PointerInfo* GetLastMouseInfo( 372 const PresShell* aRootPresShell = nullptr); 373 374 /** 375 * Return the last pointerId which has not left from any documents managed in 376 * this process. 377 */ 378 [[nodiscard]] static Maybe<uint32_t> GetLastPointerId() { 379 return sLastPointerId; 380 } 381 /** 382 * Retrun true if aPointerId is the last pointerId. 383 */ 384 [[nodiscard]] static bool IsLastPointerId(uint32_t aPointerId) { 385 return sLastPointerId && *sLastPointerId == aPointerId; 386 } 387 388 // CheckPointerCaptureState checks cases, when got/lostpointercapture events 389 // should be fired. 390 MOZ_CAN_RUN_SCRIPT 391 static void MaybeProcessPointerCapture(WidgetGUIEvent* aEvent); 392 MOZ_CAN_RUN_SCRIPT 393 static void ProcessPointerCaptureForMouse(WidgetMouseEvent* aEvent); 394 MOZ_CAN_RUN_SCRIPT 395 static void ProcessPointerCaptureForTouch(WidgetTouchEvent* aEvent); 396 MOZ_CAN_RUN_SCRIPT 397 static void CheckPointerCaptureState(WidgetPointerEvent* aEvent); 398 399 // Implicitly get and release capture of current pointer for touch. 400 static void ImplicitlyCapturePointer(nsIFrame* aFrame, WidgetEvent* aEvent); 401 MOZ_CAN_RUN_SCRIPT 402 static void ImplicitlyReleasePointerCapture(WidgetEvent* aEvent); 403 MOZ_CAN_RUN_SCRIPT static void MaybeImplicitlyReleasePointerCapture( 404 WidgetGUIEvent* aEvent); 405 406 /** 407 * GetPointerCapturingContent returns a target element which captures the 408 * pointer. It's applied to mouse or pointer event (except mousedown and 409 * pointerdown). When capturing, return the element. Otherwise, nullptr. 410 * 411 * @param aEvent A mouse event or pointer event which may be 412 * captured. 413 * 414 * @return Target element for aEvent. 415 */ 416 static dom::Element* GetPointerCapturingElement(const WidgetGUIEvent* aEvent); 417 418 static dom::Element* GetPointerCapturingElement(uint32_t aPointerId); 419 420 /** 421 * Return pending capture element of for the pointerId (of the event). 422 * - If the element has already overriden the pointer capture and there is no 423 * new pending capture element, the result is what captures the pointer right 424 * now. 425 * - If the element has not overriden the pointer capture, the result will 426 * start capturing the pointer once the pending pointer capture is processed 427 * at dispatching a pointer event later. 428 * 429 * So, in other words, the result is the element which will capture the next 430 * pointer event for the pointerId. 431 */ 432 static dom::Element* GetPendingPointerCapturingElement( 433 const WidgetGUIEvent* aEvent); 434 static dom::Element* GetPendingPointerCapturingElement(uint32_t aPointerId); 435 436 /** 437 * Return an element which captured the pointer at dispatching the last 438 * ePointerUp event caused by eMouseUp except the compatibility mouse events 439 * of Touch Events or caused by eTouchEnd whose number of touches is one, 440 * i.e., the last touch release. 441 */ 442 [[nodiscard]] static RefPtr<dom::Element> 443 GetPointerCapturingElementAtLastPointerUp(); 444 445 /** 446 * Forget the pointer capturing element at dispatching the last ePointerUp. 447 */ 448 static void ReleasePointerCapturingElementAtLastPointerUp(); 449 450 // Release pointer capture if captured by the specified content or it's 451 // descendant. This is called to handle the case that the pointer capturing 452 // content or it's parent is removed from the document. 453 static void ReleaseIfCaptureByDescendant(nsIContent* aContent); 454 455 /* 456 * This function handles the case when content had called preventDefault on 457 * the active pointer. In that case we have to prevent firing subsequent mouse 458 * to content. We check the flag PointerInfo::mPreventMouseEventByContent and 459 * call PreventDefault(false) to stop default behaviors and stop firing mouse 460 * events to content and chrome. 461 * 462 * note: mouse transition events are excluded 463 * note: we have to clean mPreventMouseEventByContent on pointerup for those 464 * devices support hover 465 * note: we don't suppress firing mouse events to chrome and system group 466 * handlers because they may implement default behaviors 467 */ 468 static void PreHandlePointerEventsPreventDefault( 469 WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent); 470 471 /* 472 * This function handles the preventDefault behavior of pointerdown. When user 473 * preventDefault on pointerdown, We have to mark the active pointer to 474 * prevent sebsequent mouse events (except mouse transition events) and 475 * default behaviors. 476 * 477 * We add mPreventMouseEventByContent flag in PointerInfo to represent the 478 * active pointer won't firing compatible mouse events. It's set to true when 479 * content preventDefault on pointerdown 480 */ 481 static void PostHandlePointerEventsPreventDefault( 482 WidgetPointerEvent* aPointerEvent, WidgetGUIEvent* aMouseOrTouchEvent); 483 484 /** 485 * Dispatch a pointer event for aMouseOrTouchEvent to aEventTargetContent. 486 * 487 * @param aShell The PresShell which is handling the event. 488 * @param aEventTargetFrame The frame for aEventTargetContent. 489 * @param aEventTargetContent The event target node. 490 * @param aPointerCapturingElement 491 * The pointer capturing element. 492 * @param aMouseOrTouchEvent A mouse or touch event. 493 * @param aDontRetargetEvents If true, this won't dispatch event with 494 * different PresShell from aShell. Otherwise, 495 * pointer events may be fired on different 496 * document if and only if aMouseOrTOuchEvent is a 497 * touch event except eTouchStart. 498 * @param aState [out] The result of the pointer event. 499 * @param aMouseOrTouchEventTarget 500 * [out] The event target for the following mouse 501 * or touch event. If aEventTargetContent has not 502 * been removed from the tree, this is always set 503 * to it. If aEventTargetContent is removed from 504 * the tree and aMouseOrTouchEvent is a mouse 505 * event, this is set to inclusive ancestor of 506 * aEventTargetContent which is still connected. 507 * If aEventTargetContent is removed from the tree 508 * and aMouseOrTouchEvent is a touch event, this is 509 * set to aEventTargetContent because touch event 510 * should be dispatched even on disconnected node. 511 * FIXME: If the event is a touch event but the 512 * message is not eTouchStart, this won't be set. 513 */ 514 MOZ_CAN_RUN_SCRIPT static void DispatchPointerFromMouseOrTouch( 515 PresShell* aShell, nsIFrame* aEventTargetFrame, 516 nsIContent* aEventTargetContent, dom::Element* aPointerCapturingElement, 517 WidgetGUIEvent* aMouseOrTouchEvent, bool aDontRetargetEvents, 518 nsEventStatus* aStatus, nsIContent** aMouseOrTouchEventTarget = nullptr); 519 520 /** 521 * Synthesize eMouseMove or ePointerMove to dispatch mouse/pointer boundary 522 * events if they are required. This dispatches the event on the widget. 523 * Therefore, this dispatches the event on correct document in the same 524 * process. However, if there is a popup under the pointer or a document in a 525 * different process, this does not work as you expected. 526 */ 527 MOZ_CAN_RUN_SCRIPT static void SynthesizeMoveToDispatchBoundaryEvents( 528 const WidgetMouseEvent* aEvent); 529 530 static void InitPointerEventFromMouse(WidgetPointerEvent* aPointerEvent, 531 const WidgetMouseEvent* aMouseEvent, 532 EventMessage aMessage); 533 534 static void InitPointerEventFromTouch(WidgetPointerEvent& aPointerEvent, 535 const WidgetTouchEvent& aTouchEvent, 536 const mozilla::dom::Touch& aTouch); 537 538 static void InitCoalescedEventFromPointerEvent( 539 WidgetPointerEvent& aCoalescedEvent, 540 const WidgetPointerEvent& aSourceEvent); 541 542 static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) { 543 return aEvent->mMessage == eMouseRawUpdate || 544 aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp || 545 (aEvent->mMessage == eMouseMove && 546 aEvent->AsMouseEvent()->IsReal()) || 547 aEvent->mMessage == eMouseExitFromWidget; 548 } 549 550 static bool ShouldGeneratePointerEventFromTouch(WidgetGUIEvent* aEvent) { 551 return aEvent->mMessage == eTouchRawUpdate || 552 aEvent->mMessage == eTouchStart || aEvent->mMessage == eTouchMove || 553 aEvent->mMessage == eTouchEnd || aEvent->mMessage == eTouchCancel || 554 aEvent->mMessage == eTouchPointerCancel; 555 } 556 557 static MOZ_ALWAYS_INLINE int32_t GetSpoofedPointerIdForRFP() { 558 return sSpoofedPointerId.valueOr(0); 559 } 560 561 static void NotifyDestroyPresContext(nsPresContext* aPresContext); 562 563 static bool IsDragAndDropEnabled(WidgetMouseEvent& aEvent); 564 565 // Get proper pointer event message for a mouse or touch event. 566 [[nodiscard]] static EventMessage ToPointerEventMessage( 567 const WidgetGUIEvent* aMouseOrTouchEvent); 568 569 /** 570 * Return true if the window containing aDocument has had a 571 * `pointerrawupdate` event listener. 572 */ 573 [[nodiscard]] static bool NeedToDispatchPointerRawUpdate( 574 const dom::Document* aDocument); 575 576 /** 577 * Return a log module reference for logging the mouse location. 578 */ 579 [[nodiscard]] static LazyLogModule& MouseLocationLogRef(); 580 581 /** 582 * Return a log module reference for logging the pointer location. 583 */ 584 [[nodiscard]] static LazyLogModule& PointerLocationLogRef(); 585 586 private: 587 // Set pointer capture of the specified pointer by the element. 588 static void SetPointerCaptureById(uint32_t aPointerId, 589 dom::Element* aElement); 590 591 // GetPointerType returns pointer type like mouse, pen or touch for pointer 592 // event with pointerId. The return value must be one of 593 // MouseEvent_Binding::MOZ_SOURCE_* 594 static uint16_t GetPointerType(uint32_t aPointerId); 595 596 // GetPointerPrimaryState returns state of attribute isPrimary for pointer 597 // event with pointerId 598 static bool GetPointerPrimaryState(uint32_t aPointerId); 599 600 // HasActiveTouchPointer returns true if there is active pointer event that is 601 // generated from touch event. 602 static bool HasActiveTouchPointer(); 603 604 MOZ_CAN_RUN_SCRIPT 605 static void DispatchGotOrLostPointerCaptureEvent( 606 bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent, 607 dom::Element* aCaptureTarget); 608 609 enum class CapturingState { Pending, Override }; 610 static dom::Element* GetPointerCapturingElementInternal( 611 CapturingState aCapturingState, const WidgetGUIEvent* aEvent); 612 613 // The cached spoofed pointer ID for fingerprinting resistance. We will use a 614 // mouse pointer id for desktop. For mobile, we should use the touch pointer 615 // id as the spoofed one, and this work will be addressed in Bug 1492775. 616 static Maybe<int32_t> sSpoofedPointerId; 617 618 // A helper function to cache the pointer id of the spoofed interface, we 619 // would only cache the pointer id once. After that, we would always stick to 620 // that pointer id for fingerprinting resistance. 621 static void MaybeCacheSpoofedPointerID(uint16_t aInputSource, 622 uint32_t aPointerId); 623 624 /** 625 * Store the pointer capturing element. 626 */ 627 static void SetPointerCapturingElementAtLastPointerUp( 628 nsWeakPtr&& aPointerCapturingElement); 629 630 /** 631 * Insert/update a pointer to/in sActivePointerIds. 632 */ 633 static const UniquePtr<PointerInfo>& InsertOrUpdateActivePointer( 634 uint32_t aPointerId, UniquePtr<PointerInfo>&& aNewPointerInfo, 635 EventMessage aEventMessage, const char* aCallerName); 636 637 /** 638 * Remove a pointer from sActivePointerIds. 639 */ 640 static void RemoveActivePointer(uint32_t aPointerId, 641 EventMessage aEventMessage, 642 const char* aCallerName); 643 644 /** 645 * Called when a new pointer event is bing fired. 646 */ 647 static void UpdateLastPointerId(uint32_t aPointerId, 648 EventMessage aEventMessage); 649 650 /** 651 * Called when a pointer is leaving from this process. 652 */ 653 static void MaybeForgetLastPointerId(uint32_t aPointerId, 654 EventMessage aEventMessage); 655 656 // Stores the last mouse info to dispatch synthetic eMouseMove in root 657 // PresShells. 658 static StaticAutoPtr<PointerInfo> sLastMouseInfo; 659 660 // Stores the last mouse info setter. 661 static StaticRefPtr<nsIWeakReference> sLastMousePresShell; 662 663 // Stores the last pointerId which has not left from all documents managed in 664 // this process. 665 static Maybe<uint32_t> sLastPointerId; 666 }; 667 668 } // namespace mozilla 669 670 #endif // mozilla_PointerEventHandler_h