[Pointer Events] "touch-action: none" does not prevent double-tap-to-zoom
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Jul 2019 18:00:33 +0000 (18:00 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Jul 2019 18:00:33 +0000 (18:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=199571
<rdar://problem/51715002>

Reviewed by Wenson Hsieh.

Source/WebKit:

We add a new WKTouchActionGestureRecognizerDelegate method to check whether a gesture recognizer may lead to
zooming the page as a result of double-tapping, which can be caused by two different gesture recognizers
managed by WKContentViewInteraction. If that delegate method returns true and we have "touch-action: none"
set for this touch, we cause those gesture recognizers to fail and prevent double-tap-to-zoom behavior.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView gestureRecognizerMayDoubleTapToZoomWebView:]):
* UIProcess/ios/WKTouchActionGestureRecognizer.h:
* UIProcess/ios/WKTouchActionGestureRecognizer.mm:
(-[WKTouchActionGestureRecognizer canPreventGestureRecognizer:]):

LayoutTests:

Add two new tests that check that setting "touch-action: none" on an element does not allow double-tap-to-zoom
and that "touch-action: manipulation" allows it.

* pointerevents/ios/touch-action-manipulation-double-tap-to-zoom-expected.txt: Added.
* pointerevents/ios/touch-action-manipulation-double-tap-to-zoom.html: Added.
* pointerevents/ios/touch-action-none-double-tap-to-zoom-expected.txt: Added.
* pointerevents/ios/touch-action-none-double-tap-to-zoom.html: Added.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247212 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom.html [new file with mode: 0644]
LayoutTests/pointerevents/utils.js
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WKTouchActionGestureRecognizer.h
Source/WebKit/UIProcess/ios/WKTouchActionGestureRecognizer.mm

index b884515..7068163 100644 (file)
@@ -1,3 +1,21 @@
+2019-07-08  Antoine Quint  <graouts@apple.com>
+
+        [Pointer Events] "touch-action: none" does not prevent double-tap-to-zoom
+        https://bugs.webkit.org/show_bug.cgi?id=199571
+        <rdar://problem/51715002>
+
+        Reviewed by Wenson Hsieh.
+
+        Add two new tests that check that setting "touch-action: none" on an element does not allow double-tap-to-zoom
+        and that "touch-action: manipulation" allows it.
+
+        * pointerevents/ios/touch-action-manipulation-double-tap-to-zoom-expected.txt: Added.
+        * pointerevents/ios/touch-action-manipulation-double-tap-to-zoom.html: Added.
+        * pointerevents/ios/touch-action-none-double-tap-to-zoom-expected.txt: Added.
+        * pointerevents/ios/touch-action-none-double-tap-to-zoom.html: Added.
+        * pointerevents/utils.js:
+        (const.ui.new.UIController.prototype.doubleTapToZoom):
+
 2019-07-08  Charlie Turner  <cturner@igalia.com>
 
         [GStreamer] media/video-volume.html broken after switching from cubic to linear scaling
