Title: [202408] trunk
Revision
202408
Author
[email protected]
Date
2016-06-23 19:38:00 -0700 (Thu, 23 Jun 2016)

Log Message

Specialize synchronous event tracking per event type
https://bugs.webkit.org/show_bug.cgi?id=158826

Reviewed by Simon Fraser.

Source/WebCore:

First, kudos to Rick Byers for all his helps on passive event dispatch.
The specs are pretty damn good and his help reviewing patches is very useful.

This patch change synchronous event dispatch to happen per event
instead of per sequence touchstart->touchend.

The big advantage of this is we can dispatch more events asynchronously.
For example, to handle a tap programmatically, you can limit the active listener
to the touchend event. The touchstart and touchmove are now dispatched asynchronously.

The implementation is a simple extension to EventTrackingRegions.
Instead of a single synchronous region, we have one region per event type.
When processing the events, we only need to send the events synchronously
if that particular event type has a synchronous region.

Note that EventDispatcher's touch event support already supports
mixing synchronous and asynchronous events. The events are always processed
in order even if asynchronous events are pending when a synchronous dispatch
happens.

Tests: fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html
       fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html
       fast/events/touch/ios/tap-with-active-touch-end-listener.html
       fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html
       fast/events/touch/ios/tap-with-passive-touch-end-listener.html
       fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html
       fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/EventTarget.cpp:
(WebCore::EventTarget::hasActiveTouchEventListeners): Deleted.
* dom/EventTarget.h:
* page/DebugPageOverlays.cpp:
(WebCore::NonFastScrollableRegionOverlay::updateRegion):
* page/Page.cpp:
(WebCore::Page::nonFastScrollableRects):
* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::absoluteEventTrackingRegionsForFrame):
* page/scrolling/ScrollingStateFrameScrollingNode.cpp:
(WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::shouldHandleWheelEventSynchronously):
(WebCore::ScrollingTree::eventTrackingTypeForPoint):
* page/scrolling/ScrollingTree.h:
* platform/EventTrackingRegions.cpp: Added.
(WebCore::EventTrackingRegions::trackingTypeForPoint):
(WebCore::EventTrackingRegions::isEmpty):
(WebCore::EventTrackingRegions::translate):
(WebCore::EventTrackingRegions::uniteSynchronousRegion):
(WebCore::EventTrackingRegions::unite):
(WebCore::operator==):
* platform/EventTrackingRegions.h:
(WebCore::EventTrackingRegions::isEmpty): Deleted.
(WebCore::EventTrackingRegions::trackingTypeForPoint): Deleted.
(WebCore::operator==): Deleted.

Source/WebKit2:

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<EventTrackingRegions>::encode):
(IPC::ArgumentCoder<EventTrackingRegions>::decode):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
(WebKit::RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::mergeTrackingTypes):
(WebKit::WebPageProxy::updateTouchEventTracking):
(WebKit::WebPageProxy::touchEventTrackingType):
(WebKit::WebPageProxy::handleTouchEventSynchronously):
(WebKit::WebPageProxy::handleTouchEventAsynchronously):
(WebKit::WebPageProxy::handleTouchEvent):
(WebKit::WebPageProxy::resetState):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::TouchEventTracking::isTrackingAnything):
(WebKit::WebPageProxy::TouchEventTracking::reset):

LayoutTests:

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

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202407 => 202408)


