⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 243539 in webkit


Ignore:
Timestamp:
Mar 27, 2019, 8:22:03 AM (7 years ago)
Author:
Simon Fraser
Message:

[iOS WK2] Fixed elements in frames can be misplaced sometimes
https://bugs.webkit.org/show_bug.cgi?id=196290

Reviewed by Frédéric Wang.

Source/WebCore:

In a page containing position:fixed inside an async-scrolling iframe, if the
main page is scrolled down, and you reload, then the fixed element in the iframe can
get misplaced or disappear.

The bug was that the reconcileViewportConstrainedLayerPositions() recursive state node
walk would cross frame boundaries, hitting subframe ScrollingStateFixedNodes with a viewport rect
for the main page.

Fix by giving ScrollingStateTree the responsibility for the recursive tree walk, and
have it bail at at frame boundaries.

Test: scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position.html

  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions):

  • page/scrolling/ScrollingStateFixedNode.cpp:

(WebCore::ScrollingStateFixedNode::reconcileLayerPositionForViewportRect):

  • page/scrolling/ScrollingStateNode.cpp:

(WebCore::ScrollingStateNode::reconcileLayerPositionForViewportRect): Deleted.

  • page/scrolling/ScrollingStateNode.h:

(WebCore::ScrollingStateNode::reconcileLayerPositionForViewportRect):

  • page/scrolling/ScrollingStateStickyNode.cpp:

(WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):

  • page/scrolling/ScrollingStateTree.cpp:

(WebCore::ScrollingStateTree::reconcileLayerPositionsRecursive):
(WebCore::ScrollingStateTree::reconcileViewportConstrainedLayerPositions):

  • page/scrolling/ScrollingStateTree.h:

