<!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>[208748] 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/208748">208748</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2016-11-15 13:06:06 -0800 (Tue, 15 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS WK2] Implement support for visual viewports
https://bugs.webkit.org/show_bug.cgi?id=164765

Reviewed by Tim Horton.

Adopt the visual viewport scrolling model in iOS WK2.
Source/WebCore:

This is more complex than the Mac implementation for two primary reasons. First,
WKWebView needs to to able to control the rectangle used for fixed position layout
to get the correct behavior when zooming all the way out, and because iOS displays
pages scaled down, exposing document overflow such that the layout viewport rectangle
has to get larger than the initial containing block size (which does not happen on Mac).

This is achieved by pushing a &quot;layoutViewportOverrideRect&quot; down onto FrameView, in
a similar way to the customFixedPositionRect that's used now. We share that name
for now in code that is agnostic to its use (e.g. VisibleContentRectUpdateInfo).

I tried so hard to write tests, but ran into various problems (webkit.org/b/164762,
webkit.org/b/164764). Will add tests via webkit.org/b/164764.

* page/FrameView.cpp:
(WebCore::FrameView::fixedScrollableAreaBoundsInflatedForScrolling): layoutViewportOrigin()
was removed.
(WebCore::FrameView::setBaseLayoutViewportOrigin): Rename with &quot;base&quot; to make it clearer that
it can be overridden.
(WebCore::FrameView::setLayoutViewportOverrideRect):
(WebCore::FrameView::baseLayoutViewportSize): Renamed.
(WebCore::FrameView::updateLayoutViewport): Logging.
(WebCore::FrameView::layoutViewportRect):
(WebCore::FrameView::scrollPositionForFixedPosition):
(WebCore::FrameView::unscaledMaximumScrollPosition): During page transitions on iOS, it
was possible for unscaledDocumentRect to be empty, but visibleSize() to be non-empty, leading
to odd negative max scroll offsets, so clamp to 0,0.
(WebCore::FrameView::setLayoutViewportOrigin): Deleted.
* page/FrameView.h:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::reconcileScrollingState): scrollPositionForFixedPosition() already does the
visualViewportEnabled() check.
* page/scrolling/mac/ScrollingTreeFixedNode.mm:
(WebCore::ScrollingTreeFixedNode::updateLayersAfterAncestorChange):
* platform/graphics/FloatSize.cpp:
(WebCore::FloatSize::constrainedBetween): Added for consistency with the other geometry types.
* platform/graphics/FloatSize.h:
* platform/graphics/LayoutSize.cpp:
(WebCore::LayoutSize::constrainedBetween): Ditto.
* platform/graphics/LayoutSize.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::clientLogicalWidthForFixedPosition): If we have an override layout viewport, its size might be different
from the RenderView's size (the initial containing block), so we need to use the layoutViewportRect here.
(WebCore::RenderView::clientLogicalHeightForFixedPosition):

Source/WebKit2:

Pass the parameters used for computing the layout viewport up to WK2 via RemoteLayerTreeTransaction.
These are stored on WebPageProxy. When they change, _didCommitLayerTree triggers a -_updateVisibleContentRects.

WebPageProxy::computeCustomFixedPositionRect() is the function that computes the &quot;override&quot; layout viewport.
It starts with the baseLayoutViewportSize from the web process (which is based on the initial containing block
size), then ensures that it's no smaller than the unobscured content rect, since it makes no sense for the
layout viewport to be smaller than the visual viewport. The static FrameView::computeLayoutViewportOrigin()
is then use to &quot;push&quot; the layout viewport around as the visual viewport changes.

* Shared/VisibleContentRectUpdateInfo.h:
* Shared/WebCoreArgumentCoders.cpp: Encode LayoutSize and LayoutPoint.
(IPC::ArgumentCoder&lt;LayoutSize&gt;::encode):
(IPC::ArgumentCoder&lt;LayoutSize&gt;::decode):
(IPC::ArgumentCoder&lt;LayoutPoint&gt;::encode):
(IPC::ArgumentCoder&lt;LayoutPoint&gt;::decode):
* Shared/WebCoreArgumentCoders.h:
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::baseLayoutViewportSize):
(WebKit::RemoteLayerTreeTransaction::setBaseLayoutViewportSize):
(WebKit::RemoteLayerTreeTransaction::minStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::setMinStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::maxStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::setMaxStableLayoutViewportOrigin):
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode):
(WebKit::RemoteLayerTreeTransaction::decode):
(WebKit::RemoteLayerTreeTransaction::description):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:]):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
(WebKit::RemoteScrollingCoordinatorProxy::visualViewportEnabled): Accessor.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::customFixedPositionRect):
* UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::customFixedPositionRect):
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
(-[WKContentView _didCommitLayerTree:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::computeCustomFixedPositionRect): When visual viewports are enabled, compute
the layout viewport rect, taking the baseLayoutViewportSize and the current unobscured rect into account.
(WebKit::WebPageProxy::updateLayoutViewportParameters):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* WebProcess/WebPage/WebPage.cpp: Encode in the transaction the layout viewport parameters (with minor refactor).
(WebKit::WebPage::willCommitLayerTree):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects): This is where the web process receives the new override layout viewport
from the web process (with some logging).

LayoutTests:

These tests don't correctly test iOS WK2's async scrolling behavior (webkit.org/b/164779)
so rebaseline.

* platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageFrameViewcpp">trunk/Source/WebCore/page/FrameView.cpp</a></li>
<li><a href="#trunkSourceWebCorepageFrameViewh">trunk/Source/WebCore/page/FrameView.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingAsyncScrollingCoordinatorcpp">trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFloatSizecpp">trunk/Source/WebCore/platform/graphics/FloatSize.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFloatSizeh">trunk/Source/WebCore/platform/graphics/FloatSize.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsLayoutSizecpp">trunk/Source/WebCore/platform/graphics/LayoutSize.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsLayoutSizeh">trunk/Source/WebCore/platform/graphics/LayoutSize.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderViewcpp">trunk/Source/WebCore/rendering/RenderView.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedVisibleContentRectUpdateInfoh">trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCoreArgumentCoderscpp">trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCoreArgumentCodersh">trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerTreeTransactionh">trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerTreeTransactionmm">trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh">trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosRemoteScrollingCoordinatorProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewmm">trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxymm">trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/</li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportnonzoomedrectsexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportrtlnonzoomedrectsexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportrtlzoomedrectsexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedfixedexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedfixedscrolldownthenupexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedrectsexpectedtxt">trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/LayoutTests/ChangeLog        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-11-15  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] Implement support for visual viewports
+        https://bugs.webkit.org/show_bug.cgi?id=164765
+
+        Reviewed by Tim Horton.
+
+        Adopt the visual viewport scrolling model in iOS WK2.
+        
+        These tests don't correctly test iOS WK2's async scrolling behavior (webkit.org/b/164779)
+        so rebaseline.
+
+        * platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
+        * platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt: Added.
+        * platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt: Added.
+        * platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt: Added.
+        * platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
+        * platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt: Added.
+
</ins><span class="cx"> 2016-11-14  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Correct handling of changing input type
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportnonzoomedrectsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+This test scrolls the page and checks that the layout and visual viewports respond as expected.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to 475, 525
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:1275,&quot;bottom&quot;:1125,&quot;left&quot;:475,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:1275,&quot;bottom&quot;:1125,&quot;left&quot;:475,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to 100, 776
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:900,&quot;bottom&quot;:1376,&quot;left&quot;:100,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:900,&quot;bottom&quot;:1376,&quot;left&quot;:100,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to 50, 300
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:850,&quot;bottom&quot;:900,&quot;left&quot;:50,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:850,&quot;bottom&quot;:900,&quot;left&quot;:50,&quot;width&quot;:800,&quot;height&quot;:600}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportrtlnonzoomedrectsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+This test scrolls the page and checks that the layout and visual viewports respond as expected.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to -475, 525
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:325,&quot;bottom&quot;:1125,&quot;left&quot;:-475,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:325,&quot;bottom&quot;:1125,&quot;left&quot;:-475,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to -100, 776
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:700,&quot;bottom&quot;:1376,&quot;left&quot;:-100,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:700,&quot;bottom&quot;:1376,&quot;left&quot;:-100,&quot;width&quot;:800,&quot;height&quot;:600}
+
+Scrolled to -50, 300
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:750,&quot;bottom&quot;:900,&quot;left&quot;:-50,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:750,&quot;bottom&quot;:900,&quot;left&quot;:-50,&quot;width&quot;:800,&quot;height&quot;:600}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportrtlzoomedrectsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+This test zooms and scrolls the page and checks that the layout and visual viewports respond as expected.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:400,&quot;bottom&quot;:300,&quot;left&quot;:0,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to -475, 525
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:-75,&quot;bottom&quot;:825,&quot;left&quot;:-475,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to -100, 776
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:300,&quot;bottom&quot;:1076,&quot;left&quot;:-100,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to -50, 300
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:350,&quot;bottom&quot;:600,&quot;left&quot;:-50,&quot;width&quot;:400,&quot;height&quot;:300}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedfixedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+This test zooms and scrolls the page and checks the positions of fixed-position objects.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:400,&quot;bottom&quot;:300,&quot;left&quot;:0,&quot;width&quot;:400,&quot;height&quot;:300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:100,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:500,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:0,&quot;right&quot;:100,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:100,&quot;height&quot;:600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:700,&quot;width&quot;:100,&quot;height&quot;:600}
+
+Scrolled to 475, 525
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:875,&quot;bottom&quot;:825,&quot;left&quot;:475,&quot;width&quot;:400,&quot;height&quot;:300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-525,&quot;right&quot;:325,&quot;bottom&quot;:-425,&quot;left&quot;:-475,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-25,&quot;right&quot;:325,&quot;bottom&quot;:75,&quot;left&quot;:-475,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-525,&quot;right&quot;:-375,&quot;bottom&quot;:75,&quot;left&quot;:-475,&quot;width&quot;:100,&quot;height&quot;:600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-525,&quot;right&quot;:325,&quot;bottom&quot;:75,&quot;left&quot;:225,&quot;width&quot;:100,&quot;height&quot;:600}
+
+Scrolled to 100, 776
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:500,&quot;bottom&quot;:1076,&quot;left&quot;:100,&quot;width&quot;:400,&quot;height&quot;:300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-776,&quot;right&quot;:700,&quot;bottom&quot;:-676,&quot;left&quot;:-100,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-276,&quot;right&quot;:700,&quot;bottom&quot;:-176,&quot;left&quot;:-100,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-776,&quot;right&quot;:0,&quot;bottom&quot;:-176,&quot;left&quot;:-100,&quot;width&quot;:100,&quot;height&quot;:600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-776,&quot;right&quot;:700,&quot;bottom&quot;:-176,&quot;left&quot;:600,&quot;width&quot;:100,&quot;height&quot;:600}
+
+Scrolled to 50, 300
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:450,&quot;bottom&quot;:600,&quot;left&quot;:50,&quot;width&quot;:400,&quot;height&quot;:300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-300,&quot;right&quot;:750,&quot;bottom&quot;:-200,&quot;left&quot;:-50,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:200,&quot;right&quot;:750,&quot;bottom&quot;:300,&quot;left&quot;:-50,&quot;width&quot;:800,&quot;height&quot;:100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-300,&quot;right&quot;:50,&quot;bottom&quot;:300,&quot;left&quot;:-50,&quot;width&quot;:100,&quot;height&quot;:600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {&quot;top&quot;:-300,&quot;right&quot;:750,&quot;bottom&quot;:300,&quot;left&quot;:650,&quot;width&quot;:100,&quot;height&quot;:600}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedfixedscrolldownthenupexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+layer at (0,0) size 2008x2016
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x2016
+  RenderBlock {HTML} at (0,0) size 800x2016
+    RenderBody {BODY} at (8,8) size 2000x2000
+layer at (200,0) size 400x100
+  RenderBlock (positioned) {DIV} at (200,0) size 400x100 [bgcolor=#808080]
+layer at (200,500) size 400x100
+  RenderBlock (positioned) {DIV} at (200,500) size 400x100 [bgcolor=#808080]
+layer at (0,150) size 100x300
+  RenderBlock (positioned) {DIV} at (0,150) size 100x300 [bgcolor=#808080]
+layer at (700,150) size 100x300
+  RenderBlock (positioned) {DIV} at (700,150) size 100x300 [bgcolor=#808080]
+scrolled to 275,10
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2fastvisualviewportzoomedrectsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt (0 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+This test zooms and scrolls the page and checks that the layout and visual viewports respond as expected.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:400,&quot;bottom&quot;:300,&quot;left&quot;:0,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to 475, 525
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:525,&quot;right&quot;:875,&quot;bottom&quot;:825,&quot;left&quot;:475,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to 100, 776
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:776,&quot;right&quot;:500,&quot;bottom&quot;:1076,&quot;left&quot;:100,&quot;width&quot;:400,&quot;height&quot;:300}
+
+Scrolled to 50, 300
+JSON.stringify(internals.layoutViewportRect()) is {&quot;top&quot;:0,&quot;right&quot;:800,&quot;bottom&quot;:600,&quot;left&quot;:0,&quot;width&quot;:800,&quot;height&quot;:600}
+JSON.stringify(internals.visualViewportRect()) is {&quot;top&quot;:300,&quot;right&quot;:450,&quot;bottom&quot;:600,&quot;left&quot;:50,&quot;width&quot;:400,&quot;height&quot;:300}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/ChangeLog        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2016-11-14  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] Implement support for visual viewports
+        https://bugs.webkit.org/show_bug.cgi?id=164765
+
+        Reviewed by Tim Horton.
+
+        Adopt the visual viewport scrolling model in iOS WK2.
+
+        This is more complex than the Mac implementation for two primary reasons. First,
+        WKWebView needs to to able to control the rectangle used for fixed position layout
+        to get the correct behavior when zooming all the way out, and because iOS displays
+        pages scaled down, exposing document overflow such that the layout viewport rectangle
+        has to get larger than the initial containing block size (which does not happen on Mac).
+
+        This is achieved by pushing a &quot;layoutViewportOverrideRect&quot; down onto FrameView, in
+        a similar way to the customFixedPositionRect that's used now. We share that name
+        for now in code that is agnostic to its use (e.g. VisibleContentRectUpdateInfo).
+
+        I tried so hard to write tests, but ran into various problems (webkit.org/b/164762,
+        webkit.org/b/164764). Will add tests via webkit.org/b/164764.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::fixedScrollableAreaBoundsInflatedForScrolling): layoutViewportOrigin()
+        was removed.
+        (WebCore::FrameView::setBaseLayoutViewportOrigin): Rename with &quot;base&quot; to make it clearer that
+        it can be overridden.
+        (WebCore::FrameView::setLayoutViewportOverrideRect):
+        (WebCore::FrameView::baseLayoutViewportSize): Renamed.
+        (WebCore::FrameView::updateLayoutViewport): Logging.
+        (WebCore::FrameView::layoutViewportRect):
+        (WebCore::FrameView::scrollPositionForFixedPosition):
+        (WebCore::FrameView::unscaledMaximumScrollPosition): During page transitions on iOS, it
+        was possible for unscaledDocumentRect to be empty, but visibleSize() to be non-empty, leading
+        to odd negative max scroll offsets, so clamp to 0,0.
+        (WebCore::FrameView::setLayoutViewportOrigin): Deleted.
+        * page/FrameView.h:
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::reconcileScrollingState): scrollPositionForFixedPosition() already does the
+        visualViewportEnabled() check.
+        * page/scrolling/mac/ScrollingTreeFixedNode.mm:
+        (WebCore::ScrollingTreeFixedNode::updateLayersAfterAncestorChange):
+        * platform/graphics/FloatSize.cpp:
+        (WebCore::FloatSize::constrainedBetween): Added for consistency with the other geometry types.
+        * platform/graphics/FloatSize.h:
+        * platform/graphics/LayoutSize.cpp:
+        (WebCore::LayoutSize::constrainedBetween): Ditto.
+        * platform/graphics/LayoutSize.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::clientLogicalWidthForFixedPosition): If we have an override layout viewport, its size might be different
+        from the RenderView's size (the initial containing block), so we need to use the layoutViewportRect here.
+        (WebCore::RenderView::clientLogicalHeightForFixedPosition):
+
</ins><span class="cx"> 2016-11-15  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebGL] Remove unused Chromium-specific OpenGL extensions
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/page/FrameView.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -1097,7 +1097,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (frame().settings().visualViewportEnabled()) {
</span><span class="cx">         // FIXME: this is wrong under zooming; uninflatedBounds is scaled but the scroll positions are not.
</span><del>-        scrollPosition = layoutViewportOrigin();
</del><ins>+        scrollPosition = layoutViewportRect().location();
</ins><span class="cx">         topLeftExpansion = scrollPosition - unscaledMinimumScrollPosition();
</span><span class="cx">         bottomRightExpansion = unscaledMaximumScrollPosition() - scrollPosition;
</span><span class="cx">     } else {
</span><span class="lines">@@ -1813,7 +1813,7 @@
</span><span class="cx">     return layoutViewportOrigin;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FrameView::setLayoutViewportOrigin(LayoutPoint origin, TriggerLayoutOrNot layoutTriggering)
</del><ins>+void FrameView::setBaseLayoutViewportOrigin(LayoutPoint origin, TriggerLayoutOrNot layoutTriggering)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(frame().settings().visualViewportEnabled());
</span><span class="cx"> 
</span><span class="lines">@@ -1831,10 +1831,35 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void FrameView::setLayoutViewportOverrideRect(Optional&lt;LayoutRect&gt; rect)
+{
+    if (rect == m_layoutViewportOverrideRect)
+        return;
+
+    LayoutRect oldRect = layoutViewportRect();
+    m_layoutViewportOverrideRect = rect;
+
+    LOG_WITH_STREAM(Scrolling, stream &lt;&lt; &quot;\nFrameView &quot; &lt;&lt; this &lt;&lt; &quot; setLayoutViewportOverrideRect() - changing layout viewport from &quot; &lt;&lt; oldRect &lt;&lt; &quot; to &quot; &lt;&lt; m_layoutViewportOverrideRect.value());
+
+    // FIXME: do we need to also do this if the origin changes?
+    if (oldRect.size() != layoutViewportRect().size())
+        setViewportConstrainedObjectsNeedLayout();
+}
+
+LayoutSize FrameView::baseLayoutViewportSize() const
+{
+    return renderView() ? renderView()-&gt;size() : size();
+}
+
</ins><span class="cx"> void FrameView::updateLayoutViewport()
</span><span class="cx"> {
</span><span class="cx">     if (!frame().settings().visualViewportEnabled())
</span><span class="cx">         return;
</span><ins>+    
+    if (m_layoutViewportOverrideRect) {
+        LOG_WITH_STREAM(Scrolling, stream &lt;&lt; &quot;\nFrameView &quot; &lt;&lt; this &lt;&lt; &quot; updateLayoutViewport() - has layoutViewportOverrideRect&quot; &lt;&lt; m_layoutViewportOverrideRect.value());
+        return;
+    }
</ins><span class="cx"> 
</span><span class="cx">     LayoutRect layoutViewport = layoutViewportRect();
</span><span class="cx"> 
</span><span class="lines">@@ -1844,8 +1869,8 @@
</span><span class="cx">     LOG_WITH_STREAM(Scrolling, stream &lt;&lt; &quot;scroll positions: min: &quot; &lt;&lt; unscaledMinimumScrollPosition() &lt;&lt; &quot; max: &quot;&lt;&lt; unscaledMaximumScrollPosition());
</span><span class="cx"> 
</span><span class="cx">     LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport);
</span><del>-    if (newLayoutViewportOrigin != layoutViewportOrigin()) {
-        setLayoutViewportOrigin(newLayoutViewportOrigin);
</del><ins>+    if (newLayoutViewportOrigin != m_layoutViewportOrigin) {
+        setBaseLayoutViewportOrigin(newLayoutViewportOrigin);
</ins><span class="cx">         LOG_WITH_STREAM(Scrolling, stream &lt;&lt; &quot;layoutViewport changed to &quot; &lt;&lt; layoutViewportRect());
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -1868,9 +1893,12 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Size of initial containing block, anchored at scroll position, in document coordinates (unchanged by scale factor).
</del><span class="cx"> LayoutRect FrameView::layoutViewportRect() const
</span><span class="cx"> {
</span><ins>+    if (m_layoutViewportOverrideRect)
+        return m_layoutViewportOverrideRect.value();
+
+    // Size of initial containing block, anchored at scroll position, in document coordinates (unchanged by scale factor).
</ins><span class="cx">     return LayoutRect(m_layoutViewportOrigin, renderView() ? renderView()-&gt;size() : size());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1912,7 +1940,7 @@
</span><span class="cx"> LayoutPoint FrameView::scrollPositionForFixedPosition() const
</span><span class="cx"> {
</span><span class="cx">     if (frame().settings().visualViewportEnabled())
</span><del>-        return layoutViewportOrigin();
</del><ins>+        return layoutViewportRect().location();
</ins><span class="cx"> 
</span><span class="cx">     return scrollPositionForFixedPosition(visibleContentRect(), totalContentsSize(), scrollPosition(), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), scrollBehaviorForFixedElements(), headerHeight(), footerHeight());
</span><span class="cx"> }
</span><span class="lines">@@ -2068,7 +2096,7 @@
</span><span class="cx">     if (RenderView* renderView = this-&gt;renderView()) {
</span><span class="cx">         IntRect unscaledDocumentRect = renderView-&gt;unscaledDocumentRect();
</span><span class="cx">         unscaledDocumentRect.expand(0, headerHeight() + footerHeight());
</span><del>-        ScrollPosition maximumPosition = unscaledDocumentRect.maxXMaxYCorner() - visibleSize();
</del><ins>+        ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize()).expandedTo({ 0, 0 });
</ins><span class="cx"> 
</span><span class="cx">         if (frame().isMainFrame() &amp;&amp; m_scrollPinningBehavior == PinToTop)
</span><span class="cx">             maximumPosition.setY(unscaledMinimumScrollPosition().y());
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/page/FrameView.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -252,15 +252,21 @@
</span><span class="cx"> 
</span><span class="cx">     IntPoint unscaledScrollOrigin() const;
</span><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT LayoutPoint minStableLayoutViewportOrigin() const;
+    WEBCORE_EXPORT LayoutPoint maxStableLayoutViewportOrigin() const;
+
</ins><span class="cx">     enum class TriggerLayoutOrNot {
</span><span class="cx">         No,
</span><span class="cx">         Yes
</span><span class="cx">     };
</span><del>-    void setLayoutViewportOrigin(LayoutPoint, TriggerLayoutOrNot = TriggerLayoutOrNot::Yes);
-    LayoutPoint layoutViewportOrigin() const { return m_layoutViewportOrigin; }
</del><ins>+    // This origin can be overridden by setLayoutViewportOverrideRect.
+    void setBaseLayoutViewportOrigin(LayoutPoint, TriggerLayoutOrNot = TriggerLayoutOrNot::Yes);
+    // This size can be overridden by setLayoutViewportOverrideRect.
+    WEBCORE_EXPORT LayoutSize baseLayoutViewportSize() const;
</ins><span class="cx">     
</span><del>-    LayoutPoint minStableLayoutViewportOrigin() const;
-    LayoutPoint maxStableLayoutViewportOrigin() const;
</del><ins>+    // If set, overrides the default &quot;m_layoutViewportOrigin, size of initial containing block&quot; rect.
+    // Used with delegated scrolling (i.e. iOS).
+    WEBCORE_EXPORT void setLayoutViewportOverrideRect(Optional&lt;LayoutRect&gt;);
</ins><span class="cx"> 
</span><span class="cx">     // These are in document coordinates, unaffected by zooming.
</span><span class="cx">     WEBCORE_EXPORT LayoutRect layoutViewportRect() const;
</span><span class="lines">@@ -304,7 +310,7 @@
</span><span class="cx">     // Static function can be called from another thread.
</span><span class="cx">     static LayoutPoint scrollPositionForFixedPosition(const LayoutRect&amp; visibleContentRect, const LayoutSize&amp; totalContentsSize, const LayoutPoint&amp; scrollPosition, const LayoutPoint&amp; scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements, int headerHeight, int footerHeight);
</span><span class="cx"> 
</span><del>-    static LayoutPoint computeLayoutViewportOrigin(const LayoutRect&amp; visualViewport, const LayoutPoint&amp; stableLayoutViewportOriginMin, const LayoutPoint&amp; stableLayoutViewportOriginMax, const LayoutRect&amp; layoutViewport);
</del><ins>+    WEBCORE_EXPORT static LayoutPoint computeLayoutViewportOrigin(const LayoutRect&amp; visualViewport, const LayoutPoint&amp; stableLayoutViewportOriginMin, const LayoutPoint&amp; stableLayoutViewportOriginMax, const LayoutRect&amp; layoutViewport);
</ins><span class="cx"> 
</span><span class="cx">     // These layers are positioned differently when there is a topContentInset, a header, or a footer. These value need to be computed
</span><span class="cx">     // on both the main thread and the scrolling thread.
</span><span class="lines">@@ -786,6 +792,7 @@
</span><span class="cx">     Optional&lt;FloatRect&gt; m_viewExposedRect;
</span><span class="cx">     
</span><span class="cx">     LayoutPoint m_layoutViewportOrigin;
</span><ins>+    Optional&lt;LayoutRect&gt; m_layoutViewportOverrideRect;
</ins><span class="cx"> 
</span><span class="cx">     unsigned m_deferSetNeedsLayoutCount;
</span><span class="cx">     bool m_setNeedsLayoutWasDeferred;
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingAsyncScrollingCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -352,7 +352,7 @@
</span><span class="cx">     WTF::switchOn(layoutViewportOriginOrOverrideRect,
</span><span class="cx">         [&amp;frameView](Optional&lt;FloatPoint&gt; origin) {
</span><span class="cx">             if (origin)
</span><del>-                frameView.setLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
</del><ins>+                frameView.setBaseLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
</ins><span class="cx">         }, [&amp;frameView](Optional&lt;FloatRect&gt; overrideRect) {
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">             if (overrideRect)
</span><span class="lines">@@ -383,7 +383,7 @@
</span><span class="cx">     GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(frameView.scrollPosition() == roundedIntPoint(scrollPosition));
</span><del>-    LayoutPoint scrollPositionForFixed = visualViewportEnabled() ? frameView.layoutViewportOrigin() : frameView.scrollPositionForFixedPosition();
</del><ins>+    LayoutPoint scrollPositionForFixed = frameView.scrollPositionForFixedPosition();
</ins><span class="cx">     float topContentInset = frameView.topContentInset();
</span><span class="cx"> 
</span><span class="cx">     FloatPoint positionForInsetClipLayer;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFloatSizecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FloatSize.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FloatSize.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/platform/graphics/FloatSize.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -41,6 +41,14 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FloatSize FloatSize::constrainedBetween(const FloatSize&amp; min, const FloatSize&amp; max) const
+{
+    return {
+        std::max(min.width(), std::min(max.width(), m_width)),
+        std::max(min.height(), std::min(max.height(), m_height))
+    };
+}
+
</ins><span class="cx"> float FloatSize::diagonalLength() const
</span><span class="cx"> {
</span><span class="cx">     return sqrtf(diagonalLengthSquared());
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFloatSizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FloatSize.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FloatSize.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/platform/graphics/FloatSize.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -95,6 +95,8 @@
</span><span class="cx">         m_height *= scaleY;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT FloatSize constrainedBetween(const FloatSize&amp; min, const FloatSize&amp; max) const;
+
</ins><span class="cx">     FloatSize expandedTo(const FloatSize&amp; other) const
</span><span class="cx">     {
</span><span class="cx">         return FloatSize(m_width &gt; other.m_width ? m_width : other.m_width,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsLayoutSizecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/LayoutSize.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/LayoutSize.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/platform/graphics/LayoutSize.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -30,6 +30,14 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+LayoutSize LayoutSize::constrainedBetween(const LayoutSize&amp; min, const LayoutSize&amp; max) const
+{
+    return {
+        std::max(min.width(), std::min(max.width(), m_width)),
+        std::max(min.height(), std::min(max.height(), m_height))
+    };
+}
+
</ins><span class="cx"> TextStream&amp; operator&lt;&lt;(TextStream&amp; ts, const LayoutSize&amp; size)
</span><span class="cx"> {
</span><span class="cx">     return ts &lt;&lt; &quot;width=&quot; &lt;&lt; size.width().toFloat() &lt;&lt; &quot; height=&quot; &lt;&lt; size.height().toFloat();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsLayoutSizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/LayoutSize.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/LayoutSize.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/platform/graphics/LayoutSize.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -87,6 +87,8 @@
</span><span class="cx">         m_width *= widthScale;
</span><span class="cx">         m_height *= heightScale;
</span><span class="cx">     }
</span><ins>+
+    LayoutSize constrainedBetween(const LayoutSize&amp; min, const LayoutSize&amp; max) const;
</ins><span class="cx">     
</span><span class="cx">     LayoutSize expandedTo(const LayoutSize&amp; other) const
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderView.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderView.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebCore/rendering/RenderView.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -407,6 +407,9 @@
</span><span class="cx">         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().width() : frameView().customFixedPositionLayoutRect().height();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    if (frameView().frame().settings().visualViewportEnabled())
+        return isHorizontalWritingMode() ? frameView().layoutViewportRect().width() : frameView().layoutViewportRect().height();
+
</ins><span class="cx">     return clientLogicalWidth();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -421,6 +424,9 @@
</span><span class="cx">         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().height() : frameView().customFixedPositionLayoutRect().width();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    if (frameView().frame().settings().visualViewportEnabled())
+        return isHorizontalWritingMode() ? frameView().layoutViewportRect().height() : frameView().layoutViewportRect().width();
+
</ins><span class="cx">     return clientLogicalHeight();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/ChangeLog        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -1,3 +1,62 @@
</span><ins>+2016-11-14  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        [iOS WK2] Implement support for visual viewports
+        https://bugs.webkit.org/show_bug.cgi?id=164765
+
+        Reviewed by Tim Horton.
+
+        Adopt the visual viewport scrolling model in iOS WK2.
+
+        Pass the parameters used for computing the layout viewport up to WK2 via RemoteLayerTreeTransaction.
+        These are stored on WebPageProxy. When they change, _didCommitLayerTree triggers a -_updateVisibleContentRects.
+        
+        WebPageProxy::computeCustomFixedPositionRect() is the function that computes the &quot;override&quot; layout viewport.
+        It starts with the baseLayoutViewportSize from the web process (which is based on the initial containing block
+        size), then ensures that it's no smaller than the unobscured content rect, since it makes no sense for the
+        layout viewport to be smaller than the visual viewport. The static FrameView::computeLayoutViewportOrigin()
+        is then use to &quot;push&quot; the layout viewport around as the visual viewport changes.
+
+        * Shared/VisibleContentRectUpdateInfo.h:
+        * Shared/WebCoreArgumentCoders.cpp: Encode LayoutSize and LayoutPoint.
+        (IPC::ArgumentCoder&lt;LayoutSize&gt;::encode):
+        (IPC::ArgumentCoder&lt;LayoutSize&gt;::decode):
+        (IPC::ArgumentCoder&lt;LayoutPoint&gt;::encode):
+        (IPC::ArgumentCoder&lt;LayoutPoint&gt;::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        * Shared/mac/RemoteLayerTreeTransaction.h:
+        (WebKit::RemoteLayerTreeTransaction::baseLayoutViewportSize):
+        (WebKit::RemoteLayerTreeTransaction::setBaseLayoutViewportSize):
+        (WebKit::RemoteLayerTreeTransaction::minStableLayoutViewportOrigin):
+        (WebKit::RemoteLayerTreeTransaction::setMinStableLayoutViewportOrigin):
+        (WebKit::RemoteLayerTreeTransaction::maxStableLayoutViewportOrigin):
+        (WebKit::RemoteLayerTreeTransaction::setMaxStableLayoutViewportOrigin):
+        * Shared/mac/RemoteLayerTreeTransaction.mm:
+        (WebKit::RemoteLayerTreeTransaction::encode):
+        (WebKit::RemoteLayerTreeTransaction::decode):
+        (WebKit::RemoteLayerTreeTransaction::description):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _didCommitLayerTree:]):
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        (WebKit::RemoteScrollingCoordinatorProxy::visualViewportEnabled): Accessor.
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::customFixedPositionRect):
+        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+        (WebKit::RemoteScrollingCoordinatorProxy::customFixedPositionRect):
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
+        (-[WKContentView _didCommitLayerTree:]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::computeCustomFixedPositionRect): When visual viewports are enabled, compute
+        the layout viewport rect, taking the baseLayoutViewportSize and the current unobscured rect into account.
+        (WebKit::WebPageProxy::updateLayoutViewportParameters):
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
+        * WebProcess/WebPage/WebPage.cpp: Encode in the transaction the layout viewport parameters (with minor refactor).
+        (WebKit::WebPage::willCommitLayerTree):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::updateVisibleContentRects): This is where the web process receives the new override layout viewport
+        from the web process (with some logging).
+
</ins><span class="cx"> 2016-11-15  Jon Lee  &lt;jonlee@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove HasMediaCaptureDevice
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedVisibleContentRectUpdateInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx">     WebCore::FloatRect m_exposedContentRect;
</span><span class="cx">     WebCore::FloatRect m_unobscuredContentRect;
</span><span class="cx">     WebCore::FloatRect m_unobscuredRectInScrollViewCoordinates;
</span><del>-    WebCore::FloatRect m_customFixedPositionRect;
</del><ins>+    WebCore::FloatRect m_customFixedPositionRect; // When visual viewports are enabled, this is the layout viewport.
</ins><span class="cx">     WebCore::FloatSize m_obscuredInset;
</span><span class="cx">     uint64_t m_lastLayerTreeTransactionID { 0 };
</span><span class="cx">     double m_scale { -1 };
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCoreArgumentCoderscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -433,6 +433,29 @@
</span><span class="cx">     return SimpleArgumentCoder&lt;IntSize&gt;::decode(decoder, intSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+void ArgumentCoder&lt;LayoutSize&gt;::encode(Encoder&amp; encoder, const LayoutSize&amp; layoutSize)
+{
+    SimpleArgumentCoder&lt;LayoutSize&gt;::encode(encoder, layoutSize);
+}
+
+bool ArgumentCoder&lt;LayoutSize&gt;::decode(Decoder&amp; decoder, LayoutSize&amp; layoutSize)
+{
+    return SimpleArgumentCoder&lt;LayoutSize&gt;::decode(decoder, layoutSize);
+}
+
+
+void ArgumentCoder&lt;LayoutPoint&gt;::encode(Encoder&amp; encoder, const LayoutPoint&amp; layoutPoint)
+{
+    SimpleArgumentCoder&lt;LayoutPoint&gt;::encode(encoder, layoutPoint);
+}
+
+bool ArgumentCoder&lt;LayoutPoint&gt;::decode(Decoder&amp; decoder, LayoutPoint&amp; layoutPoint)
+{
+    return SimpleArgumentCoder&lt;LayoutPoint&gt;::decode(decoder, layoutPoint);
+}
+
+
</ins><span class="cx"> static void pathEncodeApplierFunction(Encoder&amp; encoder, const PathElement&amp; element)
</span><span class="cx"> {
</span><span class="cx">     encoder.encodeEnum(element.type);
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCoreArgumentCodersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -54,6 +54,8 @@
</span><span class="cx"> class IntRect;
</span><span class="cx"> class IntSize;
</span><span class="cx"> class KeyframeValueList;
</span><ins>+class LayoutSize;
+class LayoutPoint;
</ins><span class="cx"> class LinearTimingFunction;
</span><span class="cx"> class Notification;
</span><span class="cx"> class Path;
</span><span class="lines">@@ -236,6 +238,16 @@
</span><span class="cx">     static bool decode(Decoder&amp;, WebCore::IntSize&amp;);
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+template&lt;&gt; struct ArgumentCoder&lt;WebCore::LayoutSize&gt; {
+    static void encode(Encoder&amp;, const WebCore::LayoutSize&amp;);
+    static bool decode(Decoder&amp;, WebCore::LayoutSize&amp;);
+};
+
+template&lt;&gt; struct ArgumentCoder&lt;WebCore::LayoutPoint&gt; {
+    static void encode(Encoder&amp;, const WebCore::LayoutPoint&amp;);
+    static bool decode(Decoder&amp;, WebCore::LayoutPoint&amp;);
+};
+
</ins><span class="cx"> template&lt;&gt; struct ArgumentCoder&lt;WebCore::Path&gt; {
</span><span class="cx">     static void encode(Encoder&amp;, const WebCore::Path&amp;);
</span><span class="cx">     static bool decode(Decoder&amp;, WebCore::Path&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerTreeTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -204,7 +204,16 @@
</span><span class="cx"> 
</span><span class="cx">     WebCore::IntPoint scrollOrigin() const { return m_scrollOrigin; }
</span><span class="cx">     void setScrollOrigin(const WebCore::IntPoint&amp; origin) { m_scrollOrigin = origin; };
</span><ins>+
+    WebCore::LayoutSize baseLayoutViewportSize() const { return m_baseLayoutViewportSize; }
+    void setBaseLayoutViewportSize(const WebCore::LayoutSize&amp; size) { m_baseLayoutViewportSize = size; };
</ins><span class="cx">     
</span><ins>+    WebCore::LayoutPoint minStableLayoutViewportOrigin() const { return m_minStableLayoutViewportOrigin; }
+    void setMinStableLayoutViewportOrigin(const WebCore::LayoutPoint&amp; point) { m_minStableLayoutViewportOrigin = point; };
+    
+    WebCore::LayoutPoint maxStableLayoutViewportOrigin() const { return m_maxStableLayoutViewportOrigin; }
+    void setMaxStableLayoutViewportOrigin(const WebCore::LayoutPoint&amp; point) { m_maxStableLayoutViewportOrigin = point; };
+    
</ins><span class="cx">     WebCore::Color pageExtendedBackgroundColor() const { return m_pageExtendedBackgroundColor; }
</span><span class="cx">     void setPageExtendedBackgroundColor(WebCore::Color color) { m_pageExtendedBackgroundColor = color; }
</span><span class="cx"> 
</span><span class="lines">@@ -267,6 +276,9 @@
</span><span class="cx"> 
</span><span class="cx">     WebCore::IntSize m_contentsSize;
</span><span class="cx">     WebCore::IntPoint m_scrollOrigin;
</span><ins>+    WebCore::LayoutSize m_baseLayoutViewportSize;
+    WebCore::LayoutPoint m_minStableLayoutViewportOrigin;
+    WebCore::LayoutPoint m_maxStableLayoutViewportOrigin;
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     WebCore::IntPoint m_scrollPosition;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerTreeTransactionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -527,6 +527,11 @@
</span><span class="cx"> 
</span><span class="cx">     encoder &lt;&lt; m_contentsSize;
</span><span class="cx">     encoder &lt;&lt; m_scrollOrigin;
</span><ins>+
+    encoder &lt;&lt; m_baseLayoutViewportSize;
+    encoder &lt;&lt; m_minStableLayoutViewportOrigin;
+    encoder &lt;&lt; m_maxStableLayoutViewportOrigin;
+
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     encoder &lt;&lt; m_scrollPosition;
</span><span class="cx"> #endif
</span><span class="lines">@@ -602,6 +607,15 @@
</span><span class="cx">     if (!decoder.decode(result.m_scrollOrigin))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (!decoder.decode(result.m_baseLayoutViewportSize))
+        return false;
+
+    if (!decoder.decode(result.m_minStableLayoutViewportOrigin))
+        return false;
+
+    if (!decoder.decode(result.m_maxStableLayoutViewportOrigin))
+        return false;
+    
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     if (!decoder.decode(result.m_scrollPosition))
</span><span class="cx">         return false;
</span><span class="lines">@@ -844,6 +858,12 @@
</span><span class="cx">     if (m_scrollOrigin != IntPoint::zero())
</span><span class="cx">         ts.dumpProperty(&quot;scrollOrigin&quot;, m_scrollOrigin);
</span><span class="cx"> 
</span><ins>+    ts.dumpProperty(&quot;baseLayoutViewportSize&quot;, FloatSize(m_baseLayoutViewportSize));
+
+    if (m_minStableLayoutViewportOrigin != LayoutPoint::zero())
+        ts.dumpProperty(&quot;minStableLayoutViewportOrigin&quot;, FloatPoint(m_minStableLayoutViewportOrigin));
+    ts.dumpProperty(&quot;maxStableLayoutViewportOrigin&quot;, FloatPoint(m_maxStableLayoutViewportOrigin));
+
</ins><span class="cx">     if (m_pageScaleFactor != 1)
</span><span class="cx">         ts.dumpProperty(&quot;pageScaleFactor&quot;, m_pageScaleFactor);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -1273,6 +1273,9 @@
</span><span class="cx">     _viewportMetaTagWidthWasExplicit = layerTreeTransaction.viewportMetaTagWidthWasExplicit();
</span><span class="cx">     _viewportMetaTagCameFromImageDocument = layerTreeTransaction.viewportMetaTagCameFromImageDocument();
</span><span class="cx">     _initialScaleFactor = layerTreeTransaction.initialScaleFactor();
</span><ins>+
+    BOOL needUpdateVisbleContentRects = _page-&gt;updateLayoutViewportParameters(layerTreeTransaction);
+
</ins><span class="cx">     if (![_contentView _mayDisableDoubleTapGesturesDuringSingleTap])
</span><span class="cx">         [_contentView _setDoubleTapGesturesEnabled:self._allowsDoubleTapGestures];
</span><span class="cx"> 
</span><span class="lines">@@ -1284,9 +1287,10 @@
</span><span class="cx">     if (_needsResetViewStateAfterCommitLoadForMainFrame &amp;&amp; layerTreeTransaction.transactionID() &gt;= _firstPaintAfterCommitLoadTransactionID) {
</span><span class="cx">         _needsResetViewStateAfterCommitLoadForMainFrame = NO;
</span><span class="cx">         [_scrollView setContentOffset:[self _adjustedContentOffset:CGPointZero]];
</span><del>-        [self _updateVisibleContentRects];
</del><span class="cx">         if (_observedRenderingProgressEvents &amp; _WKRenderingProgressEventFirstPaint)
</span><span class="cx">             _navigationState-&gt;didFirstPaint();
</span><ins>+
+        needUpdateVisbleContentRects = YES;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool isTransactionAfterPageRestore = layerTreeTransaction.transactionID() &gt;= _firstTransactionIDAfterPageRestore;
</span><span class="lines">@@ -1305,7 +1309,8 @@
</span><span class="cx">             if (_gestureController)
</span><span class="cx">                 _gestureController-&gt;didRestoreScrollPosition();
</span><span class="cx">         }
</span><del>-        [self _updateVisibleContentRects];
</del><ins>+        
+        needUpdateVisbleContentRects = YES;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (_needsToRestoreUnobscuredCenter &amp;&amp; isTransactionAfterPageRestore) {
</span><span class="lines">@@ -1323,9 +1328,13 @@
</span><span class="cx">             if (_gestureController)
</span><span class="cx">                 _gestureController-&gt;didRestoreScrollPosition();
</span><span class="cx">         }
</span><ins>+
+        needUpdateVisbleContentRects = YES;
+    }
+
+    if (needUpdateVisbleContentRects)
</ins><span class="cx">         [self _updateVisibleContentRects];
</span><del>-    }
-    
</del><ins>+
</ins><span class="cx">     if (WebKit::RemoteLayerTreeScrollingPerformanceData* scrollPerfData = _page-&gt;scrollingPerformanceData())
</span><span class="cx">         scrollPerfData-&gt;didCommitLayerTree([self visibleRectInViewCoordinates]);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -51,7 +51,9 @@
</span><span class="cx"> public:
</span><span class="cx">     explicit RemoteScrollingCoordinatorProxy(WebPageProxy&amp;);
</span><span class="cx">     virtual ~RemoteScrollingCoordinatorProxy();
</span><del>-    
</del><ins>+
+    bool visualViewportEnabled() const { return m_scrollingTree &amp;&amp; m_scrollingTree-&gt;visualViewportEnabled(); }
+
</ins><span class="cx">     // Inform the web process that the scroll position changed (called from the scrolling tree)
</span><span class="cx">     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint&amp; newScrollPosition, const Optional&lt;WebCore::FloatPoint&gt;&amp; layoutViewportOrigin, WebCore::SetOrSyncScrollingLayerPosition);
</span><span class="cx">     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint&amp; scrollPosition, bool representsProgrammaticScroll);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -461,12 +461,15 @@
</span><span class="cx">     double displayedContentScale() const { return m_lastVisibleContentRectUpdate.scale(); }
</span><span class="cx">     const WebCore::FloatRect&amp; exposedContentRect() const { return m_lastVisibleContentRectUpdate.exposedContentRect(); }
</span><span class="cx">     const WebCore::FloatRect&amp; unobscuredContentRect() const { return m_lastVisibleContentRectUpdate.unobscuredContentRect(); }
</span><ins>+    // When visual viewports are enabled, this is the layout viewport rect.
+    const WebCore::FloatRect&amp; customFixedPositionRect() const { return m_lastVisibleContentRectUpdate.customFixedPositionRect(); }
</ins><span class="cx"> 
</span><span class="cx">     void updateVisibleContentRects(const VisibleContentRectUpdateInfo&amp;);
</span><span class="cx">     void resendLastVisibleContentRects();
</span><span class="cx"> 
</span><span class="cx">     enum class UnobscuredRectConstraint { ConstrainedToDocumentRect, Unconstrained };
</span><del>-    WebCore::FloatRect computeCustomFixedPositionRect(const WebCore::FloatRect&amp; unobscuredContentRect, double displayedContentScale, UnobscuredRectConstraint = UnobscuredRectConstraint::Unconstrained) const;
</del><ins>+    WebCore::FloatRect computeCustomFixedPositionRect(const WebCore::FloatRect&amp; unobscuredContentRect, const WebCore::FloatRect&amp; currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint = UnobscuredRectConstraint::Unconstrained, bool visualViewportEnabled = false) const;
+
</ins><span class="cx">     void overflowScrollViewWillStartPanGesture();
</span><span class="cx">     void overflowScrollViewDidScroll();
</span><span class="cx">     void overflowScrollWillStartScroll();
</span><span class="lines">@@ -536,6 +539,8 @@
</span><span class="cx">     void didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction&amp;);
</span><span class="cx">     void layerTreeCommitComplete();
</span><span class="cx"> 
</span><ins>+    bool updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction&amp;);
+
</ins><span class="cx"> #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
</span><span class="cx">     void didRenderFrame(const WebCore::IntSize&amp; contentsSize, const WebCore::IntRect&amp; coveredRect);
</span><span class="cx">     void commitPageTransitionViewport();
</span><span class="lines">@@ -1875,6 +1880,11 @@
</span><span class="cx">     bool m_autoSizingShouldExpandToViewHeight;
</span><span class="cx">     WebCore::IntSize m_minimumLayoutSize;
</span><span class="cx"> 
</span><ins>+    // Visual viewports
+    WebCore::LayoutSize m_baseLayoutViewportSize;
+    WebCore::LayoutPoint m_minStableLayoutViewportOrigin;
+    WebCore::LayoutPoint m_maxStableLayoutViewportOrigin;
+
</ins><span class="cx">     float m_mediaVolume;
</span><span class="cx">     WebCore::MediaProducer::MutedStateFlags m_mutedState { WebCore::MediaProducer::NoneMuted };
</span><span class="cx">     bool m_mayStartMediaWhenInWindow;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosRemoteScrollingCoordinatorProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx"> 
</span><span class="cx"> FloatRect RemoteScrollingCoordinatorProxy::customFixedPositionRect() const
</span><span class="cx"> {
</span><del>-    return m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.displayedContentScale());
</del><ins>+    return m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteScrollingCoordinatorProxy::scrollingTreeNodeWillStartPanGesture()
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -377,9 +377,10 @@
</span><span class="cx">     else
</span><span class="cx">         _historicalKinematicData.clear();
</span><span class="cx"> 
</span><del>-    FloatRect fixedPositionRectForLayout = _page-&gt;computeCustomFixedPositionRect(unobscuredRect, zoomScale, WebPageProxy::UnobscuredRectConstraint::ConstrainedToDocumentRect);
</del><ins>+    RemoteScrollingCoordinatorProxy* scrollingCoordinator = _page-&gt;scrollingCoordinatorProxy();
+    FloatRect fixedPositionRectForLayout = _page-&gt;computeCustomFixedPositionRect(unobscuredRect, _page-&gt;customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::ConstrainedToDocumentRect, scrollingCoordinator-&gt;visualViewportEnabled());
</ins><span class="cx"> 
</span><del>-    LOG_WITH_STREAM(VisibleRects, stream &lt;&lt; &quot;didUpdateVisibleRect: visibleRect:&quot; &lt;&lt; visibleRect &lt;&lt; &quot; unobscuredRect:&quot; &lt;&lt; unobscuredRect &lt;&lt; &quot; fixedPositionRectForLayout:&quot; &lt;&lt; fixedPositionRectForLayout);
</del><ins>+    LOG_WITH_STREAM(VisibleRects, stream &lt;&lt; &quot;didUpdateVisibleRect: visibleRect:&quot; &lt;&lt; visibleRect &lt;&lt; &quot; unobscuredRect:&quot; &lt;&lt; unobscuredRect &lt;&lt; &quot; fixedPositionRectForLayout:&quot; &lt;&lt; fixedPositionRectForLayout &lt;&lt; &quot; stable: &quot; &lt;&lt; isStableState);
</ins><span class="cx"> 
</span><span class="cx">     VisibleContentRectUpdateInfo visibleContentRectUpdateInfo(
</span><span class="cx">         visibleRect,
</span><span class="lines">@@ -400,8 +401,7 @@
</span><span class="cx"> 
</span><span class="cx">     _page-&gt;updateVisibleContentRects(visibleContentRectUpdateInfo);
</span><span class="cx"> 
</span><del>-    RemoteScrollingCoordinatorProxy* scrollingCoordinator = _page-&gt;scrollingCoordinatorProxy();
-    FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), zoomScale);
</del><ins>+    FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), _page-&gt;customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::Unconstrained, scrollingCoordinator-&gt;visualViewportEnabled());
</ins><span class="cx">     scrollingCoordinator-&gt;viewportChangedViaDelegatedScrolling(scrollingCoordinator-&gt;rootScrollingNodeID(), fixedPositionRect, zoomScale);
</span><span class="cx"> 
</span><span class="cx">     drawingArea-&gt;updateDebugIndicator();
</span><span class="lines">@@ -536,7 +536,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (boundsChanged) {
</span><del>-        FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), [[_webView scrollView] zoomScale]);
</del><ins>+        // FIXME: factor computeCustomFixedPositionRect() into something that gives us this rect.
+        FloatRect fixedPositionRect = _page-&gt;computeCustomFixedPositionRect(_page-&gt;unobscuredContentRect(), _page-&gt;customFixedPositionRect(), [[_webView scrollView] zoomScale]);
</ins><span class="cx">         [self updateFixedClippingView:fixedPositionRect];
</span><span class="cx"> 
</span><span class="cx">         // We need to push the new content bounds to the webview to update fixed position rects.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #import &quot;DataReference.h&quot;
</span><span class="cx"> #import &quot;EditingRange.h&quot;
</span><span class="cx"> #import &quot;InteractionInformationAtPosition.h&quot;
</span><ins>+#import &quot;Logging.h&quot;
</ins><span class="cx"> #import &quot;NativeWebKeyboardEvent.h&quot;
</span><span class="cx"> #import &quot;PageClient.h&quot;
</span><span class="cx"> #import &quot;PrintInfo.h&quot;
</span><span class="lines">@@ -49,6 +50,7 @@
</span><span class="cx"> #import &lt;WebCore/NotImplemented.h&gt;
</span><span class="cx"> #import &lt;WebCore/PlatformScreen.h&gt;
</span><span class="cx"> #import &lt;WebCore/SharedBuffer.h&gt;
</span><ins>+#import &lt;WebCore/TextStream.h&gt;
</ins><span class="cx"> #import &lt;WebCore/UserAgent.h&gt;
</span><span class="cx"> #import &lt;WebCore/ValidationBubble.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -217,7 +219,8 @@
</span><span class="cx">     return exposedRectEdge;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect&amp; unobscuredContentRect, double displayedContentScale, UnobscuredRectConstraint constraint) const
</del><ins>+// FIXME: rename this when visual viewports are the default.
+WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect&amp; unobscuredContentRect, const FloatRect&amp; currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint constraint, bool visualViewportEnabled) const
</ins><span class="cx"> {
</span><span class="cx">     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
</span><span class="cx">     FloatRect documentRect = m_pageClient.documentRect();
</span><span class="lines">@@ -240,6 +243,21 @@
</span><span class="cx">         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (visualViewportEnabled) {
+        FloatRect layoutViewportRect = currentCustomFixedPositionRect;
+        
+        // The layout viewport is never smaller than m_baseLayoutViewportSize, and never be smaller than the constrainedUnobscuredRect.
+        FloatSize constrainedSize = m_baseLayoutViewportSize;
+        layoutViewportRect.setSize(constrainedSize.expandedTo(constrainedUnobscuredRect.size()));
+
+        LayoutPoint layoutViewportOrigin = FrameView::computeLayoutViewportOrigin(enclosingLayoutRect(constrainedUnobscuredRect), m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, enclosingLayoutRect(layoutViewportRect));
+        layoutViewportRect.setLocation(layoutViewportOrigin);
+
+        if (layoutViewportRect != currentCustomFixedPositionRect)
+            LOG_WITH_STREAM(VisibleRects, stream &lt;&lt; &quot;WebPageProxy::computeCustomFixedPositionRect: new layout viewport  &quot; &lt;&lt; layoutViewportRect);
+        return layoutViewportRect;
+    }
+    
</ins><span class="cx">     return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -377,6 +395,19 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction&amp; layerTreeTransaction)
+{
+    bool changed = m_baseLayoutViewportSize != layerTreeTransaction.baseLayoutViewportSize()
+        || m_minStableLayoutViewportOrigin != layerTreeTransaction.minStableLayoutViewportOrigin()
+        || m_maxStableLayoutViewportOrigin != layerTreeTransaction.maxStableLayoutViewportOrigin();
+
+    m_baseLayoutViewportSize = layerTreeTransaction.baseLayoutViewportSize();
+    m_minStableLayoutViewportOrigin = layerTreeTransaction.minStableLayoutViewportOrigin();
+    m_maxStableLayoutViewportOrigin = layerTreeTransaction.maxStableLayoutViewportOrigin();
+    
+    return changed;
+}
+
</ins><span class="cx"> void WebPageProxy::layerTreeCommitComplete()
</span><span class="cx"> {
</span><span class="cx">     m_pageClient.layerTreeCommitComplete();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxymm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -202,7 +202,7 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     if (m_webPageProxy.scrollingCoordinatorProxy()-&gt;hasFixedOrSticky()) {
</span><span class="cx">         // If we got a new layer for a fixed or sticky node, its position from the WebProcess is probably stale. We need to re-run the &quot;viewport&quot; changed logic to udpate it with our UI-side state.
</span><del>-        FloatRect customFixedPositionRect = m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.displayedContentScale());
</del><ins>+        FloatRect customFixedPositionRect = m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale(), WebPageProxy::UnobscuredRectConstraint::Unconstrained, m_webPageProxy.scrollingCoordinatorProxy()-&gt;visualViewportEnabled());
</ins><span class="cx">         m_webPageProxy.scrollingCoordinatorProxy()-&gt;viewportChangedViaDelegatedScrolling(m_webPageProxy.scrollingCoordinatorProxy()-&gt;rootScrollingNodeID(), customFixedPositionRect, m_webPageProxy.displayedContentScale());
</span><span class="cx">     }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -3256,11 +3256,20 @@
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> void WebPage::willCommitLayerTree(RemoteLayerTreeTransaction&amp; layerTransaction)
</span><span class="cx"> {
</span><del>-    layerTransaction.setContentsSize(corePage()-&gt;mainFrame().view()-&gt;contentsSize());
-    layerTransaction.setScrollOrigin(corePage()-&gt;mainFrame().view()-&gt;scrollOrigin());
</del><ins>+    FrameView* frameView = corePage()-&gt;mainFrame().view();
+    if (!frameView)
+        return;
+
+    layerTransaction.setContentsSize(frameView-&gt;contentsSize());
+    layerTransaction.setScrollOrigin(frameView-&gt;scrollOrigin());
</ins><span class="cx">     layerTransaction.setPageScaleFactor(corePage()-&gt;pageScaleFactor());
</span><span class="cx">     layerTransaction.setRenderTreeSize(corePage()-&gt;renderTreeSize());
</span><span class="cx">     layerTransaction.setPageExtendedBackgroundColor(corePage()-&gt;pageExtendedBackgroundColor());
</span><ins>+
+    layerTransaction.setBaseLayoutViewportSize(frameView-&gt;baseLayoutViewportSize());
+    layerTransaction.setMinStableLayoutViewportOrigin(frameView-&gt;minStableLayoutViewportOrigin());
+    layerTransaction.setMaxStableLayoutViewportOrigin(frameView-&gt;maxStableLayoutViewportOrigin());
+
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     layerTransaction.setScaleWasSetByUIProcess(scaleWasSetByUIProcess());
</span><span class="cx">     layerTransaction.setMinimumScaleFactor(m_viewportConfiguration.minimumScale());
</span><span class="lines">@@ -3271,8 +3280,9 @@
</span><span class="cx">     layerTransaction.setViewportMetaTagCameFromImageDocument(m_viewportConfiguration.viewportArguments().type == ViewportArguments::ImageDocument);
</span><span class="cx">     layerTransaction.setAllowsUserScaling(allowsUserScaling());
</span><span class="cx"> #endif
</span><ins>+
</ins><span class="cx"> #if PLATFORM(MAC)
</span><del>-    layerTransaction.setScrollPosition(corePage()-&gt;mainFrame().view()-&gt;scrollPosition());
</del><ins>+    layerTransaction.setScrollPosition(frameView-&gt;scrollPosition());
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (208747 => 208748)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-11-15 20:55:29 UTC (rev 208747)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-11-15 21:06:06 UTC (rev 208748)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #import &quot;EditorState.h&quot;
</span><span class="cx"> #import &quot;GestureTypes.h&quot;
</span><span class="cx"> #import &quot;InteractionInformationAtPosition.h&quot;
</span><ins>+#import &quot;Logging.h&quot;
</ins><span class="cx"> #import &quot;PluginView.h&quot;
</span><span class="cx"> #import &quot;RemoteLayerTreeDrawingArea.h&quot;
</span><span class="cx"> #import &quot;UserData.h&quot;
</span><span class="lines">@@ -97,6 +98,7 @@
</span><span class="cx"> #import &lt;WebCore/StyleProperties.h&gt;
</span><span class="cx"> #import &lt;WebCore/TextIndicator.h&gt;
</span><span class="cx"> #import &lt;WebCore/TextIterator.h&gt;
</span><ins>+#import &lt;WebCore/TextStream.h&gt;
</ins><span class="cx"> #import &lt;WebCore/VisibleUnits.h&gt;
</span><span class="cx"> #import &lt;WebCore/WKContentObservation.h&gt;
</span><span class="cx"> #import &lt;WebCore/WebEvent.h&gt;
</span><span class="lines">@@ -3054,8 +3056,13 @@
</span><span class="cx">     frameView.setViewportIsStable(m_isInStableState);
</span><span class="cx">     frameView.setScrollVelocity(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.timestamp());
</span><span class="cx"> 
</span><del>-    if (m_isInStableState)
-        frameView.setCustomFixedPositionLayoutRect(enclosingIntRect(visibleContentRectUpdateInfo.customFixedPositionRect()));
</del><ins>+    LOG_WITH_STREAM(VisibleRects, stream &lt;&lt; &quot;WebPage::updateVisibleContentRects setting layoutViewportOverrideRect &quot; &lt;&lt; visibleContentRectUpdateInfo.customFixedPositionRect() &lt;&lt; &quot; stable &quot; &lt;&lt; m_isInStableState);
+    if (m_isInStableState) {
+        if (frameView.frame().settings().visualViewportEnabled())
+            frameView.setLayoutViewportOverrideRect(LayoutRect(visibleContentRectUpdateInfo.customFixedPositionRect()));
+        else
+            frameView.setCustomFixedPositionLayoutRect(enclosingIntRect(visibleContentRectUpdateInfo.customFixedPositionRect()));
+    }
</ins><span class="cx"> 
</span><span class="cx">     if (!visibleContentRectUpdateInfo.isChangingObscuredInsetsInteractively())
</span><span class="cx">         frameView.setCustomSizeForResizeEvent(expandedIntSize(visibleContentRectUpdateInfo.unobscuredRectInScrollViewCoordinates().size()));
</span></span></pre>
</div>
</div>

</body>
</html>