<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[202408] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/202408">202408</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2016-06-23 19:38:00 -0700 (Thu, 23 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>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-&gt;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&lt;EventTrackingRegions&gt;::encode):
(IPC::ArgumentCoder&lt;EventTrackingRegions&gt;::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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingfixedfixedinoverflowexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframescoordinatedframeexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframescoordinatedframegainscrollingancestorexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframescoordinatedframeinfixedexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframescoordinatedframelosescrollingancestorexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframesframesetframescrollabilityexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframesframesetnestedframescrollabilityexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingframesscrollregionafterframelayoutexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoredomEventTargetcpp">trunk/Source/WebCore/dom/EventTarget.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventTargeth">trunk/Source/WebCore/dom/EventTarget.h</a></li>
<li><a href="#trunkSourceWebCorepageDebugPageOverlayscpp">trunk/Source/WebCore/page/DebugPageOverlays.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePagecpp">trunk/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingCoordinatorcpp">trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingStateFrameScrollingNodecpp">trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreecpp">trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeh">trunk/Source/WebCore/page/scrolling/ScrollingTree.h</a></li>
<li><a href="#trunkSourceWebCoreplatformEventTrackingRegionsh">trunk/Source/WebCore/platform/EventTrackingRegions.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsRegionh">trunk/Source/WebCore/platform/graphics/Region.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedScrollingRemoteScrollingCoordinatorTransactioncpp">trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCoreArgumentCoderscpp">trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxycpp">trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh">trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidedocumentwithpassivelistenerexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidedocumentwithpassivelistenerhtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidewindowwithpassivelistenerexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidewindowwithpassivelistenerhtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivetouchendlistenerexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithactivetouchendlistenerhtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivelistenerinsideactivelistenerhtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchendlistenerexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchendlistenerhtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchendlistenersonelementsexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchendlistenersonelementshtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchmovelistenersonelementsexpectedtxt">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchmovelistenersonelementshtml">trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html</a></li>
<li><a href="#trunkSourceWebCoreplatformEventTrackingRegionscpp">trunk/Source/WebCore/platform/EventTrackingRegions.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-06-24 00:59:08 UTC (rev 202407)
+++ trunk/LayoutTests/ChangeLog        2016-06-24 02:38:00 UTC (rev 202408)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-06-23  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        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.
+
</ins><span class="cx"> 2016-06-23  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update TestExpectations for a couple video track tests.
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidedocumentwithpassivelistenerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+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 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidedocumentwithpassivelistenerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-document-with-passive-listener.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getClickUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        function getDragUIScript(startX, startY, endX, endY)
+        {
+            return `
+            (function() {
+                uiController.dragFromPointToPoint(${startX}, ${startY}, ${endX}, ${endY}, 0.15, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+
+                    if (shouldPreventDefault)
+                        event.preventDefault();
+                }
+            }
+
+            document.addEventListener('touchstart', getLogEvent(&quot;document&quot;), { 'passive': true });
+            document.addEventListener('touchmove', getLogEvent(&quot;document&quot;), { 'passive': true });
+            document.addEventListener('touchend', getLogEvent(&quot;document&quot;), { 'passive': true });
+            document.addEventListener('touchcancel', getLogEvent(&quot;document&quot;), { 'passive': true });
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent(&quot;target1&quot;, true));
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchcancel', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent(&quot;target3&quot;, true));
+            target3.addEventListener('touchend', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent(&quot;target3&quot;), { 'passive': true });
+
+            output += &quot;&lt;h1&gt;Cancelled drag on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Cancelled drag on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Cancelled drag on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), function(result) {
+                        output += result;
+                        output += &quot;&lt;h1&gt;Useless Click in the document, should be passive&lt;/h1&gt;&quot;;
+                        testRunner.runUIScript(getClickUIScript(300, 300), function(result) {
+                            document.getElementById('output').innerHTML = output;
+                            testRunner.notifyDone();
+                        });
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidewindowwithpassivelistenerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+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 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivelistenerinsidewindowwithpassivelistenerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-listener-inside-window-with-passive-listener.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getClickUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        function getDragUIScript(startX, startY, endX, endY)
+        {
+            return `
+            (function() {
+                uiController.dragFromPointToPoint(${startX}, ${startY}, ${endX}, ${endY}, 0.15, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+
+                    if (shouldPreventDefault)
+                        event.preventDefault();
+                }
+            }
+
+            window.addEventListener('touchstart', getLogEvent(&quot;document&quot;), { 'passive': true });
+            window.addEventListener('touchmove', getLogEvent(&quot;document&quot;), { 'passive': true });
+            window.addEventListener('touchend', getLogEvent(&quot;document&quot;), { 'passive': true });
+            window.addEventListener('touchcancel', getLogEvent(&quot;document&quot;), { 'passive': true });
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent(&quot;target1&quot;, true));
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchcancel', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent(&quot;target3&quot;, true));
+            target3.addEventListener('touchend', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent(&quot;target3&quot;), { 'passive': true });
+
+            output += &quot;&lt;h1&gt;Cancelled drag on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Cancelled drag on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Cancelled drag on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), function(result) {
+                        output += result;
+                        output += &quot;&lt;h1&gt;Useless Click in the document, should be passive&lt;/h1&gt;&quot;;
+                        testRunner.runUIScript(getClickUIScript(300, 300), function(result) {
+                            document.getElementById('output').innerHTML = output;
+                            testRunner.notifyDone();
+                        });
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivetouchendlistenerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithactivetouchendlistenerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-active-touch-end-listener.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,106 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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 += '&lt;pre&gt;' + window.internals.scrollingStateTreeAsText() + '&lt;/pre&gt;';
+                    output += 'Listener ' + listener + ' received' + (event.cancelable ? ' cancelable' : '') + ' event ' + event.type + ' targetting ' + event.target.id;
+                    if (event.touches[0] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;));
+
+            output += &quot;&lt;h1&gt;Tap on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Tap on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Tap on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivelistenerinsideactivelistenerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-listener-inside-active-listener.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,116 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output += '&lt;br&gt;';
+                    output += 'defaultPrevented before preventDefault(): ' + event.defaultPrevented + '&lt;br&gt;';
+                    event.preventDefault();
+                    output += 'defaultPrevented after preventDefault(): ' + event.defaultPrevented + '&lt;br&gt;';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchmove', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchcancel', getLogEvent(&quot;target1&quot;));
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchend', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchcancel', getLogEvent(&quot;target3&quot;), { 'passive': true });
+
+            output += &quot;&lt;h1&gt;Tap on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Tap on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Tap on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchendlistenerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchendlistenerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-end-listener.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,105 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;), { 'passive': true });
+
+            output += &quot;&lt;h1&gt;Tap on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Tap on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Tap on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchendlistenersonelementsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchendlistenersonelementshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-end-listeners-on-elements.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function getUIScript(x, y)
+        {
+            return `
+            (function() {
+                uiController.singleTapAtPoint(${x}, ${y}, function() {
+                    uiController.uiScriptComplete(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchcancel', getLogEvent(&quot;target1&quot;));
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchend', getLogEvent(&quot;target3&quot;));
+            target3.addEventListener('touchcancel', getLogEvent(&quot;target3&quot;));
+
+            output += &quot;&lt;h1&gt;Tap on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getUIScript(50, 50), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Tap on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getUIScript(150, 50), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Tap on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getUIScript(250, 50), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchmovelistenersonelementsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements-expected.txt (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventstouchiostapwithpassivetouchstartactivetouchmovelistenersonelementshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/touch/ios/tap-with-passive-touch-start-active-touch-move-listeners-on-elements.html (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,120 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script&gt;
+        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(&quot;Done&quot;);
+                });
+            })();`
+        }
+
+        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] &amp;&amp; event.touches[0].clientX) {
+                        output += ' at ' + event.touches[0].clientX + ', ' + event.touches[0].clientY;
+                    }
+                    output +=  '&lt;br&gt;';
+
+                    if (event.type === 'touchmove')
+                        event.preventDefault();
+                }
+            }
+
+            let target1 = document.getElementById('eventTarget1');
+            target1.addEventListener('touchstart', getLogEvent(&quot;target1&quot;), { 'passive': true });
+            target1.addEventListener('touchmove', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchend', getLogEvent(&quot;target1&quot;));
+            target1.addEventListener('touchcancel', getLogEvent(&quot;target1&quot;));
+            let target3 = document.getElementById('eventTarget3');
+            target3.addEventListener('touchstart', getLogEvent(&quot;target3&quot;), { 'passive': true });
+            target3.addEventListener('touchmove', getLogEvent(&quot;target3&quot;));
+            target3.addEventListener('touchend', getLogEvent(&quot;target3&quot;));
+            target3.addEventListener('touchcancel', getLogEvent(&quot;target3&quot;));
+
+            output += &quot;&lt;h1&gt;Cancelled drag on Target1 (green)&lt;/h1&gt;&quot;;
+            testRunner.runUIScript(getDragUIScript(50, 50, 100, 100), function(result) {
+                output += result;
+                output += &quot;&lt;h1&gt;Cancelled drag on Target2 (red)&lt;/h1&gt;&quot;;
+                testRunner.runUIScript(getDragUIScript(150, 50, 200, 100), function(result) {
+                    output += result;
+                    output += &quot;&lt;h1&gt;Cancelled drag on Target3 (blue)&lt;/h1&gt;&quot;;
+                    testRunner.runUIScript(getDragUIScript(250, 50, 300, 100), function(result) {
+                        document.getElementById('output').innerHTML = output;
+                        testRunner.notifyDone();
+                    });
+                });
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    &lt;/script&gt;
+    &lt;style&gt;
+        * { 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;
+        }
+    &lt;/style&gt;
+    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1&quot;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=eventTarget1&gt;
+        &lt;div id=eventTarget2&gt;
+            &lt;div id=eventTarget3&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=output&gt;
+    This test requires UIScriptController to run.
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingfixedfixedinoverflowexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/fixed/fixed-in-overflow-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 2213)
</span><span class="cx">   (requested scroll position 0 200)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (0,13) size 204x204)
</span><span class="cx">   (children 1
</span><span class="cx">     (Fixed node
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframescoordinatedframeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 1016)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (45,47) size 404x304)
</span><span class="cx">   (children 1
</span><span class="cx">     (Frame scrolling node
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframescoordinatedframegainscrollingancestorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-gain-scrolling-ancestor-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 1016)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (45,47) size 404x304)
</span><span class="cx">   (children 1
</span><span class="cx">     (Fixed node
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframescoordinatedframeinfixedexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 1016)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (45,37) size 404x304)
</span><span class="cx">   (children 1
</span><span class="cx">     (Fixed node
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframescoordinatedframelosescrollingancestorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/coordinated-frame-lose-scrolling-ancestor-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 1016)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (45,47) size 404x304)
</span><span class="cx">   (children 1
</span><span class="cx">     (Frame scrolling node
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframesframesetframescrollabilityexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-frame-scrollability-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 800 600)
</span><span class="cx">   (contents size 800 600)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (0,0) size 800x594)
</span><span class="cx"> )
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframesframesetnestedframescrollabilityexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/frameset-nested-frame-scrollability-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 800 600)
</span><span class="cx">   (contents size 800 600)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (0,166) size 280x434)
</span><span class="cx"> )
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingframesscrollregionafterframelayoutexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/frames/scroll-region-after-frame-layout-expected.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx"> (Frame scrolling node
</span><span class="cx">   (scrollable area size 785 600)
</span><span class="cx">   (contents size 785 757)
</span><del>-  (synchronous event dispatch region
</del><ins>+  (synchronous event dispatch region for event wheel
</ins><span class="cx">     at (68,68) size 300x300)
</span><span class="cx"> )
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2114,6 +2114,7 @@
</span><span class="cx">     platform/DisplaySleepDisabler.cpp
</span><span class="cx">     platform/DragData.cpp
</span><span class="cx">     platform/DragImage.cpp
</span><ins>+    platform/EventTrackingRegions.cpp
</ins><span class="cx">     platform/FileChooser.cpp
</span><span class="cx">     platform/FileStream.cpp
</span><span class="cx">     platform/FileSystem.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2016-06-23  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        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-&gt;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.
+
</ins><span class="cx"> 2016-06-23  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         More attempting to fix external iOS builds.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1075,6 +1075,7 @@
</span><span class="cx">                 26255F0318878E110006E1FD /* UserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 26255F0118878E110006E1FD /* UserAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 26255F0418878E110006E1FD /* UserAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26255F0218878E110006E1FD /* UserAgentMac.mm */; };
</span><span class="cx">                 262EC41A1D078FB900BA78FC /* EventTrackingRegions.h in Headers */ = {isa = PBXBuildFile; fileRef = 262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                262EC41D1D110B9000BA78FC /* EventTrackingRegions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */; };
</ins><span class="cx">                 265541391489811C000DFC5D /* KeyEventCodesIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 265541371489811C000DFC5D /* KeyEventCodesIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2655413A1489811C000DFC5D /* KeyEventIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 265541381489811C000DFC5D /* KeyEventIOS.mm */; };
</span><span class="cx">                 265541521489B233000DFC5D /* CursorIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2655414B1489AA2B000DFC5D /* CursorIOS.cpp */; };
</span><span class="lines">@@ -8610,6 +8611,7 @@
</span><span class="cx">                 26255F0118878E110006E1FD /* UserAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserAgent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 26255F0218878E110006E1FD /* UserAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserAgentMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventTrackingRegions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventTrackingRegions.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 265541371489811C000DFC5D /* KeyEventCodesIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyEventCodesIOS.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 265541381489811C000DFC5D /* KeyEventIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyEventIOS.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2655414B1489AA2B000DFC5D /* CursorIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CursorIOS.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -23134,6 +23136,7 @@
</span><span class="cx">                                 A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
</span><span class="cx">                                 A7CFB3D00B7ED10A0070C32D /* DragImage.h */,
</span><span class="cx">                                 1CA19E150DC255CA0065A994 /* EventLoop.h */,
</span><ins>+                                262EC41C1D110B1F00BA78FC /* EventTrackingRegions.cpp */,
</ins><span class="cx">                                 262EC4191D078F3D00BA78FC /* EventTrackingRegions.h */,
</span><span class="cx">                                 934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
</span><span class="cx">                                 066C772A0AB603B700238CC4 /* FileChooser.h */,
</span><span class="lines">@@ -30675,6 +30678,7 @@
</span><span class="cx">                                 A7BBE26611AFB3F20005EA03 /* JSHTMLMeterElement.cpp in Sources */,
</span><span class="cx">                                 1AE2AB290A1CE63B00B42B25 /* JSHTMLModElement.cpp in Sources */,
</span><span class="cx">                                 BC305C790C076BB300CD20F0 /* JSHTMLObjectElement.cpp in Sources */,
</span><ins>+                                262EC41D1D110B9000BA78FC /* EventTrackingRegions.cpp in Sources */,
</ins><span class="cx">                                 BC305CA40C0781BB00CD20F0 /* JSHTMLObjectElementCustom.cpp in Sources */,
</span><span class="cx">                                 1A85B1EA0A1B240500D8C87C /* JSHTMLOListElement.cpp in Sources */,
</span><span class="cx">                                 A80E7E9C0A1A83E3007FB8C5 /* JSHTMLOptGroupElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -243,16 +243,6 @@
</span><span class="cx">     return !event.defaultPrevented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool EventTarget::hasActiveTouchEventListeners() const
-{
-    const EventNames&amp; names = eventNames();
-    return hasActiveEventListeners(names.touchstartEvent)
-        || hasActiveEventListeners(names.touchmoveEvent)
-        || hasActiveEventListeners(names.touchendEvent)
-        || hasActiveEventListeners(names.touchcancelEvent)
-        || hasActiveEventListeners(names.touchforcechangeEvent);
-}
-
</del><span class="cx"> void EventTarget::fireEventListeners(Event&amp; event, EventTargetData* d, EventListenerVector&amp; entry)
</span><span class="cx"> {
</span><span class="cx">     Ref&lt;EventTarget&gt; protectedThis(*this);
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -168,8 +168,6 @@
</span><span class="cx">     void visitJSEventListeners(JSC::SlotVisitor&amp;);
</span><span class="cx">     void invalidateJSEventListeners(JSC::JSObject*);
</span><span class="cx"> 
</span><del>-    bool hasActiveTouchEventListeners() const;
-
</del><span class="cx"> protected:
</span><span class="cx">     virtual ~EventTarget();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCorepageDebugPageOverlayscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DebugPageOverlays.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -133,7 +133,8 @@
</span><span class="cx">     if (Page* page = m_frame.page()) {
</span><span class="cx">         if (ScrollingCoordinator* scrollingCoordinator = page-&gt;scrollingCoordinator()) {
</span><span class="cx">             EventTrackingRegions eventTrackingRegions = scrollingCoordinator-&gt;absoluteEventTrackingRegions();
</span><del>-            *region = eventTrackingRegions.synchronousDispatchRegion;
</del><ins>+            for (const auto&amp; synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+                region-&gt;unite(synchronousEventRegion.value);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -372,8 +372,11 @@
</span><span class="cx">         document-&gt;updateLayout();
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;IntRect&gt; rects;
</span><del>-    if (ScrollingCoordinator* scrollingCoordinator = this-&gt;scrollingCoordinator())
-        rects = scrollingCoordinator-&gt;absoluteEventTrackingRegions().synchronousDispatchRegion.rects();
</del><ins>+    if (ScrollingCoordinator* scrollingCoordinator = this-&gt;scrollingCoordinator()) {
+        const EventTrackingRegions&amp; eventTrackingRegions = scrollingCoordinator-&gt;absoluteEventTrackingRegions();
+        for (const auto&amp; synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+            rects.appendVector(synchronousEventRegion.value.rects());
+    }
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;FloatQuad&gt; quads(rects.size());
</span><span class="cx">     for (size_t i = 0; i &lt; rects.size(); ++i)
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;ScrollingCoordinator.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Document.h&quot;
</span><ins>+#include &quot;EventNames.h&quot;
</ins><span class="cx"> #include &quot;FrameView.h&quot;
</span><span class="cx"> #include &quot;GraphicsLayer.h&quot;
</span><span class="cx"> #include &quot;IntRect.h&quot;
</span><span class="lines">@@ -144,18 +145,19 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // FIXME: if we've already accounted for this subframe as a scrollable area, we can avoid recursing into it here.
</span><ins>+    EventTrackingRegions eventTrackingRegions;
</ins><span class="cx">     for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe-&gt;tree().nextSibling()) {
</span><span class="cx">         FrameView* subframeView = subframe-&gt;view();
</span><span class="cx">         if (!subframeView)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        Region subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe).synchronousDispatchRegion;
</del><ins>+        EventTrackingRegions subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe);
</ins><span class="cx">         // Map from the frame document to our document.
</span><span class="cx">         IntPoint offset = subframeView-&gt;contentsToContainingViewContents(IntPoint());
</span><span class="cx"> 
</span><span class="cx">         // FIXME: this translation ignores non-trival transforms on the frame.
</span><span class="cx">         subframeRegion.translate(toIntSize(offset));
</span><del>-        nonFastScrollableRegion.unite(subframeRegion);
</del><ins>+        eventTrackingRegions.unite(subframeRegion);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Document::RegionFixedPair wheelHandlerRegion = frame.document()-&gt;absoluteRegionForEventTargets(frame.document()-&gt;wheelEventTargets());
</span><span class="lines">@@ -169,7 +171,8 @@
</span><span class="cx">     nonFastScrollableRegion.unite(wheelHandlerRegion.first);
</span><span class="cx"> 
</span><span class="cx">     // FIXME: If this is not the main frame, we could clip the region to the frame's bounds.
</span><del>-    return EventTrackingRegions { Region(), nonFastScrollableRegion };
</del><ins>+    eventTrackingRegions.uniteSynchronousRegion(eventNames().wheelEvent, nonFastScrollableRegion);
+    return eventTrackingRegions;
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingStateFrameScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -245,18 +245,20 @@
</span><span class="cx">         ts &lt;&lt; &quot;)\n&quot;;
</span><span class="cx">         indent -= 2;
</span><span class="cx">     }
</span><del>-    if (!m_eventTrackingRegions.synchronousDispatchRegion.isEmpty()) {
-        ++indent;
-        writeIndent(ts, indent);
-        ts &lt;&lt; &quot;(synchronous event dispatch region&quot;;
-        ++indent;
-        for (auto rect : m_eventTrackingRegions.synchronousDispatchRegion.rects()) {
-            ts &lt;&lt; &quot;\n&quot;;
</del><ins>+    if (!m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions.isEmpty()) {
+        for (const auto&amp; synchronousEventRegion : m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions) {
+            ++indent;
</ins><span class="cx">             writeIndent(ts, indent);
</span><del>-            ts &lt;&lt; rect;
</del><ins>+            ts &lt;&lt; &quot;(synchronous event dispatch region for event &quot; &lt;&lt; synchronousEventRegion.key;
+            ++indent;
+            for (auto rect : synchronousEventRegion.value.rects()) {
+                ts &lt;&lt; &quot;\n&quot;;
+                writeIndent(ts, indent);
+                ts &lt;&lt; rect;
+            }
+            ts &lt;&lt; &quot;)\n&quot;;
+            indent -= 2;
</ins><span class="cx">         }
</span><del>-        ts &lt;&lt; &quot;)\n&quot;;
-        indent -= 2;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_synchronousScrollingReasons) {
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ASYNC_SCROLLING)
</span><span class="cx"> 
</span><ins>+#include &quot;EventNames.h&quot;
</ins><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;PlatformWheelEvent.h&quot;
</span><span class="cx"> #include &quot;ScrollingStateTree.h&quot;
</span><span class="lines">@@ -66,7 +67,10 @@
</span><span class="cx">         FloatPoint position = wheelEvent.position();
</span><span class="cx">         position.move(frameScrollingNode.viewToContentsOffset(m_mainFrameScrollPosition));
</span><span class="cx"> 
</span><del>-        bool isSynchronousDispatchRegion = m_eventTrackingRegions.trackingTypeForPoint(roundedIntPoint(position)) == TrackingType::Synchronous;
</del><ins>+        const EventNames&amp; names = eventNames();
+        IntPoint roundedPosition = roundedIntPoint(position);
+        bool isSynchronousDispatchRegion = m_eventTrackingRegions.trackingTypeForPoint(names.wheelEvent, roundedPosition) == TrackingType::Synchronous
+            || m_eventTrackingRegions.trackingTypeForPoint(names.mousewheelEvent, roundedPosition) == TrackingType::Synchronous;
</ins><span class="cx">         LOG_WITH_STREAM(Scrolling, stream &lt;&lt; &quot;ScrollingTree::shouldHandleWheelEventSynchronously: wheelEvent at &quot; &lt;&lt; wheelEvent.position() &lt;&lt; &quot; mapped to content point &quot; &lt;&lt; position &lt;&lt; &quot;, in non-fast region &quot; &lt;&lt; isSynchronousDispatchRegion);
</span><span class="cx"> 
</span><span class="cx">         if (isSynchronousDispatchRegion)
</span><span class="lines">@@ -233,11 +237,11 @@
</span><span class="cx">     m_mainFrameScrollPosition = position;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TrackingType ScrollingTree::eventTrackingTypeForPoint(IntPoint p)
</del><ins>+TrackingType ScrollingTree::eventTrackingTypeForPoint(const AtomicString&amp; eventName, IntPoint p)
</ins><span class="cx"> {
</span><span class="cx">     LockHolder lock(m_mutex);
</span><span class="cx">     
</span><del>-    return m_eventTrackingRegions.trackingTypeForPoint(p);
</del><ins>+    return m_eventTrackingRegions.trackingTypeForPoint(eventName, p);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ScrollingTree::isRubberBandInProgress()
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">     virtual void scrollingTreeNodeDidEndScroll() { }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(IntPoint);
</del><ins>+    WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(const AtomicString&amp; eventName, IntPoint);
</ins><span class="cx">     
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     virtual void handleWheelEventPhase(PlatformWheelEventPhase) = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformEventTrackingRegionscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/EventTrackingRegions.cpp (0 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/EventTrackingRegions.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/EventTrackingRegions.cpp        2016-06-24 02:38:00 UTC (rev 202408)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+/*
+ * 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 &quot;config.h&quot;
+#include &quot;EventTrackingRegions.h&quot;
+
+namespace WebCore {
+
+TrackingType EventTrackingRegions::trackingTypeForPoint(const String&amp; eventName, const IntPoint&amp; point)
+{
+    auto synchronousRegionIterator = eventSpecificSynchronousDispatchRegions.find(eventName);
+    if (synchronousRegionIterator != eventSpecificSynchronousDispatchRegions.end()) {
+        if (synchronousRegionIterator-&gt;value.contains(point))
+            return TrackingType::Synchronous;
+    }
+
+    if (asynchronousDispatchRegion.contains(point))
+        return TrackingType::Asynchronous;
+    return TrackingType::NotTracking;
+}
+
+bool EventTrackingRegions::isEmpty() const
+{
+    return asynchronousDispatchRegion.isEmpty() &amp;&amp; eventSpecificSynchronousDispatchRegions.isEmpty();
+}
+
+void EventTrackingRegions::translate(IntSize offset)
+{
+    asynchronousDispatchRegion.translate(offset);
+    for (auto&amp; slot : eventSpecificSynchronousDispatchRegions)
+        slot.value.translate(offset);
+}
+
+void EventTrackingRegions::uniteSynchronousRegion(const String&amp; eventName, const Region&amp; region)
+{
+    if (region.isEmpty())
+        return;
+
+    auto addResult = eventSpecificSynchronousDispatchRegions.add(eventName, region);
+    if (!addResult.isNewEntry)
+        addResult.iterator-&gt;value.unite(region);
+}
+
+void EventTrackingRegions::unite(const EventTrackingRegions&amp; eventTrackingRegions)
+{
+    asynchronousDispatchRegion.unite(eventTrackingRegions.asynchronousDispatchRegion);
+    for (auto&amp; slot : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+        uniteSynchronousRegion(slot.key, slot.value);
+}
+
+bool operator==(const EventTrackingRegions&amp; a, const EventTrackingRegions&amp; b)
+{
+    return a.asynchronousDispatchRegion == b.asynchronousDispatchRegion
+        &amp;&amp; a.eventSpecificSynchronousDispatchRegions == b.eventSpecificSynchronousDispatchRegions;
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformEventTrackingRegionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/EventTrackingRegions.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -26,6 +26,9 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Region.h&quot;
</span><ins>+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/text/StringHash.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -39,32 +42,20 @@
</span><span class="cx">     // Region for which events can be dispatched without blocking scrolling.
</span><span class="cx">     Region asynchronousDispatchRegion;
</span><span class="cx"> 
</span><del>-    // Region for which events must be sent before performing the default behavior.
-    Region synchronousDispatchRegion;
</del><ins>+    // Regions for which events must be sent before performing the default behavior.
+    // The key is the Event Name with an active handler.
+    HashMap&lt;String, Region&gt; eventSpecificSynchronousDispatchRegions;
</ins><span class="cx"> 
</span><span class="cx">     bool isEmpty() const;
</span><span class="cx"> 
</span><del>-    TrackingType trackingTypeForPoint(const IntPoint&amp;);
</del><ins>+    void translate(IntSize);
+    void uniteSynchronousRegion(const String&amp; eventName, const Region&amp;);
+    void unite(const EventTrackingRegions&amp;);
+
+    TrackingType trackingTypeForPoint(const String&amp; eventName, const IntPoint&amp;);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline bool EventTrackingRegions::isEmpty() const
-{
-    return asynchronousDispatchRegion.isEmpty() &amp;&amp; synchronousDispatchRegion.isEmpty();
-}
</del><ins>+bool operator==(const EventTrackingRegions&amp;, const EventTrackingRegions&amp;);
+inline bool operator!=(const EventTrackingRegions&amp; a, const EventTrackingRegions&amp; b) { return !(a == b); }
</ins><span class="cx"> 
</span><del>-inline TrackingType EventTrackingRegions::trackingTypeForPoint(const IntPoint&amp; point)
-{
-    if (synchronousDispatchRegion.contains(point))
-        return TrackingType::Synchronous;
-    if (asynchronousDispatchRegion.contains(point))
-        return TrackingType::Asynchronous;
-    return TrackingType::NotTracking;
-}
-
-inline bool operator==(const EventTrackingRegions&amp; a, const EventTrackingRegions&amp; b)
-{
-    return a.asynchronousDispatchRegion == b.asynchronousDispatchRegion
-        &amp;&amp; a.synchronousDispatchRegion == b.synchronousDispatchRegion;
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsRegionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Region.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -198,6 +198,10 @@
</span><span class="cx"> {
</span><span class="cx">     return a.m_bounds == b.m_bounds &amp;&amp; a.m_shape == b.m_shape;
</span><span class="cx"> }
</span><ins>+inline bool operator!=(const Region&amp; a, const Region&amp; b)
+{
+    return !(a == b);
+}
</ins><span class="cx"> 
</span><span class="cx"> inline bool operator==(const Region::Shape&amp; a, const Region::Shape&amp; b)
</span><span class="cx"> {
</span><span class="lines">@@ -208,6 +212,10 @@
</span><span class="cx"> {
</span><span class="cx">     return a.y == b.y &amp;&amp; a.segmentIndex == b.segmentIndex;
</span><span class="cx"> }
</span><ins>+inline bool operator!=(const Region::Span&amp; a, const Region::Span&amp; b)
+{
+    return !(a == b);
+}
</ins><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2016-06-23  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        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&lt;EventTrackingRegions&gt;::encode):
+        (IPC::ArgumentCoder&lt;EventTrackingRegions&gt;::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):
+
</ins><span class="cx"> 2016-06-23  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         requestFrameAnimation() callback timestamp should be very close to Performance.now() 
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedScrollingRemoteScrollingCoordinatorTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -494,10 +494,11 @@
</span><span class="cx">                 ts &lt;&lt; rect;
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        {
</del><ins>+        for (const auto&amp; synchronousEventRegion : node.eventTrackingRegions().eventSpecificSynchronousDispatchRegions) {
</ins><span class="cx">             TextStream::GroupScope group(ts);
</span><del>-            ts &lt;&lt; &quot;synchronous-event-tracking-region&quot;;
-            for (auto rect : node.eventTrackingRegions().synchronousDispatchRegion.rects()) {
</del><ins>+            ts &lt;&lt; &quot;synchronous-event-tracking-region for event &quot; &lt;&lt; synchronousEventRegion.key;
+
+            for (auto rect : synchronousEventRegion.value.rects()) {
</ins><span class="cx">                 ts &lt;&lt; &quot;\n&quot;;
</span><span class="cx">                 ts.writeIndent();
</span><span class="cx">                 ts &lt;&lt; rect;
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCoreArgumentCoderscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -111,7 +111,7 @@
</span><span class="cx"> void ArgumentCoder&lt;EventTrackingRegions&gt;::encode(ArgumentEncoder&amp; encoder, const EventTrackingRegions&amp; eventTrackingRegions)
</span><span class="cx"> {
</span><span class="cx">     encoder &lt;&lt; eventTrackingRegions.asynchronousDispatchRegion;
</span><del>-    encoder &lt;&lt; eventTrackingRegions.synchronousDispatchRegion;
</del><ins>+    encoder &lt;&lt; eventTrackingRegions.eventSpecificSynchronousDispatchRegions;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ArgumentCoder&lt;EventTrackingRegions&gt;::decode(ArgumentDecoder&amp; decoder, EventTrackingRegions&amp; eventTrackingRegions)
</span><span class="lines">@@ -119,11 +119,11 @@
</span><span class="cx">     Region asynchronousDispatchRegion;
</span><span class="cx">     if (!decoder.decode(asynchronousDispatchRegion))
</span><span class="cx">         return false;
</span><del>-    Region synchronousDispatchRegion;
-    if (!decoder.decode(synchronousDispatchRegion))
</del><ins>+    HashMap&lt;String, Region&gt; eventSpecificSynchronousDispatchRegions;
+    if (!decoder.decode(eventSpecificSynchronousDispatchRegions))
</ins><span class="cx">         return false;
</span><span class="cx">     eventTrackingRegions.asynchronousDispatchRegion = WTFMove(asynchronousDispatchRegion);
</span><del>-    eventTrackingRegions.synchronousDispatchRegion = WTFMove(synchronousDispatchRegion);
</del><ins>+    eventTrackingRegions.eventSpecificSynchronousDispatchRegions = WTFMove(eventSpecificSynchronousDispatchRegions);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -149,9 +149,9 @@
</span><span class="cx">     return result == ScrollingTree::DidHandleEvent; // FIXME: handle other values.
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(IntPoint p) const
</del><ins>+TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(const AtomicString&amp; eventName, IntPoint p) const
</ins><span class="cx"> {
</span><del>-    return m_scrollingTree-&gt;eventTrackingTypeForPoint(p);
</del><ins>+    return m_scrollingTree-&gt;eventTrackingTypeForPoint(eventName, p);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect&amp; fixedPositionRect, double scale)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx">     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint&amp; newScrollPosition, WebCore::SetOrSyncScrollingLayerPosition);
</span><span class="cx">     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint&amp; scrollPosition, bool representsProgrammaticScroll);
</span><span class="cx"> 
</span><del>-    WebCore::TrackingType eventTrackingTypeForPoint(WebCore::IntPoint) const;
</del><ins>+    WebCore::TrackingType eventTrackingTypeForPoint(const AtomicString&amp; eventName, WebCore::IntPoint) const;
</ins><span class="cx"> 
</span><span class="cx">     // Called externally when native views move around.
</span><span class="cx">     void viewportChangedViaDelegatedScrolling(WebCore::ScrollingNodeID, const WebCore::FloatRect&amp; fixedPositionRect, double scale);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -110,6 +110,7 @@
</span><span class="cx"> #include &lt;WebCore/DiagnosticLoggingClient.h&gt;
</span><span class="cx"> #include &lt;WebCore/DragController.h&gt;
</span><span class="cx"> #include &lt;WebCore/DragData.h&gt;
</span><ins>+#include &lt;WebCore/EventNames.h&gt;
</ins><span class="cx"> #include &lt;WebCore/FloatRect.h&gt;
</span><span class="cx"> #include &lt;WebCore/FocusDirection.h&gt;
</span><span class="cx"> #include &lt;WebCore/JSDOMBinding.h&gt;
</span><span class="lines">@@ -1955,26 +1956,76 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span><span class="cx"> 
</span><del>-TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent&amp; touchStartEvent) const
</del><ins>+static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
</ins><span class="cx"> {
</span><ins>+    if (static_cast&lt;uintptr_t&gt;(b) &gt; static_cast&lt;uintptr_t&gt;(a))
+        return b;
+    return a;
+}
+
+void WebPageProxy::updateTouchEventTracking(const WebTouchEvent&amp; touchStartEvent)
+{
</ins><span class="cx"> #if ENABLE(ASYNC_SCROLLING)
</span><del>-    TrackingType trackingType = TrackingType::NotTracking;
</del><ins>+    const EventNames&amp; names = eventNames();
</ins><span class="cx">     for (auto&amp; touchPoint : touchStartEvent.touchPoints()) {
</span><del>-        TrackingType touchPointTrackingType = m_scrollingCoordinatorProxy-&gt;eventTrackingTypeForPoint(touchPoint.location());
-        if (touchPointTrackingType == TrackingType::Synchronous)
-            return TrackingType::Synchronous;
</del><ins>+        IntPoint location = touchPoint.location();
+        auto updateTrackingType = [this, location](TrackingType&amp; trackingType, const AtomicString&amp; eventName) {
+            if (trackingType == TrackingType::Synchronous)
+                return;
</ins><span class="cx"> 
</span><del>-        if (touchPointTrackingType == TrackingType::Asynchronous)
-            trackingType = touchPointTrackingType;
</del><ins>+            TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy-&gt;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);
</ins><span class="cx">     }
</span><del>-
-    return trackingType;
</del><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(touchStartEvent);
</span><ins>+    m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
+    m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
</ins><span class="cx"> #endif // ENABLE(ASYNC_SCROLLING)
</span><del>-    return TrackingType::Synchronous;
</del><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent&amp; 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&amp; 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;
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MAC_GESTURE_EVENTS)
</span><span class="lines">@@ -1998,14 +2049,15 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (event.type() == WebEvent::TouchStart) {
</span><del>-        m_touchEventsTrackingType = touchEventTrackingType(event);
</del><ins>+        updateTouchEventTracking(event);
</ins><span class="cx">         m_layerTreeTransactionIdAtLastTouchStart = downcast&lt;RemoteLayerTreeDrawingAreaProxy&gt;(*drawingArea()).lastCommittedLayerTreeTransactionID();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
</del><ins>+    TrackingType touchEventsTrackingType = touchEventTrackingType(event);
+    if (touchEventsTrackingType == TrackingType::NotTracking)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (m_touchEventsTrackingType == TrackingType::Asynchronous) {
</del><ins>+    if (touchEventsTrackingType == TrackingType::Asynchronous) {
</ins><span class="cx">         // We can end up here if a native gesture has not started but the event handlers are passive.
</span><span class="cx">         //
</span><span class="cx">         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
</span><span class="lines">@@ -2026,7 +2078,7 @@
</span><span class="cx">     m_process-&gt;responsivenessTimer().stop();
</span><span class="cx"> 
</span><span class="cx">     if (event.allTouchPointsAreReleased())
</span><del>-        m_touchEventsTrackingType = TrackingType::NotTracking;
</del><ins>+        m_touchEventTracking.reset();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent&amp; event)
</span><span class="lines">@@ -2034,13 +2086,14 @@
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
</del><ins>+    TrackingType touchEventsTrackingType = touchEventTrackingType(event);
+    if (touchEventsTrackingType == TrackingType::NotTracking)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     m_process-&gt;send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
</span><span class="cx"> 
</span><span class="cx">     if (event.allTouchPointsAreReleased())
</span><del>-        m_touchEventsTrackingType = TrackingType::NotTracking;
</del><ins>+        m_touchEventTracking.reset();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #elif ENABLE(TOUCH_EVENTS)
</span><span class="lines">@@ -2050,9 +2103,9 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (event.type() == WebEvent::TouchStart)
</span><del>-        m_touchEventsTrackingType = touchEventTrackingType(event);
</del><ins>+        updateTouchEventTracking(event);
</ins><span class="cx"> 
</span><del>-    if (m_touchEventsTrackingType == TrackingType::NotTracking)
</del><ins>+    if (touchEventTrackingType(event) == TrackingType::NotTracking)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // If the page is suspended, which should be the case during panning, pinching
</span><span class="lines">@@ -2075,7 +2128,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (event.allTouchPointsAreReleased())
</span><del>-        m_touchEventsTrackingType = TrackingType::NotTracking;
</del><ins>+        m_touchEventTracking.reset();
</ins><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(TOUCH_EVENTS)
</span><span class="cx"> 
</span><span class="lines">@@ -5094,7 +5147,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span><del>-    m_touchEventsTrackingType = TrackingType::NotTracking;
</del><ins>+    m_touchEventTracking.reset();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INPUT_TYPE_COLOR)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (202407 => 202408)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1468,6 +1468,7 @@
</span><span class="cx">     void sendWheelEvent(const WebWheelEvent&amp;);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span><ins>+    void updateTouchEventTracking(const WebTouchEvent&amp;);
</ins><span class="cx">     WebCore::TrackingType touchEventTrackingType(const WebTouchEvent&amp;) const;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1695,7 +1696,29 @@
</span><span class="cx">     std::unique_ptr&lt;NativeWebMouseEvent&gt; m_currentlyProcessedMouseDownEvent;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span><del>-    WebCore::TrackingType m_touchEventsTrackingType { WebCore::TrackingType::NotTracking };
</del><ins>+    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;
</ins><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS) &amp;&amp; !ENABLE(IOS_TOUCH_EVENTS)
</span><span class="cx">     Deque&lt;QueuedTouchEvents&gt; m_touchEventQueue;
</span></span></pre>
</div>
</div>

</body>
</html>