--- trunk/LayoutTests/ChangeLog	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/ChangeLog	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,3 +1,24 @@
+2016-06-23  Benjamin Poulain  <[email protected]>
+
+        Specialize synchronous event tracking per event type
+        https://bugs.webkit.org/show_bug.cgi?id=158826
+
+        Reviewed by Simon Fraser.
+
+        * fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html: Added.
+        * fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html: Added.
+        * fast/events/touch/ios/tap-with-active-touch-end-listener-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-active-touch-end-listener.html: Added.
+        * fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-end-listener-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-end-listener.html: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt: Added.
+        * fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html: Added.
+
 2016-06-23  Alexey Proskuryakov  <[email protected]>
 
         Update TestExpectations for a couple video track tests.

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


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,35 @@
+Cancelled drag on Target1 (green)
+
+Listener target1 received event touchstart targetting eventTarget1 at 50, 50
+Listener document received event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received cancelable event touchmove targetting eventTarget1 at 100, 100
+Listener document received cancelable event touchmove targetting eventTarget1 at 100, 100
+Listener target1 received cancelable event touchend targetting eventTarget1
+Listener document received cancelable event touchend targetting eventTarget1
+Done
+Cancelled drag on Target2 (red)
+
+Listener target1 received event touchstart targetting eventTarget2 at 150, 50
+Listener document received event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received cancelable event touchmove targetting eventTarget2 at 200, 100
+Listener document received cancelable event touchmove targetting eventTarget2 at 200, 100
+Listener target1 received cancelable event touchend targetting eventTarget2
+Listener document received cancelable event touchend targetting eventTarget2
+Done
+Cancelled drag on Target3 (blue)
+
+Listener target3 received event touchstart targetting eventTarget3 at 250, 50
+Listener target1 received event touchstart targetting eventTarget3 at 250, 50
+Listener document received event touchstart targetting eventTarget3 at 250, 50
+Listener target3 received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener target1 received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener document received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener target3 received cancelable event touchend targetting eventTarget3
+Listener target1 received cancelable event touchend targetting eventTarget3
+Listener document received cancelable event touchend targetting eventTarget3
+Done
+Useless Click in the document, should be passive
+
+Listener document received event touchstart targetting at 300, 300
+Listener document received event touchend targetting 
+

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getClickUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function getDragUIScript(startX, startY, endX, endY)
+        {
+            return `
+            (function() {
+                uiController.dragFromPointToPoint(${startX}, ${startY}, ${endX}, ${endY}, 0.15, 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);
+            window.addEventListener('scroll', fail);
+
+            let output = '';
+            function getLogEvent(listener, shouldPreventDefault = false) {
+                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>';
+
+                    if (shouldPreventDefault)
+                        event.preventDefault();
+                }
+            }
+
+            document.addEventListener('touchstart', getLogEvent("document"), { 'passive': true });
+            document.addEventListener('touchmove', getLogEvent("document"), { 'passive': true });
+            document.addEventListener('touchend', getLogEvent("document"), { 'passive': true });
+            document.addEventListener('touchcancel', getLogEvent("document"), { 'passive': true });
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent("target1"), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent("target1", 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", true));
+            target3.addEventListener('touchend', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent("target3"), { 'passive': true });
+
+            output += "<h1>Cancelled drag on Target1 (green)</h1>";
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += "<h1>Cancelled drag on Target2 (red)</h1>";
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += "<h1>Cancelled drag on Target3 (blue)</h1>";
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), function(result) {
+                        output += result;
+                        output += "<h1>Useless Click in the document, should be passive</h1>";
+                        testRunner.runUIScript(getClickUIScript(300, 300), 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;
+        }
+        body {
+            height: 5000px;
+        }
+    </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-inside-window-with-passive-listener-expected.txt (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,35 @@
+Cancelled drag on Target1 (green)
+
+Listener target1 received event touchstart targetting eventTarget1 at 50, 50
+Listener document received event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received cancelable event touchmove targetting eventTarget1 at 100, 100
+Listener document received cancelable event touchmove targetting eventTarget1 at 100, 100
+Listener target1 received cancelable event touchend targetting eventTarget1
+Listener document received cancelable event touchend targetting eventTarget1
+Done
+Cancelled drag on Target2 (red)
+
+Listener target1 received event touchstart targetting eventTarget2 at 150, 50
+Listener document received event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received cancelable event touchmove targetting eventTarget2 at 200, 100
+Listener document received cancelable event touchmove targetting eventTarget2 at 200, 100
+Listener target1 received cancelable event touchend targetting eventTarget2
+Listener document received cancelable event touchend targetting eventTarget2
+Done
+Cancelled drag on Target3 (blue)
+
+Listener target3 received event touchstart targetting eventTarget3 at 250, 50
+Listener target1 received event touchstart targetting eventTarget3 at 250, 50
+Listener document received event touchstart targetting eventTarget3 at 250, 50
+Listener target3 received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener target1 received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener document received cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener target3 received cancelable event touchend targetting eventTarget3
+Listener target1 received cancelable event touchend targetting eventTarget3
+Listener document received cancelable event touchend targetting eventTarget3
+Done
+Useless Click in the document, should be passive
+
+Listener document received event touchstart targetting at 300, 300
+Listener document received event touchend targetting 
+

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


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getClickUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete("Done");
+                });
+            })();`
+        }
+
+        function getDragUIScript(startX, startY, endX, endY)
+        {
+            return `
+            (function() {
+                uiController.dragFromPointToPoint(${startX}, ${startY}, ${endX}, ${endY}, 0.15, 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);
+            window.addEventListener('scroll', fail);
+
+            let output = '';
+            function getLogEvent(listener, shouldPreventDefault = false) {
+                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>';
+
+                    if (shouldPreventDefault)
+                        event.preventDefault();
+                }
+            }
+
+            window.addEventListener('touchstart', getLogEvent("document"), { 'passive': true });
+            window.addEventListener('touchmove', getLogEvent("document"), { 'passive': true });
+            window.addEventListener('touchend', getLogEvent("document"), { 'passive': true });
+            window.addEventListener('touchcancel', getLogEvent("document"), { 'passive': true });
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent("target1"), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent("target1", 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", true));
+            target3.addEventListener('touchend', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent("target3"), { 'passive': true });
+
+            output += "<h1>Cancelled drag on Target1 (green)</h1>";
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += "<h1>Cancelled drag on Target2 (red)</h1>";
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += "<h1>Cancelled drag on Target3 (blue)</h1>";
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), function(result) {
+                        output += result;
+                        output += "<h1>Useless Click in the document, should be passive</h1>";
+                        testRunner.runUIScript(getClickUIScript(300, 300), 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;
+        }
+        body {
+            height: 5000px;
+        }
+    </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-touch-end-listener-expected.txt (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,30 @@
+Tap on Target1 (green)
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (synchronous event dispatch region for event touchend
+    at (0,0) size 300x100)
+)
+Listener target1 received cancelable event touchend targetting eventTarget1
+Done
+Tap on Target2 (red)
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (synchronous event dispatch region for event touchend
+    at (0,0) size 300x100)
+)
+Listener target1 received cancelable event touchend targetting eventTarget2
+Done
+Tap on Target3 (blue)
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (synchronous event dispatch region for event touchend
+    at (0,0) size 300x100)
+)
+Listener target1 received cancelable event touchend targetting eventTarget3
+

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


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,106 @@
+<!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 += '<pre>' + window.internals.scrollingStateTreeAsText() + '</pre>';
+                    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('touchend', getLogEvent("target1"));
+
+            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-inside-active-listener.html (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,116 @@
+<!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>';
+                    output += 'defaultPrevented before preventDefault(): ' + event.defaultPrevented + '<br>';
+                    event.preventDefault();
+                    output += 'defaultPrevented after preventDefault(): ' + event.defaultPrevented + '<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"), { '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-touch-end-listener-expected.txt (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,12 @@
+Tap on Target1 (green)
+
+Listener target1 received event touchend targetting eventTarget1
+Done
+Tap on Target2 (red)
+
+Listener target1 received event touchend targetting eventTarget2
+Done
+Tap on Target3 (blue)
+
+Listener target1 received event touchend targetting eventTarget3
+

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


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,105 @@
+<!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('touchend', getLogEvent("target1"), { '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-touch-start-active-touch-end-listeners-on-elements-expected.txt (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,17 @@
+Tap on Target1 (green)
+
+Listener target1 received event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received cancelable event touchend targetting eventTarget1
+Done
+Tap on Target2 (red)
+
+Listener target1 received event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received cancelable 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 cancelable event touchend targetting eventTarget3
+Listener target1 received cancelable event touchend targetting eventTarget3
+

Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -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"));
+            target1.addEventListener('touchcancel', getLogEvent("target1"));
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent("target3"), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent("target3"), { 'passive': true });
+            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-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,21 @@
+Cancelled drag on Target1 (green)
+
+Listener target1 received event touchstart targetting eventTarget1 at 50, 50
+Listener target1 received cancelable event touchmove targetting eventTarget1 at 100, 100
+Listener target1 received cancelable event touchend targetting eventTarget1
+Done
+Cancelled drag on Target2 (red)
+
+Listener target1 received event touchstart targetting eventTarget2 at 150, 50
+Listener target1 received cancelable event touchmove targetting eventTarget2 at 200, 100
+Listener target1 received cancelable event touchend targetting eventTarget2
+Done
+Cancelled drag 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 cancelable event touchmove targetting eventTarget3 at 300, 100
+Listener target1 received cancelable event touchmove targetting eventTarget3 at 300, 100
+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-passive-touch-start-active-touch-move-listeners-on-elements.html (0 => 202408)


--- trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getDragUIScript(startX, startY, endX, endY)
+        {
+            return `
+            (function() {
+                uiController.dragFromPointToPoint(${startX}, ${startY}, ${endX}, ${endY}, 0.15, 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);
+            window.addEventListener('scroll', 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>';
+
+                    if (event.type === 'touchmove')
+                        event.preventDefault();
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent("target1"), { 'passive': true });
+            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"), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent("target3"));
+            target3.addEventListener('touchend', getLogEvent("target3"));
+            target3.addEventListener('touchcancel', getLogEvent("target3"));
+
+            output += "<h1>Cancelled drag on Target1 (green)</h1>";
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += "<h1>Cancelled drag on Target2 (red)</h1>";
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += "<h1>Cancelled drag on Target3 (blue)</h1>";
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), 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;
+        }
+        body {
+            height: 5000px;
+        }
+    </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>

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


--- trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -2,7 +2,7 @@
   (scrollable area size 785 600)
   (contents size 785 2213)
   (requested scroll position 0 200)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (0,13) size 204x204)
   (children 1
     (Fixed node

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (45,47) size 404x304)
   (children 1
     (Frame scrolling node

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (45,47) size 404x304)
   (children 1
     (Fixed node

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (45,37) size 404x304)
   (children 1
     (Fixed node

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 1016)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (45,47) size 404x304)
   (children 1
     (Frame scrolling node

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 800 600)
   (contents size 800 600)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (0,0) size 800x594)
 )
 

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,7 +1,7 @@
 (Frame scrolling node
   (scrollable area size 800 600)
   (contents size 800 600)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (0,166) size 280x434)
 )
 

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


--- trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -2,7 +2,7 @@
 (Frame scrolling node
   (scrollable area size 785 600)
   (contents size 785 757)
-  (synchronous event dispatch region
+  (synchronous event dispatch region for event wheel
     at (68,68) size 300x300)
 )
 

Modified: trunk/Source/WebCore/CMakeLists.txt (202407 => 202408)


--- trunk/Source/WebCore/CMakeLists.txt	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/CMakeLists.txt	2016-06-24 02:38:00 UTC (rev 202408)
@@ -2114,6 +2114,7 @@
     platform/DisplaySleepDisabler.cpp
     platform/DragData.cpp
     platform/DragImage.cpp
+    platform/EventTrackingRegions.cpp
     platform/FileChooser.cpp
     platform/FileStream.cpp
     platform/FileSystem.cpp

Modified: trunk/Source/WebCore/ChangeLog (202407 => 202408)


--- trunk/Source/WebCore/ChangeLog	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/ChangeLog	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,3 +1,67 @@
+2016-06-23  Benjamin Poulain  <[email protected]>
+
+        Specialize synchronous event tracking per event type
+        https://bugs.webkit.org/show_bug.cgi?id=158826
+
+        Reviewed by Simon Fraser.
+
+        First, kudos to Rick Byers for all his helps on passive event dispatch.
+        The specs are pretty damn good and his help reviewing patches is very useful.
+
+        This patch change synchronous event dispatch to happen per event
+        instead of per sequence touchstart->touchend.
+
+        The big advantage of this is we can dispatch more events asynchronously.
+        For example, to handle a tap programmatically, you can limit the active listener
+        to the touchend event. The touchstart and touchmove are now dispatched asynchronously.
+
+        The implementation is a simple extension to EventTrackingRegions.
+        Instead of a single synchronous region, we have one region per event type.
+        When processing the events, we only need to send the events synchronously
+        if that particular event type has a synchronous region.
+
+        Note that EventDispatcher's touch event support already supports
+        mixing synchronous and asynchronous events. The events are always processed
+        in order even if asynchronous events are pending when a synchronous dispatch
+        happens.
+
+        Tests: fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html
+               fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html
+               fast/events/touch/ios/tap-with-active-touch-end-listener.html
+               fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html
+               fast/events/touch/ios/tap-with-passive-touch-end-listener.html
+               fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html
+               fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::hasActiveTouchEventListeners): Deleted.
+        * dom/EventTarget.h:
+        * page/DebugPageOverlays.cpp:
+        (WebCore::NonFastScrollableRegionOverlay::updateRegion):
+        * page/Page.cpp:
+        (WebCore::Page::nonFastScrollableRects):
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::absoluteEventTrackingRegionsForFrame):
+        * page/scrolling/ScrollingStateFrameScrollingNode.cpp:
+        (WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::shouldHandleWheelEventSynchronously):
+        (WebCore::ScrollingTree::eventTrackingTypeForPoint):
+        * page/scrolling/ScrollingTree.h:
+        * platform/EventTrackingRegions.cpp: Added.
+        (WebCore::EventTrackingRegions::trackingTypeForPoint):
+        (WebCore::EventTrackingRegions::isEmpty):
+        (WebCore::EventTrackingRegions::translate):
+        (WebCore::EventTrackingRegions::uniteSynchronousRegion):
+        (WebCore::EventTrackingRegions::unite):
+        (WebCore::operator==):
+        * platform/EventTrackingRegions.h:
+        (WebCore::EventTrackingRegions::isEmpty): Deleted.
+        (WebCore::EventTrackingRegions::trackingTypeForPoint): Deleted.
+        (WebCore::operator==): Deleted.
+
 2016-06-23  Simon Fraser  <[email protected]>
 
         More attempting to fix external iOS builds.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (202407 => 202408)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1075,6 +1075,7 @@
 		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, ); }; };
