part 3: Make OverOutElementsWrapper
restore original mouseover
target if it's removed temporarily
Chromium stores the last "over" event target before dispatching the boundary
events [1][2]. However, Chrome and Safari do not fire mouse boundary events
when the last over target is removed temporarily. Therefore, I think that
they consider whether the target is removed not immediately after removing
the node. Currently, we consider whether we should dispatch mouse boundary
events for the layout/DOM changes with next mouse event or next synthesized
eMouseMove
which is enqueued when the last mouseover
target is removed [3]
(i.e., it's considered at latest next animation frame after removing the
target). Therefore, we can restore the original mouseover
target if it's
reconnected to the DOM again before that. Although the timing of considering
that could be incompatible with the other browsers in strictly speaking, but I
think that this is enough because the new tests pass on Firefox and Chrome and
I don't have any ideas about more time-sensitive test cases.
About pointerover
, we don't need to change the behavior because it's well
defined by the Pointer Events spec and the behavior is compatible between
browsers.
Note that the new test,
mouse_boundary_events_after_reappending_last_over_target.tentative.html
is not
compatible with the expectation of mouse boundary events in
pointerevent_after_target_appended.html
which is in the scope of Interop-2024.
Therefore, there are some new failures of its result (note that the tests were
not passed before D202907 (D202376 is adding the new behavior and it's enabled
by D202907). The new failure results are, we stop dispatching mouseover
and
mouseenter
after mousedown
or mouseup
whose event listener moves its event
target because it's reconnected to different position in same parent immediately
and element under the cursor is not changed by the temporary removal. Safari
behaves same as our new behavior [4][5] and this is consistent with the result
of new tests. Therefore, I think that Chrome should fix it, so I'll file a new
spec issue about this to discuss what's the best.
(Chrome passes most tests in
mouse_boundary_events_after_reappending_last_over_target.tentative.html
.
They fail the cases moving the last mouseover
event target outside the deepest
connected mouseenter
event target but it stays under the cursor because they
don't dispatch mouse boundary events and fails. This means that they won't
dispatch mouseleave
event on the ex-parent of the target. And also they fail
the cases moving the mouseover
event target outside the deepest connected
mouseenter
event target and changing the element under the cursor because
they dispatch mouseout
and mouseleave
on the moved target. Finally, they
fail the case re-appending the target in a next animation after removal because
they dispatch redundant mouseenter
events on all ancestors.)
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/input/mouse_event_manager.cc;l=415;drc=5742c2e870cdd5e453212d92f13a854993cd60bf
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/input/mouse_event_manager.cc;l=451;drc=5742c2e870cdd5e453212d92f13a854993cd60bf
- https://searchfox.org/mozilla-central/rev/294e1fbdcc9ca0c328c372392e03bb49df4ee77e/dom/events/EventStateManager.cpp#6273-6276
- https://wpt.fyi/results/pointerevents/pointerevent_after_target_appended.html%3Fmouse?run_id=6221043298992128&run_id=5090975864586240&run_id=5106342989135872&run_id=5101843876675584
- https://wpt.fyi/results/pointerevents/pointerevent_after_target_appended.html%3Ftouch?run_id=6221043298992128&run_id=5090975864586240&run_id=5106342989135872&run_id=5101843876675584
Differential Revision: https://phabricator.services.mozilla.com/D205536
bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1888018
gecko-commit: e7dea7836421319eb08c44674407ac0c85e12547
gecko-reviewers: smaug