Title: [219310] trunk
Revision
219310
Author
wenson_hs...@apple.com
Date
2017-07-10 15:08:38 -0700 (Mon, 10 Jul 2017)

Log Message

[WK2] Ignore touch events that interrupt platform-driven momentum scrolling
https://bugs.webkit.org/show_bug.cgi?id=174300
<rdar://problem/33030639>

Reviewed by Simon Fraser.

Source/WebCore:

See Source/WebKit2/ChangeLog for more detail.

Tests: fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html
       fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html
       fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html

* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::scrollingTreeNodeDidEndPanGesture):

Source/WebKit2:

Adds support for immediately failing WKContentView's UIWebTouchEventsGestureRecognizer if any touch interrupts
scroll view deceleration. Covered by 3 new LayoutTests (see Source/WebCore/ChangeLog).

* Platform/spi/ios/UIKitSPI.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView scrollViewDidEndDragging:willDecelerate:]):
(-[WKWebView scrollViewDidEndZooming:withView:atScale:]):
* UIProcess/PageClient.h:
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
* UIProcess/Scrolling/RemoteScrollingTree.cpp:
(WebKit::RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture):
* UIProcess/Scrolling/RemoteScrollingTree.h:
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
(-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture):

Adds plumbing in the UI process to alert the WKContentView when scroll view dragging has ended in an overflow
momentum scrolling region (tracked by an overflow scrolling tree node). This parallels UI process plumbing for
ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewWillStartPanGesture.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::overflowScrollViewDidEndPanGesture):
* UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView scrollViewDidEndPanOrPinchGesture]):

When the dragging phase of a scroll gesture ends, ensure that _canSendTouchEventsAsynchronously is reset to NO.
When touches are not being prevented, this flag is set to YES in -scrollViewWillStartPanOrPinchGesture: and
normally reset to NO in -_webTouchEventsRecognized: after all touch points have been released. However, in the
case where we've prematurely failed the web touch events gesture recognizer after -touchesBegan:,
-_webTouchEventsRecognized: will not be called again in a state where all touches have been released. Thus, we
also need to bookend the place where we begin allowing async touch event dispatch in
-scrollViewWillStartPanOrPinchGesture by disallowing async touch event dispatch in
-scrollViewDidEndPanOrPinchGesture.

This has no impact in the normal case where the user scrolls without momentum, since
-scrollViewDidEndPanOrPinchGesture will fire after async touch events have already been disallowed in
-_webTouchEventsRecognized:, and in the case where the page prevents default on touches, scrolling doesn't
happen anyways, so neither scrollViewWillStartPanOrPinchGesture nor scrollViewDidEndPanOrPinchGesture will be
invoked.

(-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):

Implements a new SPI hook in UIKit. This serves an identical purpose as -shouldIgnoreWebTouch, but additionally
passes the triggering UIEvent, as well as the gesture recognizer itself (following standard convention for
Objective C delegate methods). Here, we return YES in the case where one or more of the touches recognized by
the gesture is currently interrupting scroll deceleration.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::overflowScrollViewDidEndPanGesture):

LayoutTests:

Adds 3 new LayoutTests covering cases of touch event handling during scroll deceleration in mainframe and
overflow scrolling containers. See Source/WebKit2/ChangeLog for more detail.

* fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt: Added.
* fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html: Added.
* fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt: Added.
* fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html: Added.
* fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt: Added.
* fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (219309 => 219310)


--- trunk/LayoutTests/ChangeLog	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/LayoutTests/ChangeLog	2017-07-10 22:08:38 UTC (rev 219310)
@@ -1,3 +1,21 @@
+2017-07-10  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=174300
+        <rdar://problem/33030639>
+
+        Reviewed by Simon Fraser.
+
+        Adds 3 new LayoutTests covering cases of touch event handling during scroll deceleration in mainframe and
+        overflow scrolling containers. See Source/WebKit2/ChangeLog for more detail.
+
+        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt: Added.
+        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html: Added.
+        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt: Added.
+        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html: Added.
+        * fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt: Added.
+        * fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html: Added.
+
 2017-07-10  Matt Lewis  <jlew...@apple.com>
 
         Marked animations/resume-after-page-cache.html as flaky.

