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

I've written a more formal (but probably still sloppy by W3C standards)
spec for this here
<http://rbyers.github.io/EventListenerOptions/EventListenerOptions.html>.
Olli, I've tried to reflect all of your feedback, either in the spec or as
open issues (in particular #2
<https://github.com/RByers/EventListenerOptions/issues/2> and #12
<https://github.com/RByers/EventListenerOptions/issues/12>).

Please file issues <https://github.com/RByers/EventListenerOptions/issues>
or submit pull requests for other feedback.  Once there's a bit more
consensus on the API shape, I plan to write a polyfill and W3C-style tests
and bring this to www-dom.

Thanks,
   Rick

On Wed, Apr 22, 2015 at 1:04 PM, Olli Pettay <olli@pettay.fi> wrote:

> On 04/22/2015 09:49 AM, Rick Byers wrote:
>
>>
>> On Wed, Apr 22, 2015 at 12:44 PM, Olli Pettay <olli@pettay.fi <mailto:
>> olli@pettay.fi>> wrote:
>>
>>     I was thinking  { preventDefault: "never" } would be just a hint. In
>> order to be backwards compatible it would not affect at all how any other
>>     parts of the DOM Events API works.
>>     But it could affect to the behavior of the UA while it is dealing
>> with possibly asynchronous stuff, like touch/mouse/wheel.
>>
>>
>> I see.  And what should the behavior be if the "hint" is violated (call
>> preventDefault in a handler which said it wouldn't)?  I'm just worried about
>> predictability here.  I think if a developer says they won't call
>> preventDefault in a handler, we should ensure they can't (i.e. the event is
>> uncancelable), otherwise we may not be able to depend on it without
>> triggering bugs.
>>
>
>
> Well it doesn't really make sense for event listener registration to
> change the state of the DOM Event to be dispatched.
> And if the page doesn't honor the hint it set, that is a bug in it.
> Though, perhaps that hint name should be something a bit different...
> something which hints that the dispatcher of the event doesn't need to
> honor event's defaultPrevented state - in other words the return value of
> dispatchEvent().
>
>
>
>>     On 04/22/2015 09:13 AM, Rick Byers wrote:
>>
>>         On Tue, Apr 21, 2015 at 11:24 AM, Olli Pettay <olli@pettay.fi
>> <mailto:olli@pettay.fi> <mailto:olli@pettay.fi <mailto:olli@pettay.fi>>>
>> 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 <
>> olli@pettay.fi <mailto:olli@pettay.fi> <mailto:olli@pettay.fi
>>         <mailto:olli@pettay.fi>> <mailto:olli@pettay.fi <mailto:
>> olli@pettay.fi> <mailto:olli@pettay.fi <mailto:olli@pettay.fi>>>> 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 <
>> https://docs.google.com/a/chromium.org/document/d/1aOQRw76C0enLBd0mCG_-IM6bso7DxXwvqTiRWgNdTn8/edit>),
>> 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 <
>> http://www.w3.org/TR/WebIDL/#idl-overloading> (boolean is
>> "distinguishable" from dictionary) or
>>         union
>>         types <http://www.w3.org/TR/WebIDL/#idl-union>?
>>
>>
>>                      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
>>                      <
>> https://docs.google.com/document/d/1aOQRw76C0enLBd0mCG_-IM6bso7DxXwvqTiRWgNdTn8/edit#heading=h.wi06xpj70hhd>'
>> 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
>> <
>> https://groups.google.com/a/chromium.org/forum/#!topic/input-dev/4B7VFPZvHY0
>> >.
>>
>>                               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 Monday, 6 July 2015 14:34:51 UTC