diff --git a/LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom-expected.txt b/LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom-expected.txt
new file mode 100644 (file)
index 0000000..0489e34
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS Testing that setting touch-action: manipulation on an element allows double tap to zoom. 
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom.html b/LayoutTests/pointerevents/ios/touch-action-manipulation-double-tap-to-zoom.html
new file mode 100644 (file)
index 0000000..418cd3c
--- /dev/null
@@ -0,0 +1,33 @@
+<!DOCTYPE html><!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+    document.body.style.width = "2000px";
+    document.body.style.height = "2000px";
+
+    target.style.touchAction = "manipulation";
+
+    requestAnimationFrame(() => {
+        const initialPageScaleFactor = window.internals.pageScaleFactor();
+        ui.doubleTapToZoom({ x: 10, y: 10 }).then(() => {
+            assert_not_equals(window.internals.pageScaleFactor(), initialPageScaleFactor, "The page was scaled.");
+            test.done();
+        });
+    })
+
+}, "Testing that setting touch-action: manipulation on an element allows double tap to zoom.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom-expected.txt b/LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom-expected.txt
new file mode 100644 (file)
index 0000000..615738a
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS Testing that setting touch-action: none on an element prevents double tap to zoom. 
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom.html b/LayoutTests/pointerevents/ios/touch-action-none-double-tap-to-zoom.html
new file mode 100644 (file)
index 0000000..1efa00d
--- /dev/null
@@ -0,0 +1,33 @@
+<!DOCTYPE html><!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+    document.body.style.width = "2000px";
+    document.body.style.height = "2000px";
+
+    target.style.touchAction = "none";
+
+    requestAnimationFrame(() => {
+        const initialPageScaleFactor = window.internals.pageScaleFactor();
+        ui.doubleTapToZoom({ x: 10, y: 10 }).then(() => {
+            assert_equals(window.internals.pageScaleFactor(), initialPageScaleFactor, "The page was not scaled.");
+            test.done();
+        });
+    })
+
+}, "Testing that setting touch-action: none on an element prevents double tap to zoom.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
index 4892196..20878e8 100644 (file)
@@ -123,6 +123,15 @@ const ui = new (class UIController {
         return this._run(`uiController.singleTapAtPoint(${options.x}, ${options.y})`);
     }
 
+    doubleTapToZoom(options)
+    {
+        const durationInSeconds = 0.35;
+        return new Promise(resolve => this._run(`uiController.doubleTapAtPoint(${options.x}, ${options.y})`).then(() =>
+            setTimeout(resolve, durationInSeconds * 1000)
+        ));
+        return this._run();
+    }
+
     pinchOut(options)
     {
         options.x = options.x || 0;
index 4d696d3..86ae6f5 100644 (file)
@@ -1,3 +1,22 @@
+2019-07-08  Antoine Quint  <graouts@apple.com>
+
+        [Pointer Events] "touch-action: none" does not prevent double-tap-to-zoom
+        https://bugs.webkit.org/show_bug.cgi?id=199571
+        <rdar://problem/51715002>
+
+        Reviewed by Wenson Hsieh.
+
+        We add a new WKTouchActionGestureRecognizerDelegate method to check whether a gesture recognizer may lead to
+        zooming the page as a result of double-tapping, which can be caused by two different gesture recognizers
+        managed by WKContentViewInteraction. If that delegate method returns true and we have "touch-action: none"
+        set for this touch, we cause those gesture recognizers to fail and prevent double-tap-to-zoom behavior.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView gestureRecognizerMayDoubleTapToZoomWebView:]):
+        * UIProcess/ios/WKTouchActionGestureRecognizer.h:
+        * UIProcess/ios/WKTouchActionGestureRecognizer.mm:
+        (-[WKTouchActionGestureRecognizer canPreventGestureRecognizer:]):
+
 2019-07-08  Per Arne Vollan  <pvollan@apple.com>
 
         [iOS] WebContent processes should not globally allow mach lookup to the AX server.
index 479371b..8326b98 100644 (file)
@@ -1403,6 +1403,11 @@ inline static UIKeyModifierFlags gestureRecognizerModifierFlags(UIGestureRecogni
     return NO;
 }
 
+- (BOOL)gestureRecognizerMayDoubleTapToZoomWebView:(UIGestureRecognizer *)gestureRecognizer
+{
+    return gestureRecognizer == _doubleTapGestureRecognizer || gestureRecognizer == _twoFingerDoubleTapGestureRecognizer;
+}
+
 - (NSMapTable<NSNumber *, UITouch *> *)touchActionActiveTouches
 {
     return [_touchEventGestureRecognizer activeTouchesByIdentifier];
index 4afa34b..2a3f51a 100644 (file)
@@ -39,6 +39,7 @@
 
 @protocol WKTouchActionGestureRecognizerDelegate <NSObject>
 - (BOOL)gestureRecognizerMayPinchToZoomWebView:(UIGestureRecognizer *)gestureRecognizer;
+- (BOOL)gestureRecognizerMayDoubleTapToZoomWebView:(UIGestureRecognizer *)gestureRecognizer;
 - (NSMapTable<NSNumber *, UITouch *> *)touchActionActiveTouches;
 @end
 
index 835fc65..36fa845 100644 (file)
     if (_touchActionsByTouchIdentifier.isEmpty())
         return NO;
 
-    if (![_touchActionDelegate gestureRecognizerMayPinchToZoomWebView:preventedGestureRecognizer])
+    auto mayPinchToZoom = [_touchActionDelegate gestureRecognizerMayPinchToZoomWebView:preventedGestureRecognizer];
+    auto mayDoubleTapToZoom = [_touchActionDelegate gestureRecognizerMayDoubleTapToZoomWebView:preventedGestureRecognizer];
+
+    if (!mayPinchToZoom && !mayDoubleTapToZoom)
         return NO;
 
     // Now that we've established that this gesture recognizer may yield an interaction that is preventable by the "touch-action"
         auto iterator = _touchActionsByTouchIdentifier.find([touchIdentifier unsignedIntegerValue]);
         if (iterator != _touchActionsByTouchIdentifier.end() && [[activeTouches objectForKey:touchIdentifier].gestureRecognizers containsObject:preventedGestureRecognizer]) {
             // Pinch-to-zoom is only allowed if "pinch-zoom" or "manipulation" is specified.
-            if (!iterator->value.containsAny({ WebCore::TouchAction::PinchZoom, WebCore::TouchAction::Manipulation }))
+            if (mayPinchToZoom && !iterator->value.containsAny({ WebCore::TouchAction::PinchZoom, WebCore::TouchAction::Manipulation }))
+                return YES;
+            // Double-tap-to-zoom is only disallowed if "none" is specified.
+            if (mayDoubleTapToZoom && iterator->value.contains(WebCore::TouchAction::None))
                 return YES;
         }
     }