Title: [201958] trunk
Revision
201958
Author
[email protected]
Date
2016-06-10 18:18:37 -0700 (Fri, 10 Jun 2016)

Log Message

Add support for passive event listeners on touch events
https://bugs.webkit.org/show_bug.cgi?id=158601

Patch by Benjamin Poulain <[email protected]> on 2016-06-10
Reviewed by Simon Fraser.

Source/WebCore:

This patch wires "passive" state of EventTarget to the delivery of touch
events in WebKit2.

Instead of having a NonFastScrollableRegion, we have a pair of regions
in EventTrackingRegions.
The "asynchronousDispatchRegion" tracks the area for which all event
listeners are passive. For those, events should be dispatched asynchronously.
The "synchronousDispatchRegion" tracks the area for which there is at
least one active event listener. Events have to be dispatched synchronously
for correctness.

Tests: fast/events/touch/ios/tap-with-active-listener-on-elements.html
       fast/events/touch/ios/tap-with-active-listener-on-window.html
       fast/events/touch/ios/tap-with-passive-listener-on-elements.html
       fast/events/touch/ios/tap-with-passive-listener-on-window.html

* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::wheelEventHandlersChanged):
(WebCore::Document::Document): Deleted.
* dom/Document.h:

* dom/EventListenerMap.cpp:
(WebCore::EventListenerMap::containsActive):
If a Target has multiple listener for an event type, we want to know
if any of them is active.

* dom/EventListenerMap.h:
* dom/EventTarget.cpp:
(WebCore::EventTarget::hasActiveEventListeners):
(WebCore::EventTarget::hasActiveTouchEventListeners):
* dom/EventTarget.h:

* page/DebugPageOverlays.cpp:
(WebCore::NonFastScrollableRegionOverlay::updateRegion):
I did not change the debug overlays.
The NonFastScrollable area is the region for which events needs
synchronous dispatch. Everything else should scroll without delay.

* page/FrameView.cpp:
(WebCore::FrameView::scrollableAreaSetChanged):
* page/Page.cpp:
(WebCore::Page::nonFastScrollableRects):
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::setEventTrackingRegionsDirty):
(WebCore::AsyncScrollingCoordinator::willCommitTree):
(WebCore::AsyncScrollingCoordinator::updateEventTrackingRegions):
(WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
(WebCore::AsyncScrollingCoordinator::frameViewEventTrackingRegionsChanged):
(WebCore::AsyncScrollingCoordinator::scrollingStateTreeAsText):
(WebCore::AsyncScrollingCoordinator::setNonFastScrollableRegionDirty): Deleted.
(WebCore::AsyncScrollingCoordinator::updateNonFastScrollableRegion): Deleted.
(WebCore::AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Deleted.
* page/scrolling/AsyncScrollingCoordinator.h:
(WebCore::AsyncScrollingCoordinator::eventTrackingRegionsDirty):
(WebCore::AsyncScrollingCoordinator::nonFastScrollableRegionDirty): Deleted.

* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::absoluteEventTrackingRegionsForFrame):
(WebCore::ScrollingCoordinator::absoluteEventTrackingRegions):
(WebCore::ScrollingCoordinator::absoluteNonFastScrollableRegionForFrame): Deleted.
(WebCore::ScrollingCoordinator::absoluteNonFastScrollableRegion): Deleted.
I intentionally left the Wheel event with synchronous dispatch.
This use case will need its own set of tests.

* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::frameViewEventTrackingRegionsChanged):
(WebCore::ScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Deleted.
* page/scrolling/ScrollingStateFrameScrollingNode.cpp:
(WebCore::ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode):
(WebCore::ScrollingStateFrameScrollingNode::setEventTrackingRegions):
(WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
(WebCore::ScrollingStateFrameScrollingNode::setNonFastScrollableRegion): Deleted.
* page/scrolling/ScrollingStateFrameScrollingNode.h:
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::shouldHandleWheelEventSynchronously):
(WebCore::ScrollingTree::commitNewTreeState):
(WebCore::ScrollingTree::eventTrackingTypeForPoint):
(WebCore::ScrollingTree::isPointInNonFastScrollableRegion): Deleted.
* page/scrolling/ScrollingTree.h:
* page/scrolling/mac/ScrollingCoordinatorMac.mm:
(WebCore::ScrollingCoordinatorMac::scheduleTreeStateCommit):
* platform/EventTrackingRegions.h: Added.
(WebCore::EventTrackingRegions::isEmpty):
(WebCore::EventTrackingRegions::trackingTypeForPoint):
(WebCore::operator==):

Source/WebKit2:

* Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
(ArgumentCoder<ScrollingStateFrameScrollingNode>::encode):
(ArgumentCoder<ScrollingStateFrameScrollingNode>::decode):
(WebKit::dump):
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<EventTrackingRegions>::encode):
(IPC::ArgumentCoder<EventTrackingRegions>::decode):
* Shared/WebCoreArgumentCoders.h:
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
(WebKit::RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint):
(WebKit::RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion): Deleted.
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::touchEventTrackingType):
The type is the most restrictive type of all the touch points.
If any touch point needs synchronous tracking, everything has to be synchronous.

(WebKit::WebPageProxy::handleTouchEventSynchronously):
This is a very unfortunate design.

The upper layer dealing with UIKit knows about gesture and when something
can be dispatched asynchrnously because a gesture has started.
This layer knows about tracking and can use that extra inforamtion
to dispatch an event asynchrnously anyway.

In the future, we should refactor this to let WebPageProxy
always decide of the dispatch type. I am just concerned changing
the upper layer while we are stabilizing WebKit.

(WebKit::WebPageProxy::handleTouchEventAsynchronously):
(WebKit::WebPageProxy::handleTouchEvent):
(WebKit::WebPageProxy::resetState):
(WebKit::WebPageProxy::WebPageProxy): Deleted.
(WebKit::WebPageProxy::shouldStartTrackingTouchEvents): Deleted.
* UIProcess/WebPageProxy.h:

LayoutTests:

* fast/events/touch/ios/tap-with-active-listener-on-elements-expected.txt: Added.
* fast/events/touch/ios/tap-with-active-listener-on-elements.html: Added.
* fast/events/touch/ios/tap-with-active-listener-on-window-expected.txt: Added.
* fast/events/touch/ios/tap-with-active-listener-on-window.html: Added.
* fast/events/touch/ios/tap-with-passive-listener-inside-active-listener-expected.txt: Added.
* fast/events/touch/ios/tap-with-passive-listener-on-elements-expected.txt: Added.
* fast/events/touch/ios/tap-with-passive-listener-on-elements.html: Added.
* fast/events/touch/ios/tap-with-passive-listener-on-window-expected.txt: Added.
* fast/events/touch/ios/tap-with-passive-listener-on-window.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (201957 => 201958)


