Diff
Modified: trunk/LayoutTests/ChangeLog (219667 => 219668)
--- trunk/LayoutTests/ChangeLog 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/ChangeLog 2017-07-20 00:15:08 UTC (rev 219668)
@@ -1,3 +1,28 @@
+2017-07-19 Simon Fraser <[email protected]>
+
+ getBoundingClientRects not updated for programmatic scrolls
+ https://bugs.webkit.org/show_bug.cgi?id=174538
+ rdar://problem/33049012
+
+ Reviewed by Tim Horton.
+
+ New results for these tests, reflecting the fact that programmatic scrolls now update
+ the layout viewport.
+
+ Clean up fast/dom/elementFromPoint-relative-to-viewport.html, and land an iOS expectation. The test
+ uses eventSender.zoomPageOut() which is not expected to work correctly on iOS. It works when tested
+ manually.
+
+ * fast/dom/elementFromPoint-relative-to-viewport-expected.txt:
+ * fast/dom/elementFromPoint-relative-to-viewport.html:
+ * platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt: Copied from LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt.
+ * platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt:
+ * platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt:
+ * platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt:
+ * platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt:
+ * platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt:
+ * platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
+
2017-07-19 Myles C. Maxfield <[email protected]>
Setting the minimum font size preference doesn’t affect absolute line-height values, so lines overlap
Modified: trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt (219667 => 219668)
--- trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -3,14 +3,21 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+Test Initial
PASS unscrolledBoxInitial is '0'
PASS scrolledDownBoxInitial is '5'
PASS scrolledRightBoxInitial is '3'
PASS scrolledDownAndRightBoxInitial is '8'
+
+Test Offscreen
PASS unscrolledBoxOffscreen is '0'
PASS scrolledDownBoxOffscreen is '5'
PASS scrolledRightBoxOffscreen is '3'
PASS scrolledDownAndRightBoxOffscreen is '8'
+Zoomed out
+
+Test Initial
PASS unscrolledBoxInitial is '0'
PASS scrolledDownBoxInitial is '5'
PASS scrolledRightBoxInitial is '3'
Modified: trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport.html (219667 => 219668)
--- trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport.html 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport.html 2017-07-20 00:15:08 UTC (rev 219668)
@@ -43,6 +43,8 @@
description('This test document.elementFromPoint is evaluated in with respect to the viewport, not the document.');
function testElement(element, label, offsetX, offsetY, hasZoom) {
+ debug('');
+ debug('Test ' + label);
for (var i = 0; i < 25; ++i) {
var item = document.createElement("div");
item.className = "testItem";
@@ -94,7 +96,9 @@
testElement(elementInitial, "Initial", offset.left, offset.top);
testElement(elementOffscreen, "Offscreen", offset.left, offset.top + 1100);
- eventSender.zoomPageOut();
+ if (window.eventSender)
+ eventSender.zoomPageOut();
+ debug('Zoomed out');
testElement(elementInitial, "Initial", offset.left, offset.top, /* hasZoom */ true);
if (window.testRunner) {
Modified: trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -15,7 +15,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 475, 525
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":225,"width":800,"height":600,"top":225,"right":875,"bottom":825,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":400,"height":300,"top":525,"right":875,"bottom":825,"left":475}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
@@ -27,7 +27,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 100, 776
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":476,"width":800,"height":600,"top":476,"right":875,"bottom":1076,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":400,"height":300,"top":776,"right":500,"bottom":1076,"left":100}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
@@ -39,7 +39,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 50, 300
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":300,"width":800,"height":600,"top":300,"right":850,"bottom":900,"left":50}
JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":400,"height":300,"top":300,"right":450,"bottom":600,"left":50}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
Modified: trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -15,7 +15,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 475, 525
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":182,"width":800,"height":600,"top":182,"right":875,"bottom":782,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":482,"width":400,"height":300,"top":482,"right":875,"bottom":782,"left":475}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
@@ -27,7 +27,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 100, 776
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":433,"width":800,"height":600,"top":433,"right":875,"bottom":1033,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":733,"width":400,"height":300,"top":733,"right":500,"bottom":1033,"left":100}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
@@ -39,7 +39,7 @@
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
Scrolled to 50, 300
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":257,"width":800,"height":600,"top":257,"right":850,"bottom":857,"left":50}
JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":257,"width":400,"height":300,"top":257,"right":450,"bottom":557,"left":50}
client rect of top:
JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
Copied: trunk/LayoutTests/platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt (from rev 219667, trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt) (0 => 219668)
--- trunk/LayoutTests/platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -0,0 +1,28 @@
+This test document.elementFromPoint is evaluated in with respect to the viewport, not the document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Test Initial
+PASS unscrolledBoxInitial is '0'
+PASS scrolledDownBoxInitial is '5'
+PASS scrolledRightBoxInitial is '3'
+PASS scrolledDownAndRightBoxInitial is '8'
+
+Test Offscreen
+PASS unscrolledBoxOffscreen is '0'
+PASS scrolledDownBoxOffscreen is '5'
+PASS scrolledRightBoxOffscreen is '3'
+PASS scrolledDownAndRightBoxOffscreen is '8'
+Zoomed out
+
+Test Initial
+PASS unscrolledBoxInitial is '0'
+PASS scrolledDownBoxInitial is '5'
+FAIL scrolledRightBoxInitial should be 3. Was 2.
+FAIL scrolledDownAndRightBoxInitial should be 8. Was 7.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Modified: trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -11,28 +11,28 @@
absolute client rect: 120, 100 - 50 x 25
Scrolled to 476, 526
-layoutViewport: 0, 0 - 800 x 600
+layoutViewport: 76, 226 - 800 x 600
visualViewportRect: 476, 526 - 400 x 300
fixed client bounds: 12, 10 - 30 x 20
fixed client rect: 12, 10 - 30 x 20
-absolute client bounds: 120, 100 - 50 x 25
-absolute client rect: 120, 100 - 50 x 25
+absolute client bounds: 44, -126 - 50 x 25
+absolute client rect: 44, -126 - 50 x 25
Scrolled to 100, 776
-layoutViewport: 0, 0 - 800 x 600
+layoutViewport: 76, 476 - 800 x 600
visualViewportRect: 100, 776 - 400 x 300
fixed client bounds: 12, 10 - 30 x 20
fixed client rect: 12, 10 - 30 x 20
-absolute client bounds: 120, 100 - 50 x 25
-absolute client rect: 120, 100 - 50 x 25
+absolute client bounds: 44, -376 - 50 x 25
+absolute client rect: 44, -376 - 50 x 25
Scrolled to 50, 300
-layoutViewport: 0, 0 - 800 x 600
+layoutViewport: 50, 300 - 800 x 600
visualViewportRect: 50, 300 - 400 x 300
fixed client bounds: 12, 10 - 30 x 20
fixed client rect: 12, 10 - 30 x 20
-absolute client bounds: 120, 100 - 50 x 25
-absolute client rect: 120, 100 - 50 x 25
+absolute client bounds: 70, -200 - 50 x 25
+absolute client rect: 70, -200 - 50 x 25
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -7,15 +7,15 @@
JSON.stringify(internals.visualViewportRect()) is {"x":0,"y":0,"width":400,"height":300,"top":0,"right":400,"bottom":300,"left":0}
Scrolled to -475, 525
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":-475,"y":225,"width":800,"height":600,"top":225,"right":325,"bottom":825,"left":-475}
JSON.stringify(internals.visualViewportRect()) is {"x":-475,"y":525,"width":400,"height":300,"top":525,"right":-75,"bottom":825,"left":-475}
Scrolled to -100, 776
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":-475,"y":476,"width":800,"height":600,"top":476,"right":325,"bottom":1076,"left":-475}
JSON.stringify(internals.visualViewportRect()) is {"x":-100,"y":776,"width":400,"height":300,"top":776,"right":300,"bottom":1076,"left":-100}
Scrolled to -50, 300
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":-450,"y":300,"width":800,"height":600,"top":300,"right":350,"bottom":900,"left":-450}
JSON.stringify(internals.visualViewportRect()) is {"x":-50,"y":300,"width":400,"height":300,"top":300,"right":350,"bottom":600,"left":-50}
PASS successfullyParsed is true
Modified: trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -3,12 +3,12 @@
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
+layer at (200,10) size 400x100
RenderBlock (positioned) {DIV} at (200,0) size 400x100 [bgcolor=#808080]
-layer at (200,500) size 400x100
+layer at (200,510) size 400x100
RenderBlock (positioned) {DIV} at (200,500) size 400x100 [bgcolor=#808080]
-layer at (0,150) size 100x300
+layer at (0,160) size 100x300
RenderBlock (positioned) {DIV} at (0,150) size 100x300 [bgcolor=#808080]
-layer at (700,150) size 100x300
+layer at (700,160) size 100x300
RenderBlock (positioned) {DIV} at (700,150) size 100x300 [bgcolor=#808080]
scrolled to 275,10
Modified: trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt (219667 => 219668)
--- trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt 2017-07-20 00:15:08 UTC (rev 219668)
@@ -7,15 +7,15 @@
JSON.stringify(internals.visualViewportRect()) is {"x":0,"y":0,"width":400,"height":300,"top":0,"right":400,"bottom":300,"left":0}
Scrolled to 475, 525
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":225,"width":800,"height":600,"top":225,"right":875,"bottom":825,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":400,"height":300,"top":525,"right":875,"bottom":825,"left":475}
Scrolled to 100, 776
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":476,"width":800,"height":600,"top":476,"right":875,"bottom":1076,"left":75}
JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":400,"height":300,"top":776,"right":500,"bottom":1076,"left":100}
Scrolled to 50, 300
-JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
+JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":300,"width":800,"height":600,"top":300,"right":850,"bottom":900,"left":50}
JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":400,"height":300,"top":300,"right":450,"bottom":600,"left":50}
PASS successfullyParsed is true
Modified: trunk/Source/WebCore/ChangeLog (219667 => 219668)
--- trunk/Source/WebCore/ChangeLog 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/ChangeLog 2017-07-20 00:15:08 UTC (rev 219668)
@@ -1,3 +1,96 @@
+2017-07-19 Simon Fraser <[email protected]>
+
+ getBoundingClientRects not updated for programmatic scrolls
+ https://bugs.webkit.org/show_bug.cgi?id=174538
+ rdar://problem/33049012
+
+ Reviewed by Tim Horton.
+
+ Baidu.com has two event handlers on its <input>, and both query the input location with getBoundingClientRect()
+ and the current pageYOffset (via jQuery), then try to scroll the input to the top of the screen. The bug is that
+ programmatic scrolls did not immediately update the layout viewport rect, so the second call to
+ getBoundingClientRect() would return stale coordinates, triggering an extra scroll.
+
+ To fix this, undo the fix for r219320 which tried to keep getBoundingClientRect() current during unstable scroll
+ updates by adding a shadow layout viewport rect. Instead, almost always update the layout viewport rect on
+ FrameView, even during unstable visible rect updates, but not if content insets are being changed interactively,
+ since changing viewport heights cause problems with bottom-fixed elements. Also, we need to compute a new layout
+ viewport rect in FrameView::updateLayoutViewport() for programmatic scrolls.
+
+ However, always updating the layout viewport triggered issues with the scrolling tree. The scrolling state tree
+ fossilizes layer positions relative to a specific viewport rect, and that relationship has to be maintained.
+ There are code paths that recompute fixed/sticky viewport constraints when the layout viewport has changed but
+ we haven't done layout or recomputed layer positions (e.g. updating viewport-constrained layers via
+ updateScrollCoordinatedLayersAfterFlush()) and in these cases using a new layout viewport for those computations
+ results in an inconsistent scrolling tree.
+
+ Fix this by not updating scrolling constraints every time we have to re-register scrolling nodes.
+ updateScrollCoordinatedLayersAfterFlush() only needs to update the layer on the scrolling node (to handle
+ tiled/non-tiled switches), so make updateScrollCoordinatedLayer() a little more fine-grained, and only update
+ constraints when we've just computed layer geometry. This allows for different scrolling nodes to have
+ constraints computed at different times, with different layout viewports, which happens.
+
+ Two additional fixes were required to make bottom-fixed bars behave correctly.
+
+ First, FrameView::computeLayoutViewportOrigin() had a bug where rounding of half-pixel values would cause it to
+ fall into the if (visualViewport.height() > layoutViewport.height()) clause, but then fail to clamp for
+ rubber-banding.
+
+ Second, the FrameView::unscaledMaximumScrollPosition() was wrong after zooming on iOS, since it uses visibleSize()
+ which is affected by page scale on iOS only (and the function wants scale-independent values). Fix with a hack that
+ should be cleaned up via webkit.org/b/174648.
+
+ Tested by existing tests.
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::computeUpdatedLayoutViewportRect):
+ (WebCore::FrameView::computeLayoutViewportOrigin):
+ (WebCore::FrameView::setLayoutViewportOverrideRect):
+ (WebCore::FrameView::updateLayoutViewport):
+ (WebCore::FrameView::unscaledMaximumScrollPosition):
+ (WebCore::FrameView::documentToClientOffset):
+ (WebCore::FrameView::setUnstableLayoutViewportRect): Deleted.
+ * page/FrameView.h:
+ * page/scrolling/AsyncScrollingCoordinator.cpp:
+ (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
+ (WebCore::AsyncScrollingCoordinator::reconcileScrollingState):
+ (WebCore::AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions):
+ (WebCore::AsyncScrollingCoordinator::updateNodeLayer):
+ (WebCore::AsyncScrollingCoordinator::updateNodeViewportConstraints):
+ (WebCore::AsyncScrollingCoordinator::updateViewportConstrainedNode): Deleted.
+ * page/scrolling/AsyncScrollingCoordinator.h:
+ * page/scrolling/ScrollingCoordinator.cpp:
+ (WebCore::operator<<):
+ * page/scrolling/ScrollingCoordinator.h:
+ (WebCore::ScrollingCoordinator::reconcileScrollingState):
+ (WebCore::ScrollingCoordinator::updateNodeLayer):
+ (WebCore::ScrollingCoordinator::updateNodeViewportConstraints):
+ (WebCore::ScrollingCoordinator::updateViewportConstrainedNode): Deleted.
+ * page/scrolling/ScrollingStateFixedNode.cpp:
+ (WebCore::ScrollingStateFixedNode::updateConstraints):
+ * page/scrolling/ScrollingStateStickyNode.cpp:
+ (WebCore::ScrollingStateStickyNode::updateConstraints):
+ (WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):
+ * page/scrolling/ScrollingTree.cpp:
+ (WebCore::ScrollingTree::commitTreeState):
+ * page/scrolling/mac/ScrollingTreeFixedNode.mm:
+ (WebCore::ScrollingTreeFixedNode::updateLayersAfterAncestorChange):
+ * page/scrolling/mac/ScrollingTreeStickyNode.mm:
+ (WebCore::ScrollingTreeStickyNode::updateLayersAfterAncestorChange):
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore::RenderLayerBacking::updateGeometry):
+ * rendering/RenderLayerCompositor.cpp:
+ (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush):
+ (WebCore::RenderLayerCompositor::updateBacking):
+ (WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged):
+ (WebCore::RenderLayerCompositor::requiresCompositingForPosition):
+ (WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus):
+ (WebCore::RenderLayerCompositor::computeFixedViewportConstraints):
+ (WebCore::RenderLayerCompositor::computeStickyViewportConstraints):
+ (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer):
+ (WebCore::RenderLayerCompositor::didAddScrollingLayer):
+ * rendering/RenderLayerCompositor.h:
+
2017-07-19 Megan Gardner <[email protected]>
Don't write file URLs to iOS Pasteboard
Modified: trunk/Source/WebCore/page/FrameView.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/FrameView.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/FrameView.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -1828,7 +1828,8 @@
layoutViewportRect.setSize(constrainedSize.expandedTo(unobscuredContentSize));
LayoutPoint layoutViewportOrigin = computeLayoutViewportOrigin(unobscuredContentRect, stableLayoutViewportOriginMin, stableLayoutViewportOriginMax, layoutViewportRect, StickToViewportBounds);
-
+
+ // FIXME: Is this equivalent to calling computeLayoutViewportOrigin() with StickToDocumentBounds?
if (constraint == LayoutViewportConstraint::ConstrainedToDocumentRect) {
// The max stable layout viewport origin really depends on the size of the layout viewport itself, so we need to adjust the location of the layout viewport one final time to make sure it does not end up out of bounds of the document.
// Without this adjustment (and with using the non-constrained unobscuredContentRect's size as the size of the layout viewport) the layout viewport can be pushed past the bounds of the document during rubber-banding, and cannot be pushed
@@ -1847,9 +1848,15 @@
LayoutPoint layoutViewportOrigin = layoutViewport.location();
bool allowRubberBanding = fixedBehavior == StickToViewportBounds;
- if (visualViewport.width() > layoutViewport.width())
+ if (visualViewport.width() > layoutViewport.width()) {
layoutViewportOrigin.setX(visualViewport.x());
- else {
+ if (!allowRubberBanding) {
+ if (layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
+ layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
+ else if (layoutViewportOrigin.x() > stableLayoutViewportOriginMax.x())
+ layoutViewportOrigin.setX(stableLayoutViewportOriginMax.x());
+ }
+ } else {
bool rubberbandingAtLeft = allowRubberBanding && visualViewport.x() < stableLayoutViewportOriginMin.x();
bool rubberbandingAtRight = allowRubberBanding && (visualViewport.maxX() - layoutViewport.width()) > stableLayoutViewportOriginMax.x();
@@ -1858,7 +1865,7 @@
if (visualViewport.maxX() > layoutViewport.maxX() || rubberbandingAtRight)
layoutViewportOrigin.setX(visualViewport.maxX() - layoutViewport.width());
-
+
if (!rubberbandingAtLeft && layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
@@ -1866,9 +1873,15 @@
layoutViewportOrigin.setX(stableLayoutViewportOriginMax.x());
}
- if (visualViewport.height() > layoutViewport.height())
+ if (visualViewport.height() > layoutViewport.height()) {
layoutViewportOrigin.setY(visualViewport.y());
- else {
+ if (!allowRubberBanding) {
+ if (layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
+ layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
+ else if (layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
+ layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
+ }
+ } else {
bool rubberbandingAtTop = allowRubberBanding && visualViewport.y() < stableLayoutViewportOriginMin.y();
bool rubberbandingAtBottom = allowRubberBanding && (visualViewport.maxY() - layoutViewport.height()) > stableLayoutViewportOriginMax.y();
@@ -1877,10 +1890,10 @@
if (visualViewport.maxY() > layoutViewport.maxY() || rubberbandingAtBottom)
layoutViewportOrigin.setY(visualViewport.maxY() - layoutViewport.height());
-
+
if (!rubberbandingAtTop && layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
-
+
if (!rubberbandingAtBottom && layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
}
@@ -1906,7 +1919,7 @@
}
}
-void FrameView::setLayoutViewportOverrideRect(std::optional<LayoutRect> rect)
+void FrameView::setLayoutViewportOverrideRect(std::optional<LayoutRect> rect, TriggerLayoutOrNot layoutTriggering)
{
if (rect == m_layoutViewportOverrideRect)
return;
@@ -1914,20 +1927,16 @@
LayoutRect oldRect = layoutViewportRect();
m_layoutViewportOverrideRect = rect;
- LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " setLayoutViewportOverrideRect() - changing layout viewport from " << oldRect << " to " << m_layoutViewportOverrideRect.value());
+ // Triggering layout on height changes is necessary to make bottom-fixed elements behave correctly.
+ if (oldRect.height() != layoutViewportRect().height())
+ layoutTriggering = TriggerLayoutOrNot::Yes;
- if (oldRect != layoutViewportRect())
+ LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " setLayoutViewportOverrideRect() - changing override layout viewport from " << oldRect << " to " << m_layoutViewportOverrideRect.value_or(LayoutRect()) << " layoutTriggering " << (layoutTriggering == TriggerLayoutOrNot::Yes ? "yes" : "no"));
+
+ if (oldRect != layoutViewportRect() && layoutTriggering == TriggerLayoutOrNot::Yes)
setViewportConstrainedObjectsNeedLayout();
}
-void FrameView::setUnstableLayoutViewportRect(std::optional<LayoutRect> rect)
-{
- if (rect == m_unstableLayoutViewportRect)
- return;
-
- m_unstableLayoutViewportRect = rect;
-}
-
LayoutSize FrameView::baseLayoutViewportSize() const
{
return renderView() ? renderView()->size() : size();
@@ -1942,11 +1951,6 @@
// as a post-layout task.
if (m_layoutPhase == InViewSizeAdjust)
return;
-
- if (m_layoutViewportOverrideRect) {
- LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport() - has layoutViewportOverrideRect" << m_layoutViewportOverrideRect.value());
- return;
- }
LayoutRect layoutViewport = layoutViewportRect();
@@ -1953,7 +1957,15 @@
LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport() totalContentSize " << totalContentsSize() << " unscaledDocumentRect " << (renderView() ? renderView()->unscaledDocumentRect() : IntRect()) << " header height " << headerHeight() << " footer height " << footerHeight() << " fixed behavior " << scrollBehaviorForFixedElements());
LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewportRect());
- LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << unscaledMinimumScrollPosition() << " max: "<< unscaledMaximumScrollPosition());
+ LOG_WITH_STREAM(Scrolling, stream << "stable origins: min: " << minStableLayoutViewportOrigin() << " max: "<< maxStableLayoutViewportOrigin());
+
+ if (m_layoutViewportOverrideRect) {
+ if (m_inProgrammaticScroll) {
+ LayoutPoint newOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, StickToDocumentBounds);
+ setLayoutViewportOverrideRect(LayoutRect(newOrigin, m_layoutViewportOverrideRect.value().size()));
+ }
+ return;
+ }
LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, scrollBehaviorForFixedElements());
if (newLayoutViewportOrigin != m_layoutViewportOrigin) {
@@ -2205,8 +2217,12 @@
if (RenderView* renderView = this->renderView()) {
IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
unscaledDocumentRect.expand(0, headerHeight() + footerHeight());
- ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize()).expandedTo({ 0, 0 });
-
+ IntSize visibleSize = this->visibleSize();
+#if PLATFORM(IOS)
+ // FIXME: visibleSize() is the unscaled size on macOS, but the scaled size on iOS. This should be consistent. webkit.org/b/174648.
+ visibleSize.scale(visibleContentScaleFactor());
+#endif
+ ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize).expandedTo({ 0, 0 });
if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
maximumPosition.setY(unscaledMinimumScrollPosition().y());
@@ -4915,12 +4931,7 @@
FloatSize FrameView::documentToClientOffset() const
{
- FloatSize clientOrigin;
-
- if (frame().settings().visualViewportEnabled())
- clientOrigin = -toFloatSize(m_unstableLayoutViewportRect ? m_unstableLayoutViewportRect.value().location() : layoutViewportRect().location());
- else
- clientOrigin = -toFloatSize(visibleContentRect().location());
+ FloatSize clientOrigin = frame().settings().visualViewportEnabled() ? -toFloatSize(layoutViewportRect().location()) : -toFloatSize(visibleContentRect().location());
// Layout and visual viewports are affected by page zoom, so we need to factor that out.
return clientOrigin.scaled(1 / frame().pageZoomFactor());
Modified: trunk/Source/WebCore/page/FrameView.h (219667 => 219668)
--- trunk/Source/WebCore/page/FrameView.h 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/FrameView.h 2017-07-20 00:15:08 UTC (rev 219668)
@@ -257,11 +257,7 @@
// If set, overrides the default "m_layoutViewportOrigin, size of initial containing block" rect.
// Used with delegated scrolling (i.e. iOS).
- WEBCORE_EXPORT void setLayoutViewportOverrideRect(std::optional<LayoutRect>);
- // If set, overrides m_layoutViewportOverrideRect. Only used during unstable scroll updates, so that "client" coordinates are
- // computed with an origin that changes along with the scroll position.
- // FIXME: This is ugly; would be better to be able to make setLayoutViewportOverrideRect() callable during unstable updates.
- WEBCORE_EXPORT void setUnstableLayoutViewportRect(std::optional<LayoutRect>);
+ WEBCORE_EXPORT void setLayoutViewportOverrideRect(std::optional<LayoutRect>, TriggerLayoutOrNot = TriggerLayoutOrNot::Yes);
// These are in document coordinates, unaffected by page scale (but affected by zooming).
WEBCORE_EXPORT LayoutRect layoutViewportRect() const;
@@ -846,7 +842,6 @@
LayoutPoint m_layoutViewportOrigin;
std::optional<LayoutRect> m_layoutViewportOverrideRect;
- std::optional<LayoutRect> m_unstableLayoutViewportRect;
unsigned m_deferSetNeedsLayoutCount;
bool m_setNeedsLayoutWasDeferred;
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -341,7 +341,7 @@
FrameView& frameView = *frameViewPtr;
if (scrollingNodeID == frameView.scrollLayerID()) {
- reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, programmaticScroll, true, scrollingLayerPositionAction);
+ reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, programmaticScroll, ViewportRectStability::Stable, scrollingLayerPositionAction);
#if PLATFORM(COCOA)
if (m_page->expectsWheelEventTriggers()) {
@@ -372,12 +372,12 @@
}
}
-void AsyncScrollingCoordinator::reconcileScrollingState(FrameView& frameView, const FloatPoint& scrollPosition, const LayoutViewportOriginOrOverrideRect& layoutViewportOriginOrOverrideRect, bool programmaticScroll, bool inStableState, ScrollingLayerPositionAction scrollingLayerPositionAction)
+void AsyncScrollingCoordinator::reconcileScrollingState(FrameView& frameView, const FloatPoint& scrollPosition, const LayoutViewportOriginOrOverrideRect& layoutViewportOriginOrOverrideRect, bool programmaticScroll, ViewportRectStability viewportRectStability, ScrollingLayerPositionAction scrollingLayerPositionAction)
{
bool oldProgrammaticScroll = frameView.inProgrammaticScroll();
frameView.setInProgrammaticScroll(programmaticScroll);
- LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator " << this << " reconcileScrollingState scrollPosition " << scrollPosition << " programmaticScroll " << programmaticScroll << " stable " << inStableState << " " << scrollingLayerPositionAction);
+ LOG_WITH_STREAM(Scrolling, stream << getpid() << " AsyncScrollingCoordinator " << this << " reconcileScrollingState scrollPosition " << scrollPosition << " programmaticScroll " << programmaticScroll << " stability " << viewportRectStability << " " << scrollingLayerPositionAction);
std::optional<FloatRect> layoutViewportRect;
@@ -385,20 +385,15 @@
[&frameView](std::optional<FloatPoint> origin) {
if (origin)
frameView.setBaseLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
- }, [&frameView, &layoutViewportRect, inStableState, visualViewportEnabled = visualViewportEnabled()](std::optional<FloatRect> overrideRect) {
+ }, [&frameView, &layoutViewportRect, viewportRectStability, visualViewportEnabled = visualViewportEnabled()](std::optional<FloatRect> overrideRect) {
if (!overrideRect)
return;
-
+
layoutViewportRect = overrideRect;
- if (visualViewportEnabled) {
- if (inStableState) {
- frameView.setLayoutViewportOverrideRect(LayoutRect(overrideRect.value()));
- frameView.setUnstableLayoutViewportRect(std::nullopt);
- } else
- frameView.setUnstableLayoutViewportRect(LayoutRect(layoutViewportRect.value()));
- }
+ if (visualViewportEnabled && viewportRectStability != ViewportRectStability::ChangingObscuredInsetsInteractively)
+ frameView.setLayoutViewportOverrideRect(LayoutRect(overrideRect.value()), viewportRectStability == ViewportRectStability::Stable ? FrameView::TriggerLayoutOrNot::Yes : FrameView::TriggerLayoutOrNot::No);
#if PLATFORM(IOS)
- else if (inStableState)
+ else if (viewportRectStability == ViewportRectStability::Stable)
frameView.setCustomFixedPositionLayoutRect(enclosingIntRect(overrideRect.value()));
#endif
}
@@ -410,7 +405,7 @@
frameView.setInProgrammaticScroll(oldProgrammaticScroll);
if (!programmaticScroll && scrollingLayerPositionAction != ScrollingLayerPositionAction::Set) {
- if (inStableState)
+ if (viewportRectStability == ViewportRectStability::Stable)
reconcileViewportConstrainedLayerPositions(frameView.rectForFixedPositionLayout(), scrollingLayerPositionAction);
else if (layoutViewportRect)
reconcileViewportConstrainedLayerPositions(LayoutRect(layoutViewportRect.value()), scrollingLayerPositionAction);
@@ -509,7 +504,7 @@
if (!children)
return;
- LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect);
+ LOG_WITH_STREAM(Scrolling, stream << getpid() << " AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect);
// FIXME: We'll have to traverse deeper into the tree at some point.
for (auto& child : *children)
@@ -568,22 +563,29 @@
}
}
-void AsyncScrollingCoordinator::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
+void AsyncScrollingCoordinator::updateNodeLayer(ScrollingNodeID nodeID, GraphicsLayer* graphicsLayer)
{
ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
if (!node)
return;
+ node->setLayer(graphicsLayer);
+}
+
+void AsyncScrollingCoordinator::updateNodeViewportConstraints(ScrollingNodeID nodeID, const ViewportConstraints& constraints)
+{
+ ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
+ if (!node)
+ return;
+
switch (constraints.constraintType()) {
case ViewportConstraints::FixedPositionConstraint: {
ScrollingStateFixedNode& fixedNode = downcast<ScrollingStateFixedNode>(*node);
- fixedNode.setLayer(graphicsLayer);
fixedNode.updateConstraints((const FixedPositionViewportConstraints&)constraints);
break;
}
case ViewportConstraints::StickyPositionConstraint: {
ScrollingStateStickyNode& stickyNode = downcast<ScrollingStateStickyNode>(*node);
- stickyNode.setLayer(graphicsLayer);
stickyNode.updateConstraints((const StickyPositionViewportConstraints&)constraints);
break;
}
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2017-07-20 00:15:08 UTC (rev 219668)
@@ -101,12 +101,13 @@
WEBCORE_EXPORT void detachFromStateTree(ScrollingNodeID) override;
WEBCORE_EXPORT void clearStateTree() override;
- WEBCORE_EXPORT void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) override;
+ WEBCORE_EXPORT void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) override;
+ WEBCORE_EXPORT void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) override;
WEBCORE_EXPORT void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, GraphicsLayer* counterScrollingLayer, GraphicsLayer* insetClipLayer, const ScrollingGeometry* = nullptr) override;
WEBCORE_EXPORT void updateOverflowScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, const ScrollingGeometry* = nullptr) override;
- WEBCORE_EXPORT void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool programmaticScroll, bool inStableState, ScrollingLayerPositionAction) override;
+ WEBCORE_EXPORT void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool programmaticScroll, ViewportRectStability, ScrollingLayerPositionAction) override;
bool isRubberBandInProgress() const override;
void setScrollPinningBehavior(ScrollPinningBehavior) override;
Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -31,7 +31,6 @@
#include "EventNames.h"
#include "FrameView.h"
#include "GraphicsLayer.h"
-#include "IntRect.h"
#include "MainFrame.h"
#include "Page.h"
#include "PlatformWheelEvent.h"
@@ -458,4 +457,20 @@
return ts;
}
+TextStream& operator<<(TextStream& ts, ViewportRectStability stability)
+{
+ switch (stability) {
+ case ViewportRectStability::Stable:
+ ts << "stable";
+ break;
+ case ViewportRectStability::Unstable:
+ ts << "unstable";
+ break;
+ case ViewportRectStability::ChangingObscuredInsetsInteractively:
+ ts << "changing obscured insets interactively";
+ break;
+ }
+ return ts;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2017-07-20 00:15:08 UTC (rev 219668)
@@ -112,6 +112,12 @@
}
};
+enum class ViewportRectStability {
+ Stable,
+ Unstable,
+ ChangingObscuredInsetsInteractively // This implies Unstable.
+};
+
class ScrollingCoordinator : public ThreadSafeRefCounted<ScrollingCoordinator> {
public:
static Ref<ScrollingCoordinator> create(Page*);
@@ -129,7 +135,7 @@
virtual void frameViewLayoutUpdated(FrameView&) { }
using LayoutViewportOriginOrOverrideRect = WTF::Variant<std::optional<FloatPoint>, std::optional<FloatRect>>;
- virtual void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool /* programmaticScroll */, bool /* inStableState*/, ScrollingLayerPositionAction) { }
+ virtual void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool /* programmaticScroll */, ViewportRectStability, ScrollingLayerPositionAction) { }
// Should be called whenever the slow repaint objects counter changes between zero and one.
void frameViewHasSlowRepaintObjectsDidChange(FrameView&);
@@ -159,8 +165,10 @@
virtual ScrollingNodeID attachToStateTree(ScrollingNodeType, ScrollingNodeID newNodeID, ScrollingNodeID /*parentID*/) { return newNodeID; }
virtual void detachFromStateTree(ScrollingNodeID) { }
virtual void clearStateTree() { }
- virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) { }
+ virtual void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) { }
+ virtual void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) { }
+
struct ScrollingGeometry {
FloatSize scrollableAreaSize;
FloatSize contentSize;
@@ -235,7 +243,7 @@
void updateSynchronousScrollingReasonsForAllFrames();
EventTrackingRegions absoluteEventTrackingRegionsForFrame(const Frame&) const;
-
+
bool m_forceSynchronousScrollLayerPositionUpdates { false };
};
@@ -242,6 +250,7 @@
WEBCORE_EXPORT TextStream& operator<<(TextStream&, ScrollableAreaParameters);
WEBCORE_EXPORT TextStream& operator<<(TextStream&, ScrollingNodeType);
WEBCORE_EXPORT TextStream& operator<<(TextStream&, ScrollingLayerPositionAction);
+WEBCORE_EXPORT TextStream& operator<<(TextStream&, ViewportRectStability);
} // namespace WebCore
Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -65,7 +65,7 @@
if (m_constraints == constraints)
return;
- LOG_WITH_STREAM(Scrolling, stream << "ScrollingStateFixedNode " << scrollingNodeID() << " updateConstraints with viewport rect " << constraints.viewportRectAtLastLayout());
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingStateFixedNode " << scrollingNodeID() << " updateConstraints with viewport rect " << constraints.viewportRectAtLastLayout() << " layer pos at last layout " << constraints.layerPositionAtLastLayout() << " offset from top " << (constraints.layerPositionAtLastLayout().y() - constraints.viewportRectAtLastLayout().y()));
m_constraints = constraints;
setPropertyChanged(ViewportConstraints);
Modified: trunk/Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -65,6 +65,8 @@
if (m_constraints == constraints)
return;
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingStateStickyNode " << scrollingNodeID() << " updateConstraints with constraining rect " << constraints.constrainingRectAtLastLayout() << " sticky offset " << constraints.stickyOffsetAtLastLayout() << " layer pos at last layout " << constraints.layerPositionAtLastLayout());
+
m_constraints = constraints;
setPropertyChanged(ViewportConstraints);
}
@@ -75,7 +77,7 @@
if (layer().representsGraphicsLayer()) {
GraphicsLayer* graphicsLayer = static_cast<GraphicsLayer*>(layer());
- LOG_WITH_STREAM(Compositing, stream << "ScrollingStateStickyNode::reconcileLayerPositionForViewportRect setting position of layer " << graphicsLayer->primaryLayerID() << " to " << position);
+ LOG_WITH_STREAM(Compositing, stream << "ScrollingStateStickyNode " << scrollingNodeID() << " reconcileLayerPositionForViewportRect " << action << " position of layer " << graphicsLayer->primaryLayerID() << " to " << position << " sticky offset " << m_constraints.stickyOffsetAtLastLayout());
switch (action) {
case ScrollingLayerPositionAction::Set:
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -119,6 +119,8 @@
{
bool rootStateNodeChanged = scrollingStateTree->hasNewRootStateNode();
+ LOG(Scrolling, "\nScrollingTree::commitTreeState");
+
ScrollingStateScrollingNode* rootNode = scrollingStateTree->rootStateNode();
if (rootNode
&& (rootStateNodeChanged
Modified: trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.cpp (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -72,16 +72,24 @@
m_scrollingStateTree->clear();
}
-void ScrollingCoordinatorCoordinatedGraphics::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
+void ScrollingCoordinatorCoordinatedGraphics::updateNodeLayer(ScrollingNodeID nodeID, GraphicsLayer* graphicsLayer)
{
ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
if (!node)
return;
+ node->setLayer(graphicsLayer);
+}
+
+void AsyncScrollingCoordinator::updateNodeViewportConstraints(ScrollingNodeID nodeID, const ViewportConstraints& constraints)
+{
+ ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
+ if (!node)
+ return;
+
switch (constraints.constraintType()) {
case ViewportConstraints::FixedPositionConstraint: {
downcast<CoordinatedGraphicsLayer>(*graphicsLayer).setFixedToViewport(true);
- downcast<ScrollingStateFixedNode>(*node).setLayer(graphicsLayer);
break;
}
case ViewportConstraints::StickyPositionConstraint:
Modified: trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.h (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.h 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.h 2017-07-20 00:15:08 UTC (rev 219668)
@@ -42,7 +42,8 @@
void detachFromStateTree(ScrollingNodeID) override;
void clearStateTree() override;
- void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) override;
+ void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) override;
+ void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) override;
void scrollableAreaScrollLayerDidChange(ScrollableArea&) override;
void willDestroyScrollableArea(ScrollableArea&) override;
Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm 2017-07-20 00:15:08 UTC (rev 219668)
@@ -28,6 +28,7 @@
#if ENABLE(ASYNC_SCROLLING)
+#include "Logging.h"
#include "ScrollingStateFixedNode.h"
#include "ScrollingTree.h"
#include "TextStream.h"
@@ -70,6 +71,9 @@
void ScrollingTreeFixedNode::updateLayersAfterAncestorChange(const ScrollingTreeNode& changedNode, const FloatRect& fixedPositionRect, const FloatSize& cumulativeDelta)
{
FloatPoint layerPosition = m_constraints.layerPositionForViewportRect(fixedPositionRect);
+
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeFixedNode " << scrollingNodeID() << " updateLayersAfterAncestorChange: new viewport " << fixedPositionRect << " viewportRectAtLastLayout " << m_constraints.viewportRectAtLastLayout() << " last layer pos " << m_constraints.layerPositionAtLastLayout() << " new offset from bottom " << (fixedPositionRect.maxY() - layerPosition.y()));
+
layerPosition -= cumulativeDelta;
CGRect layerBounds = [m_layer bounds];
Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeStickyNode.mm (219667 => 219668)
--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeStickyNode.mm 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeStickyNode.mm 2017-07-20 00:15:08 UTC (rev 219668)
@@ -28,6 +28,7 @@
#if ENABLE(ASYNC_SCROLLING)
+#include "Logging.h"
#include "ScrollingStateStickyNode.h"
#include "ScrollingTree.h"
#include "ScrollingTreeFrameScrollingNode.h"
@@ -82,6 +83,8 @@
adjustStickyLayer = true;
}
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeStickyNode " << scrollingNodeID() << " updateLayersAfterAncestorChange: new viewport " << fixedPositionRect << " constrainingRectAtLastLayout " << m_constraints.constrainingRectAtLastLayout() << " last layer pos " << m_constraints.layerPositionAtLastLayout() << " adjustStickyLayer " << adjustStickyLayer);
+
FloatSize deltaForDescendants = cumulativeDelta;
if (adjustStickyLayer) {
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (219667 => 219668)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -1206,7 +1206,7 @@
if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay())
setContentsNeedDisplay();
- compositor().updateScrollCoordinatedStatus(m_owningLayer);
+ compositor().updateScrollCoordinatedStatus(m_owningLayer, { RenderLayerCompositor::ScrollingNodeChangeFlags::Layer, RenderLayerCompositor::ScrollingNodeChangeFlags::LayerGeometry });
}
void RenderLayerBacking::updateAfterDescendants()
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (219667 => 219668)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2017-07-20 00:15:08 UTC (rev 219668)
@@ -492,7 +492,7 @@
#endif
for (auto* layer : m_scrollCoordinatedLayersNeedingUpdate)
- updateScrollCoordinatedStatus(*layer);
+ updateScrollCoordinatedStatus(*layer, ScrollingNodeChangeFlags::Layer);
m_scrollCoordinatedLayersNeedingUpdate.clear();
}
@@ -1024,7 +1024,7 @@
layer.ensureBacking();
if (layer.isRootLayer() && useCoordinatedScrollingForLayer(layer)) {
- updateScrollCoordinatedStatus(layer);
+ updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
#if ENABLE(RUBBER_BANDING)
@@ -1820,7 +1820,7 @@
return;
if (m_renderView.layer()->isComposited())
- updateScrollCoordinatedStatus(*m_renderView.layer());
+ updateScrollCoordinatedStatus(*m_renderView.layer(), ScrollingNodeChangeFlags::Layer);
}
String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
@@ -2825,7 +2825,7 @@
if (!viewBounds.intersects(enclosingIntRect(absoluteBounds))) {
if (viewportConstrainedNotCompositedReason)
*viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
- LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " bounds " << layerBounds << " outside visible rect " << viewBounds);
+ LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " bounds " << absoluteBounds << " outside visible rect " << viewBounds);
return false;
}
@@ -3673,7 +3673,7 @@
rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
}
-void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer)
+void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer, OptionSet<ScrollingNodeChangeFlags> changes)
{
LayerScrollCoordinationRoles coordinationRoles = 0;
if (isViewportConstrainedFixedOrStickyLayer(layer))
@@ -3686,7 +3686,7 @@
if (m_scrollCoordinatedLayers.add(&layer).isNewEntry)
m_subframeScrollLayersNeedReattach = true;
- updateScrollCoordinatedLayer(layer, coordinationRoles);
+ updateScrollCoordinatedLayer(layer, coordinationRoles, changes);
} else
removeFromScrollCoordinatedLayers(layer);
}
@@ -3709,11 +3709,10 @@
ASSERT(layer.isComposited());
GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
- LayoutRect viewportRect = m_renderView.frameView().rectForFixedPositionLayout();
FixedPositionViewportConstraints constraints;
constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
- constraints.setViewportRectAtLastLayout(viewportRect);
+ constraints.setViewportRectAtLastLayout(m_renderView.frameView().rectForFixedPositionLayout());
constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
const RenderStyle& style = layer.renderer().style();
@@ -3755,7 +3754,6 @@
renderer.computeStickyPositionConstraints(constraints, renderer.constrainingRectForStickyPosition());
GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
-
constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
constraints.setStickyOffsetAtLastLayout(renderer.stickyPositionOffset());
constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
@@ -3888,7 +3886,7 @@
scrollingCoordinator->updateFrameScrollingNode(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
}
-void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles reasons)
+void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles reasons, OptionSet<ScrollingNodeChangeFlags> changes)
{
ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
if (!scrollingCoordinator || !scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView()))
@@ -3919,7 +3917,7 @@
ScrollingNodeID parentNodeID = enclosingScrollingNodeID(layer, ExcludeSelf);
if (!parentNodeID && !isRootLayer)
return;
-
+
// Always call this even if the backing is already attached because the parent may have changed.
// If a node plays both roles, fixed/sticky is always the ancestor node of scrolling.
if (reasons & ViewportConstrained) {
@@ -3935,18 +3933,23 @@
if (!nodeID)
return;
- LOG(Compositing, "Registering ViewportConstrained scrolling node %" PRIu64 " (layer %" PRIu64 ") as child of %" PRIu64, nodeID, backing->graphicsLayer()->primaryLayerID(), parentNodeID);
+ LOG_WITH_STREAM(Compositing, stream << "Registering ViewportConstrained " << nodeType << " node " << nodeID << " (layer " << backing->graphicsLayer()->primaryLayerID() << ") as child of " << parentNodeID);
- switch (nodeType) {
- case FixedNode:
- scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
- break;
- case StickyNode:
- scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
- break;
- case FrameScrollingNode:
- case OverflowScrollingNode:
- break;
+ if (changes.contains(ScrollingNodeChangeFlags::Layer))
+ scrollingCoordinator->updateNodeLayer(nodeID, backing->graphicsLayer());
+
+ if (changes.contains(ScrollingNodeChangeFlags::LayerGeometry)) {
+ switch (nodeType) {
+ case FixedNode:
+ scrollingCoordinator->updateNodeViewportConstraints(nodeID, computeFixedViewportConstraints(layer));
+ break;
+ case StickyNode:
+ scrollingCoordinator->updateNodeViewportConstraints(nodeID, computeStickyViewportConstraints(layer));
+ break;
+ case FrameScrollingNode:
+ case OverflowScrollingNode:
+ break;
+ }
}
parentNodeID = nodeID;
@@ -4090,7 +4093,7 @@
void RenderLayerCompositor::didAddScrollingLayer(RenderLayer& layer)
{
- updateScrollCoordinatedStatus(layer);
+ updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
// For Coordinated Graphics.
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (219667 => 219668)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2017-07-20 00:15:08 UTC (rev 219668)
@@ -279,7 +279,12 @@
ScrollableArea* scrollableAreaForScrollLayerID(ScrollingNodeID) const;
- void updateScrollCoordinatedStatus(RenderLayer&);
+ enum class ScrollingNodeChangeFlags {
+ Layer = 1 << 0,
+ LayerGeometry = 1 << 1,
+ };
+
+ void updateScrollCoordinatedStatus(RenderLayer&, OptionSet<ScrollingNodeChangeFlags>);
void removeFromScrollCoordinatedLayers(RenderLayer&);
void willRemoveScrollingLayerWithBacking(RenderLayer&, RenderLayerBacking&);
@@ -443,7 +448,7 @@
void updateScrollCoordinationForThisFrame(ScrollingNodeID);
ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, ScrollingNodeID parentNodeID);
- void updateScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles);
+ void updateScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles, OptionSet<ScrollingNodeChangeFlags>);
void detachScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles);
void reattachSubframeScrollLayers();
Modified: trunk/Source/WebKit/ChangeLog (219667 => 219668)
--- trunk/Source/WebKit/ChangeLog 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebKit/ChangeLog 2017-07-20 00:15:08 UTC (rev 219668)
@@ -1,3 +1,16 @@
+2017-07-19 Simon Fraser <[email protected]>
+
+ getBoundingClientRects not updated for programmatic scrolls
+ https://bugs.webkit.org/show_bug.cgi?id=174538
+ rdar://problem/33049012
+
+ Reviewed by Tim Horton.
+
+ Feed ViewportRectStability and ScrollingLayerPositionAction into reconcileScrollingState().
+
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::updateVisibleContentRects):
+
2017-07-19 Brady Eidson <[email protected]>
iBooks sometimes crashes when closing a book.
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (219667 => 219668)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2017-07-19 23:59:22 UTC (rev 219667)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2017-07-20 00:15:08 UTC (rev 219668)
@@ -3268,8 +3268,19 @@
if (!visibleContentRectUpdateInfo.isChangingObscuredInsetsInteractively())
frameView.setCustomSizeForResizeEvent(expandedIntSize(visibleContentRectUpdateInfo.unobscuredRectInScrollViewCoordinates().size()));
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->reconcileScrollingState(frameView, scrollPosition, visibleContentRectUpdateInfo.customFixedPositionRect(), false, m_isInStableState, m_isInStableState ? ScrollingLayerPositionAction::Sync : ScrollingLayerPositionAction::SetApproximate);
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+ ViewportRectStability viewportStability = ViewportRectStability::Stable;
+ ScrollingLayerPositionAction layerAction = ScrollingLayerPositionAction::Sync;
+
+ if (visibleContentRectUpdateInfo.isChangingObscuredInsetsInteractively()) {
+ viewportStability = ViewportRectStability::ChangingObscuredInsetsInteractively;
+ layerAction = ScrollingLayerPositionAction::SetApproximate;
+ } else if (!m_isInStableState) {
+ viewportStability = ViewportRectStability::Unstable;
+ layerAction = ScrollingLayerPositionAction::SetApproximate;
+ }
+ scrollingCoordinator->reconcileScrollingState(frameView, scrollPosition, visibleContentRectUpdateInfo.customFixedPositionRect(), false, viewportStability, layerAction);
+ }
}
void WebPage::willStartUserTriggeredZooming()