+		262EC41D1D110B9000BA78FC /* EventTrackingRegions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */; };
 		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 */; };
@@ -8610,6 +8611,7 @@
 		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>"; };
+		262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventTrackingRegions.cpp; 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>"; };
@@ -23134,6 +23136,7 @@
 				A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
 				A7CFB3D00B7ED10A0070C32D /* DragImage.h */,
 				1CA19E150DC255CA0065A994 /* EventLoop.h */,
+				262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */,
 				262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */,
 				934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
 				066C772A0AB603B700238CC4 /* FileChooser.h */,
@@ -30675,6 +30678,7 @@
 				A7BBE26611AFB3F20005EA03 /* JSHTMLMeterElement.cpp in Sources */,
 				1AE2AB290A1CE63B00B42B25 /* JSHTMLModElement.cpp in Sources */,
 				BC305C790C076BB300CD20F0 /* JSHTMLObjectElement.cpp in Sources */,
+				262EC41D1D110B9000BA78FC /* EventTrackingRegions.cpp in Sources */,
 				BC305CA40C0781BB00CD20F0 /* JSHTMLObjectElementCustom.cpp in Sources */,
 				1A85B1EA0A1B240500D8C87C /* JSHTMLOListElement.cpp in Sources */,
 				A80E7E9C0A1A83E3007FB8C5 /* JSHTMLOptGroupElement.cpp in Sources */,

Modified: trunk/Source/WebCore/dom/EventTarget.cpp (202407 => 202408)


--- trunk/Source/WebCore/dom/EventTarget.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/dom/EventTarget.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -243,16 +243,6 @@
     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 (202407 => 202408)


--- trunk/Source/WebCore/dom/EventTarget.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/dom/EventTarget.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -168,8 +168,6 @@
     void visitJSEventListeners(JSC::SlotVisitor&);
     void invalidateJSEventListeners(JSC::JSObject*);
 
-    bool hasActiveTouchEventListeners() const;
-
 protected:
     virtual ~EventTarget();
     

Modified: trunk/Source/WebCore/page/DebugPageOverlays.cpp (202407 => 202408)


--- trunk/Source/WebCore/page/DebugPageOverlays.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/DebugPageOverlays.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -133,7 +133,8 @@
     if (Page* page = m_frame.page()) {
         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
             EventTrackingRegions eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
-            *region = eventTrackingRegions.synchronousDispatchRegion;
+            for (const auto& synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+                region->unite(synchronousEventRegion.value);
         }
     }
 

Modified: trunk/Source/WebCore/page/Page.cpp (202407 => 202408)


--- trunk/Source/WebCore/page/Page.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/Page.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -372,8 +372,11 @@
         document->updateLayout();
 
     Vector<IntRect> rects;
