Title: [176305] trunk/Source/WebKit2
- Revision
- 176305
- Author
- [email protected]
- Date
- 2014-11-18 21:06:58 -0800 (Tue, 18 Nov 2014)
Log 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 <[email protected]> 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:]):
Modified Paths
Diff
Modified: trunk/Source/WebKit2/ChangeLog (176304 => 176305)
--- trunk/Source/WebKit2/ChangeLog 2014-11-19 04:31:51 UTC (rev 176304)
+++ trunk/Source/WebKit2/ChangeLog 2014-11-19 05:06:58 UTC (rev 176305)
@@ -1,3 +1,43 @@
+2014-11-18 Benjamin Poulain <[email protected]>
+
+ 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
+
+ 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:]):
+
2014-11-18 Ryosuke Niwa <[email protected]>
iOS build fix after r176299. This method is not defined in WKViewIOS.mm.
Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (176304 => 176305)
--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h 2014-11-19 04:31:51 UTC (rev 176304)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h 2014-11-19 05:06:58 UTC (rev 176305)
@@ -136,6 +136,7 @@
BOOL _hasValidPositionInformation;
BOOL _isTapHighlightIDValid;
BOOL _potentialTapInProgress;
+ BOOL _highlightLongPressCanClick;
BOOL _hasTapHighlightForPotentialTap;
BOOL _selectionNeedsUpdate;
BOOL _shouldRestoreSelection;
Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (176304 => 176305)
--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2014-11-19 04:31:51 UTC (rev 176304)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2014-11-19 05:06:58 UTC (rev 176305)
@@ -537,6 +537,8 @@
- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
{
if (preventsNativeGesture) {
+ _highlightLongPressCanClick = NO;
+
_canSendTouchEventsAsynchronously = YES;
[_touchEventGestureRecognizer setDefaultPrevented:YES];
}
@@ -934,19 +936,22 @@
switch ([gestureRecognizer state]) {
case UIGestureRecognizerStateBegan:
+ _highlightLongPressCanClick = YES;
cancelPotentialTapIfNecessary(self);
_page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapHighlightID);
_isTapHighlightIDValid = YES;
break;
case UIGestureRecognizerStateEnded:
- if (!_positionInformation.clickableElementName.isEmpty()) {
+ if (_highlightLongPressCanClick && !_positionInformation.clickableElementName.isEmpty()) {
[self _attemptClickAtLocation:[gestureRecognizer startPoint]];
[self _finishInteraction];
} else
[self _cancelInteraction];
+ _highlightLongPressCanClick = NO;
break;
case UIGestureRecognizerStateCancelled:
[self _cancelInteraction];
+ _highlightLongPressCanClick = NO;
break;
default:
break;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes