<!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>[169827] 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/169827">169827</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-06-11 13:43:50 -0700 (Wed, 11 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[wk2] Don't dispatch view state changes immediately
https://bugs.webkit.org/show_bug.cgi?id=133713

Reviewed by Simon Fraser.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::WebPageProxy):
(WebKit::WebPageProxy::viewStateDidChange):
(WebKit::WebPageProxy::dispatchViewStateChange):
(WebKit::WebPageProxy::updateViewState): Deleted.
* UIProcess/WebPageProxy.h:
On PLATFORM(COCOA), wait until just before CA is going to commit the UI process layer
tree to dispatch view state changes to the Web process. This avoids sending multiple
view state change messages to the Web process within one run-loop cycle, for example
when a view is moved around in the view hierarchy but the view state otherwise remains the same.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</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>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (169826 => 169827)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-06-11 20:42:34 UTC (rev 169826)
+++ trunk/Source/WebKit2/ChangeLog        2014-06-11 20:43:50 UTC (rev 169827)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2014-06-11  Timothy Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [wk2] Don't dispatch view state changes immediately
+        https://bugs.webkit.org/show_bug.cgi?id=133713
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::WebPageProxy):
+        (WebKit::WebPageProxy::viewStateDidChange):
+        (WebKit::WebPageProxy::dispatchViewStateChange):
+        (WebKit::WebPageProxy::updateViewState): Deleted.
+        * UIProcess/WebPageProxy.h:
+        On PLATFORM(COCOA), wait until just before CA is going to commit the UI process layer
+        tree to dispatch view state changes to the Web process. This avoids sending multiple
+        view state change messages to the Web process within one run-loop cycle, for example
+        when a view is moved around in the view hierarchy but the view state otherwise remains the same.
+
+2014-06-11  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
</ins><span class="cx">         Make it possible for waitForAndDispatchImmediately to bail if a sync message comes in from the other direction
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=133708
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (169826 => 169827)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-06-11 20:42:34 UTC (rev 169826)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-06-11 20:43:50 UTC (rev 169827)
</span><span class="lines">@@ -132,6 +132,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> #include &quot;ViewSnapshotStore.h&quot;
</span><ins>+#include &lt;WebCore/RunLoopObserver.h&gt;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="lines">@@ -365,6 +366,8 @@
</span><span class="cx">     , m_scrollPinningBehavior(DoNotPin)
</span><span class="cx">     , m_navigationID(0)
</span><span class="cx">     , m_configurationPreferenceValues(configuration.preferenceValues)
</span><ins>+    , m_potentiallyChangedViewStateFlags(ViewState::NoFlags)
+    , m_viewStateChangeWantsReply(WantsReplyOrNot::DoesNotWantReply)
</ins><span class="cx"> {
</span><span class="cx">     if (m_process-&gt;state() == WebProcessProxy::State::Running) {
</span><span class="cx">         if (m_userContentController)
</span><span class="lines">@@ -409,6 +412,13 @@
</span><span class="cx">     IPC::Connection* connection = m_process-&gt;state() == WebProcessProxy::State::Running ? m_process-&gt;connection() : nullptr;
</span><span class="cx">     m_process-&gt;context().storageManager().createSessionStorageNamespace(m_pageID, connection, std::numeric_limits&lt;unsigned&gt;::max());
</span><span class="cx">     setSession(*configuration.session);
</span><ins>+
+#if PLATFORM(COCOA)
+    const CFIndex viewStateChangeRunLoopOrder = (CFIndex)RunLoopObserver::WellKnownRunLoopOrders::CoreAnimationCommit - 1;
+    m_viewStateChangeDispatcher = RunLoopObserver::create(viewStateChangeRunLoopOrder, [this]() {
+        this-&gt;dispatchViewStateChange();
+    });
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebPageProxy::~WebPageProxy()
</span><span class="lines">@@ -1092,25 +1102,41 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::viewStateDidChange(ViewState::Flags mayHaveChanged, WantsReplyOrNot wantsReply)
</span><span class="cx"> {
</span><ins>+    m_potentiallyChangedViewStateFlags |= mayHaveChanged;
+    m_viewStateChangeWantsReply = (wantsReply == WantsReplyOrNot::DoesWantReply || m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply) ? WantsReplyOrNot::DoesWantReply : WantsReplyOrNot::DoesNotWantReply;
+
+#if PLATFORM(COCOA)
+    m_viewStateChangeDispatcher-&gt;schedule();
+#else
+    dispatchViewStateChange();
+#endif
+}
+
+void WebPageProxy::dispatchViewStateChange()
+{
+#if PLATFORM(COCOA)
+    m_viewStateChangeDispatcher-&gt;invalidate();
+#endif
+
</ins><span class="cx">     if (!isValid())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // If the visibility state may have changed, then so may the visually idle &amp; occluded agnostic state.
</span><del>-    if (mayHaveChanged &amp; ViewState::IsVisible)
-        mayHaveChanged |= ViewState::IsVisibleOrOccluded | ViewState::IsVisuallyIdle;
</del><ins>+    if (m_potentiallyChangedViewStateFlags &amp; ViewState::IsVisible)
+        m_potentiallyChangedViewStateFlags |= ViewState::IsVisibleOrOccluded | ViewState::IsVisuallyIdle;
</ins><span class="cx"> 
</span><span class="cx">     // Record the prior view state, update the flags that may have changed,
</span><span class="cx">     // and check which flags have actually changed.
</span><span class="cx">     ViewState::Flags previousViewState = m_viewState;
</span><del>-    updateViewState(mayHaveChanged);
</del><ins>+    updateViewState(m_potentiallyChangedViewStateFlags);
</ins><span class="cx">     ViewState::Flags changed = m_viewState ^ previousViewState;
</span><span class="cx"> 
</span><span class="cx">     if (changed)
</span><del>-        m_process-&gt;send(Messages::WebPage::SetViewState(m_viewState, wantsReply == WantsReplyOrNot::DoesWantReply), m_pageID);
-    
</del><ins>+        m_process-&gt;send(Messages::WebPage::SetViewState(m_viewState, m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply), m_pageID);
+
</ins><span class="cx">     // This must happen after the SetViewState message is sent, to ensure the page visibility event can fire.
</span><span class="cx">     updateActivityToken();
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (changed &amp; ViewState::IsVisuallyIdle)
</span><span class="cx">         m_process-&gt;pageSuppressibilityChanged(this);
</span><span class="cx"> 
</span><span class="lines">@@ -1120,7 +1146,7 @@
</span><span class="cx">     if ((changed &amp; ViewState::IsVisible) &amp;&amp; !isViewVisible())
</span><span class="cx">         m_process-&gt;responsivenessTimer()-&gt;stop();
</span><span class="cx"> 
</span><del>-    if ((mayHaveChanged &amp; ViewState::IsInWindow) &amp;&amp; (m_viewState &amp; ViewState::IsInWindow)) {
</del><ins>+    if ((m_potentiallyChangedViewStateFlags &amp; ViewState::IsInWindow) &amp;&amp; (m_viewState &amp; ViewState::IsInWindow)) {
</ins><span class="cx">         LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
</span><span class="cx">         if (m_layerHostingMode != layerHostingMode) {
</span><span class="cx">             m_layerHostingMode = layerHostingMode;
</span><span class="lines">@@ -1128,7 +1154,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if ((mayHaveChanged &amp; ViewState::IsInWindow) &amp;&amp; !(m_viewState &amp; ViewState::IsInWindow)) {
</del><ins>+    if ((m_potentiallyChangedViewStateFlags &amp; ViewState::IsInWindow) &amp;&amp; !(m_viewState &amp; ViewState::IsInWindow)) {
</ins><span class="cx"> #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
</span><span class="cx">         // When leaving the current page, close the popover color well.
</span><span class="cx">         if (m_colorPicker)
</span><span class="lines">@@ -1142,8 +1168,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     updateBackingStoreDiscardableState();
</span><ins>+
+    m_potentiallyChangedViewStateFlags = ViewState::NoFlags;
+    m_viewStateChangeWantsReply = WantsReplyOrNot::DoesNotWantReply;
</ins><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> void WebPageProxy::updateActivityToken()
</span><span class="cx"> {
</span><span class="cx"> #if PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (169826 => 169827)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-06-11 20:42:34 UTC (rev 169826)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-06-11 20:43:50 UTC (rev 169827)
</span><span class="lines">@@ -125,6 +125,7 @@
</span><span class="cx"> class GraphicsLayer;
</span><span class="cx"> class IntSize;
</span><span class="cx"> class ProtectionSpace;
</span><ins>+class RunLoopObserver;
</ins><span class="cx"> class SharedBuffer;
</span><span class="cx"> struct FileChooserSettings;
</span><span class="cx"> struct TextAlternativeWithRange;
</span><span class="lines">@@ -1458,6 +1459,8 @@
</span><span class="cx"> 
</span><span class="cx">     WebPreferencesStore preferencesStore() const;
</span><span class="cx"> 
</span><ins>+    void dispatchViewStateChange();
+
</ins><span class="cx">     PageClient&amp; m_pageClient;
</span><span class="cx">     std::unique_ptr&lt;API::LoaderClient&gt; m_loaderClient;
</span><span class="cx">     std::unique_ptr&lt;API::PolicyClient&gt; m_policyClient;
</span><span class="lines">@@ -1716,6 +1719,7 @@
</span><span class="cx">         
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     HashMap&lt;String, String&gt; m_temporaryPDFFiles;
</span><ins>+    std::unique_ptr&lt;WebCore::RunLoopObserver&gt; m_viewStateChangeDispatcher;
</ins><span class="cx"> #endif
</span><span class="cx">         
</span><span class="cx">     WebCore::ScrollPinningBehavior m_scrollPinningBehavior;
</span><span class="lines">@@ -1723,6 +1727,8 @@
</span><span class="cx">     uint64_t m_navigationID;
</span><span class="cx"> 
</span><span class="cx">     WebPreferencesStore::ValueMap m_configurationPreferenceValues;
</span><ins>+    WebCore::ViewState::Flags m_potentiallyChangedViewStateFlags;
+    WantsReplyOrNot m_viewStateChangeWantsReply;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre>
</div>
</div>

</body>
</html>