--- trunk/LayoutTests/ChangeLog	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/ChangeLog	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,3 +1,20 @@
+2016-06-10  Benjamin Poulain  <[email protected]>
+
+        Add support for passive event listeners on touch events
+        https://bugs.webkit.org/show_bug.cgi?id=158601
+
+        Reviewed by Simon Fraser.
+
+        * fast/events/touch/ios/tap-with-active-listener-on-elements-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-active-listener-on-elements.html: Added.
+        * fast/events/touch/ios/tap-with-active-listener-on-window-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-active-listener-on-window.html: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-inside-active-listener-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-on-elements-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-on-elements.html: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-on-window-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-on-window.html: Added.
+
 2016-06-10  Enrica Casucci  <[email protected]>
 
         REGRESSION(r198177): Cannot paste an image when the pasteboard format is mime type.

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements-expected.txt (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,17 @@
+Tap on Target1 (green)
+
+Listener target1 received cancelable event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received cancelable event touchend targetting eventTarget1
+Done
+Tap on Target2 (red)
+
+Listener target1 received cancelable event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received cancelable event touchend targetting eventTarget2
+Done
+Tap on Target3 (blue)
+
+Listener target3 received cancelable event touchstart targetting eventTarget3 at 250, 50
+Listener target1 received cancelable event touchstart targetting eventTarget3 at 250, 50
+Listener target3 received cancelable event touchend targetting eventTarget3
+Listener target1 received cancelable event touchend targetting eventTarget3
+

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements.html (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-elements.html	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function runTest()
+        {
+            if (!testRunner.runUIScript)
+                return;
+
+            function fail(event) {
+                output += 'FAILED!: No mouse event should be receive, we got a ' + event.type;
+            }
+            window.addEventListener('mouseover', fail);
+            window.addEventListener('mouseout', fail);
+            window.addEventListener('mouseenter', fail);
+            window.addEventListener('mouseleave', fail);
+            window.addEventListener('mousedown', fail);
+            window.addEventListener('mousemove', fail);
+            window.addEventListener('mouseup', fail);
+            window.addEventListener('click', fail);
+
+            let output = '';
+            function getLogEvent(listener) {
+                return function logEvent(event) {
+                    output += 'Listener ' + listener + ' received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + ' targetting ' + event.target.id;
+                    if (event.touches[0] && event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '<br>';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent("target1"));
+            target1.addEventListener('touchmove', getLogEvent("target1"));
+            target1.addEventListener('touchend', getLogEvent("target1"));
+            target1.addEventListener('touchcancel', getLogEvent("target1"));
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent("target3"));
+            target3.addEventListener('touchmove', getLogEvent("target3"));
+            target3.addEventListener('touchend', getLogEvent("target3"));
+            target3.addEventListener('touchcancel', getLogEvent("target3"));
+
+            output += "<h1>Tap on Target1 (green)</h1>";
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += "<h1>Tap on Target2 (red)</h1>";
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += "<h1>Tap on Target3 (blue)</h1>";
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                    document.getElementById('output').innerHTML = output;
+                    testRunner.notifyDone();
+                });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+    <style>
+        * { touch-action: manipulation; }
+        body {
+            margin: 0;
+        }
+        #eventTarget1, #eventTarget2, #eventTarget3 {
+            width: 100px;
+            height: 100px;
+        }
+        #eventTarget1 {
+            background-color: green;
+        }
+        #eventTarget2 {
+            background-color: red;
+            position: absolute;
+            left: 100px;
+        }
+        #eventTarget3 {
+            background-color: blue;
+            position: absolute;
+            left: 100px;
+        }
+    </style>
+    <meta name="viewport" content="initial-scale=1">
+</head>
+<body>
+    <div id=eventTarget1>
+        <div id=eventTarget2>
+            <div id=eventTarget3>
+            </div>
+        </div>
+    </div>
+    <div id=output>
+    This test requires UIScriptController to run.
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window-expected.txt (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,3 @@
+Received cancelable event touchstart at 50, 50
+Received cancelable event touchend
+Done

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window.html (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-on-window.html	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript()
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(50, 50, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function runTest()
+        {
+            var output = '';
+            window.addEventListener('touchstart', function(event) {
+                output += 'Received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY + '<br>';
+                event.preventDefault();
+            });
+
+            window.addEventListener('touchend', function(event) {
+                output += 'Received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + '<br>';
+            });
+
+            function fail(event) {
+                output += 'FAILED!: No mouse event should be receive, we got a ' + event.type;
+            }
+            window.addEventListener('mouseover', fail);
+            window.addEventListener('mouseout', fail);
+            window.addEventListener('mouseenter', fail);
+            window.addEventListener('mouseleave', fail);
+            window.addEventListener('mousedown', fail);
+            window.addEventListener('mousemove', fail);
+            window.addEventListener('mouseup', fail);
+            window.addEventListener('click', fail);
+
+            if (testRunner.runUIScript) {
+                testRunner.runUIScript(getUIScript(), function(result) {
+                    output += result;
+                    document.getElementById('output').innerHTML = output;
+                    testRunner.notifyDone();
+                });
+            }
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+    <style>
+        * { touch-action: manipulation; }
+    </style>
+</head>
+<body>
+    <div id=output>
+    This test requires UIScriptController to run.
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener-expected.txt (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,33 @@
+Tap on Target1 (green)
+
+Listener target1 received cancelable event touchstart targetting eventTarget1 at 50, 50
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+Listener target1 received cancelable event touchend targetting eventTarget1
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+Done
+Tap on Target2 (red)
+
+Listener target1 received cancelable event touchstart targetting eventTarget2 at 150, 50
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+Listener target1 received cancelable event touchend targetting eventTarget2
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+Done
+Tap on Target3 (blue)
+
+Listener target3 received cancelable event touchstart targetting eventTarget3 at 250, 50
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): false
+Listener target1 received cancelable event touchstart targetting eventTarget3 at 250, 50
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+Listener target3 received cancelable event touchend targetting eventTarget3
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): false
+Listener target1 received cancelable event touchend targetting eventTarget3
+defaultPrevented before preventDefault(): false
+defaultPrevented after preventDefault(): true
+

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements-expected.txt (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,17 @@
+Tap on Target1 (green)
+
+Listener target1 received event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received event touchend targetting eventTarget1
+Done
+Tap on Target2 (red)
+
+Listener target1 received event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received event touchend targetting eventTarget2
+Done
+Tap on Target3 (blue)
+
+Listener target3 received event touchstart targetting eventTarget3 at 250, 50
+Listener target1 received event touchstart targetting eventTarget3 at 250, 50
+Listener target3 received event touchend targetting eventTarget3
+Listener target1 received event touchend targetting eventTarget3
+

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements.html (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-elements.html	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function runTest()
+        {
+            if (!testRunner.runUIScript)
+                return;
+
+            function fail(event) {
+                output += 'FAILED!: No mouse event should be receive, we got a ' + event.type;
+            }
+            window.addEventListener('mouseover', fail);
+            window.addEventListener('mouseout', fail);
+            window.addEventListener('mouseenter', fail);
+            window.addEventListener('mouseleave', fail);
+            window.addEventListener('mousedown', fail);
+            window.addEventListener('mousemove', fail);
+            window.addEventListener('mouseup', fail);
+            window.addEventListener('click', fail);
+
+            let output = '';
+            function getLogEvent(listener) {
+                return function logEvent(event) {
+                    output += 'Listener ' + listener + ' received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + ' targetting ' + event.target.id;
+                    if (event.touches[0] && event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '<br>';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent("target1"), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent("target1"), { 'passive': true });
+            target1.addEventListener('touchend', getLogEvent("target1"), { 'passive': true });
+            target1.addEventListener('touchcancel', getLogEvent("target1"), { 'passive': true });
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchend', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent("target3"), { 'passive': true });
+
+            output += "<h1>Tap on Target1 (green)</h1>";
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += "<h1>Tap on Target2 (red)</h1>";
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += "<h1>Tap on Target3 (blue)</h1>";
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+    <style>
+        * { touch-action: manipulation; }
+        body {
+            margin: 0;
+        }
+        #eventTarget1, #eventTarget2, #eventTarget3 {
+            width: 100px;
+            height: 100px;
+        }
+        #eventTarget1 {
+            background-color: green;
+        }
+        #eventTarget2 {
+            background-color: red;
+            position: absolute;
+            left: 100px;
+        }
+        #eventTarget3 {
+            background-color: blue;
+            position: absolute;
+            left: 100px;
+        }
+    </style>
+    <meta name="viewport" content="initial-scale=1">
+</head>
+<body>
+    <div id=eventTarget1>
+        <div id=eventTarget2>
+            <div id=eventTarget3>
+            </div>
+        </div>
+    </div>
+    <div id=output>
+    This test requires UIScriptController to run.
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window-expected.txt (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,3 @@
+Received event touchstart at 50, 50
+Received event touchend
+Done

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window.html (0 => 201958)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-on-window.html	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript()
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(50, 50, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function runTest()
+        {
+            var output = '';
+            window.addEventListener('touchstart', function(event) {
+                output += 'Received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY + '<br>';
+                event.preventDefault();
+            }, { 'passive': true });
+
+            window.addEventListener('touchend', function(event) {
+                output += 'Received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + '<br>';
+            }, { 'passive': true });
+
+            if (testRunner.runUIScript) {
+                testRunner.runUIScript(getUIScript(), function(result) {
+                    output += result;
+                    document.getElementById('output').innerHTML = output;
+                    testRunner.notifyDone();
+                });
+            }
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+</head>
+<style>
+    * { touch-action: manipulation; }
+</style>
+<body>
+    <div id=output>
+    This test requires UIScriptController to run.
+    </div>
+</body>
+</html>

Modified: trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -2,7 +2,7 @@
   (scrollable area size 785 600)
   (contents size 785 2213)
   (requested scroll position 0 200)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (0,13) size 204x204)
   (children 1
     (Fixed node

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (45,47) size 404x304)
   (children 1
     (Frame scrolling node

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (45,47) size 404x304)
   (children 1
     (Fixed node

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (45,37) size 404x304)
   (children 1
     (Fixed node

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (45,47) size 404x304)
   (children 1
     (Frame scrolling node

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 800 600)
   (contents size 800 600)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (0,0) size 800x594)
 )
 

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 800 600)
   (contents size 800 600)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (0,166) size 280x434)
 )
 

Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt (201957 => 201958)


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt	2016-06-11 01:18:37 UTC (rev 201958)
@@ -2,7 +2,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 757)
-  (non-fast-scrollable region
+  (synchronous event dispatch region
     at (68,68) size 300x300)
 )
 

Modified: trunk/Source/WebCore/ChangeLog (201957 => 201958)


--- trunk/Source/WebCore/ChangeLog	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/ChangeLog	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,3 +1,97 @@
+2016-06-10  Benjamin Poulain  <[email protected]>
+
+        Add support for passive event listeners on touch events
+        https://bugs.webkit.org/show_bug.cgi?id=158601
+
+        Reviewed by Simon Fraser.
+
+        This patch wires "passive" state of EventTarget to the delivery of touch
+        events in WebKit2.
+
+        Instead of having a NonFastScrollableRegion, we have a pair of regions
+        in EventTrackingRegions.
+        The "asynchronousDispatchRegion" tracks the area for which all event
+        listeners are passive. For those, events should be dispatched asynchronously.
+        The "synchronousDispatchRegion" tracks the area for which there is at
+        least one active event listener. Events have to be dispatched synchronously
+        for correctness.
+
+        Tests: fast/events/touch/ios/tap-with-active-listener-on-elements.html
+               fast/events/touch/ios/tap-with-active-listener-on-window.html
+               fast/events/touch/ios/tap-with-passive-listener-on-elements.html
+               fast/events/touch/ios/tap-with-passive-listener-on-window.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Document.cpp:
+        (WebCore::Document::wheelEventHandlersChanged):
+        (WebCore::Document::Document): Deleted.
+        * dom/Document.h:
+
+        * dom/EventListenerMap.cpp:
+        (WebCore::EventListenerMap::containsActive):
+        If a Target has multiple listener for an event type, we want to know
+        if any of them is active.
+
+        * dom/EventListenerMap.h:
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::hasActiveEventListeners):
+        (WebCore::EventTarget::hasActiveTouchEventListeners):
+        * dom/EventTarget.h:
+
+        * page/DebugPageOverlays.cpp:
+        (WebCore::NonFastScrollableRegionOverlay::updateRegion):
+        I did not change the debug overlays.
+        The NonFastScrollable area is the region for which events needs
+        synchronous dispatch. Everything else should scroll without delay.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollableAreaSetChanged):
+        * page/Page.cpp:
+        (WebCore::Page::nonFastScrollableRects):
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::setEventTrackingRegionsDirty):
+        (WebCore::AsyncScrollingCoordinator::willCommitTree):
+        (WebCore::AsyncScrollingCoordinator::updateEventTrackingRegions):
+        (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
+        (WebCore::AsyncScrollingCoordinator::frameViewEventTrackingRegionsChanged):
+        (WebCore::AsyncScrollingCoordinator::scrollingStateTreeAsText):
+        (WebCore::AsyncScrollingCoordinator::setNonFastScrollableRegionDirty): Deleted.
+        (WebCore::AsyncScrollingCoordinator::updateNonFastScrollableRegion): Deleted.
+        (WebCore::AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Deleted.
+        * page/scrolling/AsyncScrollingCoordinator.h:
+        (WebCore::AsyncScrollingCoordinator::eventTrackingRegionsDirty):
+        (WebCore::AsyncScrollingCoordinator::nonFastScrollableRegionDirty): Deleted.
+
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::absoluteEventTrackingRegionsForFrame):
+        (WebCore::ScrollingCoordinator::absoluteEventTrackingRegions):
+        (WebCore::ScrollingCoordinator::absoluteNonFastScrollableRegionForFrame): Deleted.
+        (WebCore::ScrollingCoordinator::absoluteNonFastScrollableRegion): Deleted.
+        I intentionally left the Wheel event with synchronous dispatch.
+        This use case will need its own set of tests.
+
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::frameViewEventTrackingRegionsChanged):
+        (WebCore::ScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Deleted.
+        * page/scrolling/ScrollingStateFrameScrollingNode.cpp:
+        (WebCore::ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode):
+        (WebCore::ScrollingStateFrameScrollingNode::setEventTrackingRegions):
+        (WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
+        (WebCore::ScrollingStateFrameScrollingNode::setNonFastScrollableRegion): Deleted.
+        * page/scrolling/ScrollingStateFrameScrollingNode.h:
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::shouldHandleWheelEventSynchronously):
+        (WebCore::ScrollingTree::commitNewTreeState):
+        (WebCore::ScrollingTree::eventTrackingTypeForPoint):
+        (WebCore::ScrollingTree::isPointInNonFastScrollableRegion): Deleted.
+        * page/scrolling/ScrollingTree.h:
+        * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+        (WebCore::ScrollingCoordinatorMac::scheduleTreeStateCommit):
+        * platform/EventTrackingRegions.h: Added.
+        (WebCore::EventTrackingRegions::isEmpty):
+        (WebCore::EventTrackingRegions::trackingTypeForPoint):
+        (WebCore::operator==):
+
 2016-06-10  Enrica Casucci  <[email protected]>
 
         REGRESSION(r198177): Cannot paste an image when the pasteboard format is mime type.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (201957 => 201958)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1030,6 +1030,7 @@
 		26255F0018878DFF0006E1FD /* UserAgentIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26255EFF18878DFF0006E1FD /* UserAgentIOS.mm */; };
 		26255F0318878E110006E1FD /* UserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 26255F0118878E110006E1FD /* UserAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		26255F0418878E110006E1FD /* UserAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26255F0218878E110006E1FD /* UserAgentMac.mm */; };
+		262EC41A1D078FB900BA78FC /* EventTrackingRegions.h in Headers */ = {isa = PBXBuildFile; fileRef = 262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		265541391489811C000DFC5D /* KeyEventCodesIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 265541371489811C000DFC5D /* KeyEventCodesIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2655413A1489811C000DFC5D /* KeyEventIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 265541381489811C000DFC5D /* KeyEventIOS.mm */; };
 		265541521489B233000DFC5D /* CursorIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2655414B1489AA2B000DFC5D /* CursorIOS.cpp */; };
