Closed
Bug 653009
Opened 14 years ago
Closed 14 years ago
Make preventDefault for touch events compatible with WebKit/Opera
Categories
(Firefox for Android Graveyard :: General, defect)
Firefox for Android Graveyard
General
Tracking
(Not tracked)
VERIFIED
FIXED
Firefox 6
People
(Reporter: mbrubeck, Assigned: mbrubeck)
References
Details
(Keywords: compat, testcase)
Attachments
(3 files)
3.92 KB,
patch
|
wesj
:
review+
|
Details | Diff | Splinter Review |
3.92 KB,
patch
|
wesj
:
review+
|
Details | Diff | Splinter Review |
2.27 KB,
text/html
|
Details |
The W3C Touch Events spec doesn't (yet?) specify how preventDefault should behave with touch events. So I've been testing the behavior of other browsers. The following test page is useful:
http://limpet.net/w3/touchevents/preventDefault.html
Safari 4, Android 2.2 WebKit, and Opera Mobile 11 all have the following behavior:
1) preventDefault on the touchstart event prevents scrolling, double-tap zooming, and mouseup/mousedown/click events.
2) preventDefault on the touchmove event prevents scrolling.
3) preventDefault on the touchend event does NOT prevent scrolling or mouse events.
4) None of these will prevent pinch zooming. Safari implements a separate "gesturechange" event that is fired for pinch gestures and can be used to prevent zooming. This event is not implemented by Android or Opera.
For discussion of this issue on the public-webevents list, see:
http://lists.w3.org/Archives/Public/public-webevents/2011AprJun/0069.html
Assignee | ||
Comment 1•14 years ago
|
||
> 2) preventDefault on the touchmove event prevents scrolling.
Some additional research:
* In Safari and Android, preventDefault on the *first* touchmove event prevents scrolling for the entire touch sequence. (Tested on iPad and Galaxy Tab.)
* In Opera Mobile 11 for Android, preventDefault on the *first* touchmove event prevents scrolling, but only as long as you continue to call preventDefault on all subsequent touchmove events. If any touchmove event does not have preventDefault called, then scrolling starts and can no longer be prevented.
* In all three browsers, if preventDefault is *not* called on the *first* touchmove event, then scrolling happens normally.
If we emulate some version of this behavior, then it might simplify our code a bit. Basically, we only need to care about preventdefault on touchstart and on the first touchmove event; after that we enter a patch where panning/clicking always happens normally, or an alternate path where all events are sent to content and panning/clicking never happens. We don't need to send messages back for every single touch event.
Assignee | ||
Comment 2•14 years ago
|
||
This implements the WebKit (Safari/Android) behavior for preventing panning. Calling preventDefault on touchstart or the first touchmove will prevent panning from starting. Calling preventDefault on any other event has no effect.
I had to remove the code to clear pending messages on PanBegin, because it was causing the response to the first MouseMove message to be discarded.
This patch does *not* prevent mouse/click events. That will be part 2.
Assignee | ||
Comment 3•14 years ago
|
||
(In reply to comment #0)
> 3) preventDefault on the touchend event does NOT prevent scrolling or mouse
> events.
This is true for Android 2.2, iOS 3.1, and Opera 11. However, it has changed in iOS 4, where preventDefault on touchend DOES prevent mouse events.
Assignee | ||
Comment 4•14 years ago
|
||
This implements the same behavior as Android, iOS 3.1, and Opera Mobile: Calling preventDefault on the touchstart event will prevent all mouse events.
Attachment #529226 -
Flags: review?(wjohnston)
Assignee | ||
Updated•14 years ago
|
Flags: in-testsuite?
Comment 5•14 years ago
|
||
Comment on attachment 529223 [details] [diff] [review]
part 1: panning
This looks good to me.
Attachment #529223 -
Flags: review?(wjohnston) → review+
Updated•14 years ago
|
Attachment #529226 -
Flags: review?(wjohnston) → review+
Assignee | ||
Comment 6•14 years ago
|
||
http://hg.mozilla.org/mozilla-central/rev/2928d2610d74
http://hg.mozilla.org/mozilla-central/rev/2bcdd585f477
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 6
Comment 7•14 years ago
|
||
Tried to verify this but I'm not so sure about the behavior, can you help me please?
Assignee | ||
Comment 8•14 years ago
|
||
On the attached test page, if you hide the titlebar and sidebars and then start a drag in the following boxes, the page *should not* pan:
- Prevent start
- Prevent start, move
- Prevent move
- Prevent move 0
- Prevent move < 20
- Prevent start, end
If you start a drag on any other box, the page *should* pan.
Assignee | ||
Comment 9•14 years ago
|
||
After the automated tests for bug 544614 are reviewed and checked in, I will extend them to test this bug also.
Keywords: testcase
Comment 10•14 years ago
|
||
Verified fixed on:
Mozilla/5.0 (Android;Linux armv7l;rv:8.0a1)Gecko/20110904
Firefox/8.0a1 Fennec/8.0a1
Device: Samsung Galaxy S
OS: Android 2.2
Status: RESOLVED → VERIFIED
Assignee | ||
Updated•13 years ago
|
Flags: in-testsuite?
Comment 11•12 years ago
|
||
It appears that Firefox is sending the first touchmove event too quickly, and it's too sensitive to finger movement.
In my implementation I need to know direction and velocity of the movement before deciding whether to prevent scrolling or not:
http://pornel.net/slip/
In WebKit/Blink it works fine, because it seems to have some timeout or dead zone that delays the first touchmove event.
In Firefox you have to be *really lucky* to see scrolling prevented (when you try the link above keep in mind that scrolling stops when you scroll page to top/bottom, but you'll rarely see scrolling prevented by JS). I can't make my gesture recognition work with your implementation.
If prevent-only-on-first-touchmove behavior is not crucial for compatibility, I urge you to drop it, because it's a nightmare from developer's point of view.
But if you'd rather keep the behavior (AFAIK Blink's argument in favor is having smooth scrolling off the main thread), then maybe instead of preventDefault working strictly on the first event, make it work within radius of X pixels from touch start and/or first X milliseconds.
http://lists.w3.org/Archives/Public/www-dom/2014JanMar/0015.html
Assignee | ||
Comment 12•12 years ago
|
||
(In reply to porneL from comment #11)
> It appears that Firefox is sending the first touchmove event too quickly,
> and it's too sensitive to finger movement.
>
> In my implementation I need to know direction and velocity of the movement
> before deciding whether to prevent scrolling or not:
>
> http://pornel.net/slip/
>
> In WebKit/Blink it works fine, because it seems to have some timeout or dead
> zone that delays the first touchmove event.
Could you file a new bug about this, please, and CC me? I think we should consider changing Firefox to match the WebKit behavior you describe. We ran into similar problems with the current Gecko behavior when implementing the new Windows 8 UI (bug 934750).
Comment 13•12 years ago
|
||
I would rather we just break spec compatibility and let you call preventDefault() at any point during a pan (although, the APZC will obviously be delayed in responding...). I hear complaints pretty regularly about the opposite. Webkit touch events are laggy. Why am I not getting touches fine enough at the beginning of stroke. etc.
Assignee | ||
Comment 14•12 years ago
|
||
I should mention that the "touch-action" CSS property from the new Pointer Events spec (bug 795567) will provide a solution for the use case in bug 795567. It's already supported in IE10+, and work is underway to add it to Blink and Gecko.
Assignee | ||
Comment 15•12 years ago
|
||
(In reply to Matt Brubeck (:mbrubeck) from comment #14)
> I should mention that the "touch-action" CSS property from the new Pointer
> Events spec (bug 795567) will provide a solution for the use case in bug
> 795567.
I meant "for the use case in comment 11", sorry.
Comment 16•12 years ago
|
||
The touch-action spec says:
> When a user touches an element, the effect of that touch is determined by the value of the touch-action property [...] if the touch-action property of any of those elements disallows the default touch behavior, do nothing. Otherwise allow the element to start considering the touch for the purposes of executing a default touch behavior.
> During the execution of a behavior, the user agent must not dispatch subsequent pointer events for the pointer.
Do I understand correctly that "When a user touches an element" is equivalent to touchstart event and it only matters what touch-action was set on the element during the instant screen was touched? If so, then it doesn't address my use-case at all, and this behavior is equivalent of the problem in this bug.
If I knew whether I can allow panning during the first touch even, then I wouldn't have problem with preventDefault().
In my case - http://pornel.net/slip - user can either swipe element horizontally (touch-action: none) OR reorder elements after a ~500ms delay (touch-action: none or pan-x) OR scroll freely if there was a significant vertical movement within 500ms from touch start (touch-action: pan-x pan-y). So I have to wait for movement to cross my direction/velocity thresholds or time out before I can know what touch-action I should set.
Comment 17•11 years ago
|
||
In chromium we found we must suppress sending touchmove for small distances right after an unconsumed touchstart exactly because sites expect to be able to conditionally disable scrolling based eg. on direction on the first touchmove. See http://crbug.com/334040. We also always honor the preventDefault of a touchmove - if we send a touchmove at all we'll always wait to see if JS wants to consume it before scrolling (otherwise we see "double handling") issues.
These arw great topics for public-touchevents! We're making changes in chromium to give developers more control.
You need to log in
before you can comment on or make changes to this bug.
Description
•