<!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>[210059] 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/210059">210059</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2016-12-21 09:33:05 -0800 (Wed, 21 Dec 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Fixed bars are positioned incorrectly when there are header and footer banners
https://bugs.webkit.org/show_bug.cgi?id=166302
rdar://problem/29727145
Reviewed by Tim Horton.
Source/WebCore:
The computation of the visual viewport was wrong in the presence of header and footer
banners. It needs to take into account the fact that "visibleContentRect" applies to the
scroll view contents, which includes header and footer (unscaled), and the potentially scaled
document, and we need to return a rectangle in unscaled document coordinates.
Make a static method in FrameView to do this computation, and call it from FrameView::visualViewportRect()
and ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition().
layoutViewportForScrollPosition() is only called on Mac, so remove the #ifdeffing related to scaling,
and pass in an unscaled scroll position.
Test: fast/visual-viewport/zoomed-fixed-header-and-footer.html
* page/FrameView.cpp:
(WebCore::FrameView::updateLayoutViewport):
(WebCore::FrameView::maxStableLayoutViewportOrigin):
(WebCore::FrameView::visibleDocumentRect):
(WebCore::FrameView::visualViewportRect):
* page/FrameView.h:
* page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
(WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition):
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollPositionWithoutContentEdgeConstraints):
LayoutTests:
* fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt: Added.
* fast/visual-viewport/zoomed-fixed-header-and-footer.html: Added.
* platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt: Added.
* tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTeststileddrawingscrollingfixedfourbarswithheaderandfooterexpectedtxt">trunk/LayoutTests/tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt</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="#trunkSourceWebCorepagescrollingScrollingTreeFrameScrollingNodecpp">trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingmacScrollingTreeFrameScrollingNodeMacmm">trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastvisualviewportzoomedfixedheaderandfooterexpectedtxt">trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastvisualviewportzoomedfixedheaderandfooterhtml">trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer.html</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorfastvisualviewportzoomedfixedheaderandfooterexpectedtxt">trunk/LayoutTests/platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/LayoutTests/ChangeLog        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-12-21 Simon Fraser <simon.fraser@apple.com>
+
+ Fixed bars are positioned incorrectly when there are header and footer banners
+ https://bugs.webkit.org/show_bug.cgi?id=166302
+ rdar://problem/29727145
+
+ Reviewed by Tim Horton.
+
+ * fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt: Added.
+ * fast/visual-viewport/zoomed-fixed-header-and-footer.html: Added.
+ * platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt: Added.
+ * tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt:
+
</ins><span class="cx"> 2016-12-20 Myles C. Maxfield <mmaxfield@apple.com>
</span><span class="cx">
</span><span class="cx"> Skia lighter wght variation looks bolder than regular
</span></span></pre></div>
<a id="trunkLayoutTestsfastvisualviewportzoomedfixedheaderandfooterexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt (0 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt        2016-12-21 17:33:05 UTC (rev 210059)
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+JSON.stringify(internals.layoutViewportRect()) is {"top":0,"right":785,"bottom":585,"left":0,"width":785,"height":585}
+JSON.stringify(internals.visualViewportRect()) is {"top":0,"right":392.5,"bottom":271,"left":0,"width":392.5,"height":271}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":785,"bottom":100,"left":0,"width":785,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":485,"right":785,"bottom":585,"left":0,"width":785,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":100,"bottom":585,"left":0,"width":100,"height":585}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":785,"bottom":585,"left":685,"width":100,"height":585}
+
+Scrolled to 475, 525
+JSON.stringify(internals.layoutViewportRect()) is {"top":211,"right":867.5,"bottom":796,"left":82.5,"width":785,"height":585}
+JSON.stringify(internals.visualViewportRect()) is {"top":503.5,"right":867.5,"bottom":796,"left":475,"width":392.5,"height":292.5}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":392.5,"bottom":-214,"left":-392.5,"width":785,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":171,"right":392.5,"bottom":271,"left":-392.5,"width":785,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":-292.5,"bottom":271,"left":-392.5,"width":100,"height":585}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":392.5,"bottom":271,"left":292.5,"width":100,"height":585}
+
+Scrolled to 100, 776
+JSON.stringify(internals.layoutViewportRect()) is {"top":462,"right":867.5,"bottom":1047,"left":82.5,"width":785,"height":585}
+JSON.stringify(internals.visualViewportRect()) is {"top":754.5,"right":492.5,"bottom":1047,"left":100,"width":392.5,"height":292.5}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":767.5,"bottom":-214,"left":-17.5,"width":785,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":171,"right":767.5,"bottom":271,"left":-17.5,"width":785,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":82.5,"bottom":271,"left":-17.5,"width":100,"height":585}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-314,"right":767.5,"bottom":271,"left":667.5,"width":100,"height":585}
+
+Scrolled to 50, 300
+JSON.stringify(internals.layoutViewportRect()) is {"top":278.5,"right":835,"bottom":863.5,"left":50,"width":785,"height":585}
+JSON.stringify(internals.visualViewportRect()) is {"top":278.5,"right":442.5,"bottom":571,"left":50,"width":392.5,"height":292.5}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-21.5,"right":785,"bottom":78.5,"left":0,"width":785,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":463.5,"right":785,"bottom":563.5,"left":0,"width":785,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-21.5,"right":100,"bottom":563.5,"left":0,"width":100,"height":585}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-21.5,"right":785,"bottom":563.5,"left":685,"width":100,"height":585}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastvisualviewportzoomedfixedheaderandfooterhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer.html (0 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer.html         (rev 0)
+++ trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer.html        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -0,0 +1,137 @@
</span><ins>+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ body {
+ height: 2000px;
+ width: 2000px;
+ }
+
+ .fixed {
+ position: fixed;
+ background-color: gray;
+ }
+
+ #top, #bottom {
+ width: 100%;
+ left: 0;
+ height: 100px;
+ }
+
+ #left, #right {
+ width: 100px;
+ top: 0;
+ height: 100%;
+ }
+
+ #top { top: 0; }
+ #bottom { bottom: 0; }
+
+ #left { left: 0; }
+ #right { right: 0; }
+ </style>
+ <script src="../../resources/js-test-pre.js"></script>
+ <script>
+ description("This test zooms and scrolls the page and checks the positions of fixed-position objects.");
+
+ if (window.internals) {
+ internals.setHeaderHeight(43);
+ internals.setFooterHeight(56);
+ internals.settings.setVisualViewportEnabled(true);
+ }
+
+ window.jsTestIsAsync = true;
+
+ var fixedElement;
+ function logFixedObject(objectID)
+ {
+ debug('client rect of ' + objectID + ':');
+ fixedElement = document.getElementById(objectID);
+ evalAndLogResult("JSON.stringify(fixedElement.getBoundingClientRect())");
+ }
+
+ function doAfterZooming()
+ {
+ // Zooming may scroll the view away from the origin.
+ window.scrollTo(0, 0);
+
+ evalAndLogResult("JSON.stringify(internals.layoutViewportRect())");
+ evalAndLogResult("JSON.stringify(internals.visualViewportRect())");
+
+ logFixedObject('top');
+ logFixedObject('bottom');
+ logFixedObject('left');
+ logFixedObject('right');
+
+ debug('');
+ window.scrollTo(475, 525);
+ debug('Scrolled to ' + window.scrollX + ', ' + window.scrollY);
+
+ evalAndLogResult("JSON.stringify(internals.layoutViewportRect())");
+ evalAndLogResult("JSON.stringify(internals.visualViewportRect())");
+
+ logFixedObject('top');
+ logFixedObject('bottom');
+ logFixedObject('left');
+ logFixedObject('right');
+
+ debug('');
+ window.scrollTo(100, 776);
+ debug('Scrolled to ' + window.scrollX + ', ' + window.scrollY);
+
+ evalAndLogResult("JSON.stringify(internals.layoutViewportRect())");
+ evalAndLogResult("JSON.stringify(internals.visualViewportRect())");
+
+ logFixedObject('top');
+ logFixedObject('bottom');
+ logFixedObject('left');
+ logFixedObject('right');
+
+ debug('');
+ window.scrollTo(50, 300);
+ debug('Scrolled to ' + window.scrollX + ', ' + window.scrollY);
+
+ evalAndLogResult("JSON.stringify(internals.layoutViewportRect())");
+ evalAndLogResult("JSON.stringify(internals.visualViewportRect())");
+
+ logFixedObject('top');
+ logFixedObject('bottom');
+ logFixedObject('left');
+ logFixedObject('right');
+
+ window.scrollTo(0, 0);
+
+ finishJSTest();
+ }
+
+ function getUIScript()
+ {
+ return `(function() {
+ uiController.zoomToScale(2, function() {
+ uiController.uiScriptComplete(uiController.zoomScale);
+ });
+ })();`;
+ }
+
+ function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ testRunner.runUIScript(getUIScript(), function(zoomScale) {
+ doAfterZooming();
+ });
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div id="top" class="fixed"></div>
+ <div id="bottom" class="fixed"></div>
+ <div id="left" class="fixed"></div>
+ <div id="right" class="fixed"></div>
+ <script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorfastvisualviewportzoomedfixedheaderandfooterexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt (0 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt         (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt        2016-12-21 17:33:05 UTC (rev 210059)
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+JSON.stringify(internals.layoutViewportRect()) is {"top":0,"right":800,"bottom":600,"left":0,"width":800,"height":600}
+JSON.stringify(internals.visualViewportRect()) is {"top":0,"right":400,"bottom":257,"left":0,"width":400,"height":257}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":800,"bottom":100,"left":0,"width":800,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":500,"right":800,"bottom":600,"left":0,"width":800,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":100,"bottom":600,"left":0,"width":100,"height":600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":0,"right":800,"bottom":600,"left":700,"width":100,"height":600}
+
+Scrolled to 475, 525
+JSON.stringify(internals.layoutViewportRect()) is {"top":0,"right":800,"bottom":600,"left":0,"width":800,"height":600}
+JSON.stringify(internals.visualViewportRect()) is {"top":482,"right":875,"bottom":782,"left":475,"width":400,"height":300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-525,"right":325,"bottom":-425,"left":-475,"width":800,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-25,"right":325,"bottom":75,"left":-475,"width":800,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-525,"right":-375,"bottom":75,"left":-475,"width":100,"height":600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-525,"right":325,"bottom":75,"left":225,"width":100,"height":600}
+
+Scrolled to 100, 776
+JSON.stringify(internals.layoutViewportRect()) is {"top":0,"right":800,"bottom":600,"left":0,"width":800,"height":600}
+JSON.stringify(internals.visualViewportRect()) is {"top":733,"right":500,"bottom":1033,"left":100,"width":400,"height":300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-776,"right":700,"bottom":-676,"left":-100,"width":800,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-276,"right":700,"bottom":-176,"left":-100,"width":800,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-776,"right":0,"bottom":-176,"left":-100,"width":100,"height":600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-776,"right":700,"bottom":-176,"left":600,"width":100,"height":600}
+
+Scrolled to 50, 300
+JSON.stringify(internals.layoutViewportRect()) is {"top":0,"right":800,"bottom":600,"left":0,"width":800,"height":600}
+JSON.stringify(internals.visualViewportRect()) is {"top":257,"right":450,"bottom":557,"left":50,"width":400,"height":300}
+client rect of top:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-300,"right":750,"bottom":-200,"left":-50,"width":800,"height":100}
+client rect of bottom:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":200,"right":750,"bottom":300,"left":-50,"width":800,"height":100}
+client rect of left:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-300,"right":50,"bottom":300,"left":-50,"width":100,"height":600}
+client rect of right:
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"top":-300,"right":750,"bottom":300,"left":650,"width":100,"height":600}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTeststileddrawingscrollingfixedfourbarswithheaderandfooterexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/LayoutTests/tiled-drawing/scrolling/fixed/four-bars-with-header-and-footer-expected.txt        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -2,29 +2,29 @@
</span><span class="cx"> (scrollable area size 785 600)
</span><span class="cx"> (contents size 785 2421)
</span><span class="cx"> (requested scroll position 0 200)
</span><del>- (layout viewport at (0,200) size 785x600)
</del><ins>+ (layout viewport at (0,100) size 785x600)
</ins><span class="cx"> (min layout viewport origin (0,0))
</span><del>- (max layout viewport origin (0,1821))
</del><ins>+ (max layout viewport origin (0,1621))
</ins><span class="cx"> (children 4
</span><span class="cx"> (Fixed node
</span><span class="cx"> (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
</span><del>- (viewport rect at last layout: 0.00 200.00 785.00 600.00)
- (layer position at last layout 0.00 200.00)
</del><ins>+ (viewport rect at last layout: 0.00 100.00 785.00 600.00)
+ (layer position at last layout 0.00 100.00)
</ins><span class="cx"> )
</span><span class="cx"> (Fixed node
</span><span class="cx"> (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
</span><del>- (viewport rect at last layout: 0.00 200.00 785.00 600.00)
- (layer position at last layout 6.00 396.00)
</del><ins>+ (viewport rect at last layout: 0.00 100.00 785.00 600.00)
+ (layer position at last layout 6.00 296.00)
</ins><span class="cx"> )
</span><span class="cx"> (Fixed node
</span><span class="cx"> (anchor edges: AnchorEdgeRight AnchorEdgeTop)
</span><del>- (viewport rect at last layout: 0.00 200.00 785.00 600.00)
- (layer position at last layout 597.00 396.00)
</del><ins>+ (viewport rect at last layout: 0.00 100.00 785.00 600.00)
+ (layer position at last layout 597.00 296.00)
</ins><span class="cx"> )
</span><span class="cx"> (Fixed node
</span><span class="cx"> (anchor edges: AnchorEdgeLeft AnchorEdgeBottom)
</span><del>- (viewport rect at last layout: 0.00 200.00 785.00 600.00)
- (layer position at last layout 0.00 712.00)
</del><ins>+ (viewport rect at last layout: 0.00 100.00 785.00 600.00)
+ (layer position at last layout 0.00 612.00)
</ins><span class="cx"> )
</span><span class="cx"> )
</span><span class="cx"> )
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/Source/WebCore/ChangeLog        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2016-12-21 Simon Fraser <simon.fraser@apple.com>
+
+ Fixed bars are positioned incorrectly when there are header and footer banners
+ https://bugs.webkit.org/show_bug.cgi?id=166302
+ rdar://problem/29727145
+
+ Reviewed by Tim Horton.
+
+ The computation of the visual viewport was wrong in the presence of header and footer
+ banners. It needs to take into account the fact that "visibleContentRect" applies to the
+ scroll view contents, which includes header and footer (unscaled), and the potentially scaled
+ document, and we need to return a rectangle in unscaled document coordinates.
+
+ Make a static method in FrameView to do this computation, and call it from FrameView::visualViewportRect()
+ and ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition().
+
+ layoutViewportForScrollPosition() is only called on Mac, so remove the #ifdeffing related to scaling,
+ and pass in an unscaled scroll position.
+
+ Test: fast/visual-viewport/zoomed-fixed-header-and-footer.html
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::updateLayoutViewport):
+ (WebCore::FrameView::maxStableLayoutViewportOrigin):
+ (WebCore::FrameView::visibleDocumentRect):
+ (WebCore::FrameView::visualViewportRect):
+ * page/FrameView.h:
+ * page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
+ (WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition):
+ * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+ (WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollPositionWithoutContentEdgeConstraints):
+
</ins><span class="cx"> 2016-12-21 Carlos Alberto Lopez Perez <clopez@igalia.com>
</span><span class="cx">
</span><span class="cx"> [CMake] Remove remaining INDIE_UI related entries.
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.cpp (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.cpp        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/Source/WebCore/page/FrameView.cpp        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -1876,7 +1876,7 @@
</span><span class="cx">
</span><span class="cx"> LayoutRect layoutViewport = layoutViewportRect();
</span><span class="cx">
</span><del>- LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport()");
</del><ins>+ LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport() totalContentSize " << totalContentsSize() << " unscaledDocumentRect " << (renderView() ? renderView()->unscaledDocumentRect() : IntRect()) << " header height " << headerHeight() << " footer height " << footerHeight());
</ins><span class="cx"> LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
</span><span class="cx"> LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewportRect());
</span><span class="cx"> LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << unscaledMinimumScrollPosition() << " max: "<< unscaledMaximumScrollPosition());
</span><span class="lines">@@ -1895,7 +1895,9 @@
</span><span class="cx">
</span><span class="cx"> LayoutPoint FrameView::maxStableLayoutViewportOrigin() const
</span><span class="cx"> {
</span><del>- return unscaledMaximumScrollPosition();
</del><ins>+ LayoutPoint maxPosition = unscaledMaximumScrollPosition();
+ maxPosition = (maxPosition - LayoutSize(0, headerHeight() + footerHeight())).expandedTo({ });
+ return maxPosition;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IntPoint FrameView::unscaledScrollOrigin() const
</span><span class="lines">@@ -1915,12 +1917,29 @@
</span><span class="cx"> return LayoutRect(m_layoutViewportOrigin, renderView() ? renderView()->size() : size());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+// visibleContentRect is in the bounds of the scroll view content. That consists of an
+// optional header, the document, and an optional footer. Only the document is scaled,
+// so we have to compute the visible part of the document in unscaled document coordinates.
+// On iOS, pageScaleFactor is always 1 here, and we never have headers and footers.
+LayoutRect FrameView::visibleDocumentRect(const FloatRect& visibleContentRect, float headerHeight, float footerHeight, const FloatSize& totalContentsSize, float pageScaleFactor)
+{
+ FloatRect visibleDocumentRect = visibleContentRect;
+
+ float contentsHeight = totalContentsSize.height() - headerHeight - footerHeight;
+
+ float visibleScaledDocumentTop = std::max<float>(visibleContentRect.y() - headerHeight, 0);
+ float visibleScaledDocumentBottom = std::min<float>(visibleContentRect.maxY() - headerHeight, contentsHeight);
+
+ visibleDocumentRect.setY(visibleScaledDocumentTop);
+ visibleDocumentRect.setHeight(std::max<float>(visibleScaledDocumentBottom - visibleScaledDocumentTop, 0));
+ visibleDocumentRect.scale(1 / pageScaleFactor);
+ return LayoutRect(visibleDocumentRect);
+}
+
</ins><span class="cx"> LayoutRect FrameView::visualViewportRect() const
</span><span class="cx"> {
</span><del>- // This isn't visibleContentRect(), because that uses a scaled scroll origin. Confused? Me too.
</del><span class="cx"> FloatRect visibleContentRect = this->visibleContentRect(LegacyIOSDocumentVisibleRect);
</span><del>- visibleContentRect.scale(1 / frameScaleFactor()); // Note that frameScaleFactor() returns 1 for delegated scrolling (e.g. iOS WK2)
- return LayoutRect(visibleContentRect);
</del><ins>+ return visibleDocumentRect(visibleContentRect, headerHeight(), footerHeight(), totalContentsSize(), frameScaleFactor());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.h (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.h        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/Source/WebCore/page/FrameView.h        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -268,6 +268,8 @@
</span><span class="cx"> // These are in document coordinates, unaffected by zooming.
</span><span class="cx"> WEBCORE_EXPORT LayoutRect layoutViewportRect() const;
</span><span class="cx"> WEBCORE_EXPORT LayoutRect visualViewportRect() const;
</span><ins>+
+ static LayoutRect visibleDocumentRect(const FloatRect& visibleContentRect, float headerHeight, float footerHeight, const FloatSize& totalContentsSize, float pageScaleFactor);
</ins><span class="cx">
</span><span class="cx"> // This is different than visibleContentRect() in that it ignores negative (or overly positive)
</span><span class="cx"> // offsets from rubber-banding, and it takes zooming into account.
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeFrameScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -102,21 +102,14 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(scrollingTree().visualViewportEnabled());
</span><span class="cx">
</span><del>- FloatSize visibleContentSize = scrollableAreaSize();
-#if PLATFORM(MAC)
- // On Mac, FrameView.visibleContentRect(), which was used to set scrollableAreaSize(), returns a rect with scale applied (so it's not really a "content rect"),
- // so we have to convert back to unscaled coordinates here.
- visibleContentSize.scale(1 / scale);
-#else
- UNUSED_PARAM(scale);
-#endif
- FloatRect visualViewport(visibleContentOrigin, visibleContentSize);
</del><ins>+ FloatRect visibleContentRect(visibleContentOrigin, scrollableAreaSize());
+ LayoutRect visualViewport(FrameView::visibleDocumentRect(visibleContentRect, headerHeight(), footerHeight(), totalContentsSize(), scale));
</ins><span class="cx"> LayoutRect layoutViewport(m_layoutViewport);
</span><span class="cx">
</span><span class="cx"> LOG_WITH_STREAM(Scrolling, stream << "\nScrolling thread: " << "(visibleContentOrigin " << visibleContentOrigin << ")");
</span><del>- LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
- LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewport);
- LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << minLayoutViewportOrigin() << " max: "<< maxLayoutViewportOrigin());
</del><ins>+ LOG_WITH_STREAM(Scrolling, stream << " layoutViewport: " << layoutViewport);
+ LOG_WITH_STREAM(Scrolling, stream << " visualViewport: " << visualViewport);
+ LOG_WITH_STREAM(Scrolling, stream << " scroll positions: min: " << minLayoutViewportOrigin() << " max: "<< maxLayoutViewportOrigin());
</ins><span class="cx">
</span><span class="cx"> LayoutPoint newLocation = FrameView::computeLayoutViewportOrigin(LayoutRect(visualViewport), LayoutPoint(minLayoutViewportOrigin()), LayoutPoint(maxLayoutViewportOrigin()), layoutViewport);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingmacScrollingTreeFrameScrollingNodeMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (210058 => 210059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm        2016-12-21 16:42:11 UTC (rev 210058)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm        2016-12-21 17:33:05 UTC (rev 210059)
</span><span class="lines">@@ -391,8 +391,6 @@
</span><span class="cx"> std::optional<FloatPoint> layoutViewportOrigin;
</span><span class="cx"> if (scrollingTree().visualViewportEnabled()) {
</span><span class="cx"> FloatPoint visibleContentOrigin = scrollPosition;
</span><del>- float counterScale = 1 / frameScaleFactor();
- visibleContentOrigin.scale(counterScale, counterScale);
</del><span class="cx"> FloatRect newLayoutViewport = layoutViewportForScrollPosition(visibleContentOrigin, frameScaleFactor());
</span><span class="cx"> setLayoutViewport(newLayoutViewport);
</span><span class="cx"> layoutViewportOrigin = newLayoutViewport.location();
</span></span></pre>
</div>
</div>
</body>
</html>