@@ -8510,6 +8511,7 @@
 		26255EFF18878DFF0006E1FD /* UserAgentIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserAgentIOS.mm; sourceTree = "<group>"; };
 		26255F0118878E110006E1FD /* UserAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserAgent.h; sourceTree = "<group>"; };
 		26255F0218878E110006E1FD /* UserAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserAgentMac.mm; sourceTree = "<group>"; };
+		262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventTrackingRegions.h; sourceTree = "<group>"; };
 		265541371489811C000DFC5D /* KeyEventCodesIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyEventCodesIOS.h; sourceTree = "<group>"; };
 		265541381489811C000DFC5D /* KeyEventIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyEventIOS.mm; sourceTree = "<group>"; };
 		2655414B1489AA2B000DFC5D /* CursorIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CursorIOS.cpp; sourceTree = "<group>"; };
@@ -22951,6 +22953,7 @@
 				A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
 				A7CFB3D00B7ED10A0070C32D /* DragImage.h */,
 				1CA19E150DC255CA0065A994 /* EventLoop.h */,
+				262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */,
 				934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
 				066C772A0AB603B700238CC4 /* FileChooser.h */,
 				4689F1AE1267BAE100E8D380 /* FileMetadata.h */,
@@ -28143,6 +28146,7 @@
 				439D334513A6911C00C20F4F /* SVGAnimatorFactory.h in Headers */,
 				08FB3F8413BC754C0099FC18 /* SVGAttributeToPropertyMap.h in Headers */,
 				B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */,
