- From: Rick Byers <rbyers@chromium.org>
- Date: Wed, 22 Apr 2015 12:49:13 -0400
- To: Olli Pettay <olli@pettay.fi>
- Cc: "public-pointer-events@w3.org" <public-pointer-events@w3.org>, Jared Duke <jdduke@chromium.org>, Nathaniel Duca <nduca@chromium.org>
- Message-ID: <CAFUtAY9XnTPBOvv-xqb92E09VMJtSTeX8-SDoS8M__ArLcSH7w@mail.gmail.com>
On Wed, Apr 22, 2015 at 12:44 PM, Olli Pettay <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.
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>> 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>>>
>> 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 Wednesday, 22 April 2015 16:50:04 UTC