Added: trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,10 @@
+PASS document.body.scrollTop became different from 0
+PASS document.getElementById('touches').textContent is "1"
+PASS document.getElementById('touches').textContent is "1"
+PASS document.getElementById('touches').textContent is "2"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+To manually test, swipe down to scroll in the document. The touch count should update to 1. Tap anywhere to stop scrolling while decelerating. The touch count should remain at 1. Then tap again in the document. The touch count should be 2.
+
+The touch count is: 2

Added: trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src=""
+    <style>
+        body {
+            width: 100%;
+            height: 5000vh;
+            font-family: -apple-system;
+            color: white;
+            margin: 0;
+            background-color: red;
+            padding: 1em;
+            box-sizing: border-box;
+        }
+
+        .description {
+            position: fixed;
+        }
+    </style>
+</head>
+<body>
+<div class="description">
+    <p>To manually test, swipe down to scroll in the document. The touch count should update to 1. Tap anywhere to stop scrolling while decelerating. The touch count should remain at 1. Then tap again in the document. The touch count should be 2.</p>
+    <p>The touch count is: <span id="touches">0</span></p>
+</div>
+<script src=""
+<script>
+touchstartEventCount = 0;
+
+document.body.scrollTop = 0;
+document.body.addEventListener("touchstart", () => {
+    document.body.style.backgroundColor = (++touchstartEventCount == 2) ? "green" : "red";
+    touches.textContent = `${touchstartEventCount}`;
+});
+
+function getSwipeUIScript(fromX, fromY, toX, toY, duration)
+{
+    return `(() => {
+        uiController.dragFromPointToPoint(${fromX}, ${fromY}, ${toX}, ${toY}, ${duration}, () => {
+            uiController.uiScriptComplete("");
+        });
+    })();`;
+}
+
+function expectTouchCountToBe(count)
+{
+    shouldBeEqualToString("document.getElementById('touches').textContent", `${count}`);
+}
+
+if (window.testRunner && testRunner.runUIScript) {
+    testRunner.dumpAsText();
+    jsTestIsAsync = true;
+    testRunner.runUIScript(getSwipeUIScript(100, 0.75 * innerHeight, 100, 0.25 * innerHeight, 0.1), () => {
+        shouldBecomeDifferent("document.body.scrollTop", "0", () => {
+            expectTouchCountToBe(1);
+            UIHelper.tapAt(100, document.body.scrollTop + 0.75 * innerHeight).then(() => {
+                expectTouchCountToBe(1);
+                UIHelper.tapAt(100, document.body.scrollTop + 0.25 * innerHeight).then(() => {
+                    expectTouchCountToBe(2);
+                    finishJSTest();
+                });
+            });
+        });
+    });
+}
+</script>
+<script src=""
+</body>

Added: trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,10 @@
+PASS document.getElementById('container').scrollTop became different from 0
+PASS document.getElementById('touches').textContent is "1"
+PASS document.getElementById('touches').textContent is "1"
+PASS document.getElementById('touches').textContent is "2"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+To manually test, swipe down to scroll in the container. The touch count should update to 1. Tap to stop scrolling while decelerating. The touch count should remain at 1. Then tap again in the container. The touch count should be 2.
+
+The touch count is: 2

Added: trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src=""
+    <style>
+        body {
+            width: 100%;
+            height: 100%;
+            font-family: -apple-system;
+            margin: 0;
+            box-sizing: border-box;
+        }
+
+        #container {
+            width: 100%;
+            height: 300px;
+            overflow-y: scroll;
+            -webkit-overflow-scrolling: touch;
+            margin: 0 auto;
+            background-color: red;
+            top: 0;
+            position: absolute;
+        }
+
+        #container > div {
+            height: 10000px;
+            width: 100%;
+            float: left;
+        }
+
+        #description {
+            top: 300px;
+            position: absolute;
+        }
+    </style>
+</head>
+<body>
+<div id="container">
+    <div class="area"></div>
+</div>
+<div id="description">
+    <p>To manually test, swipe down to scroll in the container. The touch count should update to 1. Tap to stop scrolling while decelerating. The touch count should remain at 1. Then tap again in the container. The touch count should be 2.</p>
+    <p>The touch count is: <span id="touches">0</span></p>
+</div>
+<script src=""
+<script>
+touchstartEventCount = 0;
+container.scrollTop = 0;
+container.addEventListener("touchstart", () => {
+    container.style.backgroundColor = (++touchstartEventCount % 2) ? "green" : "red";
+    touches.textContent = `${touchstartEventCount}`;
+});
+
+function getSwipeUIScript(fromX, fromY, toX, toY, duration)
+{
+    return `(() => {
+        uiController.dragFromPointToPoint(${fromX}, ${fromY}, ${toX}, ${toY}, ${duration}, () => {
+            uiController.uiScriptComplete("");
+        });
+    })();`;
+}
+
+function expectTouchCountToBe(count)
+{
+    shouldBeEqualToString("document.getElementById('touches').textContent", `${count}`);
+}
+
+if (window.testRunner && testRunner.runUIScript) {
+    testRunner.dumpAsText();
+    jsTestIsAsync = true;
+    testRunner.runUIScript(getSwipeUIScript(100, 250, 100, 50, 0.1), () => {
+        shouldBecomeDifferent("document.getElementById('container').scrollTop", "0", () => {
+            expectTouchCountToBe(1);
+            UIHelper.tapAt(100, 250).then(() => {
+                expectTouchCountToBe(1);
+                UIHelper.tapAt(100, 50).then(() => {
+                    expectTouchCountToBe(2);
+                    finishJSTest();
+                });
+            });
+        });
+    });
+}
+</script>
+<script src=""
+</body>

