Re: [pointerevents] Clarify `pointerleave` and `pointerout` events when first pointer move after removing an element under the pointer (#477)

> > I worked on fixing the failure in Firefox of `pointerevent_after_target_removed.html`. However, its expectation does not make sense. See [web-platform-tests/interop#380](https://github.com/web-platform-tests/interop/issues/380) for the detail.
> 
> Hmm, I added this test to match the expectation in a user reported [Chrome bug](https://crbug.com/1147998). I haven't looked into all the details you mentioned above, but I can see that `pointerover/out` events were not mentioned in the Chrome bug, so I need to check if I accidentally made the test an "overfit"!

The test expects that same kind of events are dispatched with same event order between mouse events and pointer events. 

Historically, `mouseout` and `mouseleave` **are fired** when the element under the mouse cursor is removed/moved. This is [defined as](https://w3c.github.io/uievents/#event-type-mouseout):
> A [user agent](https://w3c.github.io/uievents/#user-agent) MUST dispatch this event when a pointing device is moved off of the boundaries of an element **or when the element is moved to be no longer underneath the primary pointing device**.

On the other hand, `pointerout` and `poinerleave` **does not have** the similar [definition](https://w3c.github.io/pointerevents/#the-pointerout-event) and [this issue](https://github.com/w3c/pointerevents/issues/457) clearly indicates that browsers should not dispatch the events until the pointer is moved.

I.e., they are fired in the different rules, but the test expects same result between mouse events and pointer events.

> > Some definitions indicate that `pointerleave`, `pointerout`, `pointerenter` and `pointerover` should not be fired immediately (without a pointer move) when an element under the pointer is removed by a DOM API or hidden/moved by a style change. Then, web apps may want to listen to `pointerleave` and `pointerout` at next pointer move to clear something set at `pointerenter` or `pointerover`.
> > The spec does **not** disallow to dispatch `pointerout` on removed element (which is the last `pointerover`'ed element). Safari does that, and it seems reasonable.
> 
> After the element is removed from DOM, my quick read of DOM event dispatch [algorithm](https://dom.spec.whatwg.org/#concept-event-dispatch) suggests that the algorithm shouldn't do anything at least because `event.eventPhase` becomes undefined in that case. The algorithm is a bit complicated, so please correct me if I missed anything here (which is very likely).

I think that it's fine to dispatch DOM events in a document fragment. An orphan node can be treated as the root element of a document fragment. Then, event phase can be set as same as when the node is in the owner document. (I.e., if browsers dispatch a DOM event on an orphan node, only the target phase will appear.)

> One question is: does WebKit dispatch the `pointerout` event right before the element is removed (and before any further physical movement of the pointer)?

According to the test result ([only `pointerenter` is fired on the (ex-)parent](pointerenter)), Safari dispatches `pointerout` after the node is removed (and probably at moving the pointer).

> Chrome [does not](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/blink/renderer/core/input/pointer_event_manager.cc;drc=a742c65cc620d2b7b262b5514540ebdb510a7121;l=291) store all elements, instead keeps track of the last known "element under pointer" then infers about exited/enter elements using the [common ancestor](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/blink/renderer/core/input/boundary_event_dispatcher.cc;drc=a742c65cc620d2b7b262b5514540ebdb510a7121;l=58) of previous vs current "element under pointer" in the current DOM. The big comment in the common ancestor code implies it's a legacy Chrome behavior to "match Firefox and IE".

Firefox does similar thing. Firefox stores both elements under the cursor which are targeted by `mouseover` and `pointerover` and compute ancestors to dispatch `*leave` events at dispatch. Therefore, once the DOM tree is changed from `*enter` events, elements may be targeted only by `*leave` or `*enter`.

I think that Chrome dispatches `pointerout` and `pointerover` immediately if the element under the pointer is removed. Therefore, reset the storage and store new elements under the pointer within the new DOM tree.

-- 
GitHub Notification of comment by masayuki-nakano
Please view or discuss this issue at https://github.com/w3c/pointerevents/issues/477#issuecomment-1650823681 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 26 July 2023 01:22:21 UTC