⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 176305 in webkit


Ignore:
Timestamp:
Nov 18, 2014, 9:06:58 PM (12 years ago)
Author:
benjamin@webkit.org
Message:

iOS8 new "slow tap" heuristic fires mouse compat events despite preventDefault on touchend
https://bugs.webkit.org/show_bug.cgi?id=137069
rdar://problem/18481464

Patch by Benjamin Poulain <bpoulain@apple.com> on 2014-11-18
Reviewed by Simon Fraser.

On WebKit2, we let UIWebTouchEventsGestureRecognizer and _UIWebHighlightLongPressGestureRecognizer
run concurrently. This causes a race with an incorrect behavior:
1) If UIWebTouchEventsGestureRecognizer does not cancel the native gestures on start.
2) _UIWebHighlightLongPressGestureRecognizer starts after highlightDelay.
3) When the finger leaves the screen, both gestures end.
-> If the touch end sent to JavaScript in [3] ask the priority over native events, that no longer stops

the _UIWebHighlightLongPressGestureRecognizer.

The two gesture recognizers can run in any order, there is no guarantee on which one runs first.
To solve the bug, I must make sure the _UIWebHighlightLongPressGestureRecognizer never trigger a click
if the page wants the event.

To solve the order problem, I use the fact that event recognition goes in two phases for
non cancelled events:
1) Update the gesture recognizers.
2) Trigger the actions.

I do not know the order of recognizers in [1], but I know both have run before [2] is executed.
I use that to stop _UIWebHighlightLongPressGestureRecognizer from ending with a click in the case of the bug:
1) When _UIWebHighlightLongPressGestureRecognizer starts, I set _highlightLongPressCanClick signaling

the gesture can end normally. This is done on a timer and not direct input so I don't really have to worry
about a race here.

2) When processing the touch event for UIWebTouchEventsGestureRecognizer, I reset the flag _highlightLongPressCanClick

if the page wants the event.

3) When the actions of _UIWebHighlightLongPressGestureRecognizer are processed, the touch event

has already been processed by the page and the flag has been cleared if needed.

  • UIProcess/ios/WKContentViewInteraction.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView _webTouchEvent:preventsNativeGestures:]):
(-[WKContentView _highlightLongPressRecognized:]):

Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r176304 r176305  
     12014-11-18  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        iOS8 new "slow tap" heuristic fires mouse compat events despite preventDefault on touchend
     4        https://bugs.webkit.org/show_bug.cgi?id=137069
     5        rdar://problem/18481464
     6
     7        Reviewed by Simon Fraser.
     8
     9        On WebKit2, we let UIWebTouchEventsGestureRecognizer and _UIWebHighlightLongPressGestureRecognizer
     10        run concurrently. This causes a race with an incorrect behavior:
     11        1) If UIWebTouchEventsGestureRecognizer does not cancel the native gestures on start.
     12        2) _UIWebHighlightLongPressGestureRecognizer starts after highlightDelay.
     13        3) When the finger leaves the screen, both gestures end.
     14        -> If the touch end sent to JavaScript in [3] ask the priority over native events, that no longer stops
     15           the _UIWebHighlightLongPressGestureRecognizer.
     16
     17        The two gesture recognizers can run in any order, there is no guarantee on which one runs first.
     18        To solve the bug, I must make sure the _UIWebHighlightLongPressGestureRecognizer never trigger a click
     19        if the page wants the event.
     20
     21        To solve the order problem, I use the fact that event recognition goes in two phases for
     22        non cancelled events:
     23        1) Update the gesture recognizers.
     24        2) Trigger the actions.
     25
     26        I do not know the order of recognizers in [1], but I know both have run before [2] is executed.
     27        I use that to stop _UIWebHighlightLongPressGestureRecognizer from ending with a click in the case of the bug:
     28        1) When _UIWebHighlightLongPressGestureRecognizer starts, I set _highlightLongPressCanClick signaling
     29           the gesture can end normally. This is done on a timer and not direct input so I don't really have to worry
     30           about a race here.
     31        2) When processing the touch event for UIWebTouchEventsGestureRecognizer, I reset the flag _highlightLongPressCanClick
     32           if the page wants the event.
     33        3) When the actions of _UIWebHighlightLongPressGestureRecognizer are processed, the touch event
     34           has already been processed by the page and the flag has been cleared if needed.
     35
     36        * UIProcess/ios/WKContentViewInteraction.h:
     37        * UIProcess/ios/WKContentViewInteraction.mm:
     38        (-[WKContentView _webTouchEvent:preventsNativeGestures:]):
     39        (-[WKContentView _highlightLongPressRecognized:]):
     40
    1412014-11-18  Ryosuke Niwa  <rniwa@webkit.org>
    242
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h

    r174885 r176305  
    137137    BOOL _isTapHighlightIDValid;
    138138    BOOL _potentialTapInProgress;
     139    BOOL _highlightLongPressCanClick;
    139140    BOOL _hasTapHighlightForPotentialTap;
    140141    BOOL _selectionNeedsUpdate;
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm

    r175577 r176305  
    538538{
    539539    if (preventsNativeGesture) {
     540        _highlightLongPressCanClick = NO;
     541
    540542        _canSendTouchEventsAsynchronously = YES;
    541543        [_touchEventGestureRecognizer setDefaultPrevented:YES];
     
    935937    switch ([gestureRecognizer state]) {
    936938    case UIGestureRecognizerStateBegan:
     939        _highlightLongPressCanClick = YES;
    937940        cancelPotentialTapIfNecessary(self);
    938941        _page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapHighlightID);
     
    940943        break;
    941944    case UIGestureRecognizerStateEnded:
    942         if (!_positionInformation.clickableElementName.isEmpty()) {
     945        if (_highlightLongPressCanClick && !_positionInformation.clickableElementName.isEmpty()) {
    943946            [self _attemptClickAtLocation:[gestureRecognizer startPoint]];
    944947            [self _finishInteraction];
    945948        } else
    946949            [self _cancelInteraction];
     950        _highlightLongPressCanClick = NO;
    947951        break;
    948952    case UIGestureRecognizerStateCancelled:
    949953        [self _cancelInteraction];
     954        _highlightLongPressCanClick = NO;
    950955        break;
    951956    default:
Note: See TracChangeset for help on using the changeset viewer.