<!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>[209736] 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/209736">209736</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2016-12-12 16:07:11 -0800 (Mon, 12 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Provide SPI to avoid blocking on painting when coming into view
https://bugs.webkit.org/show_bug.cgi?id=165780
&lt;rdar://problem/29009559&gt;

Reviewed by Simon Fraser.

By default, when parenting a WKWebView which was previously in-window,
we block on painting to ensure that we don't flash stale content.
We added SPI to disable this behavior to WKWebViewConfiguration, but
some clients might want the behavior most of the time, but sometimes
instead want to not block the UI process main thread, but instead do
their own work (e.g. removing a snapshot) when painting eventually occurs.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterNextPresentationUpdateWithoutWaitingForPainting:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
Tell WebPageProxy not to block on painting next time we are parented,
and use doAfterNextPresentationUpdate to call the block when the painting
does eventually happen. This SPI must be called before - but in the same
runloop cycle - the WKWebView is brought back in-window to work correctly.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::dispatchActivityStateChange):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::skipWaitingForPaintAfterNextViewDidMoveToWindow):
If we would block because we're coming in-window, but the bit to skip
blocking the next time we get brought in-window is set, reset the bit, 
and avoid blocking.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.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>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (209735 => 209736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-12-12 23:56:41 UTC (rev 209735)
+++ trunk/Source/WebKit2/ChangeLog        2016-12-13 00:07:11 UTC (rev 209736)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2016-12-12  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Provide SPI to avoid blocking on painting when coming into view
+        https://bugs.webkit.org/show_bug.cgi?id=165780
+        &lt;rdar://problem/29009559&gt;
+
+        Reviewed by Simon Fraser.
+
+        By default, when parenting a WKWebView which was previously in-window,
+        we block on painting to ensure that we don't flash stale content.
+        We added SPI to disable this behavior to WKWebViewConfiguration, but
+        some clients might want the behavior most of the time, but sometimes
+        instead want to not block the UI process main thread, but instead do
+        their own work (e.g. removing a snapshot) when painting eventually occurs.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _doAfterNextPresentationUpdateWithoutWaitingForPainting:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        Tell WebPageProxy not to block on painting next time we are parented,
+        and use doAfterNextPresentationUpdate to call the block when the painting
+        does eventually happen. This SPI must be called before - but in the same
+        runloop cycle - the WKWebView is brought back in-window to work correctly.
+        
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::dispatchActivityStateChange):
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::skipWaitingForPaintAfterNextViewDidMoveToWindow):
+        If we would block because we're coming in-window, but the bit to skip
+        blocking the next time we get brought in-window is set, reset the bit, 
+        and avoid blocking.
+
</ins><span class="cx"> 2016-12-12  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Document.visibilityState should use an IDL string enumeration
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (209735 => 209736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-12-12 23:56:41 UTC (rev 209735)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-12-13 00:07:11 UTC (rev 209736)
</span><span class="lines">@@ -4835,6 +4835,12 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_doAfterNextPresentationUpdateWithoutWaitingForPainting:(void (^)(void))updateBlock
+{
+    _page-&gt;setShouldSkipWaitingForPaintAfterNextViewDidMoveToWindow(true);
+    [self _doAfterNextPresentationUpdate:updateBlock];
+}
+
</ins><span class="cx"> - (void)_disableBackForwardSnapshotVolatilityForTesting
</span><span class="cx"> {
</span><span class="cx">     WebKit::ViewSnapshotStore::singleton().setDisableSnapshotVolatilityForTesting(true);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (209735 => 209736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-12-12 23:56:41 UTC (rev 209735)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-12-13 00:07:11 UTC (rev 209736)
</span><span class="lines">@@ -315,6 +315,7 @@
</span><span class="cx"> - (CGFloat)_pageScale WK_API_AVAILABLE(ios(WK_IOS_TBA));
</span><span class="cx"> 
</span><span class="cx"> - (void)_doAfterNextPresentationUpdate:(void (^)(void))updateBlock WK_API_AVAILABLE(macosx(10.12), ios(10.0));
</span><ins>+- (void)_doAfterNextPresentationUpdateWithoutWaitingForPainting:(void (^)(void))updateBlock WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
</ins><span class="cx"> 
</span><span class="cx"> - (void)_disableBackForwardSnapshotVolatilityForTesting WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (209735 => 209736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2016-12-12 23:56:41 UTC (rev 209735)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2016-12-13 00:07:11 UTC (rev 209736)
</span><span class="lines">@@ -1550,8 +1550,11 @@
</span><span class="cx"> 
</span><span class="cx">     bool isNowInWindow = (changed &amp; ActivityState::IsInWindow) &amp;&amp; isInWindow();
</span><span class="cx">     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
</span><del>-    if (m_viewWasEverInWindow &amp;&amp; isNowInWindow &amp;&amp; m_drawingArea-&gt;hasVisibleContent() &amp;&amp; m_waitsForPaintAfterViewDidMoveToWindow)
-        m_activityStateChangeWantsSynchronousReply = true;
</del><ins>+    if (m_viewWasEverInWindow &amp;&amp; isNowInWindow) {
+        if (m_drawingArea-&gt;hasVisibleContent() &amp;&amp; m_waitsForPaintAfterViewDidMoveToWindow &amp;&amp; !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
+            m_activityStateChangeWantsSynchronousReply = true;
+        m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
+    }
</ins><span class="cx"> 
</span><span class="cx">     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
</span><span class="cx">     if (!(m_activityState &amp; ActivityState::IsVisible))
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (209735 => 209736)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-12-12 23:56:41 UTC (rev 209735)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-12-13 00:07:11 UTC (rev 209736)
</span><span class="lines">@@ -1176,6 +1176,8 @@
</span><span class="cx"> 
</span><span class="cx">     void clearUserMediaState();
</span><span class="cx"> 
</span><ins>+    void setShouldSkipWaitingForPaintAfterNextViewDidMoveToWindow(bool shouldSkip) { m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = shouldSkip; }
+
</ins><span class="cx"> private:
</span><span class="cx">     WebPageProxy(PageClient&amp;, WebProcessProxy&amp;, uint64_t pageID, Ref&lt;API::PageConfiguration&gt;&amp;&amp;);
</span><span class="cx">     void platformInitialize();
</span><span class="lines">@@ -1711,6 +1713,7 @@
</span><span class="cx">     bool m_maintainsInactiveSelection;
</span><span class="cx"> 
</span><span class="cx">     bool m_waitsForPaintAfterViewDidMoveToWindow;
</span><ins>+    bool m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow { false };
</ins><span class="cx"> 
</span><span class="cx">     String m_toolTip;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>