Added: trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,13 @@
+PASS document.getElementById('container').scrollTop became different from 0
+PASS document.getElementById('containerTouches').textContent is "1"
+PASS document.getElementById('documentTouches').textContent is "1"
+PASS document.getElementById('containerTouches').textContent is "1"
+PASS document.getElementById('documentTouches').textContent is "2"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+To manually test, swipe down to scroll in the container. Both touch counts should update to 1. Then tap elsewhere in the document. The document touch count should increment to 2, but the container touch count should remain at 1.
+
+The touch count in the scroll container is: 1
+
+The touch count in the document is: 2

Added: trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html (0 => 219310)


--- trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html	2017-07-10 22:08:38 UTC (rev 219310)
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src=""
+    <style>
+        body {
+            width: 100%;
+            height: 500vh;
+            font-family: -apple-system;
+            margin: 0;
+            box-sizing: border-box;
+        }
+
+        #container {
+            width: 100%;
+            height: 300px;
+            overflow-y: scroll;
+            -webkit-overflow-scrolling: touch;
+            margin: 0 auto;
+            background-color: red;
+            top: 0;
+            position: absolute;
+        }
+
+        #container > div {
+            height: 10000px;
+            width: 100%;
+            float: left;
+        }
+
+        #description {
+            top: 300px;
+            position: absolute;
+        }
+    </style>
+</head>
+<body>
+<div id="container">
+    <div class="area"></div>
+</div>
+<div id="description">
+    <p>To manually test, swipe down to scroll in the container. Both touch counts should update to 1. Then tap elsewhere in the document. The document touch count should increment to 2, but the container touch count should remain at 1.</p>
+    <p>The touch count in the scroll container is: <span id="containerTouches">0</span></p>
+    <p>The touch count in the document is: <span id="documentTouches">0</span></p>
+</div>
+<script src=""
+<script>
+containerTouchstartEventCount = 0;
+documentTouchstartEventCount = 0;
+container.scrollTop = 0;
+document.body.scrollTop = 0;
+container.addEventListener("touchstart", () => {
+    container.style.backgroundColor = (++containerTouchstartEventCount == 1) ? "green" : "red";
+    containerTouches.textContent = `${containerTouchstartEventCount}`;
+});
+document.body.addEventListener("touchstart", () => {
+    document.body.style.backgroundColor = (++documentTouchstartEventCount == 2) ? "green" : "red";
+    documentTouches.textContent = `${documentTouchstartEventCount}`;
+});
+
+function getSwipeUIScript(fromX, fromY, toX, toY, duration)
+{
+    return `(() => {
+        uiController.dragFromPointToPoint(${fromX}, ${fromY}, ${toX}, ${toY}, ${duration}, () => {
+            uiController.uiScriptComplete("");
+        });
+    })();`;
+}
+
+function expectTouchCountsToBe(containerCount, documentCount)
+{
+    shouldBeEqualToString("document.getElementById('containerTouches').textContent", `${containerCount}`);
+    shouldBeEqualToString("document.getElementById('documentTouches').textContent", `${documentCount}`);
+}
+
+if (window.testRunner && testRunner.runUIScript) {
+    testRunner.dumpAsText();
+    jsTestIsAsync = true;
+    testRunner.runUIScript(getSwipeUIScript(100, 250, 100, 50, 0.1), () => {
+        shouldBecomeDifferent("document.getElementById('container').scrollTop", "0", () => {
+            expectTouchCountsToBe(1, 1);
+            UIHelper.tapAt(100, 350).then(() => {
+                expectTouchCountsToBe(1, 2);
+                finishJSTest();
+            });
+        });
+    });
+}
+</script>
+<script src=""
+</body>