+				262EC41A1D078FB900BA78FC /* EventTrackingRegions.h in Headers */,
 				B222799F0D00BF220071B782 /* SVGClipPathElement.h in Headers */,
 				B22279A20D00BF220071B782 /* SVGColor.h in Headers */,
 				B22279A50D00BF220071B782 /* SVGComponentTransferFunctionElement.h in Headers */,

Modified: trunk/Source/WebCore/dom/Document.cpp (201957 => 201958)


--- trunk/Source/WebCore/dom/Document.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/Document.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -431,8 +431,6 @@
     : ContainerNode(*this, CreateDocument)
     , TreeScope(*this)
 #if ENABLE(IOS_TOUCH_EVENTS)
-    , m_handlingTouchEvent(false)
-    , m_touchEventRegionsDirty(false)
     , m_touchEventsChangedTimer(*this, &Document::touchEventsChangedTimerFired)
 #endif
     , m_referencingNodeCount(0)
@@ -6284,7 +6282,7 @@
 
     if (FrameView* frameView = view()) {
         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-            scrollingCoordinator->frameViewNonFastScrollableRegionChanged(*frameView);
+            scrollingCoordinator->frameViewEventTrackingRegionsChanged(*frameView);
     }
 
     bool haveHandlers = m_wheelEventTargets && !m_wheelEventTargets->isEmpty();

Modified: trunk/Source/WebCore/dom/Document.h (201957 => 201958)


--- trunk/Source/WebCore/dom/Document.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/Document.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -32,6 +32,7 @@
 #include "ContainerNode.h"
 #include "DocumentEventQueue.h"
 #include "DocumentTiming.h"
+#include "EventTrackingRegions.h"
 #include "FocusDirection.h"
 #include "FontSelectorClient.h"
 #include "MediaProducer.h"

Modified: trunk/Source/WebCore/dom/EventListenerMap.cpp (201957 => 201958)


--- trunk/Source/WebCore/dom/EventListenerMap.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/EventListenerMap.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -77,6 +77,19 @@
     return false;
 }
 
+bool EventListenerMap::containsActive(const AtomicString& eventType) const
+{
+    for (auto& entry : m_entries) {
+        if (entry.first == eventType) {
+            for (auto& eventListener : *entry.second) {
+                if (!eventListener.isPassive)
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
 void EventListenerMap::clear()
 {
     assertNoActiveIterators();

Modified: trunk/Source/WebCore/dom/EventListenerMap.h (201957 => 201958)


--- trunk/Source/WebCore/dom/EventListenerMap.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/EventListenerMap.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -52,6 +52,7 @@
     bool isEmpty() const { return m_entries.isEmpty(); }
     WEBCORE_EXPORT bool contains(const AtomicString& eventType) const;
     bool containsCapturing(const AtomicString& eventType) const;
+    bool containsActive(const AtomicString& eventType) const;
 
     void clear();
 

Modified: trunk/Source/WebCore/dom/EventTarget.cpp (201957 => 201958)


--- trunk/Source/WebCore/dom/EventTarget.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/EventTarget.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -141,6 +141,14 @@
     return 0;
 }
 
+bool EventTarget::hasActiveEventListeners(const AtomicString& eventType) const
+{
+    EventTargetData* eventTargetData = const_cast<EventTarget*>(this)->eventTargetData();
+    if (!eventTargetData)
+        return false;
+    return eventTargetData->eventListenerMap.containsActive(eventType);
+}
+
 bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
 {
     EventListener* listener = getAttributeEventListener(eventType);
@@ -233,7 +241,17 @@
 
     return !event.defaultPrevented();
 }
-        
+
+bool EventTarget::hasActiveTouchEventListeners() const
+{
+    const EventNames& names = eventNames();
+    return hasActiveEventListeners(names.touchstartEvent)
+        || hasActiveEventListeners(names.touchmoveEvent)
+        || hasActiveEventListeners(names.touchendEvent)
+        || hasActiveEventListeners(names.touchcancelEvent)
+        || hasActiveEventListeners(names.touchforcechangeEvent);
+}
+
 void EventTarget::fireEventListeners(Event& event, EventTargetData* d, EventListenerVector& entry)
 {
     Ref<EventTarget> protectedThis(*this);

Modified: trunk/Source/WebCore/dom/EventTarget.h (201957 => 201958)


--- trunk/Source/WebCore/dom/EventTarget.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/dom/EventTarget.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -160,6 +160,7 @@
     bool hasEventListeners() const;
     bool hasEventListeners(const AtomicString& eventType);
     bool hasCapturingEventListeners(const AtomicString& eventType);
+    bool hasActiveEventListeners(const AtomicString& eventType) const;
     const EventListenerVector& getEventListeners(const AtomicString& eventType);
 
     bool fireEventListeners(Event&);
@@ -168,6 +169,8 @@
     void visitJSEventListeners(JSC::SlotVisitor&);
     void invalidateJSEventListeners(JSC::JSObject*);
 
+    bool hasActiveTouchEventListeners() const;
+
 protected:
     virtual ~EventTarget();
     

Modified: trunk/Source/WebCore/page/DebugPageOverlays.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/DebugPageOverlays.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/DebugPageOverlays.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -131,8 +131,10 @@
     std::unique_ptr<Region> region = std::make_unique<Region>();
 
     if (Page* page = m_frame.page()) {
-        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-            *region = scrollingCoordinator->absoluteNonFastScrollableRegion();
+        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
+            EventTrackingRegions eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
+            *region = eventTrackingRegions.synchronousDispatchRegion;
+        }
     }
 
     bool regionChanged = !m_region || !(*m_region == *region);

Modified: trunk/Source/WebCore/page/FrameView.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/FrameView.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/FrameView.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -4619,7 +4619,7 @@
 {
     if (auto* page = frame().page()) {
         if (auto* scrollingCoordinator = page->scrollingCoordinator())
-            scrollingCoordinator->frameViewNonFastScrollableRegionChanged(*this);
+            scrollingCoordinator->frameViewEventTrackingRegionsChanged(*this);
     }
 }
 

Modified: trunk/Source/WebCore/page/Page.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/Page.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/Page.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -372,7 +372,7 @@
 
     Vector<IntRect> rects;
     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
-        rects = scrollingCoordinator->absoluteNonFastScrollableRegion().rects();
+        rects = scrollingCoordinator->absoluteEventTrackingRegions().synchronousDispatchRegion.rects();
 
     Vector<FloatQuad> quads(rects.size());
     for (size_t i = 0; i < rects.size(); ++i)

Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -77,28 +77,28 @@
         node.setVerticalSnapOffsets(snapOffsetsAsFloat);
 }
 
-void AsyncScrollingCoordinator::setNonFastScrollableRegionDirty()
+void AsyncScrollingCoordinator::setEventTrackingRegionsDirty()
 {
-    m_nonFastScrollableRegionDirty = true;
+    m_eventTrackingRegionsDirty = true;
     // We have to schedule a commit, but the computed non-fast region may not have actually changed.
     scheduleTreeStateCommit();
 }
 
 void AsyncScrollingCoordinator::willCommitTree()
 {
-    updateNonFastScrollableRegion();
+    updateEventTrackingRegions();
 }
 
-void AsyncScrollingCoordinator::updateNonFastScrollableRegion()
+void AsyncScrollingCoordinator::updateEventTrackingRegions()
 {
-    if (!m_nonFastScrollableRegionDirty)
+    if (!m_eventTrackingRegionsDirty)
         return;
 
     if (!m_scrollingStateTree->rootStateNode())
         return;
 
-    m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(absoluteNonFastScrollableRegion());
-    m_nonFastScrollableRegionDirty = false;
+    m_scrollingStateTree->rootStateNode()->setEventTrackingRegions(absoluteEventTrackingRegions());
+    m_eventTrackingRegionsDirty = false;
 }
 
 void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView& frameView)
@@ -115,8 +115,8 @@
     // frame view whose layout was updated is not the main frame.
     // In the future, we may want to have the ability to set non-fast scrolling regions for more than
     // just the root node. But right now, this concept only applies to the root.
-    m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(absoluteNonFastScrollableRegion());
-    m_nonFastScrollableRegionDirty = false;
+    m_scrollingStateTree->rootStateNode()->setEventTrackingRegions(absoluteEventTrackingRegions());
+    m_eventTrackingRegionsDirty = false;
 
     if (!coordinatesScrollingForFrameView(frameView))
         return;
@@ -164,12 +164,12 @@
     node->setScrollableAreaParameters(scrollParameters);
 }
 
-void AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged(FrameView&)
+void AsyncScrollingCoordinator::frameViewEventTrackingRegionsChanged(FrameView&)
 {
     if (!m_scrollingStateTree->rootStateNode())
         return;
 
-    setNonFastScrollableRegionDirty();
+    setEventTrackingRegionsDirty();
 }
 
 void AsyncScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView)