-    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
-        rects = scrollingCoordinator->absoluteEventTrackingRegions().synchronousDispatchRegion.rects();
+    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+        const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
+        for (const auto& synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+            rects.appendVector(synchronousEventRegion.value.rects());
+    }
 
     Vector<FloatQuad> quads(rects.size());
     for (size_t i = 0; i < rects.size(); ++i)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (202407 => 202408)


--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -28,6 +28,7 @@
 #include "ScrollingCoordinator.h"
 
 #include "Document.h"
+#include "EventNames.h"
 #include "FrameView.h"
 #include "GraphicsLayer.h"
 #include "IntRect.h"
@@ -144,18 +145,19 @@
     }
     
     // FIXME: if we've already accounted for this subframe as a scrollable area, we can avoid recursing into it here.
+    EventTrackingRegions eventTrackingRegions;
     for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) {
         FrameView* subframeView = subframe->view();
         if (!subframeView)
             continue;
 
-        Region subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe).synchronousDispatchRegion;
+        EventTrackingRegions subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe);
         // Map from the frame document to our document.
         IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint());
 
         // FIXME: this translation ignores non-trival transforms on the frame.
         subframeRegion.translate(toIntSize(offset));
-        nonFastScrollableRegion.unite(subframeRegion);
+        eventTrackingRegions.unite(subframeRegion);
     }
 
     Document::RegionFixedPair wheelHandlerRegion = frame.document()->absoluteRegionForEventTargets(frame.document()->wheelEventTargets());
@@ -169,7 +171,8 @@
     nonFastScrollableRegion.unite(wheelHandlerRegion.first);
 
     // FIXME: If this is not the main frame, we could clip the region to the frame's bounds.
-    return EventTrackingRegions { Region(), nonFastScrollableRegion };
+    eventTrackingRegions.uniteSynchronousRegion(eventNames().wheelEvent, nonFastScrollableRegion);
+    return eventTrackingRegions;
 #endif
 }
 

Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp (202407 => 202408)


--- trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -245,18 +245,20 @@
         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";
+    if (!m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions.isEmpty()) {
+        for (const auto& synchronousEventRegion : m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions) {
+            ++indent;
             writeIndent(ts, indent);
-            ts << rect;
+            ts << "(synchronous event dispatch region for event " << synchronousEventRegion.key;
+            ++indent;
+            for (auto rect : synchronousEventRegion.value.rects()) {
+                ts << "\n";
+                writeIndent(ts, indent);
+                ts << rect;
+            }
+            ts << ")\n";
+            indent -= 2;
         }
-        ts << ")\n";
-        indent -= 2;
     }
 
     if (m_synchronousScrollingReasons) {

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (202407 => 202408)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -28,6 +28,7 @@
 
 #if ENABLE(ASYNC_SCROLLING)
 
+#include "EventNames.h"
 #include "Logging.h"
 #include "PlatformWheelEvent.h"
 #include "ScrollingStateTree.h"
@@ -66,7 +67,10 @@
         FloatPoint position = wheelEvent.position();
         position.move(frameScrollingNode.viewToContentsOffset(m_mainFrameScrollPosition));
 
-        bool isSynchronousDispatchRegion = m_eventTrackingRegions.trackingTypeForPoint(roundedIntPoint(position)) == TrackingType::Synchronous;
+        const EventNames& names = eventNames();
+        IntPoint roundedPosition = roundedIntPoint(position);
+        bool isSynchronousDispatchRegion = m_eventTrackingRegions.trackingTypeForPoint(names.wheelEvent, roundedPosition) == TrackingType::Synchronous
+            || m_eventTrackingRegions.trackingTypeForPoint(names.mousewheelEvent, roundedPosition) == TrackingType::Synchronous;
         LOG_WITH_STREAM(Scrolling, stream << "ScrollingTree::shouldHandleWheelEventSynchronously: wheelEvent at " << wheelEvent.position() << " mapped to content point " << position << ", in non-fast region " << isSynchronousDispatchRegion);
 
         if (isSynchronousDispatchRegion)
@@ -233,11 +237,11 @@
     m_mainFrameScrollPosition = position;
 }
 
-TrackingType ScrollingTree::eventTrackingTypeForPoint(IntPoint p)
+TrackingType ScrollingTree::eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint p)
 {
     LockHolder lock(m_mutex);
     
-    return m_eventTrackingRegions.trackingTypeForPoint(p);
+    return m_eventTrackingRegions.trackingTypeForPoint(eventName, p);
 }
 
 bool ScrollingTree::isRubberBandInProgress()

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (202407 => 202408)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -101,7 +101,7 @@
     virtual void scrollingTreeNodeDidEndScroll() { }
 #endif
 
-    WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(IntPoint);
+    WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint);
     
 #if PLATFORM(MAC)
     virtual void handleWheelEventPhase(PlatformWheelEventPhase) = 0;