Modified: trunk/Source/WebCore/ChangeLog (219309 => 219310)


--- trunk/Source/WebCore/ChangeLog	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebCore/ChangeLog	2017-07-10 22:08:38 UTC (rev 219310)
@@ -1,3 +1,20 @@
+2017-07-10  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=174300
+        <rdar://problem/33030639>
+
+        Reviewed by Simon Fraser.
+
+        See Source/WebKit2/ChangeLog for more detail.
+
+        Tests: fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html
+               fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html
+               fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html
+
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::scrollingTreeNodeDidEndPanGesture):
+
 2017-07-10  Jeremy Jones  <jere...@apple.com>
 
         Captions and subtitles not showing up in picture-in-picture for MSE content

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (219309 => 219310)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -101,6 +101,7 @@
 #if PLATFORM(IOS)
     virtual FloatRect fixedPositionRect() = 0;
     virtual void scrollingTreeNodeWillStartPanGesture() { }
+    virtual void scrollingTreeNodeDidEndPanGesture() { }
     virtual void scrollingTreeNodeWillStartScroll() { }
     virtual void scrollingTreeNodeDidEndScroll() { }
 #endif

Modified: trunk/Source/WebKit2/ChangeLog (219309 => 219310)


--- trunk/Source/WebKit2/ChangeLog	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/ChangeLog	2017-07-10 22:08:38 UTC (rev 219310)
@@ -1,3 +1,67 @@
+2017-07-10  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=174300
+        <rdar://problem/33030639>
+
+        Reviewed by Simon Fraser.
+
+        Adds support for immediately failing WKContentView's UIWebTouchEventsGestureRecognizer if any touch interrupts
+        scroll view deceleration. Covered by 3 new LayoutTests (see Source/WebCore/ChangeLog).
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView scrollViewDidEndDragging:willDecelerate:]):
+        (-[WKWebView scrollViewDidEndZooming:withView:atScale:]):
+        * UIProcess/PageClient.h:
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/Scrolling/RemoteScrollingTree.cpp:
+        (WebKit::RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture):
+        * UIProcess/Scrolling/RemoteScrollingTree.h:
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
+        (-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture):
+
+        Adds plumbing in the UI process to alert the WKContentView when scroll view dragging has ended in an overflow
+        momentum scrolling region (tracked by an overflow scrolling tree node). This parallels UI process plumbing for
+        ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewWillStartPanGesture.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::overflowScrollViewDidEndPanGesture):
+        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView scrollViewDidEndPanOrPinchGesture]):
+
+        When the dragging phase of a scroll gesture ends, ensure that _canSendTouchEventsAsynchronously is reset to NO.
+        When touches are not being prevented, this flag is set to YES in -scrollViewWillStartPanOrPinchGesture: and
+        normally reset to NO in -_webTouchEventsRecognized: after all touch points have been released. However, in the
+        case where we've prematurely failed the web touch events gesture recognizer after -touchesBegan:,
+        -_webTouchEventsRecognized: will not be called again in a state where all touches have been released. Thus, we
+        also need to bookend the place where we begin allowing async touch event dispatch in
+        -scrollViewWillStartPanOrPinchGesture by disallowing async touch event dispatch in
+        -scrollViewDidEndPanOrPinchGesture.
+
+        This has no impact in the normal case where the user scrolls without momentum, since
+        -scrollViewDidEndPanOrPinchGesture will fire after async touch events have already been disallowed in
+        -_webTouchEventsRecognized:, and in the case where the page prevents default on touches, scrolling doesn't
+        happen anyways, so neither scrollViewWillStartPanOrPinchGesture nor scrollViewDidEndPanOrPinchGesture will be
+        invoked.
+
+        (-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):
+
+        Implements a new SPI hook in UIKit. This serves an identical purpose as -shouldIgnoreWebTouch, but additionally
+        passes the triggering UIEvent, as well as the gesture recognizer itself (following standard convention for
+        Objective C delegate methods). Here, we return YES in the case where one or more of the touches recognized by
+        the gesture is currently interrupting scroll deceleration.
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::overflowScrollViewDidEndPanGesture):
+
 2017-07-10  Brent Fulgham  <bfulg...@apple.com>
 
         [WK2][macOS] Allow access to com.apple.cfnetwork.cfnetworkagent in the Network Process

