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

Introduce pointerrawupdate to address the high frequency usecases #260

Merged
merged 10 commits into from
Apr 11, 2019

Conversation

NavidZ
Copy link
Member

@NavidZ NavidZ commented Jul 4, 2018

Fixes #214

@NavidZ
Copy link
Member Author

NavidZ commented Jul 10, 2018

@smaug---- what do you think of pointerrawmove to address the low latency usecases? I tried to remove the overhead of hittesting on every one of those events by restricting it to only capturing mode.
I wanted to start the implementation in Chrome and wanted to know what you think of it first.

@smaug----
Copy link
Contributor

(discussion about features shouldn't happen in PRs, but in issues)

extension.html Outdated
<code>pointerrawmove</code> will get fired as soon as an attribute is changed
and as frequent as the javascript can handle the events.
Because of that the target of <code>pointerrawmove</code> events might be different from the <code>pointermove</code> events
due to the fact that <code>pointermove</code> events are being sent once every frame and the final position of the even
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pointermove isn't defined to be sent once every frame.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This part is not yet specced. Not sure how to get around it. More on it in the other comment.

extension.html Outdated
Because of that the target of <code>pointerrawmove</code> events might be different from the <code>pointermove</code> events
due to the fact that <code>pointermove</code> events are being sent once every frame and the final position of the even
which is used for finding the target could be different from its coalesced events.
Note that if the javascript handlers are slow, <code>pointerrawmove</code> events can also get coalesced.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, this makes the behavior from specification rather odd. pointermove isn't defined to be only once per frame and then pointerrawmove may get coalesced too, so in practice the events could be exactly the same.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was that pointermove will get delayed at the very least until right before rAF. But pointerrawmove will not have that delay at all. However both of these events might get unlimited delay and get coalesced during that time based on the how much the javascript code keeps the code busy. Does this at least make the intention for this event clear and how it is different from pointermove?

Now regarding how to spec it, the problem is that rAF related stuff is not fully specced yet and I believe I need to change HTML spec for this and reference https://html.spec.whatwg.org/#event-loop-processing-model here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand what you try to spec, it is just a tad hard to spec when pointermove isn't spec'ed to work exactly how it works in Blink (nor in Gecko). Pointerevents spec says "A user agent MUST fire a pointer event named pointermove when a pointer changes coordinates." That actually kind of prevents firing only at rAF time. So I guess we should fix that too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to explain it better and also added a new pointermove description. Let me know what you think.

@patrickhlauke
Copy link
Member

@smaug---- there's no rush on this as it targets the extension/possible v3 stuff, but...is this PR now looking better? can it be merged?

@NavidZ
Copy link
Member Author

NavidZ commented Oct 2, 2018

@smaug---- let me know if the latest of this change captures what you had in mind.

<h2>Extensions to the Pointer Event types</h2>
<p>Below is the new event type that is added to the <a href="https://w3c.github.io/pointerevents/index.html#pointer-event-types">existing pointer event types</a>.</p>
<section>
<h3>The <dfn><code>pointermove</code> event</dfn></h3>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the text. "Below is the new event type..." "the pointermove". pointermove sure isn't a new type.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

extension.html Outdated
Additionally one <code>pointermove</code> MUST be fired when pointer changes coordinates, pressure, tangential pressure, tilt, twist, or
contact geometry (e.g. <code>width</code> and <code>height</code>) and the circumstances produce no other pointer events defined in this specification.
This <code>pointermove</code> that is not caused by button state change MUST be fired only once right before firing an event caused by button state change or
<a href="https://html.spec.whatwg.org/#event-loop-processing-model">animation frame callbacks</a>. If there are mutliple changes to these attributes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutliple

extension.html Outdated
<p>A user agent MUST <a href="https://w3c.github.io/pointerevents/index.html#firing-events-using-the-pointerevent-interface">fire a pointer event</a>
named <code>pointerrawmove</code> when a pointing device attribute
(i.e. button state, coordinates, pressure, tangential pressure, tilt, twist, or contact geometry) is changed.
As oppose to <code>pointermove</code> which could be delayed until an animation frame for changes in these attributes,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this talks about "could", yet the text above uses "MUST be fired only once"

extension.html Outdated
and as frequent as the javascript can handle the events.
Because of that the target of <code>pointerrawmove</code> events might be different from the <code>pointermove</code> events
due to the fact that <code>pointermove</code> events are being coalesced and the final position of the event
which is used for finding the target could be different from its coalesced events.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to explain how coalesced events are pointerrawmove differ. For example, other than .target are the properties the same?

extension.html Outdated
@@ -90,7 +121,7 @@ <h2>Extensions to the <code>PointerEvent</code> interface</h2>
The dispatched event's attributes will be initalized in a way that is best representative of all the coalesced events.
For example its <a href="https://www.w3.org/TR/pointerlock/#widl-MouseEvent-movementX">movementX</a> and <a href="https://www.w3.org/TR/pointerlock/#widl-MouseEvent-movementY">movementY</a> ([[!POINTERLOCK]]) COULD be the sum of those of all the coalesced events.
None of the events in the sequence will have (nested) coalesced events, so <code>getCoalescedEvents</code> returns an empty sequence for them.
This API always returns at least one coalesced event for <code>pointermove</code> events and an empty list for other types of <code>PointerEvents</code>.</p>
This API always returns at least one coalesced event for <code>pointermove</code> and <code>pointerrawmove</code> events and an empty list for other types of <code>PointerEvents</code>.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need this for pointerrawmove?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the same question would also hold for a pointermove that only has one coalesced event. Because in that case pointermove itself is that coalesced events. I believe the answer is that both pointerrawmove and pointermove may get coalesced. So in javascript code it is easier to always handle coalesced events of these events (if they care about that precision) instead of a check for the size of the coalesced events and if it is 0 then use the actual event itself. That is the only reason I can think of. What do you think? Is this way more ergonomic and easy to use (like the sample drawing code later in this doc)?

extension.html Outdated
@@ -114,7 +145,7 @@ <h2>Extensions to the <code>PointerEvent</code> interface</h2>

<section>
<h2>Timing of coalesced event firing</h2>
<p>Coalescing events only happens for <code>pointermove</code> events. All the coalesced events should be fired before the next frame or before any <code>pointerup</code>, <code>pointerdown</code>, <code>pointercancel</code> events. Note that user agents don't need to hit-test all the coalesced events as none of them will have null targets.</p>
<p>Coalescing events only happens for <code>pointermove</code> events. All the coalesced events should be fired before the next frame or before any <code>pointerup</code>, <code>pointerdown</code>, <code>pointercancel</code> events. Note that user agents don't need to hit-test all the coalesced events as all of them will have the same target as the dispatched event.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... especially when this talks about coalescing happening for pointermove events only.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. I forgot to update this. Particularly I already talked about the dispatch time of these coalesced events before. I removed that sentence from this paragraph.

@NavidZ
Copy link
Member Author

NavidZ commented Jan 2, 2019

@smaug---- could you take a look at this one and see whether I addressed your concerns?

extension.html Outdated
Because of that the <code>target</code> of <code>pointerrawmove</code> events might be different from the <code>pointermove</code> events
due to the fact that <code>pointermove</code> events are being coalesced and the final position of the event
which is used for finding the <code>target</code> could be different from its coalesced events.
Note that if the javascript handlers are slow, <code>pointerrawmove</code> events can also get coalesced.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Note that if the javascript handlers are slow, pointerrawmove events can also get coalesced." what does this actually mean. What is slow JS? handler taking more than 16ms? handler forcing rAF to happen later? or what? And what is the reason for this coalescing? If the page wants raw events, it should get raw events. That would be simpler and easier to understand API.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discussion a little more about this. Just to make sure whether we should change the design and logic around this event or just the text here.

I agree that when the page does express the desire to get the pointerrawmove events then presumably they have a fast handler that doesn't take long. But imagine a case that the app is not well written and takes say a few milliseconds to handle even a pointerrawmove and I have a 1000Hz mouse and I'm interacting with the page. So in this case user agent is sending 1000 move events to the page (assuming mouse is moving around) or 1 event every millisecond. So user agent either should drop these raw move events or queue them forever but the queue is only growing in that case (as the incoming events are faster than the handled rate). So user agent should either drop some of the rawmove events or coalesce them and expose those coalesced events with getCoalescedEvents APIs. right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if events are coalesced, when does that happen? When is it ok for UA to coalesce?
Is it ok to fire just one pointerrawmove per frame and coalesce the rest. Should the spec be a bit more precise. Something like... if UA detects that rendering will be updated and there are pending pointerrawmoves, fire just one event and coalesce the rest in the queue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So in general you are okay with coalescing the rawmove events. The only problem is a reasonable definition around it and when to do the coalescing. Let me take another stab at the text.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. I pushed a new commit. I used this sentence here instead: "Note that if UA detects the thread running javascript handlers for this event is not idle, pointerrawmove events will get coalesced and they will all be delivered as coalesced events of one pointerrawmove event as soon as the thread goes idle". Is that more precise?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather vague still, since "thread" isn't defined. If we want to define this properly, it should probably talk about tasks and task queues.
Also, if there are pending idleCallbacks, will those cause coalescing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smaug---- How about now?

extension.html Outdated
Additionally one <code>pointermove</code> MUST be fired when pointer changes coordinates, pressure, tangential pressure, tilt, twist, or
contact geometry (e.g. <code>width</code> and <code>height</code>) and the circumstances produce no other pointer events defined in this specification.
This <code>pointermove</code> that is not caused by button state change MUST be fired only once right before firing an event caused by button state change or
<a href="https://html.spec.whatwg.org/#event-loop-processing-model">animation frame callbacks</a>. If there are multiple changes to these attributes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to follow what implementations do. If there is nothing animating, *move events still fire at some point.
And I think events should fire sooner even in case there is something animating. More like before resize steps.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this have to do with whether something being animated or not? Event if nothing is animating rAF is still there even if it doesn't run any callbacks in js. Can you explain what you tested? Chrome always does delay pointermoves with the current implementation to right before rAF.

extension.html Outdated
<p>A user agent MUST <a href="https://w3c.github.io/pointerevents/index.html#firing-events-using-the-pointerevent-interface">fire a pointer event</a>
named <code>pointerrawmove</code> when a pointing device attribute
(i.e. button state, coordinates, pressure, tangential pressure, tilt, twist, or contact geometry) is changed.
As oppose to <code>pointermove</code> which is delayed until an animation frame reached or button change events happen,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this doesn't seem to be what implementations do. (tested also Chrome)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the comment above. What is the scenario that you are testing that is not doing this?

extension.html Outdated
<a href="https://html.spec.whatwg.org/#event-loop-processing-model">animation frame callbacks</a>. If there are multiple changes to these attributes
the <code>pointermove</code> events before reaching animation frame callback or a button state change event,
these events will get coalesced and will be exposed via <a data-lt="getCoalescedEvents">getCoalescedEvents</a> API for the single dispatched <code>pointermove</code> event.
These events may be coalesced or aligned to <a href="https://html.spec.whatwg.org/#event-loop-processing-model">animation frame callbacks</a> basesd on UA decision.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basesd

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

extension.html Outdated
the <code>pointermove</code> events before reaching animation frame callback or a button state change event,
these events will get coalesced and will be exposed via <a data-lt="getCoalescedEvents">getCoalescedEvents</a> API for the single dispatched <code>pointermove</code> event.
These events may be coalesced or aligned to <a href="https://html.spec.whatwg.org/#event-loop-processing-model">animation frame callbacks</a> basesd on UA decision.
The coalesdced events information will be exposed via <a data-lt="getCoalescedEvents">getCoalescedEvents</a> API for the single dispatched <code>pointermove</code> event.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coalesdced

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Define a low latency event that isn't occur in the document lifecycle
3 participants