Added: trunk/Source/WebCore/platform/EventTrackingRegions.cpp (0 => 202408)


--- trunk/Source/WebCore/platform/EventTrackingRegions.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/EventTrackingRegions.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "EventTrackingRegions.h"
+
+namespace WebCore {
+
+TrackingType EventTrackingRegions::trackingTypeForPoint(const String& eventName, const IntPoint& point)
+{
+    auto synchronousRegionIterator = eventSpecificSynchronousDispatchRegions.find(eventName);
+    if (synchronousRegionIterator != eventSpecificSynchronousDispatchRegions.end()) {
+        if (synchronousRegionIterator->value.contains(point))
+            return TrackingType::Synchronous;
+    }
+
+    if (asynchronousDispatchRegion.contains(point))
+        return TrackingType::Asynchronous;
+    return TrackingType::NotTracking;
+}
+
+bool EventTrackingRegions::isEmpty() const
+{
+    return asynchronousDispatchRegion.isEmpty() && eventSpecificSynchronousDispatchRegions.isEmpty();
+}
+
+void EventTrackingRegions::translate(IntSize offset)
+{
+    asynchronousDispatchRegion.translate(offset);
+    for (auto& slot : eventSpecificSynchronousDispatchRegions)
+        slot.value.translate(offset);
+}
+
+void EventTrackingRegions::uniteSynchronousRegion(const String& eventName, const Region& region)
+{
+    if (region.isEmpty())
+        return;
+
+    auto addResult = eventSpecificSynchronousDispatchRegions.add(eventName, region);
+    if (!addResult.isNewEntry)
+        addResult.iterator->value.unite(region);
+}
+
+void EventTrackingRegions::unite(const EventTrackingRegions& eventTrackingRegions)
+{
+    asynchronousDispatchRegion.unite(eventTrackingRegions.asynchronousDispatchRegion);
+    for (auto& slot : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+        uniteSynchronousRegion(slot.key, slot.value);
+}
+
+bool operator==(const EventTrackingRegions& a, const EventTrackingRegions& b)
+{
+    return a.asynchronousDispatchRegion == b.asynchronousDispatchRegion
+        && a.eventSpecificSynchronousDispatchRegions == b.eventSpecificSynchronousDispatchRegions;
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/EventTrackingRegions.h (202407 => 202408)


--- trunk/Source/WebCore/platform/EventTrackingRegions.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/platform/EventTrackingRegions.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -26,6 +26,9 @@
 #pragma once
 
 #include "Region.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -39,32 +42,20 @@
     // 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;
+    // Regions for which events must be sent before performing the default behavior.
+    // The key is the Event Name with an active handler.
+    HashMap<String, Region> eventSpecificSynchronousDispatchRegions;
 
     bool isEmpty() const;
 
-    TrackingType trackingTypeForPoint(const IntPoint&);
+    void translate(IntSize);
+    void uniteSynchronousRegion(const String& eventName, const Region&);
+    void unite(const EventTrackingRegions&);
+
+    TrackingType trackingTypeForPoint(const String& eventName, const IntPoint&);
 };
 
-inline bool EventTrackingRegions::isEmpty() const
-{
-    return asynchronousDispatchRegion.isEmpty() && synchronousDispatchRegion.isEmpty();
-}
+bool operator==(const EventTrackingRegions&, const EventTrackingRegions&);
+inline bool operator!=(const EventTrackingRegions& a, const EventTrackingRegions& b) { return !(a == b); }
 
-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/WebCore/platform/graphics/Region.h (202407 => 202408)


--- trunk/Source/WebCore/platform/graphics/Region.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebCore/platform/graphics/Region.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -198,6 +198,10 @@
 {
     return a.m_bounds == b.m_bounds && a.m_shape == b.m_shape;
 }
+inline bool operator!=(const Region& a, const Region& b)
+{
+    return !(a == b);
+}
 
 inline bool operator==(const Region::Shape& a, const Region::Shape& b)
 {
@@ -208,6 +212,10 @@
 {
     return a.y == b.y && a.segmentIndex == b.segmentIndex;
 }
+inline bool operator!=(const Region::Span& a, const Region::Span& b)
+{
+    return !(a == b);
+}
 
 } // namespace WebCore
 

Modified: trunk/Source/WebKit2/ChangeLog (202407 => 202408)


--- trunk/Source/WebKit2/ChangeLog	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/ChangeLog	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1,3 +1,28 @@
+2016-06-23  Benjamin Poulain  <[email protected]>
+
+        Specialize synchronous event tracking per event type
+        https://bugs.webkit.org/show_bug.cgi?id=158826
+
+        Reviewed by Simon Fraser.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<EventTrackingRegions>::encode):
+        (IPC::ArgumentCoder<EventTrackingRegions>::decode):
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
+        (WebKit::RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint):
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::mergeTrackingTypes):
+        (WebKit::WebPageProxy::updateTouchEventTracking):
+        (WebKit::WebPageProxy::touchEventTrackingType):
+        (WebKit::WebPageProxy::handleTouchEventSynchronously):
+        (WebKit::WebPageProxy::handleTouchEventAsynchronously):
+        (WebKit::WebPageProxy::handleTouchEvent):
+        (WebKit::WebPageProxy::resetState):
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::TouchEventTracking::isTrackingAnything):
+        (WebKit::WebPageProxy::TouchEventTracking::reset):
+
 2016-06-23  Said Abou-Hallawa  <[email protected]>
 
         requestFrameAnimation() callback timestamp should be very close to Performance.now() 

