Re: Request for Comments: Pointer Events spec's touch-action CSS property

On Jan 17, 2013, at 5:35 PM, Jacob Rossi <Jacob.Rossi@microsoft.com> wrote:

> Apologies, I've corrected a mistake inline below (removed "AND that subsequent pointer events should be consumed and not dispatched" from the paragraph below the algorithm).  Any time a UA decides to perform a touch action, it must cancel the pointer. This is covered in the following spec text:
> 
> "A user agent must dispatch a pointercancel (and subsequently a pointerout event) whenever all of the following are true:
>  •The user agent has determined (via methods out of scope for this specification) that touch input is to be consumed for a default touch behavior,
>  •a pointerdown event has been sent for the pointer, and
>  •a pointerup or pointercancel event (following the above mentioned pointerdown) has not yet been sent for the pointer.
> 
> During the execution of the behavior (after sending the pointercancel and pointerout events), the user agent must not dispatch subsequent pointer events for the pointer. "
> 
> So in other words, if events have been sent for a pointer and you later decide to perform a touchaction then you must clean up state by firing pointercancel and pointerout.  UAs do not fire events while performing touch actions (panning/zooming/etc).
> 
> -----Original Message-----
> From: Jacob Rossi [mailto:Jacob.Rossi@microsoft.com] 
> Sent: Thursday, January 17, 2013 5:25 PM
> To: L. David Baron; public-pointer-events@w3.org; Tab Atkins Jr.
> Cc: www-style@w3.org
> Subject: RE: Request for Comments: Pointer Events spec's touch-action CSS property
> 
> Hey folks,
> 
> Thanks for the great feedback. I'll try to address all the questions thus far from Tab and David. But let me know if I miss something. First, I'll start with some background context on the feature.
> 
> This property is fundamentally about enabling better performance for touch panning, zooming, etc.  Performance is most critical for touch, where your finger is aligned 1:1 with the content and any lag is readily noticed by the user.
> 
> As a CSS property, the intended touch behavior is declarative and known ahead of interaction time. Whether panning/zooming should happen can be known *immediately* when the touch begins because the CSS property has a value. With preventDefault(), you have to dispatch an event first to answer that question. There could be script already running that could slow the dispatch of the event and/or script in the event handler could run for a while before returning. All the while, your finger has started to move yet  panning/zooming hasn't kicked in.  This can cause a substantial jump in the initiation of a pan, which is an undesirable touch experience. With touch-action, you know right away what to do and get a more fluid pan/zoom initiation.
> 
> The property acts as a filter on the behaviors a UA is allowed to perform. It doesn't inherit because it has its own processing model (I'll update the spec to remove "inherit" from the grammar--I didn't know the convention).  I hear the feedback that the spec text for this model is unclear. I think, perhaps, a more algorithmic approach might be better:
> 
> Run these steps prior to dispatching the pointerdown event for a touch:
> 1. Set ELEMENT to the target of the pointerdown.
> 2. If the value of touch-action for ELEMENT is "none" then terminate these steps.
> 3. If ELEMENT is capable of a performing a touch behavior (such as panning or zooming), then begin considering this touch for that possible behavior and abort these steps.
> 4. If ELEMENT is the root of the document, terminate these steps.
> 5. Set ELEMENT to the current ELEMENT's immediate parent and repeat steps 2-5.
> 
> This locates a "touch behavior capable element" that is monitoring active touches. When a UA determines a touch should trigger a behavior on this element (by methods outside the scope of this spec), then it must cancel that pointer by dispatching pointercancel and pointerout events.  It is not necessarily a requirement that all touch behaviors result in the consumption of pointer events, but if they do then they must dispatch the cancel/out.
> 
> Some basic examples:
> <div style="touch-action: none;" >
>     <div style="overflow:scroll;"></div> </div> A touch on the child may perform a pan on the child.
> 
> <div style="overflow:scroll;">
>   <div style="touch-action: none;" ></div>  </div> A touch on the child must not perform a pan on the parent.
> 
> <div style="overflow:scroll; touch-action: none;"></div> A touch on the element must not perform a pan on the element.

It seems like a common case might be to allow a pan on the element, but not on the parent, without necessitating a wrapper element. Something like this, perhaps: 

<div style="overflow:scroll;">
   <div style="overflow:scroll; touch-action: self;" ></div>  </div> A touch on the child may perform a pan on the child, but must not perform a pan on the parent.

Might there not be common cases where the author might want to block some touch actions and allow others on the same element? For instance, allow default behavior for pinch-resizing, but prevent the panning from affecting ancestors of an overflow:scroll element?

Also, I agree with Peter that we might be limiting ourselves by only considering this declarative default action handling for touch events only. I have, in the past, wished I could prevent mouse scroll wheels from affecting parent elements (such as the BODY), perhaps with something like this:

<body>
   <div style="overflow:scroll; pan-action: self;" ></div>  
   [full, overflowing page of stuff here....]
</body> 
A pan (scroll) action on the child performs a pan on the child, but must not perform a pan on the ancestors.

> As for the block-level restriction, this was simply an optimization we made to IE10, which the spec is based on. In general, only block-level elements are capable of these types of behaviors. As for the name, well it's the *actions* (think: default action from events) that the *touch* can perform. We'd like to shoot for interop with IE10, but we're open for suggestions on other names if there's a strong objection to the current.

Supposing we broke 'touch-action' into multiple properties, and generalized them to not be just touch-related, we could have these:

pan-action
zoom-action (pinching to zoom, if it is touch)
focus-action (such as double-tap to zoom in or out on a single element)
scale-action (pinching to resize)
move-action (dragging to translate position)
rotate-action

But it would be better if they all started with the same word instead of ending with it. And maybe we shouldn't substitute the word 'pan' for 'scroll'. 

Something like 'rotate-action: none' probably wouldn't have much effect, unless the UA actually rotated something selectable based on user action. But I think it would be very cool if 'rotate-action:self' actually allowed a user on a touch interface to do the equivalent of a 'transform:rotate(<angle-determined-by-fingers>)', without needing any JavaScript or anything else.

Received on Saturday, 19 January 2013 04:10:09 UTC