@@ -551,8 +551,8 @@
 String AsyncScrollingCoordinator::scrollingStateTreeAsText() const
 {
     if (m_scrollingStateTree->rootStateNode()) {
-        if (m_nonFastScrollableRegionDirty)
-            m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(absoluteNonFastScrollableRegion());
+        if (m_eventTrackingRegionsDirty)
+            m_scrollingStateTree->rootStateNode()->setEventTrackingRegions(absoluteEventTrackingRegions());
         return m_scrollingStateTree->rootStateNode()->scrollingStateTreeAsText();
     }
 

Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -80,7 +80,7 @@
     WEBCORE_EXPORT String scrollingStateTreeAsText() const override;
     WEBCORE_EXPORT void willCommitTree() override;
 
-    bool nonFastScrollableRegionDirty() const { return m_nonFastScrollableRegionDirty; }
+    bool eventTrackingRegionsDirty() const { return m_eventTrackingRegionsDirty; }
 
 private:
     bool isAsyncScrollingCoordinator() const override { return true; }
@@ -90,7 +90,7 @@
 
     WEBCORE_EXPORT void frameViewLayoutUpdated(FrameView&) override;
     WEBCORE_EXPORT void frameViewRootLayerDidChange(FrameView&) override;
-    WEBCORE_EXPORT void frameViewNonFastScrollableRegionChanged(FrameView&) override;
+    WEBCORE_EXPORT void frameViewEventTrackingRegionsChanged(FrameView&) override;
 
     WEBCORE_EXPORT bool requestScrollPositionUpdate(FrameView&, const IntPoint&) override;
 
@@ -121,8 +121,8 @@
     void updateMainFrameScrollLayerPosition();
 
     void updateScrollPositionAfterAsyncScrollTimerFired();
-    void setNonFastScrollableRegionDirty();
-    void updateNonFastScrollableRegion();
+    void setEventTrackingRegionsDirty();
+    void updateEventTrackingRegions();
     
     FrameView* frameViewForScrollingNode(ScrollingNodeID) const;
 
@@ -160,7 +160,7 @@
     std::unique_ptr<ScrollingStateTree> m_scrollingStateTree;
     RefPtr<ScrollingTree> m_scrollingTree;
 
-    bool m_nonFastScrollableRegionDirty { false };
+    bool m_eventTrackingRegionsDirty { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -96,11 +96,11 @@
     return renderView->usesCompositing();
 }
 
-Region ScrollingCoordinator::absoluteNonFastScrollableRegionForFrame(const Frame& frame) const
+EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegionsForFrame(const Frame& frame) const
 {
     RenderView* renderView = frame.contentRenderer();
     if (!renderView || renderView->documentBeingDestroyed())
-        return Region();
+        return EventTrackingRegions();
 
 #if ENABLE(IOS_TOUCH_EVENTS)
     // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers.
@@ -108,22 +108,13 @@
 
     Document* document = frame.document();
     if (!document)
-        return Region();
-
-    Vector<IntRect> touchRects;
-    document->getTouchRects(touchRects);
-    
-    Region touchRegion;
-    for (const auto& rect : touchRects)
-        touchRegion.unite(rect);
-
-    // FIXME: use absoluteRegionForEventTargets().
-    return touchRegion;
+        return EventTrackingRegions();
+    return document->eventTrackingRegions();
 #else
     Region nonFastScrollableRegion;
     FrameView* frameView = frame.view();
     if (!frameView)
-        return nonFastScrollableRegion;
+        return EventTrackingRegions();
 
     // FIXME: should ASSERT(!frameView->needsLayout()) here, but need to fix DebugPageOverlays
     // to not ask for regions at bad times.
@@ -158,7 +149,7 @@
         if (!subframeView)
             continue;
 
-        Region subframeRegion = absoluteNonFastScrollableRegionForFrame(*subframe);
+        Region subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe).synchronousDispatchRegion;
         // Map from the frame document to our document.
         IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint());
 
@@ -178,13 +169,13 @@
     nonFastScrollableRegion.unite(wheelHandlerRegion.first);
 
     // FIXME: If this is not the main frame, we could clip the region to the frame's bounds.
-    return nonFastScrollableRegion;
+    return EventTrackingRegions { Region(), nonFastScrollableRegion };
 #endif
 }
 
-Region ScrollingCoordinator::absoluteNonFastScrollableRegion() const
+EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegions() const
 {
-    return absoluteNonFastScrollableRegionForFrame(m_page->mainFrame());
+    return absoluteEventTrackingRegionsForFrame(m_page->mainFrame());
 }
 
 void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView& frameView)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -26,6 +26,7 @@
 #ifndef ScrollingCoordinator_h
 #define ScrollingCoordinator_h
 
+#include "EventTrackingRegions.h"
 #include "IntRect.h"
 #include "LayoutRect.h"
 #include "PlatformWheelEvent.h"
@@ -128,7 +129,7 @@
     void frameViewFixedObjectsDidChange(FrameView&);
 
     // Called whenever the non-fast scrollable region changes for reasons other than layout.
-    virtual void frameViewNonFastScrollableRegionChanged(FrameView&) { }
+    virtual void frameViewEventTrackingRegionsChanged(FrameView&) { }
 
     // Should be called whenever the root layer for the given frame view changes.
     virtual void frameViewRootLayerDidChange(FrameView&);
@@ -204,7 +205,7 @@
     static String synchronousScrollingReasonsAsText(SynchronousScrollingReasons);
     String synchronousScrollingReasonsAsText() const;
 
-    Region absoluteNonFastScrollableRegion() const;
+    EventTrackingRegions absoluteEventTrackingRegions() const;
 
 protected:
     explicit ScrollingCoordinator(Page*);
@@ -229,7 +230,7 @@
     virtual bool hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView&) const;
     void updateSynchronousScrollingReasons(const FrameView&);
 
-    Region absoluteNonFastScrollableRegionForFrame(const Frame&) const;
+    EventTrackingRegions absoluteEventTrackingRegionsForFrame(const Frame&) const;
     
     bool m_forceSynchronousScrollLayerPositionUpdates { false };
 };

Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,7 +49,7 @@
     , m_verticalScrollerImp(stateNode.verticalScrollerImp())
     , m_horizontalScrollerImp(stateNode.horizontalScrollerImp())
 #endif
-    , m_nonFastScrollableRegion(stateNode.nonFastScrollableRegion())
+    , m_eventTrackingRegions(stateNode.eventTrackingRegions())
     , m_requestedScrollPosition(stateNode.requestedScrollPosition())
     , m_frameScaleFactor(stateNode.frameScaleFactor())
     , m_topContentInset(stateNode.topContentInset())