Modified: trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp (202407 => 202408)


--- trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -494,10 +494,11 @@
                 ts << rect;
             }
         }
-        {
+        for (const auto& synchronousEventRegion : node.eventTrackingRegions().eventSpecificSynchronousDispatchRegions) {
             TextStream::GroupScope group(ts);
-            ts << "synchronous-event-tracking-region";
-            for (auto rect : node.eventTrackingRegions().synchronousDispatchRegion.rects()) {
+            ts << "synchronous-event-tracking-region for event " << synchronousEventRegion.key;
+
+            for (auto rect : synchronousEventRegion.value.rects()) {
                 ts << "\n";
                 ts.writeIndent();
                 ts << rect;

Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp (202407 => 202408)


--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -111,7 +111,7 @@
 void ArgumentCoder<EventTrackingRegions>::encode(ArgumentEncoder& encoder, const EventTrackingRegions& eventTrackingRegions)
 {
     encoder << eventTrackingRegions.asynchronousDispatchRegion;
-    encoder << eventTrackingRegions.synchronousDispatchRegion;
+    encoder << eventTrackingRegions.eventSpecificSynchronousDispatchRegions;
 }
 
 bool ArgumentCoder<EventTrackingRegions>::decode(ArgumentDecoder& decoder, EventTrackingRegions& eventTrackingRegions)
@@ -119,11 +119,11 @@
     Region asynchronousDispatchRegion;
     if (!decoder.decode(asynchronousDispatchRegion))
         return false;
-    Region synchronousDispatchRegion;
-    if (!decoder.decode(synchronousDispatchRegion))
+    HashMap<String, Region> eventSpecificSynchronousDispatchRegions;
+    if (!decoder.decode(eventSpecificSynchronousDispatchRegions))
         return false;
     eventTrackingRegions.asynchronousDispatchRegion = WTFMove(asynchronousDispatchRegion);
-    eventTrackingRegions.synchronousDispatchRegion = WTFMove(synchronousDispatchRegion);
+    eventTrackingRegions.eventSpecificSynchronousDispatchRegions = WTFMove(eventSpecificSynchronousDispatchRegions);
     return true;
 }
 

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp (202407 => 202408)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -149,9 +149,9 @@
     return result == ScrollingTree::DidHandleEvent; // FIXME: handle other values.
 }
 
-TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(IntPoint p) const
+TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint p) const
 {
-    return m_scrollingTree->eventTrackingTypeForPoint(p);
+    return m_scrollingTree->eventTrackingTypeForPoint(eventName, p);
 }
 
 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale)

Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (202407 => 202408)


--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -56,7 +56,7 @@
     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, WebCore::SetOrSyncScrollingLayerPosition);
     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
 
-    WebCore::TrackingType eventTrackingTypeForPoint(WebCore::IntPoint) const;
+    WebCore::TrackingType eventTrackingTypeForPoint(const AtomicString& eventName, 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 (202407 => 202408)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2016-06-24 02:38:00 UTC (rev 202408)
@@ -110,6 +110,7 @@
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/DragController.h>
 #include <WebCore/DragData.h>
+#include <WebCore/EventNames.h>
 #include <WebCore/FloatRect.h>
 #include <WebCore/FocusDirection.h>
 #include <WebCore/JSDOMBinding.h>
@@ -1955,26 +1956,76 @@
 
 #if ENABLE(TOUCH_EVENTS)
 
-TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
+static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
 {
+    if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
+        return b;
+    return a;
+}
+
+void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
+{
 #if ENABLE(ASYNC_SCROLLING)
-    TrackingType trackingType = TrackingType::NotTracking;
+    const EventNames& names = eventNames();
     for (auto& touchPoint : touchStartEvent.touchPoints()) {
-        TrackingType touchPointTrackingType = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(touchPoint.location());
-        if (touchPointTrackingType == TrackingType::Synchronous)
-            return TrackingType::Synchronous;
+        IntPoint location = touchPoint.location();
+        auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
+            if (trackingType == TrackingType::Synchronous)
+                return;
 
-        if (touchPointTrackingType == TrackingType::Asynchronous)
-            trackingType = touchPointTrackingType;
+            TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
+
+            trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
+        };
+        updateTrackingType(m_touchEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
+        updateTrackingType(m_touchEventTracking.touchStartTracking, names.touchstartEvent);
+        updateTrackingType(m_touchEventTracking.touchMoveTracking, names.touchmoveEvent);
+        updateTrackingType(m_touchEventTracking.touchEndTracking, names.touchendEvent);
     }
-
-    return trackingType;
 #else
     UNUSED_PARAM(touchStartEvent);
+    m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
 #endif // ENABLE(ASYNC_SCROLLING)
-    return TrackingType::Synchronous;
 }
 
+TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
+{
+    // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
+    //
+    // Touch events define a sequence with strong dependencies. For example, we can expect
+    // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
+    // the two.
+    //
+    // WebCore should not have to set up its state correctly after some events were dismissed.
+    // For example, we don't want to send a TouchMoved without a TouchPressed.
+    // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
+    TrackingType globalTrackingType = m_touchEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
+
+    globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchForceChangedTracking);
+    for (auto& touchPoint : touchStartEvent.touchPoints()) {
+        switch (touchPoint.state()) {
+        case WebPlatformTouchPoint::TouchReleased:
+            globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchEndTracking);
+            break;
+        case WebPlatformTouchPoint::TouchPressed:
+            globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchStartTracking);
+            break;
+        case WebPlatformTouchPoint::TouchMoved:
+        case WebPlatformTouchPoint::TouchStationary:
+            globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchMoveTracking);
+            break;
+        case WebPlatformTouchPoint::TouchCancelled:
+            globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
+            break;
+        }
+    }
+
+    return globalTrackingType;
+}
+
 #endif
 
 #if ENABLE(MAC_GESTURE_EVENTS)
