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

Changeset 242601 in webkit


Ignore:
Timestamp:
Mar 7, 2019, 10:03:41 AM (7 years ago)
Author:
Simon Fraser
Message:

[iOS WK] REGRESSION (r242132): Fixed position banners flicker and move when scrolling (Apple, Tesla, YouTube, Reddit)
https://bugs.webkit.org/show_bug.cgi?id=195396
rdar://problem/48518959

Reviewed by Antti Koivisto.

r242132 introduced two issues that contributed to jumpiness of position:fixed layers when scrolling.

First, ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling() would early return if the scroll position
hadn't changed. It also needs to check the supplied layoutViewport (if any), but in some cases running the
notifyRelatedNodesAfterScrollPositionChange() code is necessary even without a scroll position change:
if the web process has committed new scrolling tree state (e.g. with new fixed constraints) since
the last call, we have to run the layer positioning code to have fixed layers re-adjust their position relative
to the root. This was the primary bug fix.

Secondly, a layer tree commit can give ScrollingTreeFrameScrollingNode a new layout viewport, but we need to
adjust this by the scrolling tree's current scroll position in case it gets used before the next scroll.

Currently no way to test this, as it's very timing-dependent.

  • page/scrolling/ScrollingTreeFrameScrollingNode.cpp:

(WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren):
(WebCore::ScrollingTreeFrameScrollingNode::scrollPositionAndLayoutViewportMatch):

  • page/scrolling/ScrollingTreeFrameScrollingNode.h:
  • page/scrolling/ScrollingTreeScrollingNode.cpp:

(WebCore::ScrollingTreeScrollingNode::scrollPositionAndLayoutViewportMatch):
(WebCore::ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling):

  • page/scrolling/ScrollingTreeScrollingNode.h:
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r242599 r242601  
     12019-03-07  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK] REGRESSION (r242132): Fixed position banners flicker and move when scrolling (Apple, Tesla, YouTube, Reddit)
     4        https://bugs.webkit.org/show_bug.cgi?id=195396
     5        rdar://problem/48518959
     6
     7        Reviewed by Antti Koivisto.
     8       
     9        r242132 introduced two issues that contributed to jumpiness of position:fixed layers when scrolling.
     10       
     11        First, ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling() would early return if the scroll position
     12        hadn't changed. It also needs to check the supplied layoutViewport (if any), but in some cases running the
     13        notifyRelatedNodesAfterScrollPositionChange() code is necessary even without a scroll position change:
     14        if the web process has committed new scrolling tree state (e.g. with new fixed constraints) since
     15        the last call, we have to run the layer positioning code to have fixed layers re-adjust their position relative
     16        to the root. This was the primary bug fix.
     17
     18        Secondly, a layer tree commit can give ScrollingTreeFrameScrollingNode a new layout viewport, but we need to
     19        adjust this by the scrolling tree's current scroll position in case it gets used before the next scroll.
     20
     21        Currently no way to test this, as it's very timing-dependent.
     22
     23        * page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
     24        (WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren):
     25        (WebCore::ScrollingTreeFrameScrollingNode::scrollPositionAndLayoutViewportMatch):
     26        * page/scrolling/ScrollingTreeFrameScrollingNode.h:
     27        * page/scrolling/ScrollingTreeScrollingNode.cpp:
     28        (WebCore::ScrollingTreeScrollingNode::scrollPositionAndLayoutViewportMatch):
     29        (WebCore::ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling):
     30        * page/scrolling/ScrollingTreeScrollingNode.h:
     31
    1322019-03-07  Youenn Fablet  <youenn@apple.com>
    233
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp

    r242132 r242601  
    7373        m_fixedElementsLayoutRelativeToFrame = state.fixedElementsLayoutRelativeToFrame();
    7474
    75     if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::LayoutViewport))
     75    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::LayoutViewport)) {
    7676        m_layoutViewport = state.layoutViewport();
     77        updateViewportForCurrentScrollPosition({ });
     78    }
    7779
    7880    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MinLayoutViewportOrigin))
     
    8183    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MaxLayoutViewportOrigin))
    8284        m_maxLayoutViewportOrigin = state.maxLayoutViewportOrigin();
     85}
     86
     87bool ScrollingTreeFrameScrollingNode::scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport)
     88{
     89    return position == currentScrollPosition() && (!overrideLayoutViewport || overrideLayoutViewport.value() == m_layoutViewport);
    8390}
    8491
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.h

    r242132 r242601  
    7171
    7272    WEBCORE_EXPORT void updateViewportForCurrentScrollPosition(Optional<FloatRect>) override;
     73    bool scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport) override;
    7374
    7475    void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const override;
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r242132 r242601  
    175175}
    176176
     177bool ScrollingTreeScrollingNode::scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect>)
     178{
     179    return position == m_currentScrollPosition;
     180}
     181
    177182void ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport)
    178183{
    179     if (position == m_currentScrollPosition)
    180         return;
     184    // Even if position and overrideLayoutViewport haven't changed for this node, other nodes may have received new constraint data
     185    // via a commit, so the call to notifyRelatedNodesAfterScrollPositionChange() is necessary. We could avoid this if we knew that
     186    // no commits had happened.
     187    bool scrollPositionChanged = !scrollPositionAndLayoutViewportMatch(position, overrideLayoutViewport);
    181188
    182189    m_currentScrollPosition = adjustedScrollPosition(position, ScrollPositionClamp::None);
     
    186193
    187194    scrollingTree().notifyRelatedNodesAfterScrollPositionChange(*this);
    188     scrollingTree().scrollingTreeNodeDidScroll(*this);
     195   
     196    if (scrollPositionChanged)
     197        scrollingTree().scrollingTreeNodeDidScroll(*this);
    189198}
    190199
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h

    r242132 r242601  
    9494    virtual void currentScrollPositionChanged();
    9595    WEBCORE_EXPORT virtual void updateViewportForCurrentScrollPosition(Optional<FloatRect> = { }) { }
     96    virtual bool scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport);
    9697
    9798    WEBCORE_EXPORT virtual void repositionScrollingLayers() { }
Note: See TracChangeset for help on using the changeset viewer.