@@ -98,13 +98,13 @@
     setPropertyChanged(FrameScaleFactor);
 }
 
-void ScrollingStateFrameScrollingNode::setNonFastScrollableRegion(const Region& nonFastScrollableRegion)
+void ScrollingStateFrameScrollingNode::setEventTrackingRegions(const EventTrackingRegions& eventTrackingRegions)
 {
-    if (m_nonFastScrollableRegion == nonFastScrollableRegion)
+    if (m_eventTrackingRegions == eventTrackingRegions)
         return;
 
-    m_nonFastScrollableRegion = nonFastScrollableRegion;
-    setPropertyChanged(NonFastScrollableRegion);
+    m_eventTrackingRegions = eventTrackingRegions;
+    setPropertyChanged(EventTrackingRegion);
 }
 
 void ScrollingStateFrameScrollingNode::setSynchronousScrollingReasons(SynchronousScrollingReasons reasons)
@@ -231,13 +231,13 @@
         writeIndent(ts, indent + 1);
         ts << "(frame scale factor " << m_frameScaleFactor << ")\n";
     }
-    
-    if (!m_nonFastScrollableRegion.isEmpty()) {
+
+    if (!m_eventTrackingRegions.asynchronousDispatchRegion.isEmpty()) {
         ++indent;
         writeIndent(ts, indent);
-        ts << "(non-fast-scrollable region";
+        ts << "(asynchronous event dispatch region";
         ++indent;
-        for (auto rect : m_nonFastScrollableRegion.rects()) {
+        for (auto rect : m_eventTrackingRegions.asynchronousDispatchRegion.rects()) {
             ts << "\n";
             writeIndent(ts, indent);
             ts << rect;
@@ -245,6 +245,19 @@
         ts << ")\n";
         indent -= 2;
     }
+    if (!m_eventTrackingRegions.synchronousDispatchRegion.isEmpty()) {
+        ++indent;
+        writeIndent(ts, indent);
+        ts << "(synchronous event dispatch region";
+        ++indent;
+        for (auto rect : m_eventTrackingRegions.synchronousDispatchRegion.rects()) {
+            ts << "\n";
+            writeIndent(ts, indent);
+            ts << rect;
+        }
+        ts << ")\n";
+        indent -= 2;
+    }
 
     if (m_synchronousScrollingReasons) {
         writeIndent(ts, indent + 1);

Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.h (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,7 +28,7 @@
 
 #if ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
 
-#include "Region.h"
+#include "EventTrackingRegions.h"
 #include "ScrollTypes.h"
 #include "ScrollbarThemeComposite.h"
 #include "ScrollingCoordinator.h"
@@ -48,7 +48,7 @@
 
     enum ChangedProperty {
         FrameScaleFactor = NumScrollingStateNodeBits,
-        NonFastScrollableRegion,
+        EventTrackingRegion,
         ReasonsForSynchronousScrolling,
         ScrolledContentsLayer,
         CounterScrollingLayer,
@@ -67,8 +67,8 @@
     float frameScaleFactor() const { return m_frameScaleFactor; }
     WEBCORE_EXPORT void setFrameScaleFactor(float);
 
-    const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; }
-    WEBCORE_EXPORT void setNonFastScrollableRegion(const Region&);
+    const EventTrackingRegions& eventTrackingRegions() const { return m_eventTrackingRegions; }
+    WEBCORE_EXPORT void setEventTrackingRegions(const EventTrackingRegions&);
 
     SynchronousScrollingReasons synchronousScrollingReasons() const { return m_synchronousScrollingReasons; }
     WEBCORE_EXPORT void setSynchronousScrollingReasons(SynchronousScrollingReasons);
@@ -137,7 +137,7 @@
     RetainPtr<NSScrollerImp> m_horizontalScrollerImp;
 #endif
 
-    Region m_nonFastScrollableRegion;
+    EventTrackingRegions m_eventTrackingRegions;
     FloatPoint m_requestedScrollPosition;
     float m_frameScaleFactor { 1 };
     float m_topContentInset { 0 };

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -61,14 +61,15 @@
     if (shouldSetLatch)
         m_latchedNode = 0;
     
-    if (!m_nonFastScrollableRegion.isEmpty() && m_rootNode) {
+    if (!m_eventTrackingRegions.isEmpty() && m_rootNode) {
         ScrollingTreeFrameScrollingNode& frameScrollingNode = downcast<ScrollingTreeFrameScrollingNode>(*m_rootNode);
         FloatPoint position = wheelEvent.position();
         position.move(frameScrollingNode.viewToContentsOffset(m_mainFrameScrollPosition));
 
-        LOG_WITH_STREAM(Scrolling, stream << "ScrollingTree::shouldHandleWheelEventSynchronously: wheelEvent at " << wheelEvent.position() << " mapped to content point " << position << ", in non-fast region " << m_nonFastScrollableRegion.contains(roundedIntPoint(position)));
+        bool isSynchronousDispatchRegion = m_eventTrackingRegions.trackingTypeForPoint(roundedIntPoint(position)) == TrackingType::Synchronous;
+        LOG_WITH_STREAM(Scrolling, stream << "ScrollingTree::shouldHandleWheelEventSynchronously: wheelEvent at " << wheelEvent.position() << " mapped to content point " << position << ", in non-fast region " << isSynchronousDispatchRegion);
 
-        if (m_nonFastScrollableRegion.contains(roundedIntPoint(position)))
+        if (isSynchronousDispatchRegion)
             return true;
     }
     return false;
@@ -117,14 +118,14 @@
     ScrollingStateScrollingNode* rootNode = scrollingStateTree->rootStateNode();
     if (rootNode
         && (rootStateNodeChanged
-            || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::NonFastScrollableRegion)
+            || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::EventTrackingRegion)
             || rootNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))) {
         LockHolder lock(m_mutex);
 
         if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))
             m_mainFrameScrollPosition = FloatPoint();
-        if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::NonFastScrollableRegion))
-            m_nonFastScrollableRegion = scrollingStateTree->rootStateNode()->nonFastScrollableRegion();
+        if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::EventTrackingRegion))
+            m_eventTrackingRegions = scrollingStateTree->rootStateNode()->eventTrackingRegions();
     }
     
     bool scrollRequestIsProgammatic = rootNode ? rootNode->requestedScrollPositionRepresentsProgrammaticScroll() : false;
@@ -232,11 +233,11 @@
     m_mainFrameScrollPosition = position;
 }
 
-bool ScrollingTree::isPointInNonFastScrollableRegion(IntPoint p)
+TrackingType ScrollingTree::eventTrackingTypeForPoint(IntPoint p)
 {
     LockHolder lock(m_mutex);
     
-    return m_nonFastScrollableRegion.contains(p);
+    return m_eventTrackingRegions.trackingTypeForPoint(p);
 }
 
 bool ScrollingTree::isRubberBandInProgress()

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -101,7 +101,7 @@
     virtual void scrollingTreeNodeDidEndScroll() { }
 #endif
 
-    WEBCORE_EXPORT bool isPointInNonFastScrollableRegion(IntPoint);
+    WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(IntPoint);
     
 #if PLATFORM(MAC)
     virtual void handleWheelEventPhase(PlatformWheelEventPhase) = 0;
@@ -162,7 +162,7 @@
     ScrollingTreeNodeMap m_nodeMap;
 
     Lock m_mutex;