LayoutTests:

  • scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position-expected.txt: Added.
  • scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position.html: Added.
Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243523 r243539  
     12019-03-26  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK2] Fixed elements in frames can be misplaced sometimes
     4        https://bugs.webkit.org/show_bug.cgi?id=196290
     5
     6        Reviewed by Frédéric Wang.
     7
     8        * scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position-expected.txt: Added.
     9        * scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position.html: Added.
     10
    1112019-03-26  Chris Dumez  <cdumez@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r243538 r243539  
     12019-03-26  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK2] Fixed elements in frames can be misplaced sometimes
     4        https://bugs.webkit.org/show_bug.cgi?id=196290
     5
     6        Reviewed by Frédéric Wang.
     7
     8        In a page containing position:fixed inside an async-scrolling iframe, if the
     9        main page is scrolled down, and you reload, then the fixed element in the iframe can
     10        get misplaced or disappear.
     11
     12        The bug was that the reconcileViewportConstrainedLayerPositions() recursive state node
     13        walk would cross frame boundaries, hitting subframe ScrollingStateFixedNodes with a viewport rect
     14        for the main page.
     15
     16        Fix by giving ScrollingStateTree the responsibility for the recursive tree walk, and
     17        have it bail at at frame boundaries.
     18
     19        Test: scrollingcoordinator/ios/fixed-in-frame-layer-reconcile-layer-position.html
     20
     21        * page/scrolling/AsyncScrollingCoordinator.cpp:
     22        (WebCore::AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions):
     23        * page/scrolling/ScrollingStateFixedNode.cpp:
     24        (WebCore::ScrollingStateFixedNode::reconcileLayerPositionForViewportRect):
     25        * page/scrolling/ScrollingStateNode.cpp:
     26        (WebCore::ScrollingStateNode::reconcileLayerPositionForViewportRect): Deleted.
     27        * page/scrolling/ScrollingStateNode.h:
     28        (WebCore::ScrollingStateNode::reconcileLayerPositionForViewportRect):
     29        * page/scrolling/ScrollingStateStickyNode.cpp:
     30        (WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):
     31        * page/scrolling/ScrollingStateTree.cpp:
     32        (WebCore::ScrollingStateTree::reconcileLayerPositionsRecursive):
     33        (WebCore::ScrollingStateTree::reconcileViewportConstrainedLayerPositions):
     34        * page/scrolling/ScrollingStateTree.h:
     35
    1362019-03-27  Philippe Normand  <pnormand@igalia.com>
    237
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r243416 r243539  
    540540void AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions(ScrollingNodeID scrollingNodeID, const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
    541541{
    542     auto* scrollingNode = m_scrollingStateTree->stateNodeForID(scrollingNodeID);
    543     if (!scrollingNode)
    544         return;
    545 
    546542    LOG_WITH_STREAM(Scrolling, stream << getCurrentProcessID() << " AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect << " and node " << scrollingNodeID);
    547543
    548     scrollingNode->reconcileLayerPositionForViewportRect(viewportRect, action);
     544    m_scrollingStateTree->reconcileViewportConstrainedLayerPositions(scrollingNodeID, viewportRect, action);
    549545}
    550546
  • trunk/Source/WebCore/page/scrolling/ScrollingStateFixedNode.cpp

    r240677 r243539  
    7878void ScrollingStateFixedNode::reconcileLayerPositionForViewportRect(const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
    7979{
    80     ScrollingStateNode::reconcileLayerPositionForViewportRect(viewportRect, action);
    81 
    8280    FloatPoint position = m_constraints.layerPositionForViewportRect(viewportRect);
    8381    if (layer().representsGraphicsLayer()) {
  • trunk/Source/WebCore/page/scrolling/ScrollingStateNode.cpp

    r240861 r243539  
    152152}
    153153
    154 void ScrollingStateNode::reconcileLayerPositionForViewportRect(const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
    155 {
    156     if (!m_children)
    157         return;
    158 
    159     for (auto& child : *m_children)
    160         child->reconcileLayerPositionForViewportRect(viewportRect, action);
    161 }
    162 
    163154void ScrollingStateNode::setLayer(const LayerRepresentation& layerRepresentation)
    164155{
  • trunk/Source/WebCore/page/scrolling/ScrollingStateNode.h

    r243129 r243539  
    218218    void setChangedProperties(ChangedProperties changedProperties) { m_changedProperties = changedProperties; }
    219219   
    220     virtual void reconcileLayerPositionForViewportRect(const LayoutRect& /*viewportRect*/, ScrollingLayerPositionAction);
     220    virtual void reconcileLayerPositionForViewportRect(const LayoutRect& /*viewportRect*/, ScrollingLayerPositionAction) { }
    221221
    222222    const LayerRepresentation& layer() const { return m_layer; }
  • trunk/Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp

    r240677 r243539  
    7878void ScrollingStateStickyNode::reconcileLayerPositionForViewportRect(const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
    7979{
    80     ScrollingStateNode::reconcileLayerPositionForViewportRect(viewportRect, action);
    81 
    8280    FloatPoint position = m_constraints.layerPositionForConstrainingRect(viewportRect);
    8381    if (layer().representsGraphicsLayer()) {
  • trunk/Source/WebCore/page/scrolling/ScrollingStateTree.cpp

    r242913 r243539  
    365365}
    366366
     367void ScrollingStateTree::reconcileLayerPositionsRecursive(ScrollingStateNode& currNode, const LayoutRect& layoutViewport, ScrollingLayerPositionAction action)
     368{
     369    currNode.reconcileLayerPositionForViewportRect(layoutViewport, action);
     370
     371    if (!currNode.children())
     372        return;
     373   
     374    for (auto& child : *currNode.children()) {
     375        // Never need to cross frame boundaries, since viewport rect reconciliation is per frame.
     376        if (is<ScrollingStateFrameScrollingNode>(child))
     377            continue;
     378
     379        reconcileLayerPositionsRecursive(*child, layoutViewport, action);
     380    }
     381}
     382
     383void ScrollingStateTree::reconcileViewportConstrainedLayerPositions(ScrollingNodeID scrollingNodeID, const LayoutRect& layoutViewport, ScrollingLayerPositionAction action)
     384{
     385    auto* scrollingNode = stateNodeForID(scrollingNodeID);
     386    if (!scrollingNode)
     387        return;
     388   
     389    reconcileLayerPositionsRecursive(*scrollingNode, layoutViewport, action);
     390}
     391
    367392} // namespace WebCore
    368393
  • trunk/Source/WebCore/page/scrolling/ScrollingStateTree.h

    r240677 r243539  
    7676    void setPreferredLayerRepresentation(LayerRepresentation::Type representation) { m_preferredLayerRepresentation = representation; }
    7777
     78    void reconcileViewportConstrainedLayerPositions(ScrollingNodeID, const LayoutRect& viewportRect, ScrollingLayerPositionAction);
     79
    7880private:
    7981    void setRootStateNode(Ref<ScrollingStateFrameScrollingNode>&&);
     
    8890    void removeNodeAndAllDescendants(ScrollingStateNode*);
    8991
    90     void recursiveNodeWillBeRemoved(ScrollingStateNode* currNode);
     92    void recursiveNodeWillBeRemoved(ScrollingStateNode*);
    9193    void willRemoveNode(ScrollingStateNode*);
     94
     95    void reconcileLayerPositionsRecursive(ScrollingStateNode&, const LayoutRect& viewportRect, ScrollingLayerPositionAction);
    9296
    9397    AsyncScrollingCoordinator* m_scrollingCoordinator;
Note: See TracChangeset for help on using the changeset viewer.