@@ -1998,14 +2049,15 @@
         return;
 
     if (event.type() == WebEvent::TouchStart) {
-        m_touchEventsTrackingType = touchEventTrackingType(event);
+        updateTouchEventTracking(event);
         m_layerTreeTransactionIdAtLastTouchStart = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).lastCommittedLayerTreeTransactionID();
     }
 
-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
+    TrackingType touchEventsTrackingType = touchEventTrackingType(event);
+    if (touchEventsTrackingType == TrackingType::NotTracking)
         return;
 
-    if (m_touchEventsTrackingType == TrackingType::Asynchronous) {
+    if (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
@@ -2026,7 +2078,7 @@
     m_process->responsivenessTimer().stop();
 
     if (event.allTouchPointsAreReleased())
-        m_touchEventsTrackingType = TrackingType::NotTracking;
+        m_touchEventTracking.reset();
 }
 
 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
@@ -2034,13 +2086,14 @@
     if (!isValid())
         return;
 
-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
+    TrackingType touchEventsTrackingType = touchEventTrackingType(event);
+    if (touchEventsTrackingType == TrackingType::NotTracking)
         return;
 
     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
 
     if (event.allTouchPointsAreReleased())
-        m_touchEventsTrackingType = TrackingType::NotTracking;
+        m_touchEventTracking.reset();
 }
 
 #elif ENABLE(TOUCH_EVENTS)
@@ -2050,9 +2103,9 @@
         return;
 
     if (event.type() == WebEvent::TouchStart)
-        m_touchEventsTrackingType = touchEventTrackingType(event);
+        updateTouchEventTracking(event);
 
-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
+    if (touchEventTrackingType(event) == TrackingType::NotTracking)
         return;
 
     // If the page is suspended, which should be the case during panning, pinching
@@ -2075,7 +2128,7 @@
     }
 
     if (event.allTouchPointsAreReleased())
-        m_touchEventsTrackingType = TrackingType::NotTracking;
+        m_touchEventTracking.reset();
 }
 #endif // ENABLE(TOUCH_EVENTS)
 
@@ -5094,7 +5147,7 @@
     }
 
 #if ENABLE(TOUCH_EVENTS)
-    m_touchEventsTrackingType = TrackingType::NotTracking;
+    m_touchEventTracking.reset();
 #endif
 
 #if ENABLE(INPUT_TYPE_COLOR)

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (202407 => 202408)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2016-06-24 02:38:00 UTC (rev 202408)
@@ -1468,6 +1468,7 @@
     void sendWheelEvent(const WebWheelEvent&);
 
 #if ENABLE(TOUCH_EVENTS)
+    void updateTouchEventTracking(const WebTouchEvent&);
     WebCore::TrackingType touchEventTrackingType(const WebTouchEvent&) const;
 #endif
 
@@ -1695,7 +1696,29 @@
     std::unique_ptr<NativeWebMouseEvent> m_currentlyProcessedMouseDownEvent;
 
 #if ENABLE(TOUCH_EVENTS)
-    WebCore::TrackingType m_touchEventsTrackingType { WebCore::TrackingType::NotTracking };
+    struct TouchEventTracking {
+        WebCore::TrackingType touchForceChangedTracking { WebCore::TrackingType::NotTracking };
+        WebCore::TrackingType touchStartTracking { WebCore::TrackingType::NotTracking };
+        WebCore::TrackingType touchMoveTracking { WebCore::TrackingType::NotTracking };
+        WebCore::TrackingType touchEndTracking { WebCore::TrackingType::NotTracking };
+
+        bool isTrackingAnything() const
+        {
+            return touchForceChangedTracking != WebCore::TrackingType::NotTracking
+                || touchStartTracking != WebCore::TrackingType::NotTracking
+                || touchMoveTracking != WebCore::TrackingType::NotTracking
+                || touchEndTracking != WebCore::TrackingType::NotTracking;
+        }
+
+        void reset()
+        {
+            touchForceChangedTracking = WebCore::TrackingType::NotTracking;
+            touchStartTracking = WebCore::TrackingType::NotTracking;
+            touchMoveTracking = WebCore::TrackingType::NotTracking;
+            touchEndTracking = WebCore::TrackingType::NotTracking;
+        }
+    };
+    TouchEventTracking m_touchEventTracking;
 #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