-    Region m_nonFastScrollableRegion;
+    EventTrackingRegions m_eventTrackingRegions;
     FloatPoint m_mainFrameScrollPosition;
 
     Lock m_swipeStateMutex;

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm (201957 => 201958)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2016-06-11 01:18:37 UTC (rev 201958)
@@ -99,7 +99,7 @@
 
 void ScrollingCoordinatorMac::scheduleTreeStateCommit()
 {
-    ASSERT(scrollingStateTree()->hasChangedProperties() || nonFastScrollableRegionDirty());
+    ASSERT(scrollingStateTree()->hasChangedProperties() || eventTrackingRegionsDirty());
 
     if (m_scrollingStateTreeCommitterTimer.isActive())
         return;

Added: trunk/Source/WebCore/platform/EventTrackingRegions.h (0 => 201958)


--- trunk/Source/WebCore/platform/EventTrackingRegions.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/EventTrackingRegions.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Region.h"
+
+namespace WebCore {
+
+enum class TrackingType : uint8_t {
+    NotTracking = 0,
+    Asynchronous = 1,
+    Synchronous = 2
+};
+
+struct EventTrackingRegions {
+    // Region for which events can be dispatched without blocking scrolling.
+    Region asynchronousDispatchRegion;
+
+    // Region for which events must be sent before performing the default behavior.
+    Region synchronousDispatchRegion;
+
+    bool isEmpty() const;
+
+    TrackingType trackingTypeForPoint(const IntPoint&);
+};
+
+inline bool EventTrackingRegions::isEmpty() const
+{
+    return asynchronousDispatchRegion.isEmpty() && synchronousDispatchRegion.isEmpty();
+}
+
+inline TrackingType EventTrackingRegions::trackingTypeForPoint(const IntPoint& point)
+{
+    if (synchronousDispatchRegion.contains(point))
+        return TrackingType::Synchronous;
+    if (asynchronousDispatchRegion.contains(point))
+        return TrackingType::Asynchronous;
+    return TrackingType::NotTracking;
+}
+
+inline bool operator==(const EventTrackingRegions& a, const EventTrackingRegions& b)
+{
+    return a.asynchronousDispatchRegion == b.asynchronousDispatchRegion
+        && a.synchronousDispatchRegion == b.synchronousDispatchRegion;
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebKit2/ChangeLog (201957 => 201958)


--- trunk/Source/WebKit2/ChangeLog	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/ChangeLog	2016-06-11 01:18:37 UTC (rev 201958)
@@ -1,3 +1,46 @@
+2016-06-10  Benjamin Poulain  <[email protected]>
+
+        Add support for passive event listeners on touch events
+        https://bugs.webkit.org/show_bug.cgi?id=158601
+
+        Reviewed by Simon Fraser.
+
+        * Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
+        (ArgumentCoder<ScrollingStateFrameScrollingNode>::encode):
+        (ArgumentCoder<ScrollingStateFrameScrollingNode>::decode):
+        (WebKit::dump):
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<EventTrackingRegions>::encode):
+        (IPC::ArgumentCoder<EventTrackingRegions>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
+        (WebKit::RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint):
+        (WebKit::RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion): Deleted.
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::touchEventTrackingType):
+        The type is the most restrictive type of all the touch points.
+        If any touch point needs synchronous tracking, everything has to be synchronous.
+
+        (WebKit::WebPageProxy::handleTouchEventSynchronously):
+        This is a very unfortunate design.
+
+        The upper layer dealing with UIKit knows about gesture and when something
+        can be dispatched asynchrnously because a gesture has started.
+        This layer knows about tracking and can use that extra inforamtion
+        to dispatch an event asynchrnously anyway.
+
+        In the future, we should refactor this to let WebPageProxy
+        always decide of the dispatch type. I am just concerned changing
+        the upper layer while we are stabilizing WebKit.
+
+        (WebKit::WebPageProxy::handleTouchEventAsynchronously):
+        (WebKit::WebPageProxy::handleTouchEvent):
+        (WebKit::WebPageProxy::resetState):
+        (WebKit::WebPageProxy::WebPageProxy): Deleted.
+        (WebKit::WebPageProxy::shouldStartTrackingTouchEvents): Deleted.
+        * UIProcess/WebPageProxy.h:
+
 2016-06-10  Beth Dakin  <[email protected]>
 
         Add requestExitFullScreen to WKFullScreenWindowController

Modified: trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp (201957 => 201958)


--- trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -144,7 +144,7 @@
     encoder << static_cast<const ScrollingStateScrollingNode&>(node);
     
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::FrameScaleFactor, frameScaleFactor)
-    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::NonFastScrollableRegion, nonFastScrollableRegion)
+    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::EventTrackingRegion, eventTrackingRegions)
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::ReasonsForSynchronousScrolling, synchronousScrollingReasons)
     SCROLLING_NODE_ENCODE_ENUM(ScrollingStateFrameScrollingNode::BehaviorForFixedElements, scrollBehaviorForFixedElements)
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::HeaderHeight, headerHeight)
@@ -228,7 +228,7 @@
         return false;
 
     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::FrameScaleFactor, float, setFrameScaleFactor);
-    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::NonFastScrollableRegion, Region, setNonFastScrollableRegion);
+    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::EventTrackingRegion, EventTrackingRegions, setEventTrackingRegions);
     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::ReasonsForSynchronousScrolling, SynchronousScrollingReasons, setSynchronousScrollingReasons);
     SCROLLING_NODE_DECODE_ENUM(ScrollingStateFrameScrollingNode::BehaviorForFixedElements, ScrollBehaviorForFixedElements, setScrollBehaviorForFixedElements);
 
@@ -484,14 +484,25 @@
     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::FrameScaleFactor))
         ts.dumpProperty("frame-scale-factor", node.frameScaleFactor());
 
-    if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::NonFastScrollableRegion)) {
-        TextStream::GroupScope group(ts);
-        ts << "non-fast-scrollable-region";
-        for (auto rect : node.nonFastScrollableRegion().rects()) {
-            ts << "\n";
-            ts.writeIndent();
-            ts << rect;
+    if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateFrameScrollingNode::EventTrackingRegion)) {
+        {
+            TextStream::GroupScope group(ts);
+            ts << "asynchronous-event-tracking-region";
+            for (auto rect : node.eventTrackingRegions().asynchronousDispatchRegion.rects()) {
+                ts << "\n";
+                ts.writeIndent();
+                ts << rect;
+            }
         }
+        {
+            TextStream::GroupScope group(ts);
+            ts << "synchronous-event-tracking-region";
+            for (auto rect : node.eventTrackingRegions().synchronousDispatchRegion.rects()) {
+                ts << "\n";
+                ts.writeIndent();
+                ts << rect;
+            }
+        }
     }
 
     // FIXME: dump synchronousScrollingReasons

Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp (201957 => 201958)


--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -38,6 +38,7 @@
 #include <WebCore/DictationAlternative.h>
 #include <WebCore/DictionaryPopupInfo.h>
 #include <WebCore/Editor.h>
+#include <WebCore/EventTrackingRegions.h>
 #include <WebCore/FileChooser.h>
 #include <WebCore/FilterOperation.h>
 #include <WebCore/FilterOperations.h>
@@ -107,6 +108,25 @@
     return SimpleArgumentCoder<AffineTransform>::decode(decoder, affineTransform);
 }
 
+void ArgumentCoder<EventTrackingRegions>::encode(ArgumentEncoder& encoder, const EventTrackingRegions& eventTrackingRegions)
+{
+    encoder << eventTrackingRegions.asynchronousDispatchRegion;
+    encoder << eventTrackingRegions.synchronousDispatchRegion;
+}
+
+bool ArgumentCoder<EventTrackingRegions>::decode(ArgumentDecoder& decoder, EventTrackingRegions& eventTrackingRegions)
+{
+    Region asynchronousDispatchRegion;
+    if (!decoder.decode(asynchronousDispatchRegion))
+        return false;
+    Region synchronousDispatchRegion;
+    if (!decoder.decode(synchronousDispatchRegion))
+        return false;
+    eventTrackingRegions.asynchronousDispatchRegion = WTFMove(asynchronousDispatchRegion);
+    eventTrackingRegions.synchronousDispatchRegion = WTFMove(synchronousDispatchRegion);
+    return true;
+}
+
 void ArgumentCoder<TransformationMatrix>::encode(ArgumentEncoder& encoder, const TransformationMatrix& transformationMatrix)
 {
     encoder << transformationMatrix.m11();

Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h (201957 => 201958)


--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -72,6 +72,7 @@
 struct Cookie;
 struct DictationAlternative;
 struct DictionaryPopupInfo;
+struct EventTrackingRegions;
 struct ExceptionDetails;
 struct FileChooserSettings;
 struct Length;
@@ -132,6 +133,11 @@
     static bool decode(ArgumentDecoder&, WebCore::AffineTransform&);
 };
 