Modified: trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h (219309 => 219310)


--- trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -689,9 +689,12 @@
     bool isPotentialTap;
 };
 
-@protocol UIWebTouchEventsGestureRecognizerDelegate
+@class UIWebTouchEventsGestureRecognizer;
+
+@protocol UIWebTouchEventsGestureRecognizerDelegate <NSObject>
 - (BOOL)isAnyTouchOverActiveArea:(NSSet *)touches;
-- (BOOL)shouldIgnoreWebTouch;
+@optional
+- (BOOL)gestureRecognizer:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer shouldIgnoreWebTouchWithEvent:(UIEvent *)event;
 @end
 
 @interface UIWebTouchEventsGestureRecognizer : UIGestureRecognizer

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -2150,6 +2150,9 @@
     // If we're decelerating, scroll offset will be updated when scrollViewDidFinishDecelerating: is called.
     if (!decelerate)
         [self _didFinishScrolling];
+
+    if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded)
+        [_contentView scrollViewDidEndPanOrPinchGesture];
 }
 
 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
@@ -2184,6 +2187,9 @@
     ASSERT(scrollView == _scrollView);
     [self _scheduleVisibleContentRectUpdateAfterScrollInView:scrollView];
     [_contentView didZoomToScale:scale];
+
+    if (scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateEnded)
+        [_contentView scrollViewDidEndPanOrPinchGesture];
 }
 
 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView

Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/PageClient.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -308,6 +308,7 @@
     virtual double minimumZoomScale() const = 0;
     virtual WebCore::FloatRect documentRect() const = 0;
     virtual void overflowScrollViewWillStartPanGesture() = 0;
+    virtual void overflowScrollViewDidEndPanGesture() = 0;
     virtual void overflowScrollViewDidScroll() = 0;
     virtual void overflowScrollWillStartScroll() = 0;
     virtual void overflowScrollDidEndScroll() = 0;

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -86,6 +86,7 @@
 #if PLATFORM(IOS)
     WebCore::FloatRect customFixedPositionRect() const;
     void scrollingTreeNodeWillStartPanGesture();
+    void scrollingTreeNodeDidEndPanGesture();
     void scrollingTreeNodeWillStartScroll();
     void scrollingTreeNodeDidEndScroll();
 #if ENABLE(CSS_SCROLL_SNAP)

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp	2017-07-10 22:08:38 UTC (rev 219310)
@@ -87,6 +87,11 @@
 {
     m_scrollingCoordinatorProxy.scrollingTreeNodeWillStartPanGesture();
 }
+
+void RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture()
+{
+    m_scrollingCoordinatorProxy.scrollingTreeNodeDidEndPanGesture();
+}
     
 void RemoteScrollingTree::scrollingTreeNodeWillStartScroll()
 {

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -61,6 +61,7 @@
 #if PLATFORM(IOS)
     WebCore::FloatRect fixedPositionRect() override;
     void scrollingTreeNodeWillStartPanGesture() override;
+    void scrollingTreeNodeDidEndPanGesture() override;
     void scrollingTreeNodeWillStartScroll() override;
     void scrollingTreeNodeDidEndScroll() override;
 #endif

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -44,6 +44,7 @@
     void overflowScrollWillStart();
     void overflowScrollDidEnd();
     void overflowScrollViewWillStartPanGesture();
+    void overflowScrollViewDidEndPanGesture();
     void scrollViewDidScroll(const WebCore::FloatPoint&, bool inUserInteration);
     void currentSnapPointIndicesDidChange(unsigned horizontal, unsigned vertical);
 

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -117,6 +117,9 @@
         _scrollingTreeNode->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
         _scrollingTreeNode->overflowScrollDidEnd();
     }
+
+    if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded)
+        _scrollingTreeNode->overflowScrollViewDidEndPanGesture();
 }
 
 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
@@ -294,6 +297,11 @@
     scrollingTree().scrollingTreeNodeWillStartPanGesture();
 }
 
