Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made mouseover/out/enter/leave event firing independent of corresponding PEs #56

Merged
merged 7 commits into from May 25, 2016

Conversation

Projects
None yet
3 participants
@mustaqahmed
Copy link
Contributor

commented Apr 28, 2016

The spec currently suggests that compatibility mouse transition events (i.e. mouseover, mouseout, mouseenter and mouseleave) should be fired right after firing the corresponding PointerEvents, implying a 1:1 correspondence between the PointerEvents vs the compatibility MouseEvents. This 1:1 correspondence breaks the consistency of MouseEvent sequence itself when two or more primary pointers (of different types) are active at the same time. For example, mouseover events can be sent to two different targets without a mouseout in-between, which can possibly break the UIs based on legacy MouseEvents, e.g., by opening two menu items at the same time. (Issue #35.)

This patch fixes the problem by omitting the 1:1 correspondence altogether. More precisely, it suggests to fire the compatibility mouse transition events right before a pointerdown/up/move event.

In addition, this patch modifies the default actions of pointerover, pointerout, pointerenter and pointerleave events to "none". This keeps the spec effectively unchanged since the original default action was "the default action of corresponding MouseEvent" but the UI Event Spec defines those default actions as "none".

@@ -450,14 +450,14 @@
<td>Sync</td>
<td>Yes</td>
<td>Yes</td>
<td>Varies: when the pointer is primary, all default actions of <code>mouseover</code></td>
<td>None</td>
</tr>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

Please call out these changes in the description also (since they're only tangentially related). I.e. that since UI Events says these mouse events have no default action, we can just say the same for the pointer events.

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

Done.

index.html Outdated
<h2 id="tracking-legacy-mouse-pos">Tracking the effective position of legacy mouse pointer</h2>
<div>
<p>While only <a href="#the-primary-pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own stream of compatibility mouse events. Since all these compatibility events would appear to a legacy mouse-specific code to be coming from a single mouse hardware, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [<cite><a class="bibref" href="#bib-DOM-LEVEL-3-EVENTS">DOM-LEVEL-3-EVENTS</a></cite>]. Users agents MAY guarantee this by maintaining the <dfn id="dfn-legacy-mouse-pos">effective position of legacy mouse pointer</dfn> in the document as follows.</p>
<p>Right before firing a <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event, the user agent MAY run the following steps:</p>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

The way to officially reference another spec normatively is [[!DOM-LEVEL-3-EVENTS]] - see the ReSpec guide.

However "DOM-LEVEL-3" is the old name for that spec and so kinda confusing now. Would you mind updating all the various references to it to "UIEVENTS" instead? Probably best to do that in a separate CL to avoid polluting this one if you don't mind.

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

Fixed my links. Filed #60 for the reference label change.

index.html Outdated
<p>While only <a href="#the-primary-pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own stream of compatibility mouse events. Since all these compatibility events would appear to a legacy mouse-specific code to be coming from a single mouse hardware, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [<cite><a class="bibref" href="#bib-DOM-LEVEL-3-EVENTS">DOM-LEVEL-3-EVENTS</a></cite>]. Users agents MAY guarantee this by maintaining the <dfn id="dfn-legacy-mouse-pos">effective position of legacy mouse pointer</dfn> in the document as follows.</p>
<p>Right before firing a <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event, the user agent MAY run the following steps:</p>
<ol>
<li>Let <code>T</code> be the target of the event above.</li>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

nit: "target of the pointer event being dispatched"?

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

Done.

index.html Outdated
@@ -819,20 +819,26 @@
</section>
</div>
<section>
<h2 id="tracking-legacy-mouse-pos">Tracking the effective position of legacy mouse pointer</h2>
<div>
<p>While only <a href="#the-primary-pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own stream of compatibility mouse events. Since all these compatibility events would appear to a legacy mouse-specific code to be coming from a single mouse hardware, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [<cite><a class="bibref" href="#bib-DOM-LEVEL-3-EVENTS">DOM-LEVEL-3-EVENTS</a></cite>]. Users agents MAY guarantee this by maintaining the <dfn id="dfn-legacy-mouse-pos">effective position of legacy mouse pointer</dfn> in the document as follows.</p>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

Please use ReSpec's definition and linking support rather than writing your own a href links.

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

We should probably be using "SHOULD" instead of "MAY" here. The section is optional, but if it's being used then it should be followed exactly.

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

nit: s/"a legacy mouse-specific code"/"MouseEvent handling code"

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

nit: s/"a single mouse hardware"/"a single mouse device"

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

All done. Used "MouseEvent code" instead of "MouseEvent handling code".

index.html Outdated
@@ -819,20 +819,26 @@
</section>
</div>
<section>
<h2 id="tracking-legacy-mouse-pos">Tracking the effective position of legacy mouse pointer</h2>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

nit: "of the legacy"

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

Done.

index.html Outdated
<p>Right before firing a <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event, the user agent MAY run the following steps:</p>
<ol>
<li>Let <code>T</code> be the target of the event above.</li>
<li>If <code>T</code> is equal to current <a href="#dfn-legacy-mouse-pos" class="internalDFN">effective legacy mouse pointer position</a>, terminate these steps.</li>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

This algorithm doesn't define what happens at the beginning (when the legacy-mouse-pos has not yet been defined). I'm not sure exactly what do do about this - UI Events certainly doesn't seem very precise on this point to me. Thoughts?

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

I was originally planning to say that it starts with a NULL value, meaning outside the document/window. This would be helpful to handle the pointer exit case too, by adding this:
"If event to be fired is a pointerleave at document/window, let T be NULL",
then add a few lines below to handle the NULL case.

Finally I thought: may be it is an implementation details and/or understood concept.

Do you find such details helpful?

This comment has been minimized.

Copy link
@RByers

RByers May 3, 2016

Contributor

The way I see it there are two styles of spec writing - algorithm heavy and prose heavy. The WhatWG DOM spec is algorithm heavy - very precisely defines what is supposed to happen but can be harder to follow. The UI Events spec is prose heavy - you get the basic idea pretty easily but there can be ambiguity in the edge cases (though if that's resolved by precise tests then it should be fine IMHO). I like that you're trying to define an algorithm here, but it's hard to do well when you're referring to stuff that's defined in a more handy-wavy prose style elsewhere.

So if we want to be consistent with the UI Event spec treatment, we could just remove the algorithm and definition and say (somewhat vaguely) that the transition events follow from the UI Events definition corresponding to a single mouse being moved around.

Or if you'd like to try to make it more precise, then yes I think you need some text around the default value, and unsetting it on pointerleave from the window etc. That's a really going point actually - as written now it looks like it's illegal to send a mouseleave event when the mouse leaves the window (because there is no corresponding pointermove sent). If you want to keep the algorithm style you'll need to expand the usage of this section to handle that special case. Note that specs usually use the simpler concept of "is set" and "unset" rather than using a programming value like "NULL" (these aren't real variables afterall).

This comment has been minimized.

Copy link
@RByers

RByers May 3, 2016

Contributor

Oh and are you planning on writing some web-platform-tests for this? I think that's the most valuable part to really making what you're describing concrete. Eg. will we test anything about the interleaving of pointer and mouse transition events, or leave some flexibility there? Eg. when entering a new element, are both of these legal event orderings or do you intend to require the latter?:

  1. pointerover, mouseover, pointerenter, mouseenter, pointermove, mousemove
  2. pointerover, pointerenter, mouseover, mouseenter, pointermove, mousemove
index.html Outdated
<ol>
<li>Let <code>T</code> be the target of the event above.</li>
<li>If <code>T</code> is equal to current <a href="#dfn-legacy-mouse-pos" class="internalDFN">effective legacy mouse pointer position</a>, terminate these steps.</li>
<li>Dispatch the same sequence of <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code> events that would be dispatched as per [<cite><a class="bibref" href="#bib-DOM-LEVEL-3-EVENTS">DOM-LEVEL-3-EVENTS</a></cite>] if a (legacy) mouse pointer had moved from current <a href="#dfn-legacy-mouse-pos" class="internalDFN">effective legacy mouse pointer position</a> directly to <code>T</code>.</li>

This comment has been minimized.

Copy link
@RByers

RByers Apr 29, 2016

Contributor

nit: maybe rather than "dispatch the same sequence ... that would be dispatched ..." we can simplify this to: "dispatch ... events as per ... for a mouse moving moving from the legacy mouse position to T"?

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed Apr 29, 2016

Author Contributor

Done.

@RByers

This comment has been minimized.

Copy link
Contributor

commented Apr 29, 2016

The basic approach here seems good to me. @teddink any concerns? I think this is closer (but still not exactly) to what Edge is doing today and makes more conceptual sense IMHO.

@mustaqahmed mustaqahmed changed the title Made mouseover/out/enter/leave event firing independent of corresponding PEs. Made mouseover/out/enter/leave event firing independent of corresponding PEs Apr 29, 2016

@mustaqahmed mustaqahmed force-pushed the mustaqahmed:gh-pages branch from ed0f096 to 82c2193 Apr 29, 2016

index.html Outdated
@@ -819,20 +819,26 @@
</section>
</div>
<section>
<h2 id="tracking-legacy-mouse-pos">Tracking the effective position of the legacy mouse pointer</h2>
<div>
<p>While only <a href="#the-primary-pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own stream of compatibility mouse events. Since all these compatibility events would appear to MouseEvent code to be coming from a single mouse device, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [[!DOM-LEVEL-3-EVENTS]]. Users agents SHOULD guarantee this by maintaining the <dfn id="dfn-legacy-mouse-pos">effective position of the legacy mouse pointer</dfn> in the document as follows.</p>

This comment has been minimized.

Copy link
@RByers

RByers May 3, 2016

Contributor

sorry another for "each producing its own stream of compatibility mouse events" I'd suggest removing the "stream of". "own stream" sounds like they're really independent streams. The whole point of this section is to say that, although each device produces compat mouse events, it's a single logical stream.

This comment has been minimized.

Copy link
@RByers

RByers May 3, 2016

Contributor

Again you should avoid use any hrefs in your internal <a> links. ReSpec handles this automatically for you. For example see the various other places in the spec which do simply <a>primary pointer</a>. When necessary you can use data-lt on the a tag to specify a definition name that's different from the anchor content (eg. see examples like <a data-lt="Chorded Button Interactions">). I don't know why this is really any better than using <a href=...> but we should at least be consistent across the spec.

index.html Outdated
<h2 id="tracking-legacy-mouse-pos">Tracking the effective position of the legacy mouse pointer</h2>
<div>
<p>While only <a href="#the-primary-pointer">primary pointers</a> can produce compatibility mouse events, <a href="#multiple-primary-pointers">multiple primary pointers</a> can be active simultaneously, each producing its own stream of compatibility mouse events. Since all these compatibility events would appear to MouseEvent code to be coming from a single mouse device, user agents are encouraged to guarantee that the compatibility mouse events are consistent from a single device perspective. For mouse transition events (i.e., <code>mouseover</code>, <code>mouseout</code>, <code>mouseenter</code> and <code>mouseleave</code>), this means the entry/exit state for every event target is valid as implied by [[!DOM-LEVEL-3-EVENTS]]. Users agents SHOULD guarantee this by maintaining the <dfn id="dfn-legacy-mouse-pos">effective position of the legacy mouse pointer</dfn> in the document as follows.</p>
<p>Right before firing a <code>pointerdown</code>, <code>pointerup</code> or <code>pointermove</code> event, the user agent MAY run the following steps:</p>

This comment has been minimized.

Copy link
@RByers

RByers May 3, 2016

Contributor

s/MAY/SHOULD/

This comment has been minimized.

Copy link
@mustaqahmed

mustaqahmed May 3, 2016

Author Contributor

All done.

@mustaqahmed mustaqahmed force-pushed the mustaqahmed:gh-pages branch 9 times, most recently from 4b18ac0 to 813d1af May 3, 2016

index.html Outdated
@@ -374,7 +374,7 @@
<dt>primary pen input</dt><dd>A pointer representing pen input is considered the <i>primary pen input</i> if its <code>pointerdown</code> event was dispatched when no other active pointers representing pen input existed.</dd>
</dl>
<div class="note" id="multiple-primary-pointers">When two or more pointer device types are being used concurrently, multiple pointers (one for each <code>pointerType</code>) are considered primary. For example, a touch contact and a mouse cursor moved simultaneously will produce pointers that are both considered primary.</div>
<div class="note">In the case where there are multiple <a href="#the-primary-pointer">primary pointers</a>,
<div class="note">In the case where there are multiple <a data-lt="The Primary Pointer">primary pointers</a>,

This comment has been minimized.

Copy link
@RByers

RByers May 4, 2016

Contributor

Oh, it looks like the uses of <a>primary pointer</a> I was looking at are actually broken! I think that's just because <dfn>The Primary Pointer</dfn> should be The <dfn>Primary Pointer</dfn>. If you change that, then I think you can avoid the data-lt here and elsewhere.

@RByers

This comment has been minimized.

Copy link
Contributor

commented May 4, 2016

On the call we agreed this was nearly good to merge, just blocked on some editorial feedback from @patrickhlauke.

@patrickhlauke patrickhlauke self-assigned this May 4, 2016

@patrickhlauke

This comment has been minimized.

Copy link
Member

commented May 5, 2016

wondering if the entire paragraph

The compatibility mapping with mouse events are an optional feature of this specification. User agents are encouraged to support the feature for best compatibility with existing legacy content. User agents that do not support compatibility mouse events are still encouraged to support the click and contextmenu events (see the note below).

should be moved to the very start of the section, right after the "Compatibility Mapping with Mouse Events" heading. this would make it a bit more immediately clear right from the start when a reader delves into the section that this is optional, rather than burying the lede in between two notes.

Perhaps even wrapped as a note (though this would make it non-normative?) or some other form of styling change/block-out if available.

@mustaqahmed

This comment has been minimized.

Copy link
Contributor Author

commented May 6, 2016

Done.

@patrickhlauke

This comment has been minimized.

Copy link
Member

commented May 9, 2016

Sorry, you're right @mustaqahmed ... your update slipped me by.

At the risk of sounding nitpicky, I'd say that now the rationale for why there's even compatibility mapping is a bit buried. I'd suggest ripping out the first paragraph or the rationale and grafting it right at the start, so something like:

<h1><dfn lt="compatibility mouse events">Compatibility Mapping with Mouse Events</dfn></h1>
<p>The vast majority of web content existing today codes only to Mouse Events. The following describes an algorithm for how a user agent MAY map generic pointer input to mouse events for compatibility with this content. The compatibility mapping with mouse events are an OPTIONAL...

and then leaving the rest as you have it.

@mustaqahmed mustaqahmed force-pushed the mustaqahmed:gh-pages branch from 22c482e to 47318c1 May 10, 2016

@mustaqahmed

This comment has been minimized.

Copy link
Contributor Author

commented May 10, 2016

ptal. Thanks for the suggestion, the rationale is clearer now.

@patrickhlauke

This comment has been minimized.

Copy link
Member

commented May 10, 2016

LGTM (once merge conflicts are resolved)

@patrickhlauke patrickhlauke removed their assignment May 10, 2016

@mustaqahmed

This comment has been minimized.

Copy link
Contributor Author

commented May 10, 2016

Thanks Patrick. I will resolve the merge conflict after adding the boundary condition handling (see @RByers's comments on May 3).

@mustaqahmed mustaqahmed force-pushed the mustaqahmed:gh-pages branch 2 times, most recently from e1428ae to 7e7cb4e May 17, 2016

@mustaqahmed

This comment has been minimized.

Copy link
Contributor Author

commented May 17, 2016

@RByers, I have updated the algorithm in Sec11.1 to handle unset values correctly.

mustaqahmed added some commits Apr 27, 2016

Updated compatibility mouse transition event firing.
The spec currently suggests that compatibility mouse transition
events (i.e. mouseover, mouseout, mouseenter and mouseleave) should be
fired right after firing the corresponding PointerEvents, implying a 1:1
correspondence between the PointerEvents vs the compatibility
MouseEvents. This 1:1 correspondence breaks the consistency of
MouseEvent sequence itself when two or more primary pointers (of
different types) are active at the same time. For example, mouseover
events can be sent to two different targets without a mouseout
in-between, which can possibly break the UIs based on legacy
MouseEvents, e.g., by opening two menu items at the same time. (Issue

This patch fixes the problem by omitting the 1:1 correspondence
altogether. More precisely, it suggests to fire the compatibility mouse
transition events right before a pointerdown/up/move event.

In addition, this patch modifies the default actions of pointerover,
pointerout, pointerenter and pointerleave events to "none". This keeps
the spec effectively unchanged since the original default action was
"the default action of corresponding MouseEvent" but the UI Event Spec
defines those default actions as "none".

@mustaqahmed mustaqahmed force-pushed the mustaqahmed:gh-pages branch from 7e7cb4e to 3dc8ae4 May 17, 2016

@RByers

This comment has been minimized.

Copy link
Contributor

commented May 25, 2016

On today's call @teddink said it was their intention to have Edge's behavior match this PR but it'll take them some time to try coding it up and understand the full impact in practice.

@RByers

This comment has been minimized.

Copy link
Contributor

commented May 25, 2016

Sorry for the delay (fell off my notifications list somehow), looks good to me. As discussed in the call today, let's merge (we can always continue to tweak the details as needed of course).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.