+template<> struct ArgumentCoder<WebCore::EventTrackingRegions> {
+    static void encode(ArgumentEncoder&, const WebCore::EventTrackingRegions&);
+    static bool decode(ArgumentDecoder&, WebCore::EventTrackingRegions&);
+};
+
 template<> struct ArgumentCoder<WebCore::TransformationMatrix> {
     static void encode(ArgumentEncoder&, const WebCore::TransformationMatrix&);
     static bool decode(ArgumentDecoder&, WebCore::TransformationMatrix&);

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp (201957 => 201958)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -149,9 +149,9 @@
     return result == ScrollingTree::DidHandleEvent; // FIXME: handle other values.
 }
 
-bool RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion(const IntPoint& p) const
+TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(IntPoint p) const
 {
-    return m_scrollingTree->isPointInNonFastScrollableRegion(p);
+    return m_scrollingTree->eventTrackingTypeForPoint(p);
 }
 
 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale)

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (201957 => 201958)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -56,7 +56,7 @@
     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, WebCore::SetOrSyncScrollingLayerPosition);
     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
 
-    bool isPointInNonFastScrollableRegion(const WebCore::IntPoint&) const;
+    WebCore::TrackingType eventTrackingTypeForPoint(WebCore::IntPoint) const;
 
     // Called externally when native views move around.
     void viewportChangedViaDelegatedScrolling(WebCore::ScrollingNodeID, const WebCore::FloatRect& fixedPositionRect, double scale);

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (201957 => 201958)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2016-06-11 01:18:37 UTC (rev 201958)
@@ -383,9 +383,6 @@
     , m_syncNavigationActionPolicyAction(PolicyUse)
     , m_syncNavigationActionPolicyDownloadID(0)
     , m_processingMouseMoveEvent(false)
-#if ENABLE(TOUCH_EVENTS)
-    , m_isTrackingTouchEvents(false)
-#endif
     , m_pageID(pageID)
     , m_sessionID(m_configuration->sessionID())
     , m_isPageSuspended(false)
@@ -1939,19 +1936,24 @@
 
 #if ENABLE(TOUCH_EVENTS)
 
-bool WebPageProxy::shouldStartTrackingTouchEvents(const WebTouchEvent& touchStartEvent) const
+TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
 {
 #if ENABLE(ASYNC_SCROLLING)
+    TrackingType trackingType = TrackingType::NotTracking;
     for (auto& touchPoint : touchStartEvent.touchPoints()) {
-        if (m_scrollingCoordinatorProxy->isPointInNonFastScrollableRegion(touchPoint.location()))
-            return true;
+        TrackingType touchPointTrackingType = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(touchPoint.location());
+        if (touchPointTrackingType == TrackingType::Synchronous)
+            return TrackingType::Synchronous;
+
+        if (touchPointTrackingType == TrackingType::Asynchronous)
+            trackingType = touchPointTrackingType;
     }
 
-    return false;
+    return trackingType;
 #else
     UNUSED_PARAM(touchStartEvent);
 #endif // ENABLE(ASYNC_SCROLLING)
-    return true;
+    return TrackingType::Synchronous;
 }
 
 #endif
@@ -1971,19 +1973,32 @@
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
-void WebPageProxy::handleTouchEventSynchronously(const NativeWebTouchEvent& event)
+void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
 {
     if (!isValid())
         return;
 
     if (event.type() == WebEvent::TouchStart) {
-        m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
+        m_touchEventsTrackingType = touchEventTrackingType(event);
         m_layerTreeTransactionIdAtLastTouchStart = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).lastCommittedLayerTreeTransactionID();
     }
 
-    if (!m_isTrackingTouchEvents)
+    if (m_touchEventsTrackingType == TrackingType::NotTracking)
         return;
 
+    if (m_touchEventsTrackingType == TrackingType::Asynchronous) {
+        // We can end up here if a native gesture has not started but the event handlers are passive.
+        //
+        // The client of WebPageProxy asks the event to be sent synchronously since the touch event
+        // can prevent a native gesture.
+        // But, here we know that all events handlers that can handle this events are passive.
+        // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
+        event.setCanPreventNativeGestures(false);
+        handleTouchEventAsynchronously(event);
+        didReceiveEvent(event.type(), false);
+        return;
+    }
+
     m_process->responsivenessTimer().start();
     bool handled = false;
     m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
@@ -1992,7 +2007,7 @@
     m_process->responsivenessTimer().stop();
 
     if (event.allTouchPointsAreReleased())
-        m_isTrackingTouchEvents = false;
+        m_touchEventsTrackingType = TrackingType::NotTracking;
 }
 
 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
@@ -2000,13 +2015,13 @@
     if (!isValid())
         return;
 
-    if (!m_isTrackingTouchEvents)
+    if (m_touchEventsTrackingType == TrackingType::NotTracking)
         return;
 
     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
 
     if (event.allTouchPointsAreReleased())
-        m_isTrackingTouchEvents = false;
+        m_touchEventsTrackingType = TrackingType::NotTracking;
 }
 
 #elif ENABLE(TOUCH_EVENTS)
@@ -2016,9 +2031,9 @@
         return;
 
     if (event.type() == WebEvent::TouchStart)
-        m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
+        m_touchEventsTrackingType = touchEventTrackingType(event);
 
-    if (!m_isTrackingTouchEvents)
+    if (m_touchEventsTrackingType == TrackingType::NotTracking)
         return;
 
     // If the page is suspended, which should be the case during panning, pinching
@@ -2041,7 +2056,7 @@
     }
 
     if (event.allTouchPointsAreReleased())
-        m_isTrackingTouchEvents = false;
+        m_touchEventsTrackingType = TrackingType::NotTracking;
 }
 #endif // ENABLE(TOUCH_EVENTS)
 
@@ -5060,7 +5075,7 @@
     }
 
 #if ENABLE(TOUCH_EVENTS)
-    m_isTrackingTouchEvents = false;
+    m_touchEventsTrackingType = TrackingType::NotTracking;
 #endif
 
 #if ENABLE(INPUT_TYPE_COLOR)

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (201957 => 201958)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2016-06-11 00:48:43 UTC (rev 201957)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2016-06-11 01:18:37 UTC (rev 201958)
@@ -63,6 +63,7 @@
 #include "WebProcessLifetimeTracker.h"
 #include <WebCore/Color.h>
 #include <WebCore/DragActions.h>
+#include <WebCore/EventTrackingRegions.h>
 #include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/HitTestResult.h>
 #include <WebCore/MediaProducer.h>
@@ -615,7 +616,7 @@
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
-    void handleTouchEventSynchronously(const NativeWebTouchEvent&);
+    void handleTouchEventSynchronously(NativeWebTouchEvent&);
     void handleTouchEventAsynchronously(const NativeWebTouchEvent&);
 
 #elif ENABLE(TOUCH_EVENTS)
@@ -1463,7 +1464,7 @@
     void sendWheelEvent(const WebWheelEvent&);
 
 #if ENABLE(TOUCH_EVENTS)
-    bool shouldStartTrackingTouchEvents(const WebTouchEvent&) const;
+    WebCore::TrackingType touchEventTrackingType(const WebTouchEvent&) const;
 #endif
 
 #if ENABLE(NETSCAPE_PLUGIN_API)
@@ -1690,7 +1691,7 @@
     std::unique_ptr<NativeWebMouseEvent> m_currentlyProcessedMouseDownEvent;
 
 #if ENABLE(TOUCH_EVENTS)
-    bool m_isTrackingTouchEvents;
+    WebCore::TrackingType m_touchEventsTrackingType { WebCore::TrackingType::NotTracking };
 #endif
 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
     Deque<QueuedTouchEvents> m_touchEventQueue;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to