+void ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture()
+{
+    scrollingTree().scrollingTreeNodeDidEndPanGesture();
+}
+
 void ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll(const FloatPoint& scrollPosition, bool inUserInteration)
 {
     if (m_updatingFromStateNode)

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -495,6 +495,7 @@
     WebCore::FloatRect computeCustomFixedPositionRect(const WebCore::FloatRect& unobscuredContentRect, const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds, const WebCore::FloatRect& currentCustomFixedPositionRect, double displayedContentScale, WebCore::FrameView::LayoutViewportConstraint = WebCore::FrameView::LayoutViewportConstraint::Unconstrained, bool visualViewportEnabled = false) const;
 
     void overflowScrollViewWillStartPanGesture();
+    void overflowScrollViewDidEndPanGesture();
     void overflowScrollViewDidScroll();
     void overflowScrollWillStartScroll();
     void overflowScrollDidEndScroll();

Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -151,6 +151,7 @@
     void disableInspectorNodeSearch() override;
 
     void overflowScrollViewWillStartPanGesture() override;
+    void overflowScrollViewDidEndPanGesture() override;
     void overflowScrollViewDidScroll() override;
     void overflowScrollWillStartScroll() override;
     void overflowScrollDidEndScroll() override;

Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -671,6 +671,11 @@
     [m_contentView scrollViewWillStartPanOrPinchGesture];
 }
 
+void PageClientImpl::overflowScrollViewDidEndPanGesture()
+{
+    [m_contentView scrollViewDidEndPanOrPinchGesture];
+}
+
 void PageClientImpl::overflowScrollViewDidScroll()
 {
     [m_contentView _didScroll];

Modified: trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -104,6 +104,11 @@
     m_webPageProxy.overflowScrollViewWillStartPanGesture();
 }
 
+void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture()
+{
+    m_webPageProxy.overflowScrollViewDidEndPanGesture();
+}
+
 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeWillStartScroll()
 {
     m_webPageProxy.overflowScrollWillStartScroll();

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h	2017-07-10 22:08:38 UTC (rev 219310)
@@ -279,6 +279,7 @@
 - (void)cleanupInteraction;
 
 - (void)scrollViewWillStartPanOrPinchGesture;
+- (void)scrollViewDidEndPanOrPinchGesture;
 
 - (BOOL)canBecomeFirstResponderForWebView;
 - (BOOL)becomeFirstResponderForWebView;

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -1845,6 +1845,11 @@
     _canSendTouchEventsAsynchronously = YES;
 }
 
+- (void)scrollViewDidEndPanOrPinchGesture
+{
+    _canSendTouchEventsAsynchronously = NO;
+}
+
 - (void)_didEndScrollingOrZooming
 {
     if (!_needsDeferredEndScrollingSelectionUpdate) {
@@ -4050,11 +4055,22 @@
 
 #pragma mark - Implementation of UIWebTouchEventsGestureRecognizerDelegate.
 
+// FIXME: Remove once -gestureRecognizer:shouldIgnoreWebTouchWithEvent: is in UIWebTouchEventsGestureRecognizer.h. Refer to <rdar://problem/33217525> for more details.
 - (BOOL)shouldIgnoreWebTouch
 {
     return NO;
 }
 
+- (BOOL)gestureRecognizer:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer shouldIgnoreWebTouchWithEvent:(UIEvent *)event
+{
+    NSSet<UITouch *> *touches = [event touchesForGestureRecognizer:gestureRecognizer];
+    for (UITouch *touch in touches) {
+        if ([touch.view isKindOfClass:[UIScrollView class]] && [(UIScrollView *)touch.view _isInterruptingDeceleration])
+            return YES;
+    }
+    return self._scroller._isInterruptingDeceleration;
+}
+
 - (BOOL)isAnyTouchOverActiveArea:(NSSet *)touches
 {
     return YES;

Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (219309 => 219310)


--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm	2017-07-10 21:31:50 UTC (rev 219309)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm	2017-07-10 22:08:38 UTC (rev 219310)
@@ -272,6 +272,11 @@
     m_pageClient.overflowScrollViewWillStartPanGesture();
 }
 
+void WebPageProxy::overflowScrollViewDidEndPanGesture()
+{
+    m_pageClient.overflowScrollViewDidEndPanGesture();
+}
+
 void WebPageProxy::overflowScrollViewDidScroll()
 {
     m_pageClient.overflowScrollViewDidScroll();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to