Revert "Bug 1550462 - part 3: Enable pointerrawupdate event r=smaug" for causing mochitest failures @ test_pointerrawupdate_event_count.html

This reverts commit eb27445e03.

Revert "Bug 1550462 - part 2: Make `PresShell::HandleEvent` dispatch preceding `pointerrawupdate` event r=smaug,dom-core,edgar"

This reverts commit 502f22686c.

Revert "Bug 1550462 - part 1: Define `pointerawupdate` event r=smaug"

This reverts commit 2b13850454.
This commit is contained in:
Alexandru Marc
2025-05-16 09:30:09 +03:00
committed by amarc@mozilla.com
parent 3ae4b28862
commit 46de26821c
42 changed files with 184 additions and 1052 deletions

View File

@@ -1133,8 +1133,6 @@ void nsGlobalWindowInner::FreeInnerObjects() {
}
StartDying();
ClearHasPointerRawUpdateEventListeners();
if (mDoc && mDoc->GetWindowContext()) {
// The document is about to lose its window, so this is a good time to send
// our page use counters.
@@ -7689,26 +7687,6 @@ TrustedTypePolicyFactory* nsGlobalWindowInner::TrustedTypes() {
return mTrustedTypePolicyFactory;
}
void nsPIDOMWindowInner::MaybeSetHasPointerRawUpdateEventListeners() {
if (HasPointerRawUpdateEventListeners() || !IsSecureContext()) {
return;
}
mMayHavePointerRawUpdateEventListener = true;
if (BrowserChild* const browserChild = BrowserChild::GetFrom(this)) {
browserChild->OnPointerRawUpdateEventListenerAdded(this);
}
}
void nsPIDOMWindowInner::ClearHasPointerRawUpdateEventListeners() {
if (!HasPointerRawUpdateEventListeners()) {
return;
}
mMayHavePointerRawUpdateEventListener = false;
if (BrowserChild* const browserChild = BrowserChild::GetFrom(this)) {
browserChild->OnPointerRawUpdateEventListenerRemoved(this);
}
}
nsIURI* nsPIDOMWindowInner::GetDocumentURI() const {
return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
}
@@ -7799,7 +7777,29 @@ CloseWatcherManager* nsPIDOMWindowInner::EnsureCloseWatcherManager() {
nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
WindowGlobalChild* aActor)
: mOuterWindow(aOuterWindow), mWindowGlobalChild(aActor) {
: mMutationBits(0),
mIsDocumentLoaded(false),
mIsHandlingResizeEvent(false),
mMayHaveDOMActivateEventListeners(false),
mMayHaveTouchEventListener(false),
mMayHaveSelectionChangeEventListener(false),
mMayHaveFormSelectEventListener(false),
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mMayHaveTransitionEventListener(false),
mMayHaveSMILTimeEventListener(false),
mMayHaveBeforeInputEventListenerForTelemetry(false),
mMutationObserverHasObservedNodeForTelemetry(false),
mOuterWindow(aOuterWindow),
mWindowID(0),
mHasNotifiedGlobalCreated(false),
mMarkedCCGeneration(0),
mHasTriedToCacheTopInnerWindow(false),
mNumOfIndexedDBDatabases(0),
mNumOfOpenWebSockets(0),
mEvent(nullptr),
mWindowGlobalChild(aActor),
mWasSuspendedByGroup(false) {
MOZ_ASSERT(aOuterWindow);
mBrowsingContext = aOuterWindow->GetBrowsingContext();

View File

@@ -3656,9 +3656,6 @@ already_AddRefed<nsINode> nsINode::CloneAndAdopt(
if (elm->MayHavePointerEnterLeaveEventListener()) {
window->SetHasPointerEnterLeaveEventListeners();
}
if (elm->MayHavePointerRawUpdateEventListener()) {
window->MaybeSetHasPointerRawUpdateEventListeners();
}
if (elm->MayHaveSelectionChangeEventListener()) {
window->SetHasSelectionChangeEventListeners();
}

View File

@@ -224,29 +224,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
mMayHavePointerEnterLeaveEventListener = true;
}
/**
* Call this to check whether some node (this window, its document,
* or content in that document) has a pointerrawupdate event listener.
*/
bool HasPointerRawUpdateEventListeners() const {
return mMayHavePointerRawUpdateEventListener;
}
/**
* Call this to indicate that some node (this window, its document,
* or content in that document) has a pointerrawupdate event listener.
* This may not accept that if the event is not available in this window.
*/
void MaybeSetHasPointerRawUpdateEventListeners();
protected:
/**
* Call this to clear whether some nodes has a pointerrawupdate event
* listener.
*/
void ClearHasPointerRawUpdateEventListeners();
public:
/**
* Call this to check whether some node (this window, its document,
* or content in that document) has a transition* event listeners.
@@ -672,25 +649,24 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
RefPtr<mozilla::dom::Navigator> mNavigator;
// These variables are only used on inner windows.
uint32_t mMutationBits = 0;
uint32_t mMutationBits;
uint32_t mActivePeerConnections = 0;
bool mIsDocumentLoaded = false;
bool mIsHandlingResizeEvent = false;
bool mMayHaveDOMActivateEventListeners = false;
bool mMayHaveTouchEventListener = false;
bool mMayHaveSelectionChangeEventListener = false;
bool mMayHaveFormSelectEventListener = false;
bool mMayHaveMouseEnterLeaveEventListener = false;
bool mMayHavePointerEnterLeaveEventListener = false;
bool mMayHavePointerRawUpdateEventListener = false;
bool mMayHaveTransitionEventListener = false;
bool mMayHaveSMILTimeEventListener = false;
bool mIsDocumentLoaded;
bool mIsHandlingResizeEvent;
bool mMayHaveDOMActivateEventListeners;
bool mMayHaveTouchEventListener;
bool mMayHaveSelectionChangeEventListener;
bool mMayHaveFormSelectEventListener;
bool mMayHaveMouseEnterLeaveEventListener;
bool mMayHavePointerEnterLeaveEventListener;
bool mMayHaveTransitionEventListener;
bool mMayHaveSMILTimeEventListener;
// Only used for telemetry probes. This may be wrong if some nodes have
// come from another document with `Document.adoptNode`.
bool mMayHaveBeforeInputEventListenerForTelemetry = false;
bool mMutationObserverHasObservedNodeForTelemetry = false;
bool mMayHaveBeforeInputEventListenerForTelemetry;
bool mMutationObserverHasObservedNodeForTelemetry;
// Our inner window's outer window.
nsCOMPtr<nsPIDOMWindowOuter> mOuterWindow;
@@ -711,11 +687,11 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// A unique (as long as our 64-bit counter doesn't roll over) id for
// this window.
uint64_t mWindowID = 0;
uint64_t mWindowID;
// Set to true once we've sent the (chrome|content)-document-global-created
// notification.
bool mHasNotifiedGlobalCreated = false;
bool mHasNotifiedGlobalCreated;
// Whether when focused via an "unknown" focus method, we should show outlines
// by default or not. The initial value of this is true (so as to show
@@ -723,7 +699,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// without any other user interaction).
bool mUnknownFocusMethodShouldShowOutline = true;
uint32_t mMarkedCCGeneration = 0;
uint32_t mMarkedCCGeneration;
// mTopInnerWindow is used for tab-wise check by timeout throttling. It could
// be null.
@@ -732,17 +708,17 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// The evidence that we have tried to cache mTopInnerWindow only once from
// SetNewDocument(). Note: We need this extra flag because mTopInnerWindow
// could be null and we don't want it to be set multiple times.
bool mHasTriedToCacheTopInnerWindow = false;
bool mHasTriedToCacheTopInnerWindow;
// The number of active IndexedDB databases.
uint32_t mNumOfIndexedDBDatabases = 0;
uint32_t mNumOfIndexedDBDatabases;
// The number of open WebSockets.
uint32_t mNumOfOpenWebSockets = 0;
uint32_t mNumOfOpenWebSockets;
// The event dispatch code sets and unsets this while keeping
// the event object alive.
mozilla::dom::Event* mEvent = nullptr;
mozilla::dom::Event* mEvent;
// The WindowGlobalChild actor for this window.
//
@@ -750,7 +726,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// during SetNewDocument, and cleared during FreeInnerObjects.
RefPtr<mozilla::dom::WindowGlobalChild> mWindowGlobalChild;
bool mWasSuspendedByGroup = false;
bool mWasSuspendedByGroup;
/**
* Count of the number of active LockRequest objects, including ones from

View File

@@ -25,12 +25,8 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/AbortSignal.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/EventCallbackDebuggerNotification.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
@@ -41,6 +37,9 @@
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/ChromeUtils.h"
#include "EventListenerService.h"
#include "nsCOMPtr.h"
@@ -146,7 +145,6 @@ EventListenerManagerBase::EventListenerManagerBase()
mMayHaveTouchEventListener(false),
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mMayHavePointerRawUpdateEventListener(false),
mMayHaveSelectionChangeEventListener(false),
mMayHaveFormSelectEventListener(false),
mMayHaveTransitionEventListener(false),
@@ -415,18 +413,6 @@ void EventListenerManager::AddEventListenerInternal(
window->SetHasPointerEnterLeaveEventListeners();
}
break;
case ePointerRawUpdate:
if (!StaticPrefs::dom_event_pointer_rawupdate_enabled()) {
break;
}
mMayHavePointerRawUpdateEventListener = true;
if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
NS_WARNING_ASSERTION(
!nsContentUtils::IsChromeDoc(window->GetExtantDoc()),
"Please do not use pointerrawupdate event in chrome.");
window->MaybeSetHasPointerRawUpdateEventListeners();
}
break;
case eGamepadButtonDown:
case eGamepadButtonUp:
case eGamepadAxisMove:
@@ -876,15 +862,6 @@ void EventListenerManager::RemoveEventListenerInternal(
DisableDevice(aUserType);
}
}
// XXX Should we clear mMayHavePointerRawUpdateEventListener if the last
// pointerrawupdate event listener is removed? If so, nsPIDOMWindowInner
// needs to count how may event listener managers had some pointerrawupdate
// event listener. If we've notified the window of having a pointerrawupdate
// event listener, some behavior is changed because pointerrawupdate event
// dispatcher needs to handle some things before dispatching an event to the
// DOM. However, it is expected that web apps using `pointerrawupdate` don't
// remove the event listeners.
}
static bool IsDefaultPassiveWhenOnRoot(EventMessage aMessage) {
@@ -1852,20 +1829,16 @@ bool EventListenerManager::HasNonPassiveListenersFor(
// After dispatching wheel, legacy mouse scroll events are dispatched
// and listeners on those can also default prevent the behavior.
if (aEvent->mMessage == eWheel) {
if (const auto& listeners =
mListenerMap.GetListenersForType(nsGkAtoms::onDOMMouseScroll)) {
if (const auto& listeners = mListenerMap.GetListenersForType(nsGkAtoms::onDOMMouseScroll)) {
for (const Listener& listener : listeners->NonObservingRange()) {
if (!listener.mFlags.mPassive &&
ListenerCanHandle(&listener, aEvent)) {
if (!listener.mFlags.mPassive && ListenerCanHandle(&listener, aEvent)) {
return true;
}
}
}
if (const auto& listeners = mListenerMap.GetListenersForType(
nsGkAtoms::onMozMousePixelScroll)) {
if (const auto& listeners = mListenerMap.GetListenersForType(nsGkAtoms::onMozMousePixelScroll)) {
for (const Listener& listener : listeners->NonObservingRange()) {
if (!listener.mFlags.mPassive &&
ListenerCanHandle(&listener, aEvent)) {
if (!listener.mFlags.mPassive && ListenerCanHandle(&listener, aEvent)) {
return true;
}
}

View File

@@ -159,7 +159,6 @@ class EventListenerManagerBase {
uint16_t mMayHaveTouchEventListener : 1;
uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
uint16_t mMayHavePointerEnterLeaveEventListener : 1;
uint16_t mMayHavePointerRawUpdateEventListener : 1;
uint16_t mMayHaveSelectionChangeEventListener : 1;
uint16_t mMayHaveFormSelectEventListener : 1;
uint16_t mMayHaveTransitionEventListener : 1;
@@ -555,9 +554,6 @@ class EventListenerManager final : public EventListenerManagerBase {
bool MayHavePointerEnterLeaveEventListener() const {
return mMayHavePointerEnterLeaveEventListener;
}
bool MayHavePointerRawUpdateEventListener() const {
return mMayHavePointerRawUpdateEventListener;
}
bool MayHaveSelectionChangeEventListener() const {
return mMayHaveSelectionChangeEventListener;
}

View File

@@ -225,8 +225,6 @@ EVENT(pointerover, ePointerOver, EventNameType_All, ePointerEventClass)
EVENT(pointerout, ePointerOut, EventNameType_All, ePointerEventClass)
EVENT(pointerenter, ePointerEnter, EventNameType_All, ePointerEventClass)
EVENT(pointerleave, ePointerLeave, EventNameType_All, ePointerEventClass)
EVENT(pointerrawupdate, ePointerRawUpdate, EventNameType_All,
ePointerEventClass)
EVENT(gotpointercapture, ePointerGotCapture, EventNameType_All,
ePointerEventClass)
EVENT(lostpointercapture, ePointerLostCapture, EventNameType_All,

View File

@@ -995,7 +995,6 @@ nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
if (touchEvent->mMessage == eTouchMove) {
GenerateDragGesture(aPresContext, touchEvent);
} else {
MOZ_ASSERT(touchEvent->mMessage != eTouchRawUpdate);
mInTouchDrag = false;
StopTrackingDragGesture(true);
}
@@ -1143,8 +1142,7 @@ nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
}
[[fallthrough]];
case eMouseMove:
case ePointerMove:
case ePointerRawUpdate: {
case ePointerMove: {
if (aEvent->mMessage == ePointerMove) {
PointerEventHandler::UpdateActivePointerState(mouseEvent,
aTargetContent);
@@ -4368,22 +4366,20 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// events after they have been processed. When determining if
// a swipe should occur, we should not prefer the current wheel
// transaction.
nsIFrame* lastScrollFrame =
WheelTransaction::GetScrollTargetFrame();
nsIFrame* lastScrollFrame = WheelTransaction::GetScrollTargetFrame();
bool wheelTransactionHandlesInput = false;
if (lastScrollFrame) {
ScrollContainerFrame* scrollContainerFrame =
lastScrollFrame->GetScrollTargetFrame();
ScrollContainerFrame* scrollContainerFrame = lastScrollFrame->GetScrollTargetFrame();
if (scrollContainerFrame->IsRootScrollFrameOfDocument()) {
// If the current wheel transaction target is the root scroll
// frame and is not scrollable on the x-axis, all delta is
// overflown and swipe-to-nav may occur.
wheelTransactionHandlesInput = true;
allDeltaOverflown = !WheelHandlingUtils::CanScrollOn(
scrollContainerFrame, wheelEvent->mDeltaX, 0.0);
} else if (WheelHandlingUtils::CanScrollOn(
scrollContainerFrame, wheelEvent->mDeltaX,
wheelEvent->mDeltaY)) {
allDeltaOverflown = !WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
wheelEvent->mDeltaX, 0.0);
} else if(WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
wheelEvent->mDeltaX,
wheelEvent->mDeltaY)) {
// If the current wheel transaction target is not the root
// scroll frame, ensure that swipe to nav does not occur if
// the scroll frame is scrollable on the x or y axis. If the
@@ -5568,8 +5564,7 @@ void EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
/* static */
void EventStateManager::UpdateLastRefPointOfMouseEvent(
WidgetMouseEvent* aMouseEvent) {
if (aMouseEvent->mMessage != ePointerRawUpdate &&
aMouseEvent->mMessage != eMouseMove &&
if (aMouseEvent->mMessage != eMouseMove &&
aMouseEvent->mMessage != ePointerMove) {
return;
}
@@ -5602,8 +5597,7 @@ void EventStateManager::UpdateLastRefPointOfMouseEvent(
void EventStateManager::ResetPointerToWindowCenterWhilePointerLocked(
WidgetMouseEvent* aMouseEvent) {
MOZ_ASSERT(PointerLockManager::IsLocked());
if ((aMouseEvent->mMessage != ePointerRawUpdate &&
aMouseEvent->mMessage != eMouseMove &&
if ((aMouseEvent->mMessage != eMouseMove &&
aMouseEvent->mMessage != ePointerMove) ||
!aMouseEvent->mWidget) {
return;
@@ -5664,7 +5658,6 @@ void EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent) {
switch (aMouseEvent->mMessage) {
case eMouseMove:
case ePointerMove:
case ePointerRawUpdate:
case ePointerDown:
case ePointerGotCapture: {
// Get the target content target (mousemove target == mouseover target)

View File

@@ -385,9 +385,7 @@ void PointerEvent::GetCoalescedEvents(
void PointerEvent::EnsureFillingCoalescedEvents(
WidgetPointerEvent& aWidgetEvent) {
if (!aWidgetEvent.IsTrusted() ||
(aWidgetEvent.mMessage != ePointerMove &&
aWidgetEvent.mMessage != ePointerRawUpdate) ||
if (!aWidgetEvent.IsTrusted() || aWidgetEvent.mMessage != ePointerMove ||
!mCoalescedEvents.IsEmpty() ||
(aWidgetEvent.mCoalescedWidgetEvents &&
!aWidgetEvent.mCoalescedWidgetEvents->mEvents.IsEmpty()) ||

View File

@@ -715,9 +715,7 @@ void PointerEventHandler::InitPointerEventFromTouch(
WidgetPointerEvent& aPointerEvent, const WidgetTouchEvent& aTouchEvent,
const mozilla::dom::Touch& aTouch) {
// Use mButton/mButtons only when mButton got a value (from pen input)
int16_t button = aTouchEvent.mMessage == eTouchRawUpdate ||
aTouchEvent.mMessage == eTouchMove
? MouseButton::eNotPressed
int16_t button = aTouchEvent.mMessage == eTouchMove ? MouseButton::eNotPressed
: aTouchEvent.mButton != MouseButton::eNotPressed
? aTouchEvent.mButton
: MouseButton::ePrimary;
@@ -785,9 +783,6 @@ EventMessage PointerEventHandler::ToPointerEventMessage(
MOZ_ASSERT(aMouseOrTouchEvent);
switch (aMouseOrTouchEvent->mMessage) {
case eMouseRawUpdate:
case eTouchRawUpdate:
return ePointerRawUpdate;
case eMouseMove:
return ePointerMove;
case eMouseUp:
@@ -814,15 +809,6 @@ EventMessage PointerEventHandler::ToPointerEventMessage(
}
}
/* static */
bool PointerEventHandler::NeedToDispatchPointerRawUpdate(
const Document* aDocument) {
const nsPIDOMWindowInner* const innerWindow =
aDocument ? aDocument->GetInnerWindow() : nullptr;
return innerWindow && innerWindow->HasPointerRawUpdateEventListeners() &&
innerWindow->IsSecureContext();
}
/* static */
void PointerEventHandler::DispatchPointerFromMouseOrTouch(
PresShell* aShell, nsIFrame* aEventTargetFrame,
@@ -852,8 +838,10 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch(
}
// 1. If it is not mouse then it is likely will come as touch event
// 2. We don't synthesize pointer events for synthesized mouse move
if (!mouseEvent->convertToPointer || mouseEvent->IsSynthesized()) {
// 2. We don't synthesize pointer events for those events that are not
// dispatched to DOM.
if (!mouseEvent->convertToPointer ||
!aMouseOrTouchEvent->IsAllowedToDispatchDOMEvent()) {
return;
}
@@ -861,30 +849,6 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch(
if (pointerMessage == eVoidEvent) {
return;
}
#ifdef DEBUG
if (pointerMessage == ePointerRawUpdate) {
const nsIContent* const targetContent =
aEventTargetContent ? aEventTargetContent
: aEventTargetFrame->GetContent();
NS_ASSERTION(targetContent, "Where do we want to try to dispatch?");
if (targetContent) {
NS_ASSERTION(
targetContent->IsInComposedDoc(),
nsPrintfCString("Do we want to dispatch ePointerRawUpdate onto "
"disconnected content? (targetContent=%s)",
ToString(*targetContent).c_str())
.get());
if (!NeedToDispatchPointerRawUpdate(targetContent->OwnerDoc())) {
NS_ASSERTION(
false,
nsPrintfCString(
"Did we fail to retarget the document? (targetContent=%s)",
ToString(*targetContent).c_str())
.get());
}
}
}
#endif // #ifdef DEBUG
WidgetPointerEvent event(*mouseEvent);
InitPointerEventFromMouse(&event, mouseEvent, pointerMessage);
event.convertToPointer = mouseEvent->convertToPointer = false;
@@ -963,7 +927,7 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch(
// all pointer events should be dispatched to the same target as their
// corresponding touch events. Call PresShell::HandleEvent so that we do
// hit test for pointer events.
// FIXME: If aDontRetargetEvents is false and the event is fired on
// FIXME: If aDontRetargetEvents is true and the event is fired on
// different document, we cannot track the pointer event target when
// it's removed from the tree.
PreHandlePointerEventsPreventDefault(&event, aMouseOrTouchEvent);
@@ -1028,15 +992,9 @@ void PointerEventHandler::NotifyDestroyPresContext(
bool PointerEventHandler::IsDragAndDropEnabled(WidgetMouseEvent& aEvent) {
// We shouldn't start a drag session if the event is synthesized one because
// aEvent doesn't have enough information for initializing the ePointerCancel.
if (aEvent.IsSynthesized()) {
if (!aEvent.IsReal()) {
return false;
}
// And we should not start with raw update events, which should be used only
// for notifying web apps of the pointer state changes ASAP.
if (aEvent.mMessage == ePointerRawUpdate) {
return false;
}
MOZ_ASSERT(aEvent.mMessage != eMouseRawUpdate);
#ifdef XP_WIN
if (StaticPrefs::dom_w3c_pointer_events_dispatch_by_pointer_messages()) {
// WM_POINTER does not support drag and drop, see bug 1692277

View File

@@ -270,16 +270,14 @@ class PointerEventHandler final {
const WidgetPointerEvent& aSourceEvent);
static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) {
return aEvent->mMessage == eMouseRawUpdate ||
aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp ||
return 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 ||
return aEvent->mMessage == eTouchStart || aEvent->mMessage == eTouchMove ||
aEvent->mMessage == eTouchEnd || aEvent->mMessage == eTouchCancel ||
aEvent->mMessage == eTouchPointerCancel;
}
@@ -292,18 +290,11 @@ class PointerEventHandler final {
static bool IsDragAndDropEnabled(WidgetMouseEvent& aEvent);
private:
// Get proper pointer event message for a mouse or touch event.
[[nodiscard]] static EventMessage ToPointerEventMessage(
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);
private:
// Set pointer capture of the specified pointer by the element.
static void SetPointerCaptureById(uint32_t aPointerId,
dom::Element* aElement);

View File

@@ -100,20 +100,6 @@ skip-if = [
["test_pointermove_isPrimary_subsequent_pens.html"]
["test_pointerrawupdate_event_count.html"]
scheme = "https"
skip-if = ["os == 'android'"] # Bug 1312791
["test_pointerrawupdate_event_count_touch.html"]
scheme = "https"
skip-if = [
"os == 'android'", # Bug 1312791
"verify && os == 'win'", # Bug 1659744
"win11_2009", # Bug 1781388
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && opt", # Bug 1781388
]
support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"]
["test_remove_frame_when_got_pointer_capture.html"]
["test_synthesized_touch.html"]

View File

@@ -1,129 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test for number of pointerrawupdate events</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="target0" style="width: 50px; height: 50px; background: green"></div>
<script>
SimpleTest.waitForExplicitFinish();
SimpleTest.requestCompleteLog();
SimpleTest.waitForFocus(async () => {
await SpecialPowers.pushPrefEnv({"set": [
["dom.event.pointer.rawupdate.enabled", true],
["dom.events.coalesce.mousemove", true],
["test.events.async.enabled", true],
]});
const target0 = window.document.getElementById("target0");
// First for flushing pending events in the main process, we should synthesize
// a simple click and wait for that.
info("Waiting for a click for waiting for stable state...");
await new Promise(resolve => {
target0.addEventListener("click", resolve, {once: true});
synthesizeMouseAtCenter(target0, {});
});
info("Got a click which must be synthesized by us!");
const utils = SpecialPowers.getDOMWindowUtils(window);
utils.advanceTimeAndRefresh(0);
await new Promise(resolve => SimpleTest.executeSoon(resolve));
function stringifyPointerEvent(event) {
return `{ screenX: ${event.screenX}, screenY: ${
event.screenY
}, clientX: ${event.clientX}, clientY:${event.clientY}, buttons:${
event.buttons
} }`;
}
const allEvents = [];
const pointerRawUpdateEvents = [];
function onPointerRawUpdate(event) {
allEvents.push(event);
pointerRawUpdateEvents.push(event);
// Currently, we need to compute the coordinates of the coalesced events
// while the host event is being dispatched. See bug 1960530.
event.getCoalescedEvents();
if (pointerRawUpdateEvents.length == 4) {
utils.restoreNormalRefresh();
}
}
target0.addEventListener("pointerrawupdate", onPointerRawUpdate);
const coalescedPointerMoveEvents = [];
const waitForPointerMove = new Promise(function (resolve) {
function onPointerMove(event) {
allEvents.push(event);
for (const coalescedEvent of event.getCoalescedEvents()) {
coalescedPointerMoveEvents.push(coalescedEvent);
}
if (coalescedPointerMoveEvents.length == 4) {
target0.removeEventListener("pointermove", onPointerMove);
target0.removeEventListener("pointerrawupdate", onPointerRawUpdate);
resolve();
}
};
target0.addEventListener("pointermove", onPointerMove);
});
info("Synthesizing mouse moves....");
synthesizeMouse(target0, 5, 5, {type: "mousemove"});
synthesizeMouse(target0, 10, 10, {type: "mousemove"});
synthesizeMouse(target0, 15, 15, {type: "mousemove"});
synthesizeMouse(target0, 20, 20, {type: "mousemove"});
info("Waiting for 4 coalesced pointermove events...");
await waitForPointerMove;
for (const event of allEvents) {
info(`${event.type}: ${stringifyPointerEvent(event)}`);
}
ok(!!pointerRawUpdateEvents.length, "At least one pointerrawupdate event should be fired");
is(
pointerRawUpdateEvents.length,
coalescedPointerMoveEvents.length,
`pointermove.getCoalescedEvents().length should be same as the number of preceding pointerrawupdate`
);
{
let i = 0;
for (const pointerRawUpdateEvent of pointerRawUpdateEvents) {
const coalescedEvents = pointerRawUpdateEvent.getCoalescedEvents();
is(
coalescedEvents.length,
1,
`pointerrawupdate(${i}): should have only one coalesced event`
);
is(
`${coalescedEvents[0].type}: ${stringifyPointerEvent(coalescedEvents[0])}`,
`${pointerRawUpdateEvent.type}: ${stringifyPointerEvent(pointerRawUpdateEvent)}`,
`pointerrawupdate(${i++}): the coalesced event should have same values as the host event`
);
}
}
for (let i = 0; i < Math.min(pointerRawUpdateEvents.length, coalescedPointerMoveEvents.length); i++) {
is(
stringifyPointerEvent(pointerRawUpdateEvents[i]),
stringifyPointerEvent(coalescedPointerMoveEvents[i]),
`pointerrawupdate(${i++}): should have same values as coalesced pointermove events`
);
}
info("Waiting for a click for waiting for stable state after the test...");
await new Promise(resolve => {
target0.addEventListener("click", resolve, {once: true});
synthesizeMouseAtCenter(target0, {});
});
info("Got a click after the test!");
utils.restoreNormalRefresh();
SimpleTest.finish();
});
</script>
</body>
</html>

View File

@@ -1,125 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test for number of pointerrawupdate events of touch</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="target0" style="margin: 50px; width: 50px; height: 50px; background: green"></div>
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
SimpleTest.requestCompleteLog();
if (!window.opener) {
// the utils function in apz can't not be used in remote iframe, so run the
// test in a new tab.
info("run tests in a new tab");
window.open("test_pointerrawupdate_event_count_touch.html");
} else {
function runTests() {
const target0 = window.document.getElementById("target0");
const utils = SpecialPowers.getDOMWindowUtils(window);
utils.advanceTimeAndRefresh(0);
const allEvents = [];
const pointerRawUpdateEvents = [];
const coalescedPointerMoveEvents = [];
function stringifyPointerEvent(event) {
return `{ screenX: ${event.screenX}, screenY: ${
event.screenY
}, clientX: ${event.clientX}, clientY:${event.clientY}, buttons:${
event.buttons
} }`;
}
SimpleTest.executeSoon(async () => {
function onPointerRawUpdate(event) {
allEvents.push(event);
pointerRawUpdateEvents.push(event);
// Currently, we need to compute the coordinates of the coalesced events
// while the host event is being dispatched. See bug 1960530.
event.getCoalescedEvents();
}
target0.addEventListener("pointerrawupdate", onPointerRawUpdate);
const waitForPointerMove = new Promise(resolve => {
function onPointerMove(event) {
allEvents.push(event);
for (const coalescedEvent of event.getCoalescedEvents()) {
coalescedPointerMoveEvents.push(coalescedEvent);
}
if (pointerRawUpdateEvents.length > 1) {
target0.removeEventListener("pointermove", onPointerMove);
target0.removeEventListener("pointerrawupdate", onPointerRawUpdate);
resolve();
}
}
target0.addEventListener("pointermove", onPointerMove);
});
target0.addEventListener("pointerup", async event => {
utils.restoreNormalRefresh();
await waitForPointerMove;
for (const event of allEvents) {
info(`${event.type}: ${stringifyPointerEvent(event)}`);
}
opener.ok(!!pointerRawUpdateEvents.length, "At least one pointerrawupdate event should be fired");
opener.is(
pointerRawUpdateEvents.length,
coalescedPointerMoveEvents.length,
`pointermove.getCoalescedEvents().length should be same as the number of preceding pointerrawupdate`
);
{
let i = 0;
for (const pointerRawUpdateEvent of pointerRawUpdateEvents) {
const coalescedEvents = pointerRawUpdateEvent.getCoalescedEvents();
opener.is(
coalescedEvents.length,
1,
`pointerrawupdate(${i}): should have only one coalesced event`
);
opener.is(
`${coalescedEvents[0].type}: ${stringifyPointerEvent(coalescedEvents[0])}`,
`${pointerRawUpdateEvent.type}: ${stringifyPointerEvent(pointerRawUpdateEvent)}`,
`pointerrawupdate(${i++}): the coalesced event should have same values as the host event`
);
}
}
for (let i = 0; i < Math.min(pointerRawUpdateEvents.length, coalescedPointerMoveEvents.length); i++) {
opener.is(
stringifyPointerEvent(pointerRawUpdateEvents[i]),
stringifyPointerEvent(coalescedPointerMoveEvents[i]),
`pointerrawupdate(${i++}): should have same values as coalesced pointermove events`
);
}
opener.SimpleTest.finish();
window.close();
}, { once: true });
let positions = [];
for (let i = 10; i <= 40; i+=5) {
positions.push([{ x: i, y: i }]);
}
await synthesizeNativeTouchSequences(target0, positions);
});
}
SimpleTest.waitForFocus(() => {
SpecialPowers.pushPrefEnv({"set": [
["dom.event.pointer.rawupdate.enabled", true],
["dom.events.coalesce.touchmove", true],
["dom.events.compress.touchmove", false],
]}, runTests);
});
}
</script>
</body>
</html>

View File

@@ -4895,16 +4895,13 @@ void HTMLMediaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
// element, allowing media control exclusive consumption on these events,
// and preventing the content from handling them.
switch (aVisitor.mEvent->mMessage) {
case eTouchRawUpdate:
MOZ_FALLTHROUGH_ASSERT(
"eTouchRawUpdate event shouldn't be dispatched into the DOM");
case ePointerDown:
case ePointerUp:
case eTouchEnd:
// Always prevent touchmove captured in video element from being handled by
// content, since we always do that for touchstart.
case eTouchMove:
case eTouchEnd:
case eTouchStart:
case ePointerDown:
case ePointerUp:
case ePointerClick:
case eMouseDoubleClick:
case eMouseDown:
@@ -4912,13 +4909,9 @@ void HTMLMediaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
aVisitor.mCanHandle = false;
return;
// The *move events however are only consumed when the range input is being
// The *move events however are only comsumed when the range input is being
// dragged.
case eMouseRawUpdate:
MOZ_FALLTHROUGH_ASSERT(
"eMouseRawUpdate event shouldn't be dispatched into the DOM");
case ePointerMove:
case ePointerRawUpdate:
case eMouseMove: {
nsINode* node =
nsINode::FromEventTargetOrNull(aVisitor.mEvent->mOriginalTarget);

View File

@@ -1489,7 +1489,7 @@ void BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() {
// mToBeDispatchedMouseData while dispatching an event.
// We may have some pending coalesced data while dispatch an event and reentry
// the event loop. In that case we don't have chance to consume the remaining
// the event loop. In that case we don't have chance to consume the remainding
// pending data until we get new mouse events. Get some helps from
// mCoalescedMouseEventFlusher to trigger it.
mCoalescedMouseEventFlusher->StartObserver();
@@ -1500,13 +1500,6 @@ void BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() {
UniquePtr<WidgetMouseEvent> event = data->TakeCoalescedEvent();
if (event) {
// When the real mouse event receivers put the received event into the
// queue, they should dispatch eMouseRawUpdate event immediately (if and
// only if it's required). Therefore, unless the event is the last one
// of the queue, the pending events should've been marked as "Do not
// convert to "pointerrawupdate".
MOZ_ASSERT_IF(mToBeDispatchedMouseData.GetSize() > 0,
!event->convertToPointerRawUpdate);
// Dispatch the pending events. Using HandleRealMouseButtonEvent
// to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
// RecvRealMouseButtonEvent because we may also put some mouse events
@@ -1563,20 +1556,11 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealMouseMoveEvent(
CoalescedMouseData* data =
mCoalescedMouseData.GetOrInsertNew(aEvent.pointerId);
MOZ_ASSERT(data);
if (data->CanCoalesce(aEvent, aGuid, aInputBlockId,
mCoalescedMouseEventFlusher->GetRefreshDriver())) {
// We don't need to dispatch aEvent immediately. However, we need to
// dispatch eMouseRawUpdate immediately if there is a `pointerrawupdate`
// event listener. Therefore, the cloned event in the queue shouldn't
// cause eMouseRawUpdate later when it'll be dispatched.
WidgetMouseEvent pendingMouseMoveEvent(aEvent);
pendingMouseMoveEvent.convertToPointerRawUpdate = false;
data->Coalesce(pendingMouseMoveEvent, aGuid, aInputBlockId);
if (data->CanCoalesce(aEvent, aGuid, aInputBlockId)) {
data->Coalesce(aEvent, aGuid, aInputBlockId);
mCoalescedMouseEventFlusher->StartObserver();
HandleMouseRawUpdateEvent(pendingMouseMoveEvent, aGuid, aInputBlockId);
return IPC_OK();
}
// Can't coalesce current mousemove event. Put the coalesced mousemove data
// with the same pointer id to mToBeDispatchedMouseData, coalesce the
// current one, and process all pending data in mToBeDispatchedMouseData.
@@ -1591,50 +1575,17 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealMouseMoveEvent(
mCoalescedMouseData
.InsertOrUpdate(aEvent.pointerId, MakeUnique<CoalescedMouseData>())
.get();
// We don't want to dispatch aEvent immediately. However, we need to
// dispatch eMouseRawUpdate immediately if there is a `pointerrawupdate`
// event listener. Therefore, the cloned event in the queue shouldn't
// cause eMouseRawUpdate later when it'll be dispatched.
WidgetMouseEvent pendingMouseMoveEvent(aEvent);
pendingMouseMoveEvent.convertToPointerRawUpdate = false;
newData->Coalesce(pendingMouseMoveEvent, aGuid, aInputBlockId);
newData->Coalesce(aEvent, aGuid, aInputBlockId);
// Dispatch all pending mouse events which does NOT include aEvent.
// Dispatch all pending mouse events.
ProcessPendingCoalescedMouseDataAndDispatchEvents();
mCoalescedMouseEventFlusher->StartObserver();
// Finally, dispatch eMouseRawUpdate for aEvent right now.
HandleMouseRawUpdateEvent(pendingMouseMoveEvent, aGuid, aInputBlockId);
return IPC_OK();
}
if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
} else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
void BrowserChild::HandleMouseRawUpdateEvent(
const WidgetMouseEvent& aPendingMouseEvent,
const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId) {
// If there is no window containing pointerrawupdate event listeners or the
// event is a synthesized mousemove, we don't need to dispatch eMouseRawUpdate
// event.
if (!mPointerRawUpdateWindowCount || aPendingMouseEvent.IsSynthesized()) {
return;
}
WidgetMouseEvent mouseRawUpdateEvent(aPendingMouseEvent);
mouseRawUpdateEvent.mMessage = eMouseRawUpdate;
mouseRawUpdateEvent.mCoalescedWidgetEvents = nullptr;
mouseRawUpdateEvent.convertToPointer = true;
// Nobody checks `convertToPointerRawUpdate` of eMouseRawUpdate event.
// However, the name indicates that it would cause ePointerRawUpdate.
// For avoiding to make the developers who watch the value with the debugger
// confused, here sets it to `true`.
mouseRawUpdateEvent.convertToPointerRawUpdate = true;
HandleRealMouseButtonEvent(mouseRawUpdateEvent, aGuid, aInputBlockId);
}
mozilla::ipc::IPCResult BrowserChild::RecvRealMouseMoveEventForTests(
const WidgetMouseEvent& aEvent, const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) {
@@ -1686,16 +1637,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealMouseButtonEvent(
UniquePtr<CoalescedMouseData> dispatchData =
MakeUnique<CoalescedMouseData>();
// We'll dispatch aEvent immediately via
// ProcessPendingCoalescedMouseDataAndDispatchEvents().
// Therefore, PresShell should convert it to eMouseRawUpdate when it starts
// handling aEvent if and only if there is a `pointerrawupdate` event
// listener. Therefore, let's assert the allowing flag to convert it to
// eMouseRawUpdate here.
MOZ_ASSERT(aEvent.convertToPointerRawUpdate);
dispatchData->Coalesce(aEvent, aGuid, aInputBlockId);
mToBeDispatchedMouseData.Push(dispatchData.release());
ProcessPendingCoalescedMouseDataAndDispatchEvents();
return IPC_OK();
}
@@ -1886,7 +1830,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchEvent(
ProcessPendingCoalescedTouchData();
}
if (aEvent.mMessage != eTouchMove && aEvent.mMessage != eTouchRawUpdate) {
if (aEvent.mMessage != eTouchMove) {
sConsecutiveTouchMoveCount = 0;
}
}
@@ -1949,88 +1893,33 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchMoveEvent(
++sConsecutiveTouchMoveCount;
if (mCoalescedTouchMoveEventFlusher) {
MOZ_ASSERT(aEvent.mMessage == eTouchMove);
// NOTE: While dispatching eTouchMove or eTouchRawUpdate,
// sConsecutiveTouchMoveCount may be changed by the event loop spun,
// e.g., an event listener uses sync XHR or calling window.alert().
const auto PostponeDispatchingTouchMove = [&]() {
return sConsecutiveTouchMoveCount > 1;
};
if (mCoalescedTouchData.IsEmpty() ||
mCoalescedTouchData.CanCoalesce(aEvent, aGuid, aInputBlockId,
aApzResponse)) {
if (PostponeDispatchingTouchMove()) {
WidgetTouchEvent pendingTouchMoveEvent(
aEvent, WidgetTouchEvent::CloneTouches::Yes);
// We don't dispatch aEvent immediately here. However, we need to
// dispatch eTouchRawUpdate immediately if and only if there is a
// `pointerrawupdate` event listener. Therefore, the cloned event in
// the queue and it shouldn't cause eTouchRawUpdate again.
pendingTouchMoveEvent.SetConvertToPointerRawUpdate(false);
mCoalescedTouchData.Coalesce(pendingTouchMoveEvent, aGuid,
aInputBlockId, aApzResponse);
MOZ_ASSERT(PostponeDispatchingTouchMove());
mCoalescedTouchMoveEventFlusher->StartObserver();
// Let's notify the web app of `pointerrawupdate` immediately if and
// only if they listen to it.
HandleTouchRawUpdateEvent(pendingTouchMoveEvent, aGuid, aInputBlockId,
aApzResponse);
return IPC_OK();
}
// We'll dispatch aEvent via ProcessPendingCoalescedTouchData() below.
// Therefore, the touches should cause eTouchRawUpdate event.
MOZ_ASSERT(aEvent.CanConvertToPointerRawUpdate());
mCoalescedTouchData.Coalesce(aEvent, aGuid, aInputBlockId,
aApzResponse);
MOZ_ASSERT(!PostponeDispatchingTouchMove());
} else {
UniquePtr<WidgetTouchEvent> touchMoveEvent =
mCoalescedTouchData.TakeCoalescedEvent();
MOZ_ASSERT(touchMoveEvent->mMessage == eTouchMove);
// Before dispatching touchMoveEvent, we need to put aEvent into the
// queue for keeping the event order even if an event listener spins the
// event loop and we'll receive another touch event. So, aEvent may be
// dispatched while we're dispatching touchMoveEvent. Therefore, we need
// to make it convertible to eTouchRawUpdate.
MOZ_ASSERT(aEvent.CanConvertToPointerRawUpdate());
mCoalescedTouchData.Coalesce(aEvent, aGuid, aInputBlockId,
aApzResponse);
MOZ_ASSERT(!PostponeDispatchingTouchMove());
// touchMoveEvent was stored by mCoalescedTouchData before receiving
// aEvent. Therefore, the receiver should've already dispatched
// eTouchRawUpdate for dispatching `pointerrawupdate` and let web apps
// know the update immediately (with sacrificing the performance).
// Therefore, we don't need to dispatch eTouchRawUpdate here before
// dispatching the touchMoveEvent.
MOZ_ASSERT(!touchMoveEvent->CanConvertToPointerRawUpdate());
const uint32_t generation = mCoalescedTouchData.Generation();
if (!RecvRealTouchEvent(*touchMoveEvent,
mCoalescedTouchData.GetScrollableLayerGuid(),
mCoalescedTouchData.GetInputBlockId(),
mCoalescedTouchData.GetApzResponse())) {
return IPC_FAIL_NO_REASON(this);
}
// RecvRealTouchEvent() may have caused spinning the event loop and
// changed sConsecutiveTouchMoveCount. So, we need to check it now.
if (PostponeDispatchingTouchMove()) {
mCoalescedTouchMoveEventFlusher->StartObserver();
if (generation == mCoalescedTouchData.Generation()) {
// Let's notify the web app of `pointerrawupdate` immediately if and
// only if they listen to it. Additionally, we don't want to notify
// eTouchRawUpdate when ProcessPendingCoalescedTouchData() is called
// later.
mCoalescedTouchData.NotifyTouchRawUpdateOfHandled(aEvent);
HandleTouchRawUpdateEvent(aEvent, aGuid, aInputBlockId,
aApzResponse);
}
return IPC_OK();
}
}
// Flush the pending coalesced touch in order to avoid the first
// touchmove be overridden by the second one, this contains aEvent.
ProcessPendingCoalescedTouchData();
if (sConsecutiveTouchMoveCount > 1) {
mCoalescedTouchMoveEventFlusher->StartObserver();
} else {
// Flush the pending coalesced touch in order to avoid the first
// touchmove be overridden by the second one.
ProcessPendingCoalescedTouchData();
}
return IPC_OK();
}
}
@@ -2041,30 +1930,6 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchMoveEvent(
return IPC_OK();
}
void BrowserChild::HandleTouchRawUpdateEvent(
const WidgetTouchEvent& aPendingTouchEvent,
const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId,
const nsEventStatus& aApzResponse) {
if (!mPointerRawUpdateWindowCount) {
return; // There is no window containing pointerrawupdate event listeners
}
WidgetTouchEvent touchRawUpdateEvent(aPendingTouchEvent,
WidgetTouchEvent::CloneTouches::Yes);
touchRawUpdateEvent.mMessage = eTouchRawUpdate;
for (Touch* const touch : touchRawUpdateEvent.mTouches) {
touch->mMessage = eTouchRawUpdate;
touch->mCoalescedWidgetEvents = nullptr;
touch->convertToPointer = true;
// Although nobody checks `convertToPointerRawUpdate` of eTouchRawUpdate.
// However, the name indicates it would cause ePointerRawUpdate or not, so,
// for avoiding to make developers confused when they watch the value with
// the debugger, we should set this to `true`.
touch->convertToPointerRawUpdate = true;
}
RecvRealTouchEvent(touchRawUpdateEvent, aGuid, aInputBlockId, aApzResponse);
}
mozilla::ipc::IPCResult BrowserChild::RecvNormalPriorityRealTouchMoveEvent(
const WidgetTouchEvent& aEvent, const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId, const nsEventStatus& aApzResponse) {
@@ -4169,27 +4034,6 @@ void BrowserChild::SetDragSession(nsIDragSession* aSession) {
mDragSession = aSession;
}
LazyLogModule gPointerRawUpdateEventListenersLog(
"PointerRawUpdateEventListeners");
void BrowserChild::OnPointerRawUpdateEventListenerAdded(
const nsPIDOMWindowInner* aWindow) {
mPointerRawUpdateWindowCount++;
MOZ_LOG(gPointerRawUpdateEventListenersLog, LogLevel::Info,
("Added for %p (total: %u)", aWindow, mPointerRawUpdateWindowCount));
}
void BrowserChild::OnPointerRawUpdateEventListenerRemoved(
const nsPIDOMWindowInner* aWindow) {
MOZ_ASSERT(mPointerRawUpdateWindowCount);
if (MOZ_LIKELY(mPointerRawUpdateWindowCount)) {
mPointerRawUpdateWindowCount--;
}
MOZ_LOG(gPointerRawUpdateEventListenersLog, LogLevel::Info,
("Removed for %p (remaining: %u)", aWindow,
mPointerRawUpdateWindowCount));
}
BrowserChildMessageManager::BrowserChildMessageManager(
BrowserChild* aBrowserChild)
: ContentFrameMessageManager(new nsFrameMessageManager(aBrowserChild)),

View File

@@ -46,7 +46,6 @@ class nsIHttpChannel;
class nsIRequest;
class nsISerialEventTarget;
class nsIWebProgress;
class nsPIDOMWindowInner;
class nsWebBrowser;
class nsDocShellLoadState;
@@ -641,36 +640,14 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
// may reentry the event loop and access to the same hashtable. It's
// called when dispatching some mouse events other than mousemove.
void FlushAllCoalescedMouseData();
void ProcessPendingCoalescedMouseDataAndDispatchEvents();
void ProcessPendingCoalescedTouchData();
/**
* Dispatch an eMouseRawUpdate event for dispatching ePointerRawUpdate event
* into the DOM immediately when aPendingEvent will be dispatched later.
* This does nothing if there is no window which has at least one
* `pointerrawupdate` event listener.
*/
void HandleMouseRawUpdateEvent(const WidgetMouseEvent& aPendingMouseEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
void HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
/**
* Dispatch an eTouchRawUpdate event for dispatching ePointerRawUpdate event
* into the DOM immediately when aPendingEvent will be dispatched later.
* This does nothing if there is no window which has at least one
* `pointerrawupdate` event listener.
*/
void HandleTouchRawUpdateEvent(const WidgetTouchEvent& aPendingTouchEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const nsEventStatus& aApzResponse);
void SetCancelContentJSEpoch(int32_t aEpoch) {
mCancelContentJSEpoch = aEpoch;
}
@@ -735,13 +712,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
mozilla::ipc::IPCResult RecvDispatchToDropTargetAndResumeEndDragSession(
bool aShouldDrop);
void OnPointerRawUpdateEventListenerAdded(const nsPIDOMWindowInner* aWindow);
void OnPointerRawUpdateEventListenerRemoved(
const nsPIDOMWindowInner* aWindow);
[[nodiscard]] bool HasPointerRawUpdateEventListeners() const {
return !!mPointerRawUpdateWindowCount;
}
protected:
virtual ~BrowserChild();
@@ -853,8 +823,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
Maybe<CodeNameIndex> mPreviousConsumedKeyDownCode;
uint32_t mChromeFlags;
uint32_t mMaxTouchPoints;
// The number of windows which may have ePointerRawUpdate event listener.
uint32_t mPointerRawUpdateWindowCount = 0;
layers::LayersId mLayersId;
CSSRect mUnscaledOuterRect;
Maybe<bool> mLayersConnected;

View File

@@ -24,21 +24,12 @@ class CoalescedInputData {
UniquePtr<InputEventType> mCoalescedInputEvent;
ScrollableLayerGuid mGuid;
uint64_t mInputBlockId = 0;
uint32_t mGeneration = 0;
void AdvanceGeneration() {
if (!IsEmpty()) {
mGeneration++;
}
}
uint64_t mInputBlockId;
public:
CoalescedInputData() = default;
CoalescedInputData() : mInputBlockId(0) {}
void RetrieveDataFrom(CoalescedInputData& aSource) {
aSource.AdvanceGeneration();
AdvanceGeneration();
mCoalescedInputEvent = std::move(aSource.mCoalescedInputEvent);
mGuid = aSource.mGuid;
mInputBlockId = aSource.mInputBlockId;
@@ -51,23 +42,12 @@ class CoalescedInputData {
const uint64_t& aInputBlockId);
UniquePtr<InputEventType> TakeCoalescedEvent() {
AdvanceGeneration();
return std::move(mCoalescedInputEvent);
}
ScrollableLayerGuid GetScrollableLayerGuid() { return mGuid; }
uint64_t GetInputBlockId() { return mInputBlockId; }
/**
* The generation number of the latest state stored by the instance.
* It'll be incremented when the coalesced event data is retrieved or taken.
* So, this is useful to avoid handling same coalesced events twice when
* a nested event loop may handle this.
* NOTE: You should compare the value only with `==` or `!=`. Do not use
* `<` nor `>` because the value may circulate to 0 from UINT32_MAX.
*/
[[nodiscard]] uint32_t Generation() const { return mGeneration; }
};
class CoalescedInputFlusher : public nsARefreshObserver {
@@ -81,17 +61,12 @@ class CoalescedInputFlusher : public nsARefreshObserver {
void StartObserver();
void RemoveObserver();
/**
* Return a refresh driver which is proper one for BrowserChild.
* Note that this is not a getter of mRefreshDriver.
*/
[[nodiscard]] nsRefreshDriver* GetRefreshDriver();
protected:
virtual ~CoalescedInputFlusher();
nsRefreshDriver* GetRefreshDriver();
BrowserChild* mBrowserChild;
// A refresh driver which this instance waits for the next refresh of.
RefPtr<nsRefreshDriver> mRefreshDriver;
};
} // namespace mozilla::dom

View File

@@ -58,29 +58,17 @@ void CoalescedMouseData::Coalesce(const WidgetMouseEvent& aEvent,
bool CoalescedMouseData::CanCoalesce(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const nsRefreshDriver* aRefreshDriver) {
const uint64_t& aInputBlockId) {
MOZ_ASSERT(aEvent.mMessage == eMouseMove);
if (!mCoalescedInputEvent) {
return true;
}
if (mCoalescedInputEvent->mFlags.mIsSynthesizedForTests !=
aEvent.mFlags.mIsSynthesizedForTests ||
mCoalescedInputEvent->mModifiers != aEvent.mModifiers ||
mCoalescedInputEvent->mInputSource != aEvent.mInputSource ||
mCoalescedInputEvent->pointerId != aEvent.pointerId ||
mCoalescedInputEvent->mButton != aEvent.mButton ||
mCoalescedInputEvent->mButtons != aEvent.mButtons || mGuid != aGuid ||
mInputBlockId != aInputBlockId) {
return false;
}
// Basically, tests do not want to coalesces the consecutive mouse events.
// However, if the test calls nsIDOMWindowUtils::AdvanceTimeAndRefresh(0),
// they must try to check coalesced mouse move events.
if (!aEvent.mFlags.mIsSynthesizedForTests) {
return true;
}
return aRefreshDriver && aRefreshDriver->IsTestControllingRefreshesEnabled();
return !mCoalescedInputEvent ||
(!mCoalescedInputEvent->mFlags.mIsSynthesizedForTests &&
!aEvent.mFlags.mIsSynthesizedForTests &&
mCoalescedInputEvent->mModifiers == aEvent.mModifiers &&
mCoalescedInputEvent->mInputSource == aEvent.mInputSource &&
mCoalescedInputEvent->pointerId == aEvent.pointerId &&
mCoalescedInputEvent->mButton == aEvent.mButton &&
mCoalescedInputEvent->mButtons == aEvent.mButtons && mGuid == aGuid &&
mInputBlockId == aInputBlockId);
}
CoalescedMouseMoveFlusher::CoalescedMouseMoveFlusher(

View File

@@ -27,8 +27,7 @@ class CoalescedMouseData final : public CoalescedInputData<WidgetMouseEvent> {
bool CanCoalesce(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const nsRefreshDriver* aRefreshDriver);
const uint64_t& aInputBlockId);
};
class CoalescedMouseMoveFlusher final : public CoalescedInputFlusher {

View File

@@ -28,7 +28,6 @@ void CoalescedTouchData::CreateCoalescedTouchEvent(
PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch);
event->mFlags.mBubbles = false;
event->mFlags.mCancelable = false;
event->convertToPointerRawUpdate = false;
}
}
@@ -48,9 +47,10 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent,
MOZ_ASSERT(mCoalescedInputEvent->mModifiers == aEvent.mModifiers);
MOZ_ASSERT(mCoalescedInputEvent->mInputSource == aEvent.mInputSource);
for (const RefPtr<Touch>& touch : aEvent.mTouches) {
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
const RefPtr<Touch>& touch = aEvent.mTouches[i];
// Get the same touch in the original event
const RefPtr<Touch> sameTouch = GetTouch(touch->Identifier());
RefPtr<Touch> sameTouch = GetTouch(touch->Identifier());
// The checks in CoalescedTouchData::CanCoalesce ensure it should never
// be null.
MOZ_ASSERT(sameTouch);
@@ -58,7 +58,6 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent,
MOZ_ASSERT(!sameTouch->mCoalescedWidgetEvents->mEvents.IsEmpty());
if (!sameTouch->Equals(touch)) {
sameTouch->SetSameAs(touch);
sameTouch->convertToPointerRawUpdate = touch->convertToPointerRawUpdate;
WidgetPointerEvent* event =
sameTouch->mCoalescedWidgetEvents->mEvents.AppendElement(
WidgetPointerEvent(aEvent.IsTrusted(), ePointerMove,
@@ -73,18 +72,6 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent,
}
}
void CoalescedTouchData::NotifyTouchRawUpdateOfHandled(
const WidgetTouchEvent& aEvent) {
if (IsEmpty()) {
return;
}
for (const RefPtr<Touch>& touch : aEvent.mTouches) {
if (const RefPtr<Touch> sameTouch = GetTouch(touch->Identifier())) {
sameTouch->convertToPointerRawUpdate = false;
}
}
}
bool CoalescedTouchData::CanCoalesce(const WidgetTouchEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,

View File

@@ -27,8 +27,6 @@ class CoalescedTouchData final : public CoalescedInputData<WidgetTouchEvent> {
nsEventStatus GetApzResponse() { return mApzResponse; }
void NotifyTouchRawUpdateOfHandled(const WidgetTouchEvent& aEvent);
private:
Touch* GetTouch(int32_t aIdentifier);

View File

@@ -1857,8 +1857,6 @@ let interfaceNamesInGlobalScope = [
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onpointerover", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onpointerrawupdate" },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onpointerup", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onpopstate", insecureContext: true },

View File

@@ -116,8 +116,6 @@ interface mixin GlobalEventHandlers {
attribute EventHandler onpointerover;
attribute EventHandler onpointerenter;
attribute EventHandler onpointerleave;
[SecureContext, Pref="dom.event.pointer.rawupdate.enabled"]
attribute EventHandler onpointerrawupdate;
attribute EventHandler ongotpointercapture;
attribute EventHandler onlostpointercapture;

View File

@@ -336,9 +336,6 @@ void APZEventState::ProcessTouchEvent(
break;
}
case eTouchRawUpdate:
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown touch event type");
break;

View File

@@ -7069,8 +7069,6 @@ void PresShell::RecordPointerLocation(WidgetGUIEvent* aEvent) {
break;
}
case ePointerMove:
case ePointerRawUpdate:
case eMouseRawUpdate:
if (!aEvent->AsMouseEvent()->IsReal()) {
break;
}
@@ -7155,7 +7153,6 @@ PresShell* PresShell::GetShellForEventTarget(nsIFrame* aFrame,
PresShell* PresShell::GetShellForTouchEvent(WidgetGUIEvent* aEvent) {
switch (aEvent->mMessage) {
case eTouchMove:
case eTouchRawUpdate:
case eTouchCancel:
case eTouchEnd: {
// get the correct shell to dispatch to
@@ -7307,7 +7304,6 @@ nsresult PresShell::HandleEvent(nsIFrame* aFrameForPresShell,
if (mPresContext) {
switch (aGUIEvent->mMessage) {
case eMouseMove:
case eMouseRawUpdate:
if (!aGUIEvent->AsMouseEvent()->IsReal()) {
break;
}
@@ -7352,124 +7348,11 @@ nsresult PresShell::HandleEvent(nsIFrame* aFrameForPresShell,
}
}
// If the event may cause ePointerMove, we need to dispatch ePointerRawUpdate
// before that if and only if there are some `pointerrawupdate` event
// listeners. Note that if a `pointerrawupdate` event listener destroys its
// document/window, we need to dispatch the following pointer event (e.g.,
// ePointerMove) in the parent document/window with the parent PresShell.
// Therefore, we need to consider the target PresShell for each event
// (ePointerRawUpdate and the following pointer event) in
// EventHandler::HandleEvent(). Thus, we need to dispatch the internal event
// for ePointerRawUpdate before calling EventHandler::HandleEvent() below.
if (!aDontRetargetEvents &&
StaticPrefs::dom_event_pointer_rawupdate_enabled()) {
nsresult rv = EnsurePrecedingPointerRawUpdate(
weakFrameForPresShell, *aGUIEvent, aDontRetargetEvents);
if (NS_FAILED(rv)) {
return rv;
}
if (!CanHandleUserInputEvents(aGUIEvent)) {
return NS_OK;
}
}
EventHandler eventHandler(*this);
return eventHandler.HandleEvent(weakFrameForPresShell, aGUIEvent,
aDontRetargetEvents, aEventStatus);
}
nsresult PresShell::EnsurePrecedingPointerRawUpdate(
AutoWeakFrame& aWeakFrameForPresShell, const WidgetGUIEvent& aSourceEvent,
bool aDontRetargetEvents) {
MOZ_ASSERT(StaticPrefs::dom_event_pointer_rawupdate_enabled());
if (PointerEventHandler::ToPointerEventMessage(&aSourceEvent) !=
ePointerMove) {
return NS_OK;
}
// We should not dispatch ePointerRawUpdate directly because dispatching
// it requires some steps which are defined by "fire a pointer event" section
// in the spec. https://w3c.github.io/pointerevents/#dfn-fire-a-pointer-event
// We handle the steps when we call DispatchPrecedingPointerEvent().
// Therefore, this method dispatches eMouseRawUpdate or eTouchRawUpdate event
// if the event should follow a ePointerRawUpdate. Then,
// HandleEventUsingCoordinates() will stop handling the internal events after
// calling DispatchPrecedingPointerEvent().
MOZ_ASSERT(aSourceEvent.mMessage != eMouseRawUpdate);
MOZ_ASSERT(aSourceEvent.mMessage != eTouchRawUpdate);
// If no window in the browser child has `pointerrawupdate` event listener,
// we should do nothing.
if (auto* const browserChild = BrowserChild::GetFrom(this)) {
if (!browserChild->HasPointerRawUpdateEventListeners()) {
return NS_OK;
}
}
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
static bool sDispatchingRawUpdateEventFromHere = false;
MOZ_DIAGNOSTIC_ASSERT(
!sDispatchingRawUpdateEventFromHere,
"Dispatching ePointerRawUpdate should not be done recursively");
AutoRestore<bool> restoreDispathingFlag(sDispatchingRawUpdateEventFromHere);
sDispatchingRawUpdateEventFromHere = true;
#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (const WidgetMouseEvent* const mouseEvent = aSourceEvent.AsMouseEvent()) {
// If `convertToPointer` is `false`, it means that we've already handled the
// event to dispatch a preceding pointer event. Therefore, its preceding
// event should've already been handled.
// If `convertToPointerRawUpdate` is `false`, it means that the event was in
// the queue in BrowserChild and BrowserChild has already dispatched
// `eMouseRawUpdate`. Therefore, we don't need to dispatch it again here.
if (mouseEvent->IsSynthesized() || !mouseEvent->convertToPointer ||
!mouseEvent->convertToPointerRawUpdate) {
return NS_OK;
}
WidgetMouseEvent mouseRawUpdateEvent(*mouseEvent);
mouseRawUpdateEvent.mMessage = eMouseRawUpdate;
mouseRawUpdateEvent.mCoalescedWidgetEvents = nullptr;
nsEventStatus rawUpdateStatus = nsEventStatus_eIgnore;
EventHandler eventHandler(*this);
return eventHandler.HandleEvent(aWeakFrameForPresShell,
&mouseRawUpdateEvent, aDontRetargetEvents,
&rawUpdateStatus);
}
if (const WidgetTouchEvent* const touchEvent = aSourceEvent.AsTouchEvent()) {
WidgetTouchEvent touchRawUpdate(*touchEvent,
WidgetTouchEvent::CloneTouches::No);
touchRawUpdate.mMessage = eTouchRawUpdate;
touchRawUpdate.mTouches.Clear();
for (const RefPtr<Touch>& touch : touchEvent->mTouches) {
// If `convertToPointer` is `false`, it means that we've already handled
// the event to dispatch a preceding pointer event. Therefore, its
// preceding event should've already been handled.
// If ShouldConvertTouchToPointer() returns `false`, the touch is not an
// active pointer or the touch hasn't been changed from the previous
// state. Therefore, we don't need to dispatch ePointerRawUpdate for the
// touch.
if (!touch->convertToPointerRawUpdate ||
!TouchManager::ShouldConvertTouchToPointer(touch, &touchRawUpdate)) {
continue;
}
RefPtr<Touch> newTouch = new Touch(*touch);
newTouch->mMessage = eTouchRawUpdate;
newTouch->mCoalescedWidgetEvents = nullptr;
touchRawUpdate.mTouches.AppendElement(std::move(newTouch));
}
nsEventStatus rawUpdateStatus = nsEventStatus_eIgnore;
if (touchRawUpdate.mTouches.IsEmpty()) {
return NS_OK;
}
EventHandler eventHandler(*this);
return eventHandler.HandleEvent(aWeakFrameForPresShell, &touchRawUpdate,
aDontRetargetEvents, &rawUpdateStatus);
}
MOZ_ASSERT_UNREACHABLE("Handle the event to dispatch ePointerRawUpdate");
return NS_OK;
}
bool PresShell::EventHandler::UpdateFocusSequenceNumber(
nsIFrame* aFrameForPresShell, uint64_t aEventFocusSequenceNumber) {
uint64_t focusSequenceNumber;
@@ -7602,24 +7485,6 @@ nsresult PresShell::EventHandler::HandleEventUsingCoordinates(
return NS_OK;
}
// If we are trying to dispatch an ePointerRawUpdate but it's not allowed in
// the (maybe retargetted) document, we should not flush the capture state
// below.
if (aGUIEvent->mMessage == eMouseRawUpdate ||
aGUIEvent->mMessage == eTouchRawUpdate) {
EventTargetDataWithCapture eventTargetData =
EventTargetDataWithCapture::QueryEventTargetUsingCoordinates(
*this, aWeakFrameForPresShell,
EventTargetDataWithCapture::Query::PendingState, aGUIEvent);
if (!PointerEventHandler::NeedToDispatchPointerRawUpdate(
eventTargetData.GetDocument())) {
return NS_OK;
}
// Then, we need to recompute the target with processing the pending pointer
// capture. Note that the result may be differnet since `gotpointercapture`
// event listener does something tricky things.
}
EventTargetDataWithCapture eventTargetData =
EventTargetDataWithCapture::QueryEventTargetUsingCoordinates(
*this, aWeakFrameForPresShell,
@@ -7744,12 +7609,6 @@ PresShell::EventHandler::EventTargetDataWithCapture::EventTargetDataWithCapture(
if (GetDocument() && aGUIEvent->mClass == eTouchEventClass) {
PointerLockManager::Unlock("TouchEvent");
}
// XXX If aGUIEvent is eMouseRawUpdate or eTouchRawUpdate and it's
// dispatched by BrowserChild, i.e., the event won't cause ePointerMove
// immediately after ePointerRawUpdate, should we skip fluhsing pending
// animations here? Doing this could cause different animation result while
// the user moves mouse cursor during a long animation whether there is a
// `pointerrawupdate` event listener or not.
aEventHandler.MaybeFlushThrottledStyles(aWeakFrameForPresShell);
// Previously, MaybeFlushThrottledStyles() recomputed the closest ancestor
// frame for view of mPresShell if it's reframed. Therefore, we should keep
@@ -8055,15 +7914,11 @@ bool PresShell::EventHandler::DispatchPrecedingPointerEvent(
aPointerCapturingElement, aGUIEvent, aDontRetargetEvents, aEventStatus,
getter_AddRefs(mouseOrTouchEventTargetContent));
const bool maybeCallerCanHandleEvent =
aGUIEvent->mMessage != eMouseRawUpdate &&
aGUIEvent->mMessage != eTouchRawUpdate;
// If the target frame is alive, the caller should keep handling the event
// unless event target frame is destroyed.
if (weakTargetFrame.IsAlive() && weakFrame.IsAlive()) {
aEventTargetData->UpdateTouchEventTarget(aGUIEvent);
return maybeCallerCanHandleEvent;
return true;
}
presShell->FlushPendingNotifications(FlushType::Layout);
@@ -8101,7 +7956,7 @@ bool PresShell::EventHandler::DispatchPrecedingPointerEvent(
}
aEventTargetData->UpdateTouchEventTarget(aGUIEvent);
return maybeCallerCanHandleEvent;
return true;
}
/**
@@ -8521,16 +8376,6 @@ bool PresShell::EventHandler::MaybeDiscardOrDelayMouseEvent(
MOZ_ASSERT(aFrameToHandleEvent);
MOZ_ASSERT(aGUIEvent);
// We must not need to let suspend listeners know ePointerRawUpdate events.
// And also the delayed events will be dispatched via widget. Therefore,
// ePointerRawUpdate event will be dispatched by PresShell::HandleEvent()
// again.
if (aGUIEvent->mMessage == eMouseRawUpdate ||
aGUIEvent->mMessage == eTouchRawUpdate ||
aGUIEvent->mMessage == ePointerRawUpdate) {
return false;
}
if (!aGUIEvent->IsMouseEventClassOrHasClickRelatedPointerEvent()) {
return false;
}
@@ -9232,11 +9077,6 @@ bool PresShell::EventHandler::PrepareToDispatchEvent(
MaybeHandleKeyboardEventBeforeDispatch(keyboardEvent);
return true;
}
case eMouseRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"eMouseRawUpdate shouldn't be handled as a DOM event");
return false;
case eMouseMove: {
bool allowCapture = EventStateManager::GetActiveEventStateManager() &&
GetPresContext() &&
@@ -9291,10 +9131,6 @@ bool PresShell::EventHandler::PrepareToDispatchEvent(
return mPresShell->mTouchManager.PreHandleEvent(
aEvent, aEventStatus, *aTouchIsNew,
mPresShell->mCurrentEventTarget.mContent);
case eTouchRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"eTouchRawUpdate shouldn't be handled as a DOM event");
return false;
default:
return true;
}
@@ -9336,10 +9172,6 @@ void PresShell::EventHandler::FinalizeHandlingEvent(
// reset the capturing content now that the mouse button is up
PresShell::ReleaseCapturingContent();
break;
case eMouseRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"eMouseRawUpdate shouldn't be handled as a DOM event");
break;
case eMouseMove:
PresShell::AllowMouseCapture(false);
break;
@@ -9369,10 +9201,6 @@ void PresShell::EventHandler::FinalizeHandlingEvent(
mPresShell->mTouchManager.PostHandleEvent(aEvent, aStatus);
break;
}
case eTouchRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"eTouchRawUpdate shouldn't be handled as a DOM event");
break;
default:
break;
}
@@ -9485,10 +9313,6 @@ void PresShell::EventHandler::RecordEventPreparationPerformance(
nsPresContext::InteractionType::ClickInteraction, aEvent->mTimeStamp);
return;
case eMouseRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"eMouseRawUpdate shouldn't be handled as a DOM event");
break;
case eMouseMove:
GetPresContext()->RecordInteractionTime(
nsPresContext::InteractionType::MouseMoveInteraction,
@@ -9669,7 +9493,6 @@ nsresult PresShell::EventHandler::DispatchEventToDOM(
void PresShell::EventHandler::DispatchTouchEventToDOM(
WidgetEvent* aEvent, nsEventStatus* aEventStatus,
nsPresShellEventCB* aEventCB, bool aTouchIsNew) {
MOZ_ASSERT(aEvent->mMessage != eTouchRawUpdate);
// calling preventDefault on touchstart or the first touchmove for a
// point prevents mouse events. calling it on the touchend should
// prevent click dispatching.

View File

@@ -1996,15 +1996,6 @@ class PresShell final : public nsStubDocumentObserver,
// Utility method to restore the root scrollframe state
void RestoreRootScrollPosition();
/**
* Dispatch eMouseRawUpdate or eTouchRawUpdate event if aSourceEvent requires
* a preceding "pointerrawupdate" event and there are some windows which have
* its listener.
*/
MOZ_CAN_RUN_SCRIPT nsresult EnsurePrecedingPointerRawUpdate(
AutoWeakFrame& aWeakFrameForPresShell, const WidgetGUIEvent& aSourceEvent,
bool aDontRetargetEvents);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void MaybeReleaseCapturingContent();
class DelayedEvent {

View File

@@ -303,9 +303,6 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
}
break;
}
case eTouchRawUpdate:
MOZ_ASSERT_UNREACHABLE("eTouchRawUpdate shouldn't be handled as a touch");
break;
case eTouchMove: {
// Check for touches that changed. Mark them add to queue
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
@@ -451,9 +448,6 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
void TouchManager::PostHandleEvent(const WidgetEvent* aEvent,
const nsEventStatus* aStatus) {
switch (aEvent->mMessage) {
case eTouchRawUpdate:
MOZ_ASSERT_UNREACHABLE("eTouchRawUpdate shouldn't be handled as a touch");
break;
case eTouchMove: {
if (sSingleTouchStartTimeStamp.IsNull()) {
break;
@@ -565,8 +559,7 @@ bool TouchManager::ShouldConvertTouchToPointer(const Touch* aTouch,
// We don't want to fire duplicated pointerdown.
return false;
}
case eTouchMove:
case eTouchRawUpdate: {
case eTouchMove: {
return !aTouch->Equals(info.mTouch);
}
default:

View File

@@ -2820,12 +2820,6 @@
value: true
mirror: always
# Whether pointerrawupdate event is enabled or disabled.
- name: dom.event.pointer.rawupdate.enabled
type: bool
value: true
mirror: always
# Whether wheel event target's should be grouped. When enabled, all wheel
# events that occur in a given wheel transaction have the same event target.
- name: dom.event.wheel-event-groups.enabled

View File

@@ -1,4 +1,19 @@
[idlharness.https.window.html]
[Document interface: attribute onpointerrawupdate]
expected: FAIL
[Document interface: document must inherit property "onpointerrawupdate" with the proper type]
expected: FAIL
[Window interface: attribute onpointerrawupdate]
expected: FAIL
[HTMLElement interface: attribute onpointerrawupdate]
expected: FAIL
[Window interface: window must inherit property "onpointerrawupdate" with the proper type]
expected: FAIL
[PointerEvent interface: attribute persistentDeviceId]
expected: FAIL

View File

@@ -0,0 +1,3 @@
[pointerevent_boundary_events_before_pointerrawupdate.https.html]
[Pointer boundary events should be fired before `pointerrawupdate`]
expected: FAIL

View File

@@ -0,0 +1,4 @@
[pointerevent_pointerrawupdate.https.html]
[pointerrawupdate event received]
expected: FAIL

View File

@@ -0,0 +1,3 @@
[pointerevent_pointerrawupdate_after_adoption_from_child.https.html]
[`pointerrawupdate` events should be fired after the element is moved from the parent doc to a child doc]
expected: FAIL

View File

@@ -0,0 +1,3 @@
[pointerevent_pointerrawupdate_after_adoption_from_parent.https.html]
[`pointerrawupdate` events should be fired after the element is moved from a child doc to the parent doc]
expected: FAIL

View File

@@ -0,0 +1,3 @@
[pointerevent_pointerrawupdate_flush_pointercapture.https.html]
[Pointer capture state should be updated before `pointerrawupdate`]
expected: FAIL

View File

@@ -1,3 +1,9 @@
[pointerevent_pointerrawupdate_remove_target.https.html]
["pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its target]
expected: FAIL
["pointermove" and its preceding boundary events should be fired on ancestor if "pointerrawupdate" event listener removes its target parent]
expected: FAIL
["pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its document]
expected: FAIL

View File

@@ -1,8 +1,13 @@
[pointerevent_pointerrawupdate_in_pointerlock.https.html]
max-asserts: 1 # in PointerEventHandler::DispatchPointerFromMouseOrTouch
expected:
if (os == "win") and debug and (processor == "x86_64"): [OK, TIMEOUT]
if (os == "win") and debug and (processor == "x86"): TIMEOUT
if (os == "linux") and debug and fission: [OK, TIMEOUT]
if (os == "linux") and debug and not fission: [OK, ERROR, TIMEOUT]
if (os == "linux") and not debug: [OK, TIMEOUT]
[pointerrawupdate event received]
expected:
if (os == "win") and debug and (processor == "x86_64"): [FAIL, NOTRUN]
if (os == "win") and debug and (processor == "x86"): NOTRUN
if os == "linux": [FAIL, NOTRUN]
FAIL

View File

@@ -454,9 +454,9 @@ class WidgetEvent : public WidgetEventTime {
break;
case ePointerEventClass:
mFlags.mCancelable =
(mMessage != ePointerRawUpdate && mMessage != ePointerEnter &&
mMessage != ePointerLeave && mMessage != ePointerCancel &&
mMessage != ePointerGotCapture && mMessage != ePointerLostCapture);
(mMessage != ePointerEnter && mMessage != ePointerLeave &&
mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
mMessage != ePointerLostCapture);
mFlags.mBubbles =
(mMessage != ePointerEnter && mMessage != ePointerLeave);
break;
@@ -931,12 +931,12 @@ class WidgetEvent : public WidgetEventTime {
case ePointerEventClass:
// All pointer events are composed
mFlags.mComposed =
mMessage == ePointerRawUpdate || mMessage == ePointerMove ||
mMessage == ePointerClick || mMessage == ePointerAuxClick ||
mMessage == eContextMenu || mMessage == ePointerDown ||
mMessage == ePointerUp || mMessage == ePointerCancel ||
mMessage == ePointerOver || mMessage == ePointerOut ||
mMessage == ePointerGotCapture || mMessage == ePointerLostCapture;
mMessage == ePointerMove || mMessage == ePointerUp ||
mMessage == ePointerCancel || mMessage == ePointerOver ||
mMessage == ePointerOut || mMessage == ePointerGotCapture ||
mMessage == ePointerLostCapture;
break;
case eTouchEventClass:
// All touch events are composed
@@ -1011,7 +1011,6 @@ class WidgetEvent : public WidgetEventTime {
aEventTypeArg.EqualsLiteral("pointerout") ||
aEventTypeArg.EqualsLiteral("pointerenter") ||
aEventTypeArg.EqualsLiteral("pointerleave") ||
aEventTypeArg.EqualsLiteral("pointerrawupdate") ||
aEventTypeArg.EqualsLiteral("gotpointercapture") ||
aEventTypeArg.EqualsLiteral("lostpointercapture") ||
// touch events

View File

@@ -93,14 +93,6 @@ NS_EVENT_MESSAGE(eMouseEnter)
NS_EVENT_MESSAGE(eMouseLeave)
NS_EVENT_MESSAGE(eMouseTouchDrag)
NS_EVENT_MESSAGE(eMouseLongTap)
// eMouseRawUpdate is for dispatching ePointerRawUpdate caused by a mouse input.
// When we dispatch ePointerRawUpdate, we need to handle the steps defined by
// the spec in "fire a pointer event" section like the other pointer event.
// The steps are handled by
// PresShell::EventHandler::DispatchPrecedingPointerEvent() and for using it, we
// should dispatch this internal event instead of dispatching ePointerRawUpdate
// directly.
NS_EVENT_MESSAGE(eMouseRawUpdate)
NS_EVENT_MESSAGE(eMouseExploreByTouch)
NS_EVENT_MESSAGE_FIRST_LAST(eMouseEvent, eMouseMove, eMouseExploreByTouch)
@@ -108,13 +100,6 @@ NS_EVENT_MESSAGE(ePointerClick)
NS_EVENT_MESSAGE(ePointerAuxClick)
// Pointer spec events
// NOTE: We handle the steps before dispatching a pointer event which is defined
// by the spec in "fire a pointer event" section in
// PresShell::EventHandler::DispatchPrecedingPointerEvent(). Therefore,
// we should not dispatch ePointer* events with
// `PresShell::EventHandler::HandleEvent` directly. Create a new internal
// message for implementing a new pointer event if the new event is defined as
// dispatched with "fire a pointer event" steps.
NS_EVENT_MESSAGE(ePointerMove)
NS_EVENT_MESSAGE(ePointerUp)
NS_EVENT_MESSAGE(ePointerDown)
@@ -123,7 +108,6 @@ NS_EVENT_MESSAGE(ePointerOut)
NS_EVENT_MESSAGE(ePointerEnter)
NS_EVENT_MESSAGE(ePointerLeave)
NS_EVENT_MESSAGE(ePointerCancel)
NS_EVENT_MESSAGE(ePointerRawUpdate)
NS_EVENT_MESSAGE(ePointerGotCapture)
NS_EVENT_MESSAGE(ePointerLostCapture)
NS_EVENT_MESSAGE_FIRST_LAST(ePointerEvent, ePointerMove, ePointerLostCapture)
@@ -448,14 +432,6 @@ NS_EVENT_MESSAGE(eTouchMove)
NS_EVENT_MESSAGE(eTouchEnd)
NS_EVENT_MESSAGE(eTouchCancel)
NS_EVENT_MESSAGE(eTouchPointerCancel)
// eTouchRawUpdate is for dispatching ePointerRawUpdate caused by a touch.
// When we dispatch ePointerRawUpdate, we need to handle the steps defined by
// the spec in "fire a pointer event" section like the other pointer event.
// The steps are handled by
// PresShell::EventHandler::DispatchPrecedingPointerEvent() and for using it, we
// should dispatch this internal event instead of dispatching ePointerRawUpdate
// directly.
NS_EVENT_MESSAGE(eTouchRawUpdate)
// Pointerlock DOM API
NS_EVENT_MESSAGE(ePointerLockChange)

View File

@@ -43,22 +43,22 @@ class WidgetPointerEventHolder final {
class WidgetPointerHelper {
public:
uint32_t pointerId = 0;
int32_t tiltX = 0;
int32_t tiltY = 0;
int32_t twist = 0;
float tangentialPressure = 0.0f;
bool convertToPointer = true;
// When convertToPointerRawUpdate is set to true, the event or the touch may
// cause ePointerRawUpdate event in PresShell::HandleEvent() if it's requested
// by the web app. This is set to false if the source mouse event or the
// source touch move event is not dispatched immediately by BrowserChild
// because BrowserChild dispatches only eMouseRawUpdate or eTouchRawUpdate to
// dispatch ePointerRawUpdate immediately.
bool convertToPointerRawUpdate = true;
uint32_t pointerId;
int32_t tiltX;
int32_t tiltY;
int32_t twist;
float tangentialPressure;
bool convertToPointer;
RefPtr<WidgetPointerEventHolder> mCoalescedWidgetEvents;
WidgetPointerHelper() = default;
WidgetPointerHelper()
: pointerId(0),
tiltX(0),
tiltY(0),
twist(0),
tangentialPressure(0),
convertToPointer(true) {}
WidgetPointerHelper(uint32_t aPointerId, uint32_t aTiltX, uint32_t aTiltY,
uint32_t aTwist = 0, float aTangentialPressure = 0)
: pointerId(aPointerId),
@@ -108,7 +108,6 @@ class WidgetPointerHelper {
twist = aEvent.twist;
tangentialPressure = aEvent.tangentialPressure;
convertToPointer = aEvent.convertToPointer;
convertToPointerRawUpdate = aEvent.convertToPointerRawUpdate;
if (aCopyCoalescedEvents) {
mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents;
}
@@ -414,13 +413,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase,
* Returns true if the event is a real mouse event. Otherwise, i.e., it's
* a synthesized event by scroll or something, returns false.
*/
[[nodiscard]] bool IsReal() const { return mReason == eReal; }
/**
* Returns true if the event is synthesized for scroll or layout change.
* Do not confuse this with a synthesized event for tests.
*/
[[nodiscard]] bool IsSynthesized() const { return mReason == eSynthesized; }
bool IsReal() const { return mReason == eReal; }
/**
* Returns true if middle click paste is enabled.

View File

@@ -151,23 +151,13 @@ class WidgetTouchEvent final : public WidgetInputEvent {
MOZ_COUNTED_DEFAULT_CTOR(WidgetTouchEvent)
enum class CloneTouches : bool { No, Yes };
WidgetTouchEvent(const WidgetTouchEvent& aOther,
CloneTouches aCloneTouches = CloneTouches::No)
WidgetTouchEvent(const WidgetTouchEvent& aOther)
: WidgetInputEvent(aOther.IsTrusted(), aOther.mMessage, aOther.mWidget,
eTouchEventClass) {
MOZ_COUNT_CTOR(WidgetTouchEvent);
mModifiers = aOther.mModifiers;
mTimeStamp = aOther.mTimeStamp;
if (static_cast<bool>(aCloneTouches)) {
mTouches.SetCapacity(aOther.mTouches.Length());
for (const RefPtr<dom::Touch>& touch : aOther.mTouches) {
RefPtr<dom::Touch> clonedTouch = new dom::Touch(*touch);
mTouches.AppendElement(std::move(clonedTouch));
}
} else {
mTouches.AppendElements(aOther.mTouches);
}
mTouches.AppendElements(aOther.mTouches);
mInputSource = aOther.mInputSource;
mButton = aOther.mButton;
mButtons = aOther.mButtons;
@@ -223,20 +213,6 @@ class WidgetTouchEvent final : public WidgetInputEvent {
mTouches.AppendElements(aEvent.mTouches);
mInputSource = aEvent.mInputSource;
}
void SetConvertToPointerRawUpdate(bool aConvert) {
for (dom::Touch* const touch : mTouches) {
touch->convertToPointerRawUpdate = aConvert;
}
}
[[nodiscard]] bool CanConvertToPointerRawUpdate() const {
for (const dom::Touch* const touch : mTouches) {
if (touch->convertToPointerRawUpdate) {
return true;
}
}
return false;
}
};
} // namespace mozilla

View File

@@ -73,7 +73,6 @@ bool IsPointerEventMessage(EventMessage aMessage) {
case ePointerOut:
case ePointerEnter:
case ePointerLeave:
case ePointerRawUpdate:
case ePointerGotCapture:
case ePointerLostCapture:
case ePointerClick:
@@ -122,7 +121,6 @@ bool IsForbiddenDispatchingToNonElementContent(EventMessage aMessage) {
case ePointerOut:
case ePointerEnter:
case ePointerLeave:
case ePointerRawUpdate:
case ePointerCancel:
case ePointerGotCapture:
case ePointerLostCapture:
@@ -174,12 +172,6 @@ bool IsForbiddenDispatchingToNonElementContent(EventMessage aMessage) {
case eTouchPointerCancel:
return true;
case eMouseRawUpdate:
case eTouchRawUpdate:
MOZ_ASSERT_UNREACHABLE(
"Internal raw update events shouldn't be dispatched to the DOM");
return true;
default:
return false;
}
@@ -390,7 +382,6 @@ bool WidgetEvent::HasMouseEventMessage() const {
case eMouseOut:
case eMouseHitTest:
case eMouseMove:
case eMouseRawUpdate:
return true;
// TODO: Perhaps, we should rename this method.
case ePointerClick:
@@ -538,7 +529,7 @@ bool WidgetEvent::IsTargetedAtFocusedContent() const {
bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
switch (mClass) {
case eMouseEventClass:
if (mMessage == eMouseRawUpdate || mMessage == eMouseTouchDrag) {
if (mMessage == eMouseTouchDrag) {
return false;
}
[[fallthrough]];
@@ -548,7 +539,7 @@ bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
// DOM events.
// Synthesized button up events also do not cause DOM events because they
// do not have a reliable mRefPoint.
return AsMouseEvent()->IsReal();
return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
case eWheelEventClass: {
// wheel event whose all delta values are zero by user pref applied, it
@@ -558,7 +549,7 @@ bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
wheelEvent->mDeltaZ != 0.0;
}
case eTouchEventClass:
return mMessage != eTouchRawUpdate && mMessage != eTouchPointerCancel;
return mMessage != eTouchPointerCancel;
// Following events are handled in EventStateManager, so, we don't need to
// dispatch DOM event for them into the DOM tree.
case eQueryContentEventClass:
@@ -915,7 +906,6 @@ float WidgetMouseEventBase::ComputeMouseButtonPressure() const {
switch (mMessage) {
// This method is designed for mouse events.
case eMouseMove:
case eMouseRawUpdate:
case eMouseUp:
case eMouseDown:
case eMouseEnterIntoWidget:
@@ -944,7 +934,6 @@ float WidgetMouseEventBase::ComputeMouseButtonPressure() const {
case ePointerClick:
case ePointerAuxClick:
case ePointerMove:
case ePointerRawUpdate:
case ePointerUp:
case ePointerDown:
case ePointerCancel:

View File

@@ -1955,7 +1955,6 @@ STATIC_ATOMS = [
Atom("onpointerout", "onpointerout"),
Atom("onpointerenter", "onpointerenter"),
Atom("onpointerleave", "onpointerleave"),
Atom("onpointerrawupdate", "onpointerrawupdate"),
Atom("ongotpointercapture", "ongotpointercapture"),
Atom("onlostpointercapture", "onlostpointercapture"),
# orientation support