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