Changeset 219668 in webkit


Ignore:
Timestamp:
Jul 19, 2017 5:15:08 PM (7 years ago)
Author:
Simon Fraser
Message:

getBoundingClientRects not updated for programmatic scrolls
https://bugs.webkit.org/show_bug.cgi?id=174538
rdar://problem/33049012

Reviewed by Tim Horton.
Source/WebCore:

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:

Source/WebKit:

Feed ViewportRectStability and ScrollingLayerPositionAction into reconcileScrollingState().

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::updateVisibleContentRects):

LayoutTests:

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:
Location:
trunk
Files:
28 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r219665 r219668  
     12017-07-19  Simon Fraser  <simon.fraser@apple.com>
     2
     3        getBoundingClientRects not updated for programmatic scrolls
     4        https://bugs.webkit.org/show_bug.cgi?id=174538
     5        rdar://problem/33049012
     6
     7        Reviewed by Tim Horton.
     8       
     9        New results for these tests, reflecting the fact that programmatic scrolls now update
     10        the layout viewport.
     11       
     12        Clean up fast/dom/elementFromPoint-relative-to-viewport.html, and land an iOS expectation. The test
     13        uses eventSender.zoomPageOut() which is not expected to work correctly on iOS. It works when tested
     14        manually.
     15
     16        * fast/dom/elementFromPoint-relative-to-viewport-expected.txt:
     17        * fast/dom/elementFromPoint-relative-to-viewport.html:
     18        * platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt: Copied from LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt.
     19        * platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt:
     20        * platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt:
     21        * platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt:
     22        * platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt:
     23        * platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt:
     24        * platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
     25
    1262017-07-19  Myles C. Maxfield  <mmaxfield@apple.com>
    227
  • trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport-expected.txt

    r49990 r219668  
    44
    55
     6
     7Test Initial
    68PASS unscrolledBoxInitial is '0'
    79PASS scrolledDownBoxInitial is '5'
    810PASS scrolledRightBoxInitial is '3'
    911PASS scrolledDownAndRightBoxInitial is '8'
     12
     13Test Offscreen
    1014PASS unscrolledBoxOffscreen is '0'
    1115PASS scrolledDownBoxOffscreen is '5'
    1216PASS scrolledRightBoxOffscreen is '3'
    1317PASS scrolledDownAndRightBoxOffscreen is '8'
     18Zoomed out
     19
     20Test Initial
    1421PASS unscrolledBoxInitial is '0'
    1522PASS scrolledDownBoxInitial is '5'
  • trunk/LayoutTests/fast/dom/elementFromPoint-relative-to-viewport.html

    r155265 r219668  
    4444
    4545    function testElement(element, label, offsetX, offsetY, hasZoom) {
     46        debug('');
     47        debug('Test ' + label);
    4648        for (var i = 0; i < 25; ++i) {
    4749            var item = document.createElement("div");
     
    9597    testElement(elementOffscreen, "Offscreen", offset.left, offset.top + 1100);
    9698
    97     eventSender.zoomPageOut();
     99    if (window.eventSender)
     100        eventSender.zoomPageOut();
     101    debug('Zoomed out');
    98102    testElement(elementInitial, "Initial", offset.left, offset.top, /* hasZoom */ true);
    99103
  • trunk/LayoutTests/platform/ios-wk2/fast/dom/elementFromPoint-relative-to-viewport-expected.txt

    r219667 r219668  
    44
    55
     6
     7Test Initial
    68PASS unscrolledBoxInitial is '0'
    79PASS scrolledDownBoxInitial is '5'
    810PASS scrolledRightBoxInitial is '3'
    911PASS scrolledDownAndRightBoxInitial is '8'
     12
     13Test Offscreen
    1014PASS unscrolledBoxOffscreen is '0'
    1115PASS scrolledDownBoxOffscreen is '5'
    1216PASS scrolledRightBoxOffscreen is '3'
    1317PASS scrolledDownAndRightBoxOffscreen is '8'
     18Zoomed out
     19
     20Test Initial
    1421PASS unscrolledBoxInitial is '0'
    1522PASS scrolledDownBoxInitial is '5'
    16 PASS scrolledRightBoxInitial is '3'
    17 PASS scrolledDownAndRightBoxInitial is '8'
     23FAIL scrolledRightBoxInitial should be 3. Was 2.
     24FAIL scrolledDownAndRightBoxInitial should be 8. Was 7.
    1825PASS successfullyParsed is true
    1926
  • trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt

    r216803 r219668  
    1212
    1313Scrolled to 476, 526
    14 layoutViewport: 0, 0 - 800 x 600
     14layoutViewport: 76, 226 - 800 x 600
    1515visualViewportRect: 476, 526 - 400 x 300
    1616fixed client bounds: 12, 10 - 30 x 20
    1717fixed client rect: 12, 10 - 30 x 20
    18 absolute client bounds: 120, 100 - 50 x 25
    19 absolute client rect: 120, 100 - 50 x 25
     18absolute client bounds: 44, -126 - 50 x 25
     19absolute client rect: 44, -126 - 50 x 25
    2020
    2121Scrolled to 100, 776
    22 layoutViewport: 0, 0 - 800 x 600
     22layoutViewport: 76, 476 - 800 x 600
    2323visualViewportRect: 100, 776 - 400 x 300
    2424fixed client bounds: 12, 10 - 30 x 20
    2525fixed client rect: 12, 10 - 30 x 20
    26 absolute client bounds: 120, 100 - 50 x 25
    27 absolute client rect: 120, 100 - 50 x 25
     26absolute client bounds: 44, -376 - 50 x 25
     27absolute client rect: 44, -376 - 50 x 25
    2828
    2929Scrolled to 50, 300
    30 layoutViewport: 0, 0 - 800 x 600
     30layoutViewport: 50, 300 - 800 x 600
    3131visualViewportRect: 50, 300 - 400 x 300
    3232fixed client bounds: 12, 10 - 30 x 20
    3333fixed client rect: 12, 10 - 30 x 20
    34 absolute client bounds: 120, 100 - 50 x 25
    35 absolute client rect: 120, 100 - 50 x 25
     34absolute client bounds: 70, -200 - 50 x 25
     35absolute client rect: 70, -200 - 50 x 25
    3636PASS successfullyParsed is true
    3737
  • trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt

    r216025 r219668  
    88
    99Scrolled to -475, 525
    10 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     10JSON.stringify(internals.layoutViewportRect()) is {"x":-475,"y":225,"width":800,"height":600,"top":225,"right":325,"bottom":825,"left":-475}
    1111JSON.stringify(internals.visualViewportRect()) is {"x":-475,"y":525,"width":400,"height":300,"top":525,"right":-75,"bottom":825,"left":-475}
    1212
    1313Scrolled to -100, 776
    14 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     14JSON.stringify(internals.layoutViewportRect()) is {"x":-475,"y":476,"width":800,"height":600,"top":476,"right":325,"bottom":1076,"left":-475}
    1515JSON.stringify(internals.visualViewportRect()) is {"x":-100,"y":776,"width":400,"height":300,"top":776,"right":300,"bottom":1076,"left":-100}
    1616
    1717Scrolled to -50, 300
    18 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     18JSON.stringify(internals.layoutViewportRect()) is {"x":-450,"y":300,"width":800,"height":600,"top":300,"right":350,"bottom":900,"left":-450}
    1919JSON.stringify(internals.visualViewportRect()) is {"x":-50,"y":300,"width":400,"height":300,"top":300,"right":350,"bottom":600,"left":-50}
    2020PASS successfullyParsed is true
  • trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt

    r208748 r219668  
    44  RenderBlock {HTML} at (0,0) size 800x2016
    55    RenderBody {BODY} at (8,8) size 2000x2000
    6 layer at (200,0) size 400x100
     6layer at (200,10) size 400x100
    77  RenderBlock (positioned) {DIV} at (200,0) size 400x100 [bgcolor=#808080]
    8 layer at (200,500) size 400x100
     8layer at (200,510) size 400x100
    99  RenderBlock (positioned) {DIV} at (200,500) size 400x100 [bgcolor=#808080]
    10 layer at (0,150) size 100x300
     10layer at (0,160) size 100x300
    1111  RenderBlock (positioned) {DIV} at (0,150) size 100x300 [bgcolor=#808080]
    12 layer at (700,150) size 100x300
     12layer at (700,160) size 100x300
    1313  RenderBlock (positioned) {DIV} at (700,150) size 100x300 [bgcolor=#808080]
    1414scrolled to 275,10
  • trunk/LayoutTests/platform/ios-wk2/fast/visual-viewport/zoomed-rects-expected.txt

    r216025 r219668  
    88
    99Scrolled to 475, 525
    10 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     10JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":225,"width":800,"height":600,"top":225,"right":875,"bottom":825,"left":75}
    1111JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":400,"height":300,"top":525,"right":875,"bottom":825,"left":475}
    1212
    1313Scrolled to 100, 776
    14 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     14JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":476,"width":800,"height":600,"top":476,"right":875,"bottom":1076,"left":75}
    1515JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":400,"height":300,"top":776,"right":500,"bottom":1076,"left":100}
    1616
    1717Scrolled to 50, 300
    18 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     18JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":300,"width":800,"height":600,"top":300,"right":850,"bottom":900,"left":50}
    1919JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":400,"height":300,"top":300,"right":450,"bottom":600,"left":50}
    2020PASS successfullyParsed is true
  • trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt

    r216803 r219668  
    1616
    1717Scrolled to 475, 525
    18 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     18JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":225,"width":800,"height":600,"top":225,"right":875,"bottom":825,"left":75}
    1919JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":400,"height":300,"top":525,"right":875,"bottom":825,"left":475}
    2020client rect of top:
     
    2828
    2929Scrolled to 100, 776
    30 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     30JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":476,"width":800,"height":600,"top":476,"right":875,"bottom":1076,"left":75}
    3131JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":400,"height":300,"top":776,"right":500,"bottom":1076,"left":100}
    3232client rect of top:
     
    4040
    4141Scrolled to 50, 300
    42 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     42JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":300,"width":800,"height":600,"top":300,"right":850,"bottom":900,"left":50}
    4343JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":400,"height":300,"top":300,"right":450,"bottom":600,"left":50}
    4444client rect of top:
  • trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt

    r216803 r219668  
    1616
    1717Scrolled to 475, 525
    18 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     18JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":182,"width":800,"height":600,"top":182,"right":875,"bottom":782,"left":75}
    1919JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":482,"width":400,"height":300,"top":482,"right":875,"bottom":782,"left":475}
    2020client rect of top:
     
    2828
    2929Scrolled to 100, 776
    30 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     30JSON.stringify(internals.layoutViewportRect()) is {"x":75,"y":433,"width":800,"height":600,"top":433,"right":875,"bottom":1033,"left":75}
    3131JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":733,"width":400,"height":300,"top":733,"right":500,"bottom":1033,"left":100}
    3232client rect of top:
     
    4040
    4141Scrolled to 50, 300
    42 JSON.stringify(internals.layoutViewportRect()) is {"x":0,"y":0,"width":800,"height":600,"top":0,"right":800,"bottom":600,"left":0}
     42JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":257,"width":800,"height":600,"top":257,"right":850,"bottom":857,"left":50}
    4343JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":257,"width":400,"height":300,"top":257,"right":450,"bottom":557,"left":50}
    4444client rect of top:
  • trunk/Source/WebCore/ChangeLog

    r219666 r219668  
     12017-07-19  Simon Fraser  <simon.fraser@apple.com>
     2
     3        getBoundingClientRects not updated for programmatic scrolls
     4        https://bugs.webkit.org/show_bug.cgi?id=174538
     5        rdar://problem/33049012
     6
     7        Reviewed by Tim Horton.
     8
     9        Baidu.com has two event handlers on its <input>, and both query the input location with getBoundingClientRect()
     10        and the current pageYOffset (via jQuery), then try to scroll the input to the top of the screen. The bug is that
     11        programmatic scrolls did not immediately update the layout viewport rect, so the second call to
     12        getBoundingClientRect() would return stale coordinates, triggering an extra scroll.
     13
     14        To fix this, undo the fix for r219320 which tried to keep getBoundingClientRect() current during unstable scroll
     15        updates by adding a shadow layout viewport rect. Instead, almost always update the layout viewport rect on
     16        FrameView, even during unstable visible rect updates, but not if content insets are being changed interactively,
     17        since changing viewport heights cause problems with bottom-fixed elements. Also, we need to compute a new layout
     18        viewport rect in FrameView::updateLayoutViewport() for programmatic scrolls.
     19
     20        However, always updating the layout viewport triggered issues with the scrolling tree. The scrolling state tree
     21        fossilizes layer positions relative to a specific viewport rect, and that relationship has to be maintained.
     22        There are code paths that recompute fixed/sticky viewport constraints when the layout viewport has changed but
     23        we haven't done layout or recomputed layer positions (e.g. updating viewport-constrained layers via
     24        updateScrollCoordinatedLayersAfterFlush()) and in these cases using a new layout viewport for those computations
     25        results in an inconsistent scrolling tree.
     26
     27        Fix this by not updating scrolling constraints every time we have to re-register scrolling nodes.
     28        updateScrollCoordinatedLayersAfterFlush() only needs to update the layer on the scrolling node (to handle
     29        tiled/non-tiled switches), so make updateScrollCoordinatedLayer() a little more fine-grained, and only update
     30        constraints when we've just computed layer geometry. This allows for different scrolling nodes to have
     31        constraints computed at different times, with different layout viewports, which happens.
     32
     33        Two additional fixes were required to make bottom-fixed bars behave correctly.
     34
     35        First, FrameView::computeLayoutViewportOrigin() had a bug where rounding of half-pixel values would cause it to
     36        fall into the if (visualViewport.height() > layoutViewport.height()) clause, but then fail to clamp for
     37        rubber-banding.
     38       
     39        Second, the FrameView::unscaledMaximumScrollPosition() was wrong after zooming on iOS, since it uses visibleSize()
     40        which is affected by page scale on iOS only (and the function wants scale-independent values). Fix with a hack that
     41        should be cleaned up via webkit.org/b/174648.
     42
     43        Tested by existing tests.
     44
     45        * page/FrameView.cpp:
     46        (WebCore::FrameView::computeUpdatedLayoutViewportRect):
     47        (WebCore::FrameView::computeLayoutViewportOrigin):
     48        (WebCore::FrameView::setLayoutViewportOverrideRect):
     49        (WebCore::FrameView::updateLayoutViewport):
     50        (WebCore::FrameView::unscaledMaximumScrollPosition):
     51        (WebCore::FrameView::documentToClientOffset):
     52        (WebCore::FrameView::setUnstableLayoutViewportRect): Deleted.
     53        * page/FrameView.h:
     54        * page/scrolling/AsyncScrollingCoordinator.cpp:
     55        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
     56        (WebCore::AsyncScrollingCoordinator::reconcileScrollingState):
     57        (WebCore::AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions):
     58        (WebCore::AsyncScrollingCoordinator::updateNodeLayer):
     59        (WebCore::AsyncScrollingCoordinator::updateNodeViewportConstraints):
     60        (WebCore::AsyncScrollingCoordinator::updateViewportConstrainedNode): Deleted.
     61        * page/scrolling/AsyncScrollingCoordinator.h:
     62        * page/scrolling/ScrollingCoordinator.cpp:
     63        (WebCore::operator<<):
     64        * page/scrolling/ScrollingCoordinator.h:
     65        (WebCore::ScrollingCoordinator::reconcileScrollingState):
     66        (WebCore::ScrollingCoordinator::updateNodeLayer):
     67        (WebCore::ScrollingCoordinator::updateNodeViewportConstraints):
     68        (WebCore::ScrollingCoordinator::updateViewportConstrainedNode): Deleted.
     69        * page/scrolling/ScrollingStateFixedNode.cpp:
     70        (WebCore::ScrollingStateFixedNode::updateConstraints):
     71        * page/scrolling/ScrollingStateStickyNode.cpp:
     72        (WebCore::ScrollingStateStickyNode::updateConstraints):
     73        (WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):
     74        * page/scrolling/ScrollingTree.cpp:
     75        (WebCore::ScrollingTree::commitTreeState):
     76        * page/scrolling/mac/ScrollingTreeFixedNode.mm:
     77        (WebCore::ScrollingTreeFixedNode::updateLayersAfterAncestorChange):
     78        * page/scrolling/mac/ScrollingTreeStickyNode.mm:
     79        (WebCore::ScrollingTreeStickyNode::updateLayersAfterAncestorChange):
     80        * rendering/RenderLayerBacking.cpp:
     81        (WebCore::RenderLayerBacking::updateGeometry):
     82        * rendering/RenderLayerCompositor.cpp:
     83        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush):
     84        (WebCore::RenderLayerCompositor::updateBacking):
     85        (WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged):
     86        (WebCore::RenderLayerCompositor::requiresCompositingForPosition):
     87        (WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus):
     88        (WebCore::RenderLayerCompositor::computeFixedViewportConstraints):
     89        (WebCore::RenderLayerCompositor::computeStickyViewportConstraints):
     90        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer):
     91        (WebCore::RenderLayerCompositor::didAddScrollingLayer):
     92        * rendering/RenderLayerCompositor.h:
     93
    1942017-07-19  Megan Gardner  <megan_gardner@apple.com>
    295
  • trunk/Source/WebCore/page/FrameView.cpp

    r219645 r219668  
    18291829       
    18301830    LayoutPoint layoutViewportOrigin = computeLayoutViewportOrigin(unobscuredContentRect, stableLayoutViewportOriginMin, stableLayoutViewportOriginMax, layoutViewportRect, StickToViewportBounds);
    1831        
     1831
     1832    // FIXME: Is this equivalent to calling computeLayoutViewportOrigin() with StickToDocumentBounds?
    18321833    if (constraint == LayoutViewportConstraint::ConstrainedToDocumentRect) {
    18331834        // 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.
     
    18481849    bool allowRubberBanding = fixedBehavior == StickToViewportBounds;
    18491850
    1850     if (visualViewport.width() > layoutViewport.width())
     1851    if (visualViewport.width() > layoutViewport.width()) {
    18511852        layoutViewportOrigin.setX(visualViewport.x());
    1852     else {
     1853        if (!allowRubberBanding) {
     1854            if (layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
     1855                layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
     1856            else if (layoutViewportOrigin.x() > stableLayoutViewportOriginMax.x())
     1857                layoutViewportOrigin.setX(stableLayoutViewportOriginMax.x());
     1858        }
     1859    } else {
    18531860        bool rubberbandingAtLeft = allowRubberBanding && visualViewport.x() < stableLayoutViewportOriginMin.x();
    18541861        bool rubberbandingAtRight = allowRubberBanding && (visualViewport.maxX() - layoutViewport.width()) > stableLayoutViewportOriginMax.x();
     
    18591866        if (visualViewport.maxX() > layoutViewport.maxX() || rubberbandingAtRight)
    18601867            layoutViewportOrigin.setX(visualViewport.maxX() - layoutViewport.width());
    1861        
     1868
    18621869        if (!rubberbandingAtLeft && layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
    18631870            layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
     
    18671874    }
    18681875
    1869     if (visualViewport.height() > layoutViewport.height())
     1876    if (visualViewport.height() > layoutViewport.height()) {
    18701877        layoutViewportOrigin.setY(visualViewport.y());
    1871     else {
     1878        if (!allowRubberBanding) {
     1879            if (layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
     1880                layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
     1881            else if (layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
     1882                layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
     1883        }
     1884    } else {
    18721885        bool rubberbandingAtTop = allowRubberBanding && visualViewport.y() < stableLayoutViewportOriginMin.y();
    18731886        bool rubberbandingAtBottom = allowRubberBanding && (visualViewport.maxY() - layoutViewport.height()) > stableLayoutViewportOriginMax.y();
     
    18781891        if (visualViewport.maxY() > layoutViewport.maxY() || rubberbandingAtBottom)
    18791892            layoutViewportOrigin.setY(visualViewport.maxY() - layoutViewport.height());
    1880        
     1893
    18811894        if (!rubberbandingAtTop && layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
    18821895            layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
    1883        
     1896
    18841897        if (!rubberbandingAtBottom && layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
    18851898            layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
     
    19071920}
    19081921
    1909 void FrameView::setLayoutViewportOverrideRect(std::optional<LayoutRect> rect)
     1922void FrameView::setLayoutViewportOverrideRect(std::optional<LayoutRect> rect, TriggerLayoutOrNot layoutTriggering)
    19101923{
    19111924    if (rect == m_layoutViewportOverrideRect)
     
    19151928    m_layoutViewportOverrideRect = rect;
    19161929
    1917     LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " setLayoutViewportOverrideRect() - changing layout viewport from " << oldRect << " to " << m_layoutViewportOverrideRect.value());
    1918 
    1919     if (oldRect != layoutViewportRect())
     1930    // Triggering layout on height changes is necessary to make bottom-fixed elements behave correctly.
     1931    if (oldRect.height() != layoutViewportRect().height())
     1932        layoutTriggering = TriggerLayoutOrNot::Yes;
     1933
     1934    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"));
     1935
     1936    if (oldRect != layoutViewportRect() && layoutTriggering == TriggerLayoutOrNot::Yes)
    19201937        setViewportConstrainedObjectsNeedLayout();
    1921 }
    1922 
    1923 void FrameView::setUnstableLayoutViewportRect(std::optional<LayoutRect> rect)
    1924 {
    1925     if (rect == m_unstableLayoutViewportRect)
    1926         return;
    1927 
    1928     m_unstableLayoutViewportRect = rect;
    19291938}
    19301939
     
    19431952    if (m_layoutPhase == InViewSizeAdjust)
    19441953        return;
    1945    
    1946     if (m_layoutViewportOverrideRect) {
    1947         LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport() - has layoutViewportOverrideRect" << m_layoutViewportOverrideRect.value());
    1948         return;
    1949     }
    19501954
    19511955    LayoutRect layoutViewport = layoutViewportRect();
     
    19541958    LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
    19551959    LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewportRect());
    1956     LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << unscaledMinimumScrollPosition() << " max: "<< unscaledMaximumScrollPosition());
     1960    LOG_WITH_STREAM(Scrolling, stream << "stable origins: min: " << minStableLayoutViewportOrigin() << " max: "<< maxStableLayoutViewportOrigin());
     1961   
     1962    if (m_layoutViewportOverrideRect) {
     1963        if (m_inProgrammaticScroll) {
     1964            LayoutPoint newOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, StickToDocumentBounds);
     1965            setLayoutViewportOverrideRect(LayoutRect(newOrigin, m_layoutViewportOverrideRect.value().size()));
     1966        }
     1967        return;
     1968    }
    19571969
    19581970    LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, scrollBehaviorForFixedElements());
     
    22062218        IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
    22072219        unscaledDocumentRect.expand(0, headerHeight() + footerHeight());
    2208         ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize()).expandedTo({ 0, 0 });
    2209 
     2220        IntSize visibleSize = this->visibleSize();
     2221#if PLATFORM(IOS)
     2222        // FIXME: visibleSize() is the unscaled size on macOS, but the scaled size on iOS. This should be consistent. webkit.org/b/174648.
     2223        visibleSize.scale(visibleContentScaleFactor());
     2224#endif       
     2225        ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize).expandedTo({ 0, 0 });
    22102226        if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
    22112227            maximumPosition.setY(unscaledMinimumScrollPosition().y());
     
    49164932FloatSize FrameView::documentToClientOffset() const
    49174933{
    4918     FloatSize clientOrigin;
    4919    
    4920     if (frame().settings().visualViewportEnabled())
    4921         clientOrigin = -toFloatSize(m_unstableLayoutViewportRect ? m_unstableLayoutViewportRect.value().location() : layoutViewportRect().location());
    4922     else
    4923         clientOrigin = -toFloatSize(visibleContentRect().location());
     4934    FloatSize clientOrigin = frame().settings().visualViewportEnabled() ? -toFloatSize(layoutViewportRect().location()) : -toFloatSize(visibleContentRect().location());
    49244935
    49254936    // Layout and visual viewports are affected by page zoom, so we need to factor that out.
  • trunk/Source/WebCore/page/FrameView.h

    r219342 r219668  
    258258    // If set, overrides the default "m_layoutViewportOrigin, size of initial containing block" rect.
    259259    // Used with delegated scrolling (i.e. iOS).
    260     WEBCORE_EXPORT void setLayoutViewportOverrideRect(std::optional<LayoutRect>);
    261     // If set, overrides m_layoutViewportOverrideRect. Only used during unstable scroll updates, so that "client" coordinates are
    262     // computed with an origin that changes along with the scroll position.
    263     // FIXME: This is ugly; would be better to be able to make setLayoutViewportOverrideRect() callable during unstable updates.
    264     WEBCORE_EXPORT void setUnstableLayoutViewportRect(std::optional<LayoutRect>);
     260    WEBCORE_EXPORT void setLayoutViewportOverrideRect(std::optional<LayoutRect>, TriggerLayoutOrNot = TriggerLayoutOrNot::Yes);
    265261
    266262    // These are in document coordinates, unaffected by page scale (but affected by zooming).
     
    847843    LayoutPoint m_layoutViewportOrigin;
    848844    std::optional<LayoutRect> m_layoutViewportOverrideRect;
    849     std::optional<LayoutRect> m_unstableLayoutViewportRect;
    850845
    851846    unsigned m_deferSetNeedsLayoutCount;
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r219320 r219668  
    342342
    343343    if (scrollingNodeID == frameView.scrollLayerID()) {
    344         reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, programmaticScroll, true, scrollingLayerPositionAction);
     344        reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, programmaticScroll, ViewportRectStability::Stable, scrollingLayerPositionAction);
    345345
    346346#if PLATFORM(COCOA)
     
    373373}
    374374
    375 void AsyncScrollingCoordinator::reconcileScrollingState(FrameView& frameView, const FloatPoint& scrollPosition, const LayoutViewportOriginOrOverrideRect& layoutViewportOriginOrOverrideRect, bool programmaticScroll, bool inStableState, ScrollingLayerPositionAction scrollingLayerPositionAction)
     375void AsyncScrollingCoordinator::reconcileScrollingState(FrameView& frameView, const FloatPoint& scrollPosition, const LayoutViewportOriginOrOverrideRect& layoutViewportOriginOrOverrideRect, bool programmaticScroll, ViewportRectStability viewportRectStability, ScrollingLayerPositionAction scrollingLayerPositionAction)
    376376{
    377377    bool oldProgrammaticScroll = frameView.inProgrammaticScroll();
    378378    frameView.setInProgrammaticScroll(programmaticScroll);
    379379
    380     LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator " << this << " reconcileScrollingState scrollPosition " << scrollPosition << " programmaticScroll " << programmaticScroll << " stable " << inStableState << " " << scrollingLayerPositionAction);
     380    LOG_WITH_STREAM(Scrolling, stream << getpid() << " AsyncScrollingCoordinator " << this << " reconcileScrollingState scrollPosition " << scrollPosition << " programmaticScroll " << programmaticScroll << " stability " << viewportRectStability << " " << scrollingLayerPositionAction);
    381381
    382382    std::optional<FloatRect> layoutViewportRect;
     
    386386            if (origin)
    387387                frameView.setBaseLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
    388         }, [&frameView, &layoutViewportRect, inStableState, visualViewportEnabled = visualViewportEnabled()](std::optional<FloatRect> overrideRect) {
     388        }, [&frameView, &layoutViewportRect, viewportRectStability, visualViewportEnabled = visualViewportEnabled()](std::optional<FloatRect> overrideRect) {
    389389            if (!overrideRect)
    390390                return;
    391        
     391
    392392            layoutViewportRect = overrideRect;
    393             if (visualViewportEnabled) {
    394                 if (inStableState) {
    395                     frameView.setLayoutViewportOverrideRect(LayoutRect(overrideRect.value()));
    396                     frameView.setUnstableLayoutViewportRect(std::nullopt);
    397                 } else
    398                     frameView.setUnstableLayoutViewportRect(LayoutRect(layoutViewportRect.value()));
    399             }
     393            if (visualViewportEnabled && viewportRectStability != ViewportRectStability::ChangingObscuredInsetsInteractively)
     394                frameView.setLayoutViewportOverrideRect(LayoutRect(overrideRect.value()), viewportRectStability == ViewportRectStability::Stable ? FrameView::TriggerLayoutOrNot::Yes : FrameView::TriggerLayoutOrNot::No);
    400395#if PLATFORM(IOS)
    401             else if (inStableState)
     396            else if (viewportRectStability == ViewportRectStability::Stable)
    402397                frameView.setCustomFixedPositionLayoutRect(enclosingIntRect(overrideRect.value()));
    403398#endif
     
    411406
    412407    if (!programmaticScroll && scrollingLayerPositionAction != ScrollingLayerPositionAction::Set) {
    413         if (inStableState)
     408        if (viewportRectStability == ViewportRectStability::Stable)
    414409            reconcileViewportConstrainedLayerPositions(frameView.rectForFixedPositionLayout(), scrollingLayerPositionAction);
    415410        else if (layoutViewportRect)
     
    510505        return;
    511506
    512     LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect);
     507    LOG_WITH_STREAM(Scrolling, stream << getpid() << " AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect);
    513508
    514509    // FIXME: We'll have to traverse deeper into the tree at some point.
     
    569564}
    570565
    571 void AsyncScrollingCoordinator::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
     566void AsyncScrollingCoordinator::updateNodeLayer(ScrollingNodeID nodeID, GraphicsLayer* graphicsLayer)
     567{
     568    ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
     569    if (!node)
     570        return;
     571
     572    node->setLayer(graphicsLayer);
     573}
     574
     575void AsyncScrollingCoordinator::updateNodeViewportConstraints(ScrollingNodeID nodeID, const ViewportConstraints& constraints)
    572576{
    573577    ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
     
    578582    case ViewportConstraints::FixedPositionConstraint: {
    579583        ScrollingStateFixedNode& fixedNode = downcast<ScrollingStateFixedNode>(*node);
    580         fixedNode.setLayer(graphicsLayer);
    581584        fixedNode.updateConstraints((const FixedPositionViewportConstraints&)constraints);
    582585        break;
     
    584587    case ViewportConstraints::StickyPositionConstraint: {
    585588        ScrollingStateStickyNode& stickyNode = downcast<ScrollingStateStickyNode>(*node);
    586         stickyNode.setLayer(graphicsLayer);
    587589        stickyNode.updateConstraints((const StickyPositionViewportConstraints&)constraints);
    588590        break;
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h

    r217737 r219668  
    102102    WEBCORE_EXPORT void clearStateTree() override;
    103103   
    104     WEBCORE_EXPORT void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) override;
     104    WEBCORE_EXPORT void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) override;
     105    WEBCORE_EXPORT void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) override;
    105106   
    106107    WEBCORE_EXPORT void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, GraphicsLayer* counterScrollingLayer, GraphicsLayer* insetClipLayer, const ScrollingGeometry* = nullptr) override;
    107108    WEBCORE_EXPORT void updateOverflowScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, const ScrollingGeometry* = nullptr) override;
    108109   
    109     WEBCORE_EXPORT void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool programmaticScroll, bool inStableState, ScrollingLayerPositionAction) override;
     110    WEBCORE_EXPORT void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool programmaticScroll, ViewportRectStability, ScrollingLayerPositionAction) override;
    110111
    111112    bool isRubberBandInProgress() const override;
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp

    r219301 r219668  
    3232#include "FrameView.h"
    3333#include "GraphicsLayer.h"
    34 #include "IntRect.h"
    3534#include "MainFrame.h"
    3635#include "Page.h"
     
    459458}
    460459
     460TextStream& operator<<(TextStream& ts, ViewportRectStability stability)
     461{
     462    switch (stability) {
     463    case ViewportRectStability::Stable:
     464        ts << "stable";
     465        break;
     466    case ViewportRectStability::Unstable:
     467        ts << "unstable";
     468        break;
     469    case ViewportRectStability::ChangingObscuredInsetsInteractively:
     470        ts << "changing obscured insets interactively";
     471        break;
     472    }
     473    return ts;
     474}
     475
    461476} // namespace WebCore
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h

    r219301 r219668  
    113113};
    114114
     115enum class ViewportRectStability {
     116    Stable,
     117    Unstable,
     118    ChangingObscuredInsetsInteractively // This implies Unstable.
     119};
     120
    115121class ScrollingCoordinator : public ThreadSafeRefCounted<ScrollingCoordinator> {
    116122public:
     
    130136
    131137    using LayoutViewportOriginOrOverrideRect = WTF::Variant<std::optional<FloatPoint>, std::optional<FloatRect>>;
    132     virtual void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool /* programmaticScroll */, bool /* inStableState*/, ScrollingLayerPositionAction) { }
     138    virtual void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, bool /* programmaticScroll */, ViewportRectStability, ScrollingLayerPositionAction) { }
    133139
    134140    // Should be called whenever the slow repaint objects counter changes between zero and one.
     
    160166    virtual void detachFromStateTree(ScrollingNodeID) { }
    161167    virtual void clearStateTree() { }
    162     virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) { }
     168
     169    virtual void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) { }
     170    virtual void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) { }
    163171
    164172    struct ScrollingGeometry {
     
    236244
    237245    EventTrackingRegions absoluteEventTrackingRegionsForFrame(const Frame&) const;
    238    
     246
    239247    bool m_forceSynchronousScrollLayerPositionUpdates { false };
    240248};
     
    243251WEBCORE_EXPORT TextStream& operator<<(TextStream&, ScrollingNodeType);
    244252WEBCORE_EXPORT TextStream& operator<<(TextStream&, ScrollingLayerPositionAction);
     253WEBCORE_EXPORT TextStream& operator<<(TextStream&, ViewportRectStability);
    245254
    246255} // namespace WebCore
  • trunk/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp

    r219320 r219668  
    6666        return;
    6767
    68     LOG_WITH_STREAM(Scrolling, stream << "ScrollingStateFixedNode " << scrollingNodeID() << " updateConstraints with viewport rect " << constraints.viewportRectAtLastLayout());
     68    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()));
    6969
    7070    m_constraints = constraints;
  • trunk/Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp

    r216478 r219668  
    6666        return;
    6767
     68    LOG_WITH_STREAM(Scrolling, stream << "ScrollingStateStickyNode " << scrollingNodeID() << " updateConstraints with constraining rect " << constraints.constrainingRectAtLastLayout() << " sticky offset " << constraints.stickyOffsetAtLastLayout() << " layer pos at last layout " << constraints.layerPositionAtLastLayout());
     69
    6870    m_constraints = constraints;
    6971    setPropertyChanged(ViewportConstraints);
     
    7678        GraphicsLayer* graphicsLayer = static_cast<GraphicsLayer*>(layer());
    7779
    78         LOG_WITH_STREAM(Compositing, stream << "ScrollingStateStickyNode::reconcileLayerPositionForViewportRect setting position of layer " << graphicsLayer->primaryLayerID() << " to " << position);
     80        LOG_WITH_STREAM(Compositing, stream << "ScrollingStateStickyNode " << scrollingNodeID() << " reconcileLayerPositionForViewportRect " << action << " position of layer " << graphicsLayer->primaryLayerID() << " to " << position << " sticky offset " << m_constraints.stickyOffsetAtLastLayout());
    7981       
    8082        switch (action) {
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp

    r211033 r219668  
    120120    bool rootStateNodeChanged = scrollingStateTree->hasNewRootStateNode();
    121121   
     122    LOG(Scrolling, "\nScrollingTree::commitTreeState");
     123   
    122124    ScrollingStateScrollingNode* rootNode = scrollingStateTree->rootStateNode();
    123125    if (rootNode
  • trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.cpp

    r216130 r219668  
    7373}
    7474
    75 void ScrollingCoordinatorCoordinatedGraphics::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
     75void ScrollingCoordinatorCoordinatedGraphics::updateNodeLayer(ScrollingNodeID nodeID, GraphicsLayer* graphicsLayer)
     76{
     77    ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
     78    if (!node)
     79        return;
     80
     81    node->setLayer(graphicsLayer);
     82}
     83
     84void AsyncScrollingCoordinator::updateNodeViewportConstraints(ScrollingNodeID nodeID, const ViewportConstraints& constraints)
    7685{
    7786    ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
     
    8291    case ViewportConstraints::FixedPositionConstraint: {
    8392        downcast<CoordinatedGraphicsLayer>(*graphicsLayer).setFixedToViewport(true);
    84         downcast<ScrollingStateFixedNode>(*node).setLayer(graphicsLayer);
    8593        break;
    8694    }
  • trunk/Source/WebCore/page/scrolling/coordinatedgraphics/ScrollingCoordinatorCoordinatedGraphics.h

    r216130 r219668  
    4343    void clearStateTree() override;
    4444
    45     void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) override;
     45    void updateNodeLayer(ScrollingNodeID, GraphicsLayer*) override;
     46    void updateNodeViewportConstraints(ScrollingNodeID, const ViewportConstraints&) override;
    4647
    4748    void scrollableAreaScrollLayerDidChange(ScrollableArea&) override;
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFixedNode.mm

    r218915 r219668  
    2929#if ENABLE(ASYNC_SCROLLING)
    3030
     31#include "Logging.h"
    3132#include "ScrollingStateFixedNode.h"
    3233#include "ScrollingTree.h"
     
    7172{
    7273    FloatPoint layerPosition = m_constraints.layerPositionForViewportRect(fixedPositionRect);
     74
     75    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()));
     76
    7377    layerPosition -= cumulativeDelta;
    7478
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeStickyNode.mm

    r208666 r219668  
    2929#if ENABLE(ASYNC_SCROLLING)
    3030
     31#include "Logging.h"
    3132#include "ScrollingStateStickyNode.h"
    3233#include "ScrollingTree.h"
     
    8384    }
    8485
     86    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeStickyNode " << scrollingNodeID() << " updateLayersAfterAncestorChange: new viewport " << fixedPositionRect << " constrainingRectAtLastLayout " << m_constraints.constrainingRectAtLastLayout() << " last layer pos " << m_constraints.layerPositionAtLastLayout() << " adjustStickyLayer " << adjustStickyLayer);
     87
    8588    FloatSize deltaForDescendants = cumulativeDelta;
    8689
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r219620 r219668  
    12071207        setContentsNeedDisplay();
    12081208
    1209     compositor().updateScrollCoordinatedStatus(m_owningLayer);
     1209    compositor().updateScrollCoordinatedStatus(m_owningLayer, { RenderLayerCompositor::ScrollingNodeChangeFlags::Layer, RenderLayerCompositor::ScrollingNodeChangeFlags::LayerGeometry });
    12101210}
    12111211
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r219620 r219668  
    493493
    494494    for (auto* layer : m_scrollCoordinatedLayersNeedingUpdate)
    495         updateScrollCoordinatedStatus(*layer);
     495        updateScrollCoordinatedStatus(*layer, ScrollingNodeChangeFlags::Layer);
    496496
    497497    m_scrollCoordinatedLayersNeedingUpdate.clear();
     
    10251025
    10261026            if (layer.isRootLayer() && useCoordinatedScrollingForLayer(layer)) {
    1027                 updateScrollCoordinatedStatus(layer);
     1027                updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
    10281028                if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
    10291029                    scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
     
    18211821
    18221822    if (m_renderView.layer()->isComposited())
    1823         updateScrollCoordinatedStatus(*m_renderView.layer());
     1823        updateScrollCoordinatedStatus(*m_renderView.layer(), ScrollingNodeChangeFlags::Layer);
    18241824}
    18251825
     
    28262826        if (viewportConstrainedNotCompositedReason)
    28272827            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
    2828         LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " bounds " << layerBounds << " outside visible rect " << viewBounds);
     2828        LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " bounds " << absoluteBounds << " outside visible rect " << viewBounds);
    28292829        return false;
    28302830    }
     
    36743674}
    36753675
    3676 void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer)
     3676void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer, OptionSet<ScrollingNodeChangeFlags> changes)
    36773677{
    36783678    LayerScrollCoordinationRoles coordinationRoles = 0;
     
    36873687            m_subframeScrollLayersNeedReattach = true;
    36883688
    3689         updateScrollCoordinatedLayer(layer, coordinationRoles);
     3689        updateScrollCoordinatedLayer(layer, coordinationRoles, changes);
    36903690    } else
    36913691        removeFromScrollCoordinatedLayers(layer);
     
    37103710
    37113711    GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
    3712     LayoutRect viewportRect = m_renderView.frameView().rectForFixedPositionLayout();
    37133712
    37143713    FixedPositionViewportConstraints constraints;
    37153714    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
    3716     constraints.setViewportRectAtLastLayout(viewportRect);
     3715    constraints.setViewportRectAtLastLayout(m_renderView.frameView().rectForFixedPositionLayout());
    37173716    constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
    37183717
     
    37563755
    37573756    GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
    3758 
    37593757    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
    37603758    constraints.setStickyOffsetAtLastLayout(renderer.stickyPositionOffset());
     
    38893887}
    38903888
    3891 void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles reasons)
     3889void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles reasons, OptionSet<ScrollingNodeChangeFlags> changes)
    38923890{
    38933891    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
     
    39203918    if (!parentNodeID && !isRootLayer)
    39213919        return;
    3922    
     3920
    39233921    // Always call this even if the backing is already attached because the parent may have changed.
    39243922    // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling.
     
    39363934            return;
    39373935           
    3938         LOG(Compositing, "Registering ViewportConstrained scrolling node %" PRIu64 " (layer %" PRIu64 ") as child of %" PRIu64, nodeID, backing->graphicsLayer()->primaryLayerID(), parentNodeID);
    3939 
    3940         switch (nodeType) {
    3941         case FixedNode:
    3942             scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
    3943             break;
    3944         case StickyNode:
    3945             scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
    3946             break;
    3947         case FrameScrollingNode:
    3948         case OverflowScrollingNode:
    3949             break;
     3936        LOG_WITH_STREAM(Compositing, stream << "Registering ViewportConstrained " << nodeType << " node " << nodeID << " (layer " << backing->graphicsLayer()->primaryLayerID() << ") as child of " << parentNodeID);
     3937
     3938        if (changes.contains(ScrollingNodeChangeFlags::Layer))
     3939            scrollingCoordinator->updateNodeLayer(nodeID, backing->graphicsLayer());
     3940
     3941        if (changes.contains(ScrollingNodeChangeFlags::LayerGeometry)) {
     3942            switch (nodeType) {
     3943            case FixedNode:
     3944                scrollingCoordinator->updateNodeViewportConstraints(nodeID, computeFixedViewportConstraints(layer));
     3945                break;
     3946            case StickyNode:
     3947                scrollingCoordinator->updateNodeViewportConstraints(nodeID, computeStickyViewportConstraints(layer));
     3948                break;
     3949            case FrameScrollingNode:
     3950            case OverflowScrollingNode:
     3951                break;
     3952            }
    39503953        }
    39513954       
     
    40914094void RenderLayerCompositor::didAddScrollingLayer(RenderLayer& layer)
    40924095{
    4093     updateScrollCoordinatedStatus(layer);
     4096    updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
    40944097
    40954098    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r219620 r219668  
    280280    ScrollableArea* scrollableAreaForScrollLayerID(ScrollingNodeID) const;
    281281
    282     void updateScrollCoordinatedStatus(RenderLayer&);
     282    enum class ScrollingNodeChangeFlags {
     283        Layer           = 1 << 0,
     284        LayerGeometry   = 1 << 1,
     285    };
     286
     287    void updateScrollCoordinatedStatus(RenderLayer&, OptionSet<ScrollingNodeChangeFlags>);
    283288    void removeFromScrollCoordinatedLayers(RenderLayer&);
    284289
     
    444449    void updateScrollCoordinationForThisFrame(ScrollingNodeID);
    445450    ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, ScrollingNodeID parentNodeID);
    446     void updateScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles);
     451    void updateScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles, OptionSet<ScrollingNodeChangeFlags>);
    447452    void detachScrollCoordinatedLayer(RenderLayer&, LayerScrollCoordinationRoles);
    448453    void reattachSubframeScrollLayers();
  • trunk/Source/WebKit/ChangeLog

    r219664 r219668  
     12017-07-19  Simon Fraser  <simon.fraser@apple.com>
     2
     3        getBoundingClientRects not updated for programmatic scrolls
     4        https://bugs.webkit.org/show_bug.cgi?id=174538
     5        rdar://problem/33049012
     6
     7        Reviewed by Tim Horton.
     8       
     9        Feed ViewportRectStability and ScrollingLayerPositionAction into reconcileScrollingState().
     10
     11        * WebProcess/WebPage/ios/WebPageIOS.mm:
     12        (WebKit::WebPage::updateVisibleContentRects):
     13
    1142017-07-19  Brady Eidson  <beidson@apple.com>
    215
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r219594 r219668  
    32693269        frameView.setCustomSizeForResizeEvent(expandedIntSize(visibleContentRectUpdateInfo.unobscuredRectInScrollViewCoordinates().size()));
    32703270
    3271     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
    3272         scrollingCoordinator->reconcileScrollingState(frameView, scrollPosition, visibleContentRectUpdateInfo.customFixedPositionRect(), false, m_isInStableState, m_isInStableState ? ScrollingLayerPositionAction::Sync : ScrollingLayerPositionAction::SetApproximate);
     3271    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
     3272        ViewportRectStability viewportStability = ViewportRectStability::Stable;
     3273        ScrollingLayerPositionAction layerAction = ScrollingLayerPositionAction::Sync;
     3274       
     3275        if (visibleContentRectUpdateInfo.isChangingObscuredInsetsInteractively()) {
     3276            viewportStability = ViewportRectStability::ChangingObscuredInsetsInteractively;
     3277            layerAction = ScrollingLayerPositionAction::SetApproximate;
     3278        } else if (!m_isInStableState) {
     3279            viewportStability = ViewportRectStability::Unstable;
     3280            layerAction = ScrollingLayerPositionAction::SetApproximate;
     3281        }
     3282        scrollingCoordinator->reconcileScrollingState(frameView, scrollPosition, visibleContentRectUpdateInfo.customFixedPositionRect(), false, viewportStability, layerAction);
     3283    }
    32733284}
    32743285
Note: See TracChangeset for help on using the changeset viewer.