<!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>[167698] trunk/Source/WebKit2</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/167698">167698</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-04-22 22:53:05 -0700 (Tue, 22 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS][WK2] Split iOS touch event dispatch for the regular touch event dispatch
https://bugs.webkit.org/show_bug.cgi?id=132033

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2014-04-22
Reviewed by Simon Fraser.

The generic touch event dispatching does not work well with iOS gesture recognizers.
Some events are required to be synchronous, while other needs can be asynchronous and
can even use event coalescing. We only need UI callback for the synchronous events.

Previously, that was implemented by changing the property ShouldSendEventsSynchronously
on WebPageProxy. That is causing issues when synchronous events are sent right after asynchronous
events because the responses in WebPageProxy::didReceiveEvent() easily get out of order.

This patch completely split the UIGestureRecognizerDispatching from the normal asynchronous event dispatching.

Synchronous events are sent directly to the WebProcess and report the result to the PageClient right away.

Asynchronous events are sent to the EventDispatcher where they are coalesced until the main thread is free
to process events.

There can be a race where a synchronous event comes before the asynchronous events are processed. In that case,
the synchronous event handler starts by getting the events out of the EventDispatcher and dispatch them first.

* Shared/NativeWebTouchEvent.h:
(WebKit::NativeWebTouchEvent::uniqueId): Deleted.
* Shared/ios/NativeWebTouchEventIOS.mm:
(WebKit::NativeWebTouchEvent::NativeWebTouchEvent):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handleSynchronousTouchEvent):
(WebKit::WebPageProxy::sendAsynchronousTouchEvent):
(WebKit::WebPageProxy::didReceiveEvent):
(WebKit::WebPageProxy::resetStateAfterProcessExited):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _webTouchEventsRecognized:]):
(-[WKContentView _webTouchEvent:WebKit::preventsNativeGestures:]):
* WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::EventDispatcher):
(WebKit::EventDispatcher::clearQueuedTouchEventsForPage):
(WebKit::EventDispatcher::getQueuedTouchEventsForPage):
(WebKit::EventDispatcher::touchEvent):
(WebKit::EventDispatcher::dispatchTouchEvents):
* WebProcess/WebPage/EventDispatcher.h:
* WebProcess/WebPage/EventDispatcher.messages.in:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::dispatchTouchEvent):
(WebKit::WebPage::touchEventSync):
(WebKit::WebPage::touchEvent):
(WebKit::WebPage::touchEventSyncForTesting):
(WebKit::WebPage::didCommitLoad):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::dispatchAsynchronousTouchEventsQueue):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedNativeWebTouchEventh">trunk/Source/WebKit2/Shared/NativeWebTouchEvent.h</a></li>
<li><a href="#trunkSourceWebKit2SharediosNativeWebTouchEventIOSmm">trunk/Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm</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>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionh">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageEventDispatchercpp">trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageEventDispatcherh">trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageEventDispatchermessagesin">trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPageh">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagemessagesin">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/ChangeLog        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2014-04-22  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [iOS][WK2] Split iOS touch event dispatch for the regular touch event dispatch
+        https://bugs.webkit.org/show_bug.cgi?id=132033
+
+        Reviewed by Simon Fraser.
+
+        The generic touch event dispatching does not work well with iOS gesture recognizers.
+        Some events are required to be synchronous, while other needs can be asynchronous and
+        can even use event coalescing. We only need UI callback for the synchronous events.
+
+        Previously, that was implemented by changing the property ShouldSendEventsSynchronously
+        on WebPageProxy. That is causing issues when synchronous events are sent right after asynchronous
+        events because the responses in WebPageProxy::didReceiveEvent() easily get out of order.
+
+        This patch completely split the UIGestureRecognizerDispatching from the normal asynchronous event dispatching.
+
+        Synchronous events are sent directly to the WebProcess and report the result to the PageClient right away.
+
+        Asynchronous events are sent to the EventDispatcher where they are coalesced until the main thread is free
+        to process events.
+
+        There can be a race where a synchronous event comes before the asynchronous events are processed. In that case,
+        the synchronous event handler starts by getting the events out of the EventDispatcher and dispatch them first.
+
+        * Shared/NativeWebTouchEvent.h:
+        (WebKit::NativeWebTouchEvent::uniqueId): Deleted.
+        * Shared/ios/NativeWebTouchEventIOS.mm:
+        (WebKit::NativeWebTouchEvent::NativeWebTouchEvent):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::handleSynchronousTouchEvent):
+        (WebKit::WebPageProxy::sendAsynchronousTouchEvent):
+        (WebKit::WebPageProxy::didReceiveEvent):
+        (WebKit::WebPageProxy::resetStateAfterProcessExited):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _webTouchEventsRecognized:]):
+        (-[WKContentView _webTouchEvent:WebKit::preventsNativeGestures:]):
+        * WebProcess/WebPage/EventDispatcher.cpp:
+        (WebKit::EventDispatcher::EventDispatcher):
+        (WebKit::EventDispatcher::clearQueuedTouchEventsForPage):
+        (WebKit::EventDispatcher::getQueuedTouchEventsForPage):
+        (WebKit::EventDispatcher::touchEvent):
+        (WebKit::EventDispatcher::dispatchTouchEvents):
+        * WebProcess/WebPage/EventDispatcher.h:
+        * WebProcess/WebPage/EventDispatcher.messages.in:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::dispatchTouchEvent):
+        (WebKit::WebPage::touchEventSync):
+        (WebKit::WebPage::touchEvent):
+        (WebKit::WebPage::touchEventSyncForTesting):
+        (WebKit::WebPage::didCommitLoad):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::dispatchAsynchronousTouchEventsQueue):
+
</ins><span class="cx"> 2014-04-22  Chris Fleizach  &lt;cfleizach@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AX: iOS hit-testing does not work when page is zoomed
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedNativeWebTouchEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/NativeWebTouchEvent.h (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/NativeWebTouchEvent.h        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/Shared/NativeWebTouchEvent.h        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -48,7 +48,6 @@
</span><span class="cx"> public:
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     explicit NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *);
</span><del>-    unsigned uniqueId() const { return m_uniqueID; }
</del><span class="cx"> #elif PLATFORM(GTK)
</span><span class="cx">     NativeWebTouchEvent(const NativeWebTouchEvent&amp;);
</span><span class="cx">     NativeWebTouchEvent(GdkEvent*, WebCore::GtkTouchContextHelper&amp;);
</span><span class="lines">@@ -60,9 +59,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-#if PLATFORM(IOS)
-    unsigned m_uniqueID;
-#elif PLATFORM(GTK)
</del><ins>+#if PLATFORM(GTK)
</ins><span class="cx">     GUniquePtr&lt;GdkEvent&gt; m_nativeEvent;
</span><span class="cx">     const WebCore::GtkTouchContextHelper&amp; m_touchContext;
</span><span class="cx"> #elif PLATFORM(EFL)
</span></span></pre></div>
<a id="trunkSourceWebKit2SharediosNativeWebTouchEventIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -37,8 +37,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-static unsigned uniqueTouchEventIdIndex = 0;
-
</del><span class="cx"> static inline WebEvent::Type webEventTypeForUIWebTouchEventType(UIWebTouchEventType type)
</span><span class="cx"> {
</span><span class="cx">     switch (type) {
</span><span class="lines">@@ -99,7 +97,6 @@
</span><span class="cx"> 
</span><span class="cx"> NativeWebTouchEvent::NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *gestureRecognizer)
</span><span class="cx">     : WebTouchEvent(webEventTypeForUIWebTouchEventType(gestureRecognizer.type), static_cast&lt;Modifiers&gt;(0), WTF::currentTime(), extractWebTouchPoint(gestureRecognizer), positionForCGPoint(gestureRecognizer.locationInWindow), gestureRecognizer.inJavaScriptGesture, gestureRecognizer.scale, gestureRecognizer.rotation)
</span><del>-    , m_uniqueID(uniqueTouchEventIdIndex++)
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -1493,7 +1493,48 @@
</span><span class="cx"> #endif // ENABLE(ASYNC_SCROLLING)
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+void WebPageProxy::handleTouchEventSynchronously(const NativeWebTouchEvent&amp; event)
+{
+    if (!isValid())
+        return;
+
+    if (event.type() == WebEvent::TouchStart)
+        m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
+
+    if (!m_isTrackingTouchEvents)
+        return;
+
+    m_process-&gt;responsivenessTimer()-&gt;start();
+    bool handled = false;
+    m_process-&gt;sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
+    didReceiveEvent(event.type(), handled);
+    m_pageClient.doneWithTouchEvent(event, handled);
+    m_process-&gt;responsivenessTimer()-&gt;stop();
+
+    if (event.type() == WebEvent::TouchEnd || event.type() == WebEvent::TouchCancel)
+        m_isTrackingTouchEvents = false;
+}
+
+void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent&amp; event)
+{
+    if (!isValid())
+        return;
+
+    ASSERT(event.type() != WebEvent::TouchStart);
+
+    if (!m_isTrackingTouchEvents)
+        return;
+
+    m_process-&gt;send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
+
+    if (event.type() == WebEvent::TouchEnd || event.type() == WebEvent::TouchCancel)
+        m_isTrackingTouchEvents = false;
+}
+
+#elif ENABLE(TOUCH_EVENTS)
</ins><span class="cx"> void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent&amp; event)
</span><span class="cx"> {
</span><span class="cx">     if (!isValid())
</span><span class="lines">@@ -3797,10 +3838,16 @@
</span><span class="cx">             m_uiClient-&gt;didNotHandleKeyEvent(this, event);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-#if ENABLE(TOUCH_EVENTS)
</del><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
</ins><span class="cx">     case WebEvent::TouchStart:
</span><span class="cx">     case WebEvent::TouchMove:
</span><span class="cx">     case WebEvent::TouchEnd:
</span><ins>+    case WebEvent::TouchCancel:
+        break;
+#elif ENABLE(TOUCH_EVENTS)
+    case WebEvent::TouchStart:
+    case WebEvent::TouchMove:
+    case WebEvent::TouchEnd:
</ins><span class="cx">     case WebEvent::TouchCancel: {
</span><span class="cx">         MESSAGE_CHECK(!m_touchEventQueue.isEmpty());
</span><span class="cx">         QueuedTouchEvents queuedEvents = m_touchEventQueue.takeFirst();
</span><span class="lines">@@ -4153,7 +4200,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_processingMouseMoveEvent = false;
</span><span class="cx"> 
</span><del>-#if ENABLE(TOUCH_EVENTS)
</del><ins>+#if ENABLE(TOUCH_EVENTS) &amp;&amp; !ENABLE(IOS_TOUCH_EVENTS)
</ins><span class="cx">     m_touchEventQueue.clear();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -694,7 +694,10 @@
</span><span class="cx">     void handleMouseEvent(const NativeWebMouseEvent&amp;);
</span><span class="cx">     void handleWheelEvent(const NativeWebWheelEvent&amp;);
</span><span class="cx">     void handleKeyboardEvent(const NativeWebKeyboardEvent&amp;);
</span><del>-#if ENABLE(TOUCH_EVENTS)
</del><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    void handleTouchEventSynchronously(const NativeWebTouchEvent&amp;);
+    void handleTouchEventAsynchronously(const NativeWebTouchEvent&amp;);
+#elif ENABLE(TOUCH_EVENTS)
</ins><span class="cx">     void handleTouchEvent(const NativeWebTouchEvent&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1563,8 +1566,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span><span class="cx">     bool m_isTrackingTouchEvents;
</span><ins>+#endif
+#if ENABLE(TOUCH_EVENTS) &amp;&amp; !ENABLE(IOS_TOUCH_EVENTS)
</ins><span class="cx">     Deque&lt;QueuedTouchEvents&gt; m_touchEventQueue;
</span><span class="cx"> #endif
</span><ins>+
</ins><span class="cx"> #if ENABLE(INPUT_TYPE_COLOR)
</span><span class="cx">     RefPtr&lt;WebColorPicker&gt; m_colorPicker;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -80,7 +80,6 @@
</span><span class="cx">     RetainPtr&lt;UIWebTouchEventsGestureRecognizer&gt; _touchEventGestureRecognizer;
</span><span class="cx"> 
</span><span class="cx">     BOOL _canSendTouchEventsAsynchronously;
</span><del>-    unsigned _nativeWebTouchEventUniqueIdBeingSentSynchronously;
</del><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;UITapGestureRecognizer&gt; _singleTapGestureRecognizer;
</span><span class="cx">     RetainPtr&lt;_UIWebHighlightLongPressGestureRecognizer&gt; _highlightLongPressGestureRecognizer;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -291,16 +291,13 @@
</span><span class="cx"> - (void)_webTouchEventsRecognized:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer
</span><span class="cx"> {
</span><span class="cx">     NativeWebTouchEvent nativeWebTouchEvent(gestureRecognizer);
</span><del>-
</del><span class="cx">     if (nativeWebTouchEvent.type() == WebKit::WebEvent::TouchStart)
</span><span class="cx">         _canSendTouchEventsAsynchronously = NO;
</span><span class="cx"> 
</span><del>-    if (!_canSendTouchEventsAsynchronously)
-        _nativeWebTouchEventUniqueIdBeingSentSynchronously = nativeWebTouchEvent.uniqueId();
-
-    _page-&gt;setShouldSendEventsSynchronously(!_canSendTouchEventsAsynchronously);
-    _page-&gt;handleTouchEvent(nativeWebTouchEvent);
-    _page-&gt;setShouldSendEventsSynchronously(false);
</del><ins>+    if (_canSendTouchEventsAsynchronously)
+        _page-&gt;handleTouchEventAsynchronously(nativeWebTouchEvent);
+    else
+        _page-&gt;handleTouchEventSynchronously(nativeWebTouchEvent);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static FloatQuad inflateQuad(const FloatQuad&amp; quad, float inflateSize)
</span><span class="lines">@@ -343,12 +340,6 @@
</span><span class="cx"> - (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&amp;)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
</span><span class="cx"> {
</span><span class="cx">     if (preventsNativeGesture) {
</span><del>-        // If we are dispatching events synchronously and the event coming back is not the one we are sending, it is a callback
-        // from an event sent asynchronously prior to the synchronous event. In that case, it should not use that information
-        // to update UIWebTouchEventsGestureRecognizer.
-        if (!_canSendTouchEventsAsynchronously &amp;&amp; _nativeWebTouchEventUniqueIdBeingSentSynchronously != touchEvent.uniqueId())
-            return;
-
</del><span class="cx">         _canSendTouchEventsAsynchronously = YES;
</span><span class="cx">         [_touchEventGestureRecognizer setDefaultPrevented:YES];
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageEventDispatchercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -54,6 +54,9 @@
</span><span class="cx"> EventDispatcher::EventDispatcher()
</span><span class="cx">     : m_queue(WorkQueue::create(&quot;com.apple.WebKit.EventDispatcher&quot;))
</span><span class="cx">     , m_recentWheelEventDeltaTracker(adoptPtr(new WheelEventDeltaTracker))
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    , m_touchEventsLock(SPINLOCK_INITIALIZER)
+#endif
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -143,6 +146,61 @@
</span><span class="cx">     RunLoop::main().dispatch(bind(&amp;EventDispatcher::dispatchWheelEvent, this, pageID, wheelEvent));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+void EventDispatcher::clearQueuedTouchEventsForPage(const WebPage&amp; webPage)
+{
+    SpinLockHolder locker(&amp;m_touchEventsLock);
+    m_touchEvents.remove(webPage.pageID());
+}
+
+void EventDispatcher::getQueuedTouchEventsForPage(const WebPage&amp; webPage, TouchEventQueue&amp; destinationQueue)
+{
+    SpinLockHolder locker(&amp;m_touchEventsLock);
+    destinationQueue = std::move(m_touchEvents.take(webPage.pageID()));
+}
+
+void EventDispatcher::touchEvent(uint64_t pageID, const WebKit::WebTouchEvent&amp; touchEvent)
+{
+    bool updateListWasEmpty;
+    {
+        SpinLockHolder locker(&amp;m_touchEventsLock);
+        updateListWasEmpty = m_touchEvents.isEmpty();
+        auto addResult = m_touchEvents.add(pageID, std::move(TouchEventQueue()));
+        if (addResult.isNewEntry)
+            addResult.iterator-&gt;value.append(touchEvent);
+        else {
+            TouchEventQueue&amp; queuedEvents = addResult.iterator-&gt;value;
+            ASSERT(!queuedEvents.isEmpty());
+            const WebTouchEvent&amp; lastTouchEvent = queuedEvents.last();
+
+            // Coalesce touch move events.
+            WebEvent::Type type = lastTouchEvent.type();
+            if (type == WebEvent::TouchMove)
+                queuedEvents.last() = touchEvent;
+            else
+                queuedEvents.append(touchEvent);
+        }
+    }
+
+    if (updateListWasEmpty)
+        RunLoop::main().dispatch(bind(&amp;EventDispatcher::dispatchTouchEvents, this));
+}
+
+void EventDispatcher::dispatchTouchEvents()
+{
+    HashMap&lt;uint64_t, TouchEventQueue&gt; localCopy;
+    {
+        SpinLockHolder locker(&amp;m_touchEventsLock);
+        localCopy.swap(m_touchEvents);
+    }
+
+    for (auto&amp; slot : localCopy) {
+        if (WebPage* webPage = WebProcess::shared().webPage(slot.key))
+            webPage-&gt;dispatchAsynchronousTouchEvents(slot.value);
+    }
+}
+#endif
+
</ins><span class="cx"> void EventDispatcher::dispatchWheelEvent(uint64_t pageID, const WebWheelEvent&amp; wheelEvent)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(RunLoop::isMain());
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageEventDispatcherh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,9 +29,11 @@
</span><span class="cx"> #include &quot;Connection.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &lt;WebCore/WheelEventDeltaTracker.h&gt;
</span><ins>+#include &lt;WebEvent.h&gt;
</ins><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><ins>+#include &lt;wtf/TCSpinLock.h&gt;
</ins><span class="cx"> #include &lt;wtf/ThreadingPrimitives.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -54,6 +56,13 @@
</span><span class="cx">     void removeScrollingTreeForPage(WebPage*);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    typedef Vector&lt;WebTouchEvent, 1&gt; TouchEventQueue;
+
+    void clearQueuedTouchEventsForPage(const WebPage&amp;);
+    void getQueuedTouchEventsForPage(const WebPage&amp;, TouchEventQueue&amp;);
+#endif
+
</ins><span class="cx">     void initializeConnection(IPC::Connection*);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -64,9 +73,16 @@
</span><span class="cx"> 
</span><span class="cx">     // Message handlers
</span><span class="cx">     void wheelEvent(uint64_t pageID, const WebWheelEvent&amp;, bool canRubberBandAtLeft, bool canRubberBandAtRight, bool canRubberBandAtTop, bool canRubberBandAtBottom);
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    void touchEvent(uint64_t pageID, const WebTouchEvent&amp;);
+#endif
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     // This is called on the main thread.
</span><span class="cx">     void dispatchWheelEvent(uint64_t pageID, const WebWheelEvent&amp;);
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    void dispatchTouchEvents();
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ASYNC_SCROLLING)
</span><span class="cx">     void sendDidReceiveEvent(uint64_t pageID, const WebEvent&amp;, bool didHandleEvent);
</span><span class="lines">@@ -79,6 +95,10 @@
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;WebCore::ThreadedScrollingTree&gt;&gt; m_scrollingTrees;
</span><span class="cx"> #endif
</span><span class="cx">     OwnPtr&lt;WebCore::WheelEventDeltaTracker&gt; m_recentWheelEventDeltaTracker;
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    SpinLock m_touchEventsLock;
+    HashMap&lt;uint64_t, TouchEventQueue&gt; m_touchEvents;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageEventDispatchermessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -22,4 +22,7 @@
</span><span class="cx"> 
</span><span class="cx"> messages -&gt; EventDispatcher {
</span><span class="cx">     WheelEvent(uint64_t pageID, WebKit::WebWheelEvent event, bool canRubberBandAtLeft, bool canRubberBandAtRight, bool canRubberBandAtTop, bool canRubberBandAtBottom)
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    TouchEvent(uint64_t pageID, WebKit::WebTouchEvent event)
+#endif
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -1948,12 +1948,28 @@
</span><span class="cx"> 
</span><span class="cx">     return page-&gt;mainFrame().eventHandler().handleTouchEvent(platform(touchEvent));
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+void WebPage::dispatchTouchEvent(const WebTouchEvent&amp; touchEvent, bool&amp; handled)
+{
+    m_lastInteractionLocation = touchEvent.position();
+    CurrentEvent currentEvent(touchEvent);
+    handled = handleTouchEvent(touchEvent, m_page.get());
+}
+
+void WebPage::touchEventSync(const WebTouchEvent&amp; touchEvent, bool&amp; handled)
+{
+    EventDispatcher::TouchEventQueue queuedEvents;
+    WebProcess::shared().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents);
+    dispatchAsynchronousTouchEvents(queuedEvents);
+
+    dispatchTouchEvent(touchEvent, handled);
+}
+#elif ENABLE(TOUCH_EVENTS)
</ins><span class="cx"> void WebPage::touchEvent(const WebTouchEvent&amp; touchEvent)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
-    m_lastInteractionLocation = touchEvent.position();
-#endif
</del><ins>+
</ins><span class="cx">     bool handled = false;
</span><span class="cx">     if (canHandleUserEvents()) {
</span><span class="cx">         CurrentEvent currentEvent(touchEvent);
</span><span class="lines">@@ -1965,9 +1981,6 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPage::touchEventSyncForTesting(const WebTouchEvent&amp; touchEvent, bool&amp; handled)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
-    m_lastInteractionLocation = touchEvent.position();
-#endif
</del><span class="cx">     CurrentEvent currentEvent(touchEvent);
</span><span class="cx">     handled = handleTouchEvent(touchEvent, m_page.get());
</span><span class="cx"> }
</span><span class="lines">@@ -4239,6 +4252,8 @@
</span><span class="cx">     m_hasReceivedVisibleContentRectsAfterDidCommitLoad = false;
</span><span class="cx">     m_userHasChangedPageScaleFactor = false;
</span><span class="cx"> 
</span><ins>+    WebProcess::shared().eventDispatcher().clearQueuedTouchEventsForPage(*this);
+
</ins><span class="cx">     Document* document = frame-&gt;coreFrame()-&gt;document();
</span><span class="cx">     if (document-&gt;isImageDocument())
</span><span class="cx">         m_viewportConfiguration.setDefaultConfiguration(ViewportConfiguration::imageDocumentParameters());
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -478,6 +478,7 @@
</span><span class="cx">     void setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection);
</span><span class="cx">     WebCore::IntRect rectForElementAtInteractionLocation();
</span><span class="cx"> 
</span><ins>+    void dispatchAsynchronousTouchEvents(const Vector&lt;WebTouchEvent, 1&gt;&amp; queue);
</ins><span class="cx"> #if ENABLE(INSPECTOR)
</span><span class="cx">     void showInspectorIndication();
</span><span class="cx">     void hideInspectorIndication();
</span><span class="lines">@@ -705,6 +706,7 @@
</span><span class="cx">     void applicationWillEnterForeground();
</span><span class="cx">     void applicationDidBecomeActive();
</span><span class="cx">     void zoomToRect(WebCore::FloatRect, double minimumScale, double maximumScale);
</span><ins>+    void dispatchTouchEvent(const WebTouchEvent&amp;, bool&amp; handled);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK) &amp;&amp; USE(TEXTURE_MAPPER_GL)
</span><span class="lines">@@ -855,7 +857,9 @@
</span><span class="cx">     void wheelEventSyncForTesting(const WebWheelEvent&amp;, bool&amp;);
</span><span class="cx">     void keyEvent(const WebKeyboardEvent&amp;);
</span><span class="cx">     void keyEventSyncForTesting(const WebKeyboardEvent&amp;, bool&amp;);
</span><del>-#if ENABLE(TOUCH_EVENTS)
</del><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    void touchEventSync(const WebTouchEvent&amp;, bool&amp; handled);
+#elif ENABLE(TOUCH_EVENTS)
</ins><span class="cx">     void touchEvent(const WebTouchEvent&amp;);
</span><span class="cx">     void touchEventSyncForTesting(const WebTouchEvent&amp;, bool&amp; handled);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -81,7 +81,10 @@
</span><span class="cx">     SetAllowsRemoteInspection(bool allow)
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-#if ENABLE(TOUCH_EVENTS)
</del><ins>+#if ENABLE(IOS_TOUCH_EVENTS)
+    TouchEventSync(WebKit::WebTouchEvent event) -&gt; (bool handled)
+#endif
+#if !ENABLE(IOS_TOUCH_EVENTS) &amp;&amp; ENABLE(TOUCH_EVENTS)
</ins><span class="cx">     TouchEvent(WebKit::WebTouchEvent event)
</span><span class="cx">     TouchEventSyncForTesting(WebKit::WebTouchEvent event) -&gt; (bool handled)
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (167697 => 167698)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-04-23 05:28:20 UTC (rev 167697)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-04-23 05:53:05 UTC (rev 167698)
</span><span class="lines">@@ -2059,6 +2059,13 @@
</span><span class="cx">     send(Messages::WebPageProxy::ZoomToRect(rect, minimumScale, maximumScale));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::dispatchAsynchronousTouchEvents(const Vector&lt;WebTouchEvent, 1&gt;&amp; queue)
+{
+    bool ignored;
+    for (const WebTouchEvent&amp; event : queue)
+        dispatchTouchEvent(event, ignored);
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // PLATFORM(IOS)
</span></span></pre>
</div>
</div>

</body>
</html>