Closed Bug 2018625 Opened 6 months ago Closed 10 days ago

touchmove is frequently fired twice with the exact same coordinates

Categories

(Core :: DOM: Events, defect)

defect

Tracking

()

RESOLVED FIXED
157 Branch
Tracking Status
firefox157 --- fixed

People

(Reporter: saschanaz, Assigned: hiro)

References

Details

(Keywords: webcompat:platform-bug, Whiteboard: [tracked-in:FFXP-3766], [wptsync upstream])

User Story

user-impact-score:680

Attachments

(3 files)

Attached file 1953164.html β€”
  1. Open the attachment with a touch capable display
  2. Try pinch-to-zoom
  3. See the reported distance

Expected: No duplicated report for the same distance
Actual: It very frequently happens for most of touchmove

Blocks: 2007555
Severity: -- → S3

I experienced the similar thing with WM_MOUSEMOVE on Windows when a pen device is connected. To save the IPC cost, I added a check into the widget/windows/nsWindow,.cpp. Perhaps, it's a good way to do the similar thing in APZC before sending the event to another process?

(Can see this on Windows and Android)

OS: Unspecified → All
Hardware: Unspecified → All
User Story: (updated)
User Story: (updated)

I wonder this is about subpixel coordinates all rounded πŸ€”

Whiteboard: [tracked-in:FFXP-3766]

Though I've identified that the multiple touchmove events come from this loop in EventHandler::DispatchTouchEventToDOM, I've struggled with figuring out a way how we can avoid the multiple events.

I am moderately sure that filtering out the same target event is the right approach since since that's how Chrome handles the case.

That's being said, it works for touchmove events, but it regresses a couple of tests checking touchend events, test_mouse_events_aftertouchend.html for example.

For touchend events, there's a complexity/divergence:

  1. On android platforms multiple touchends at the same time never happen this code supposes it
  2. Our EventUtils can generate mutiple touchends at the same time

There are some caveats:

  1. Chrome never generates multiple touchends at the same time either in their implementation or in synthesizing events
  2. Our Windows implementation seems to generate multiple touchends
  3. Our native touch event synthesizing function, sendNativeTouchPoint can NOT generate multiple touchend events at the same time since it needs a pointer id

Note that the WebDriver's spec is supposed to generate multiple touchend events at the same time: See https://w3c.github.io/webdriver/#example-11

I was about opening a new spec issue on https://github.com/w3c/touch-events/issues to clarify the multiple touch events behavior but the repo has been closed since 2024. :/

Anyway, I am going to align our behavior with other browsers.

The Actions API divides time into ticks, and the actions of every input source
within one tick happen at the same moment: the remote end "will dispatch the
first action of each source together, then the second actions together, and
lastly, the final actions together" (https://w3c.github.io/webdriver/#actions,
example 11).

Touch Events makes that observable without measuring any timing, because
changedTouches is defined per moment rather than per event target. Two touch
pointers released from different elements in one tick produce one touchend per
target either way, so the number of events says nothing; what distinguishes a
simultaneous release is that both events report both removed touch points and
an empty touches list.

Gecko passes. Chrome 153.0.8010.0 reports one changed touch point per event
and, in the first of the two events, a touches list that still contains the
other finger, i.e. a state that cannot exist if the two releases happened at
the same moment.

The events are compared target-sorted because the order in which a user agent
dispatches the events for the several targets of one moment is not defined.

Assignee: nobody → hikezoe.birchill
Status: NEW → ASSIGNED

PresShell::EventHandler::DispatchTouchEventToDOM() loops over every changed
touch point and dispatches a separate DOM event for each one. When more than
one touch point changes in a single widget event -- which happens constantly
while pinching -- the page therefore receives several touchmove events in a
row carrying identical touches and changedTouches lists, since both lists are
derived from the full touch list of the widget event.

Dispatch at most one event per distinct target instead. Both Blink and WebKit
do the same, collecting the targets of the changed touch points into a set and
dispatching one TouchEvent per entry, so this follows them.

test_mouse_events_after_touchend.html and mouseevents-after-touchend.tentative.html
released two touch points on the same target at once and expected two touchend
events, so they now expect the single touchend that carries both of them. For
the latter that is also what the WebDriver actions it performs should produce:
actions belonging to one tick happen at the same moment
(https://w3c.github.io/webdriver/#actions, example 11), so the two touch points
are removed at the same moment. The test reports changedTouches and touches now
so that a mismatch says which behaviour a browser has rather than only that the
number of events differs.

multi-touch-interactions.html gains two subtests and loses one. The one that
starts failing hits the same assertion that already fails for touchend #1, that
the previously received targetTouches for the target is not empty, so it is a
pre-existing problem now reached for a second target rather than a new one.

Pushed by hikezoe.birchill@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/9c99c20ed4a6 https://hg.mozilla.org/integration/autoland/rev/6849bb4ae5cd Add a wdspec test for touch pointers released in a single tick. r=whimboo https://github.com/mozilla-firefox/firefox/commit/83fc5601a797 https://hg.mozilla.org/integration/autoland/rev/6817e1b29dd4 Dispatch one touch event per distinct target rather than one per changed touch point. r=edgar
Pushed by imoraru@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/686599be10a4 https://hg.mozilla.org/integration/autoland/rev/f6a4445d7786 Revert "Bug 2018625 - Dispatch one touch event per distinct target rather than one per changed touch point. r=edgar" for causing bc assertion failures on MouseEvent.cpp.

Revert for causing bc assertion failures on MouseEvent.cpp.

Flags: needinfo?(hikezoe.birchill)
Pushed by imoraru@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/9e431c392f17 https://hg.mozilla.org/integration/autoland/rev/d40928b676a9 Add a wdspec test for touch pointers released in a single tick. r=whimboo https://github.com/mozilla-firefox/firefox/commit/b5c49ed2300f https://hg.mozilla.org/integration/autoland/rev/c03d3fc66992 Dispatch one touch event per distinct target rather than one per changed touch point. r=edgar

This was re-landed. Sorry for any inconvenience caused.

Flags: needinfo?(hikezoe.birchill)
Status: ASSIGNED → RESOLVED
Closed: 10 days ago
Resolution: --- → FIXED
Target Milestone: --- → 157 Branch

Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/62319 for changes under testing/web-platform/tests

Whiteboard: [tracked-in:FFXP-3766] → [tracked-in:FFXP-3766], [wptsync upstream]

Upstream PR merged by moz-wptsync-bot

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: