Re: Non-scroll-blocking wheel events listeners / relationship to PEWG?

On Tue, Apr 21, 2015 at 11:24 AM, Olli Pettay <> wrote:

> On 04/21/2015 08:00 AM, Olli Pettay wrote:
>> On 04/21/2015 07:10 AM, Rick Byers wrote:
>>> On Tue, Apr 21, 2015 at 9:43 AM, Olli Pettay < <mailto:
>>>>> wrote:
>>>     On 04/15/2015 08:31 AM, Rick Byers wrote:
>>>         It's common for libraries (eg. ads frameworks) to want to
>>> passively track some notion of user interaction with the page.  For touch,
>>> Pointer
>>>         Events is
>>>         a good API for this because the event listeners don't block
>>> scrolling.  But what about for wheel events?  Adding a document wheel event
>>>         handler for
>>>         this (when none existed previously) is bad for scroll
>>> performance.
>>>     I wonder how bad the performance issues actually are here. Comparing
>>> to pointer events, wheel events fire rarely, and there are just couple of
>>> them
>>>     in a row. So an implementation could have enough time to hit test
>>> and dispatch an event before the next animation frame tick.
>>>     (I'm a bit worried making the platform more complicated than it
>>> needs to be.)
>>> Why do you say there's just a couple of them in a row?
>> I'm comparing to touch events for example. But you're right, pixel level
>> wheel events happen rather often.
>>  I'm thinking primarily of scrolling on high-quality touchpads here (eg.
>>> macbooks,
>>> chromebooks).  There wheel events are similar to touchmove events in
>>> terms of frequency and duration during a scroll.  That said, there are some
>>> big
>>> differences:
>>> 1) wheel scrolling tends to be done on much faster devices than touch
>>> scrolling
>>> 2) indirect manipulation is more forgiving psychologically than direct
>>> manipulation (since with touch your finger acts as a point of reference that
>>> makes at least latency substantially more noticeable, but I'm not sure
>>> how it affects the perception of smoothness).
>>> So I agree it may not be that important.  But as we look to provide
>>> control over the blocking behavior of touch and scroll handlers (eg.
>>> scroll-blocks-on proposal <
>>> I'm trying to
>>> consider wheel handlers also for consistency and completeness.
>> Would wheel+ctrl behave differently to wheel? Or other event+modifier
>> combinations? (I think events should be for consistency dispatched the same
>> way,
>> either always async or always sync, whether or not there are modifiers)
>>>         Should PEWG consider trying to address this scenario?
>>>         One option (that I think we've discussed a bit in some form)
>>> would be to have a new non-blocking event ('pointerwheel' maybe?) and a new
>>>         'wheel-action' CSS property (similar to touch-action) that
>>> declaratively says what sort of wheel movement should cause scrolling.
>>> This would
>>>         be most
>>>         like pointer events, but adding new event types for this seems
>>> unfortunate (now what about keyboard scrolling?).
>>>     well, keyboard scrolling doesn't cause wheel events either.
>>> Right, but the same problem exists there in theory.  Perhaps there
>>> should be some mechanism to permit keyboard event listeners that won't block
>>> scrolling?  But this is even less important than the wheel case IMHO.
>>>         Another option would be to augment event handler registration
>>> with an options dictionary (instead of just the single 'capture' boolean).
>>> Eg:
>>>         addEventListener('wheel', myHandler, {blocksScroll: false});
>>>     Definitely not this. This is not a strong enough case to change an
>>> API which has existed for 15+ years, IMO.
>>> Would you feel any better about this if the API had a new name?
>> Not really
>>  Although I share your gut reaction that we shouldn't be messing with
>>> addEventListener, in debates internally I haven't been able to formulate
>>> a clear technical argument against extending addEventListener to have some
>>> mechanism for additional options.  If what the developer wants to say is
>>> "I want to observe wheel events, but I'm never going to call preventDefault
>>> on them so please don't block scrolling"
>> Aha, if you formulate the behavior in a bit different way, then it
>> becomes more generic...
>> So, "I'm not going to call preventDefault()" might be such, useful also
>> in other cases than just with wheel.
>> A bit odd API, but might be useful, really useful.
>> enum PreventDefaultHints {
>>    "never"
>>    ""
>> };
>> addEventListener("wheel", listener, { preventDefault: "never",
>>                                        capture: true});
That's an interesting idea. If all handlers say they they'll never
preventDefault then Event.cancelable should be false so that preventDefault
is ignored (Chrome also generates a console warning if you attempt to
cancel an uncancelable event).  Perhaps we'd want to phrase the API as
indicating whether you want cancelable events or not rather than a "prevent
default hint".

A couple issues:
1) What if one handler asks for cancelable events and other asks for
uncancelable events?  Should 'Event.cancelable' just be true on the events
that are fired?  That risks developers having bugs where their handler
accidentally relies on being able to cancel an event they requested to be
uncancelable (due to some other component on the test page asking for
cancelable events).  Perhaps we should allow Event.cancelable to change for
each handler receiving the event?

2) Only some event types support cancellation.  I think it's fine to
request cancelable=false on events that are always cancelable (just
indicating your intent not to cancel them yourself).  But what if a
developer requests cancelable events of a type that can never be canceled
(eg. scroll events)?  Should it fail somehow? Should a developer be able to
feature detect this somehow?

3) The one thing my earlier proposal here (or my scroll-blocks-on design)
could support that this can't is scroll event listeners that block
scrolling.  scroll events should never be cancelable, but we argue (to much
debate) that there are some limited scenarios where we should allow a site
to opt-in to scroll event handlers that run in-sync with scrolling.  You
could argue that scenario is different enough that it either should never
be supported or should require a different API.

...but unfortunately that is not backwards compatible. If we could find a
> nice backwards compatible syntax.
> addEventListener("wheel", listener, true, { preventDefault: "never" });
> would behave fine, but is a bit long.
> Would it be good enough?

Why not?  Couldn't we either use overloading
<> (boolean is
"distinguishable" from dictionary) or union types

>  then it does feel most natural to allow them to say that at event handler
>>> registration time somehow.  Any
>>> suggestion for how such a mechanism should look?
>>>         A third option is to leave the event system unmodified and rely
>>> on a CSS property to independently control when events block scrolling.
>>> This
>>>         is what
>>>         my 'scroll-blocks-on <
>>> proposal
>>>         does (for
>>>         which I've landed an experimental partial implementation in
>>> blink).  A key downside here is the 'spooky action at a distance' between
>>> event
>>>         registration and CSS property application.  Eg. how to multiple
>>> components each putting wheel handlers on the document effectively
>>> co-ordinate
>>>         on what
>>>         the combined effect on the document should be? For this
>>> particular scenario (not one of the original goals of scroll-blocks-on)
>>> indicating
>>>         intent at
>>>         event registration time seems much better for composition.
>>>     But this would work with keyboard events too.
>>>     In fact, what do we actually want here. wheel/key event handling, or
>>> notification about what user just did?
>>>     So, would some kind intentional event work here?
>>>     addEventListener("userIntention", function(e) {
>>>        if (e.intention == "scroll") {
>>>          // do something
>>>        }
>>>     });
>>>     Or should "scroll" event be extended so that it tells what triggered
>>> the action? That can be a bit difficult to implement, but might be rather
>>>     nice to have.
>>> The main use case I've got in mind is activity tracking.  Most ad
>>> frameworks have some system (like it or not) of monitoring user activity
>>> (where was
>>> the mouse cursor, where on the page is the user touching, etc.).  Today
>>> this hurts scroll performance substantially.  Pointer events solves this for
>>> touch (although I'm not sure yet whether that's good enough - we may
>>> still pursue a solution with touch events), but no-one has proposed a good
>>> design
>>> that could also address the touchpad case (scroll-blocks-on gets awkward
>>> in the composition cases - all components on the page need to use some
>>> library/pattern to mediate the combination of desires from the different
>>> components).
>>> So for that use case, I don't think a scroll intention is really
>>> adequate.  We could have some generic 'user activity' intention that
>>> included a
>>> screen co-ordinate, but that would quickly end up looking pretty
>>> redundant with pointer events.
>> well, pointer events don't deal with key events.
>> I can see non-ad use cases for user-activity events too (do some heavy
>> clean up in the page while user isn't interacting with it and there are no
>> rAF
>> callbacks called and so.)
>>>         See some more chromium-specific debate here <
>>> >.
>>>         Thoughts?  Out of scope for this group?
>>>     Sounds like out of scope for this group, but I don't really mind
>>> whether discussed here or in WebApps.
>>>     -Olli
>>>         Rick

Received on Wednesday, 22 April 2015 16:14:09 UTC