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

Changeset 267673 in webkit


Ignore:
Timestamp:
Sep 27, 2020, 1:00:14 PM (6 years ago)
Author:
Alan Coon
Message:

Cherry-pick r267002. rdar://problem/69594199

Overflow:scroll rubberbanding is interrupted by post-layout scrolling
https://bugs.webkit.org/show_bug.cgi?id=216463
<rdar://problem/67095741>

Reviewed by Darin Adler.

When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
clamp the scroll offset, causing the rubberband to collapse which interferes with
the user interaction. This happend on Gmail when composing a reply.

Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
and isScrollSnapInProgress() work.

This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
was just based on when the timer was started and stopped, which did not match the
implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
correctly notifies its clients when the rubberbanding state changes by updating that
state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.

Source/WebCore:

I tried to make tests for this, but the timing of wheel and scroll event delivery makes
reliable detection of interrupted rubberbands impossible in WebKitTestRunner.

  • page/FrameView.cpp: (WebCore::FrameView::isRubberBandInProgress const):
  • page/scrolling/AsyncScrollingCoordinator.cpp: (WebCore::AsyncScrollingCoordinator::isRubberBandInProgress const):
  • page/scrolling/AsyncScrollingCoordinator.h:
  • page/scrolling/ScrollingCoordinator.h: (WebCore::ScrollingCoordinator::isRubberBandInProgress const):
  • page/scrolling/ScrollingTree.cpp: (WebCore::ScrollingTree::isRubberBandInProgressForNode): (WebCore::ScrollingTree::setRubberBandingInProgressForNode): (WebCore::ScrollingTree::isRubberBandInProgress): Deleted. (WebCore::ScrollingTree::setMainFrameIsRubberBanding): Deleted.
  • page/scrolling/ScrollingTree.h:
  • page/scrolling/ScrollingTreeScrollingNode.cpp: (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
  • page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm: (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged): (WebCore::ScrollingTreeFrameScrollingNodeMac::updateMainFramePinAndRubberbandState):
  • page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
  • page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm: (WebCore::ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged):
  • page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
  • page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm: (WebCore::ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged): (WebCore::ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress const): (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation): (WebCore::ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged):
  • platform/ScrollAnimator.cpp: (WebCore::ScrollAnimator::notifyPositionChanged):
  • platform/cocoa/ScrollController.h: (WebCore::ScrollControllerClient::rubberBandingStateChanged):
  • platform/cocoa/ScrollController.mm: (WebCore::ScrollController::handleWheelEvent): (WebCore::ScrollController::snapRubberBandTimerFired): (WebCore::ScrollController::scrollPositionChanged): (WebCore::ScrollController::isRubberBandInProgress const): (WebCore::ScrollController::stopSnapRubberbandTimer): (WebCore::ScrollController::isRubberBandInProgressInternal const): (WebCore::ScrollController::updateRubberBandingState): (WebCore::ScrollController::updateGestureInProgressState):
  • rendering/RenderLayer.cpp: (WebCore::RenderLayer::isRubberBandInProgress const): (WebCore::RenderLayer::updateScrollInfoAfterLayout):

Source/WebKit:

  • WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
  • WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm: (WebKit::RemoteScrollingCoordinator::isRubberBandInProgress const): (WebKit::RemoteScrollingCoordinator::scrollingStateInUIProcessChanged):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267002 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Location:
branches/safari-610-branch/Source
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-610-branch/Source/WebCore/ChangeLog

    r267672 r267673  
     12020-09-27  Alan Coon  <alancoon@apple.com>
     2
     3        Cherry-pick r267002. rdar://problem/69594199
     4
     5    Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     6    https://bugs.webkit.org/show_bug.cgi?id=216463
     7    <rdar://problem/67095741>
     8   
     9    Reviewed by Darin Adler.
     10   
     11    When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     12    If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     13    clamp the scroll offset, causing the rubberband to collapse which interferes with
     14    the user interaction. This happend on Gmail when composing a reply.
     15   
     16    Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     17    query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     18    already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     19    and isScrollSnapInProgress() work.
     20   
     21    This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     22    was just based on when the timer was started and stopped, which did not match the
     23    implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     24    correctly notifies its clients when the rubberbanding state changes by updating that
     25    state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     26   
     27    Source/WebCore:
     28   
     29    I tried to make tests for this, but the timing of wheel and scroll event delivery makes
     30    reliable detection of interrupted rubberbands impossible in WebKitTestRunner.
     31   
     32    * page/FrameView.cpp:
     33    (WebCore::FrameView::isRubberBandInProgress const):
     34    * page/scrolling/AsyncScrollingCoordinator.cpp:
     35    (WebCore::AsyncScrollingCoordinator::isRubberBandInProgress const):
     36    * page/scrolling/AsyncScrollingCoordinator.h:
     37    * page/scrolling/ScrollingCoordinator.h:
     38    (WebCore::ScrollingCoordinator::isRubberBandInProgress const):
     39    * page/scrolling/ScrollingTree.cpp:
     40    (WebCore::ScrollingTree::isRubberBandInProgressForNode):
     41    (WebCore::ScrollingTree::setRubberBandingInProgressForNode):
     42    (WebCore::ScrollingTree::isRubberBandInProgress): Deleted.
     43    (WebCore::ScrollingTree::setMainFrameIsRubberBanding): Deleted.
     44    * page/scrolling/ScrollingTree.h:
     45    * page/scrolling/ScrollingTreeScrollingNode.cpp:
     46    (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
     47    * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     48    (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
     49    (WebCore::ScrollingTreeFrameScrollingNodeMac::updateMainFramePinAndRubberbandState):
     50    * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
     51    * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
     52    (WebCore::ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged):
     53    * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
     54    * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
     55    (WebCore::ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged):
     56    (WebCore::ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress const):
     57    (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation):
     58    (WebCore::ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged):
     59    * platform/ScrollAnimator.cpp:
     60    (WebCore::ScrollAnimator::notifyPositionChanged):
     61    * platform/cocoa/ScrollController.h:
     62    (WebCore::ScrollControllerClient::rubberBandingStateChanged):
     63    * platform/cocoa/ScrollController.mm:
     64    (WebCore::ScrollController::handleWheelEvent):
     65    (WebCore::ScrollController::snapRubberBandTimerFired):
     66    (WebCore::ScrollController::scrollPositionChanged):
     67    (WebCore::ScrollController::isRubberBandInProgress const):
     68    (WebCore::ScrollController::stopSnapRubberbandTimer):
     69    (WebCore::ScrollController::isRubberBandInProgressInternal const):
     70    (WebCore::ScrollController::updateRubberBandingState):
     71    (WebCore::ScrollController::updateGestureInProgressState):
     72    * rendering/RenderLayer.cpp:
     73    (WebCore::RenderLayer::isRubberBandInProgress const):
     74    (WebCore::RenderLayer::updateScrollInfoAfterLayout):
     75   
     76    Source/WebKit:
     77   
     78    * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
     79    * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
     80    (WebKit::RemoteScrollingCoordinator::isRubberBandInProgress const):
     81    (WebKit::RemoteScrollingCoordinator::scrollingStateInUIProcessChanged):
     82   
     83   
     84    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267002 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     85
     86    2020-09-13  Simon Fraser  <simon.fraser@apple.com>
     87
     88            Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     89            https://bugs.webkit.org/show_bug.cgi?id=216463
     90            <rdar://problem/67095741>
     91
     92            Reviewed by Darin Adler.
     93
     94            When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     95            If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     96            clamp the scroll offset, causing the rubberband to collapse which interferes with
     97            the user interaction. This happend on Gmail when composing a reply.
     98
     99            Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     100            query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     101            already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     102            and isScrollSnapInProgress() work.
     103
     104            This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     105            was just based on when the timer was started and stopped, which did not match the
     106            implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     107            correctly notifies its clients when the rubberbanding state changes by updating that
     108            state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     109
     110            I tried to make tests for this, but the timing of wheel and scroll event delivery makes
     111            reliable detection of interrupted rubberbands impossible in WebKitTestRunner.
     112
     113            * page/FrameView.cpp:
     114            (WebCore::FrameView::isRubberBandInProgress const):
     115            * page/scrolling/AsyncScrollingCoordinator.cpp:
     116            (WebCore::AsyncScrollingCoordinator::isRubberBandInProgress const):
     117            * page/scrolling/AsyncScrollingCoordinator.h:
     118            * page/scrolling/ScrollingCoordinator.h:
     119            (WebCore::ScrollingCoordinator::isRubberBandInProgress const):
     120            * page/scrolling/ScrollingTree.cpp:
     121            (WebCore::ScrollingTree::isRubberBandInProgressForNode):
     122            (WebCore::ScrollingTree::setRubberBandingInProgressForNode):
     123            (WebCore::ScrollingTree::isRubberBandInProgress): Deleted.
     124            (WebCore::ScrollingTree::setMainFrameIsRubberBanding): Deleted.
     125            * page/scrolling/ScrollingTree.h:
     126            * page/scrolling/ScrollingTreeScrollingNode.cpp:
     127            (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
     128            * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     129            (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
     130            (WebCore::ScrollingTreeFrameScrollingNodeMac::updateMainFramePinAndRubberbandState):
     131            * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
     132            * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
     133            (WebCore::ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged):
     134            * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
     135            * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
     136            (WebCore::ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged):
     137            (WebCore::ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress const):
     138            (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation):
     139            (WebCore::ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged):
     140            * platform/ScrollAnimator.cpp:
     141            (WebCore::ScrollAnimator::notifyPositionChanged):
     142            * platform/cocoa/ScrollController.h:
     143            (WebCore::ScrollControllerClient::rubberBandingStateChanged):
     144            * platform/cocoa/ScrollController.mm:
     145            (WebCore::ScrollController::handleWheelEvent):
     146            (WebCore::ScrollController::snapRubberBandTimerFired):
     147            (WebCore::ScrollController::scrollPositionChanged):
     148            (WebCore::ScrollController::isRubberBandInProgress const):
     149            (WebCore::ScrollController::stopSnapRubberbandTimer):
     150            (WebCore::ScrollController::isRubberBandInProgressInternal const):
     151            (WebCore::ScrollController::updateRubberBandingState):
     152            (WebCore::ScrollController::updateGestureInProgressState):
     153            * rendering/RenderLayer.cpp:
     154            (WebCore::RenderLayer::isRubberBandInProgress const):
     155            (WebCore::RenderLayer::updateScrollInfoAfterLayout):
     156
    11572020-09-27  Alan Coon  <alancoon@apple.com>
    2158
  • branches/safari-610-branch/Source/WebCore/page/FrameView.cpp

    r266549 r267673  
    26332633    if (auto scrollingCoordinator = this->scrollingCoordinator()) {
    26342634        if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously(*this))
    2635             return scrollingCoordinator->isRubberBandInProgress();
     2635            return scrollingCoordinator->isRubberBandInProgress(scrollingNodeID());
    26362636    }
    26372637
  • branches/safari-610-branch/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r267271 r267673  
    840840}
    841841
    842 bool AsyncScrollingCoordinator::isRubberBandInProgress() const
     842bool AsyncScrollingCoordinator::isRubberBandInProgress(ScrollingNodeID nodeID) const
    843843{
    844844    if (m_scrollingTree)
    845         return m_scrollingTree->isRubberBandInProgress();
     845        return m_scrollingTree->isRubberBandInProgressForNode(nodeID);
    846846
    847847    return false;
  • branches/safari-610-branch/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h

    r267271 r267673  
    130130
    131131    WEBCORE_EXPORT bool isUserScrollInProgress(ScrollingNodeID) const override;
    132     bool isRubberBandInProgress() const override;
     132    bool isRubberBandInProgress(ScrollingNodeID) const override;
    133133
    134134#if ENABLE(CSS_SCROLL_SNAP)
  • branches/safari-610-branch/Source/WebCore/page/scrolling/ScrollingCoordinator.h

    r267271 r267673  
    171171    virtual String scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior = ScrollingStateTreeAsTextBehaviorNormal) const;
    172172    virtual String scrollingTreeAsText(ScrollingStateTreeAsTextBehavior = ScrollingStateTreeAsTextBehaviorNormal) const;
    173     virtual bool isRubberBandInProgress() const { return false; }
     173    virtual bool isRubberBandInProgress(ScrollingNodeID) const { return false; }
    174174    virtual bool isUserScrollInProgress(ScrollingNodeID) const { return false; }
    175175    virtual bool isScrollSnapInProgress(ScrollingNodeID) const { return false; }
  • branches/safari-610-branch/Source/WebCore/page/scrolling/ScrollingTree.cpp

    r266851 r267673  
    466466
    467467// Can be called from the main thread.
    468 bool ScrollingTree::isRubberBandInProgress()
    469 {
     468bool ScrollingTree::isRubberBandInProgressForNode(ScrollingNodeID nodeID)
     469{
     470    if (!nodeID)
     471        return false;
     472
    470473    LockHolder lock(m_treeStateMutex);
    471     return m_treeState.mainFrameIsRubberBanding;
    472 }
    473 
    474 void ScrollingTree::setMainFrameIsRubberBanding(bool isRubberBanding)
     474    return m_treeState.nodesWithActiveRubberBanding.contains(nodeID);
     475}
     476
     477void ScrollingTree::setRubberBandingInProgressForNode(ScrollingNodeID nodeID, bool isRubberBanding)
    475478{
    476479    LockHolder locker(m_treeStateMutex);
    477     m_treeState.mainFrameIsRubberBanding = isRubberBanding;
     480    if (isRubberBanding)
     481        m_treeState.nodesWithActiveRubberBanding.add(nodeID);
     482    else
     483        m_treeState.nodesWithActiveRubberBanding.remove(nodeID);
    478484}
    479485
  • branches/safari-610-branch/Source/WebCore/page/scrolling/ScrollingTree.h

    r266549 r267673  
    9393    WEBCORE_EXPORT virtual WheelEventHandlingResult handleWheelEvent(const PlatformWheelEvent&);
    9494
    95     void setMainFrameIsRubberBanding(bool);
    96     bool isRubberBandInProgress();
     95    bool isRubberBandInProgressForNode(ScrollingNodeID);
     96    void setRubberBandingInProgressForNode(ScrollingNodeID, bool);
    9797
    9898    bool isUserScrollInProgressForNode(ScrollingNodeID);
     
    258258        PlatformDisplayID displayID { 0 };
    259259        Optional<unsigned> nominalFramesPerSecond;
     260        HashSet<ScrollingNodeID> nodesWithActiveRubberBanding;
    260261        HashSet<ScrollingNodeID> nodesWithActiveScrollSnap;
    261262        HashSet<ScrollingNodeID> nodesWithActiveUserScrolls;
    262         bool mainFrameIsRubberBanding { false };
    263263    };
    264264   
  • branches/safari-610-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r265820 r267673  
    5555
    5656    if (state.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize)) {
    57         if (scrollingTree().isRubberBandInProgress())
     57        if (scrollingTree().isRubberBandInProgressForNode(scrollingNodeID()))
    5858            m_totalContentsSizeForRubberBand = m_totalContentsSize;
    5959        else
  • branches/safari-610-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm

    r264008 r267673  
    144144    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged to " << currentScrollPosition() << " min: " << minimumScrollPosition() << " max: " << maximumScrollPosition() << " sync: " << hasSynchronousScrollingReasons());
    145145
     146    m_delegate.currentScrollPositionChanged();
     147
    146148    if (isRootNode())
    147149        updateMainFramePinAndRubberbandState();
     
    225227{
    226228    ASSERT(isRootNode());
    227 
    228229    scrollingTree().setMainFramePinnedState(edgePinnedState());
    229     scrollingTree().setMainFrameIsRubberBanding(isRubberBanding());
    230230}
    231231
  • branches/safari-610-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h

    r262294 r267673  
    4848    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const override;
    4949
     50    void currentScrollPositionChanged(ScrollingLayerPositionAction) final;
     51
    5052    void repositionScrollingLayers() override;
    5153    void repositionRelatedLayers() override;
  • branches/safari-610-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm

    r264008 r267673  
    8787}
    8888
     89void ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged(ScrollingLayerPositionAction action)
     90{
     91    ScrollingTreeOverflowScrollingNode::currentScrollPositionChanged(action);
     92    m_delegate.currentScrollPositionChanged();
     93}
     94
    8995FloatPoint ScrollingTreeOverflowScrollingNodeMac::adjustedScrollPosition(const FloatPoint& position, ScrollClamping clamp) const
    9096{
  • branches/safari-610-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h

    r264008 r267673  
    5151
    5252    bool handleWheelEvent(const PlatformWheelEvent&);
     53   
     54    void currentScrollPositionChanged();
    5355
    5456#if ENABLE(CSS_SCROLL_SNAP)
     
    5961    bool isScrollSnapInProgress() const;
    6062#endif
     63
     64    bool isRubberBandInProgress() const;
    6165
    6266    void updateFromStateNode(const ScrollingStateScrollingNode&);
     
    8185    void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) final;
    8286    void didStopRubberbandSnapAnimation() final;
     87    void rubberBandingStateChanged(bool) final;
    8388    void adjustScrollPositionToBoundsIfNecessary() final;
    8489
  • branches/safari-610-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm

    r264908 r267673  
    161161}
    162162
     163void ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged()
     164{
     165    m_scrollController.scrollPositionChanged();
     166}
     167
     168bool ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress() const
     169{
     170    return m_scrollController.isRubberBandInProgress();
     171}
     172
    163173bool ScrollingTreeScrollingNodeDelegateMac::isScrollSnapInProgress() const
    164174{
     
    319329void ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation()
    320330{
    321     scrollingTree().setMainFrameIsRubberBanding(false);
    322 
    323331    // Since the rubberband timer has stopped, totalContentsSizeForRubberBand can be synchronized with totalContentsSize.
    324332    scrollingNode().setTotalContentsSizeForRubberBand(totalContentsSize());
     333}
     334
     335void ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged(bool inRubberBand)
     336{
     337    scrollingTree().setRubberBandingInProgressForNode(scrollingNode().scrollingNodeID(), inRubberBand);
    325338}
    326339
  • branches/safari-610-branch/Source/WebCore/platform/ScrollAnimator.cpp

    r264908 r267673  
    215215    // FIXME: need to not map back and forth all the time.
    216216    m_scrollableArea.setScrollOffsetFromAnimation(m_scrollableArea.scrollOffsetFromPosition(roundedIntPoint(currentPosition())));
     217
     218#if ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)
     219    m_scrollController.scrollPositionChanged();
     220#endif
    217221}
    218222
  • branches/safari-610-branch/Source/WebCore/platform/cocoa/ScrollController.h

    r264891 r267673  
    8484    virtual void immediateScrollBy(const FloatSize&) = 0;
    8585    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
     86   
    8687    virtual void willStartRubberBandSnapAnimation() { }
    8788    virtual void didStopRubberbandSnapAnimation() { }
    88    
     89
     90    virtual void rubberBandingStateChanged(bool) { }
     91
    8992    // If the current scroll position is within the overhang area, this function will cause
    9093    // the page to scroll to the nearest boundary point.
     
    143146    bool isRubberBandInProgress() const;
    144147    bool isScrollSnapInProgress() const;
     148   
     149    void scrollPositionChanged();
    145150
    146151#if ENABLE(CSS_SCROLL_SNAP)
     
    176181    bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&) const;
    177182    bool shouldRubberBandInDirection(ScrollDirection) const;
     183
     184    bool isRubberBandInProgressInternal() const;
     185    void updateRubberBandingState();
    178186#endif
    179187
     
    224232    bool m_momentumScrollInProgress { false };
    225233    bool m_ignoreMomentumScrolls { false };
     234    bool m_isRubberBanding { false };
    226235#endif
    227236
  • branches/safari-610-branch/Source/WebCore/platform/cocoa/ScrollController.mm

    r265545 r267673  
    149149
    150150        stopSnapRubberbandTimer();
    151 
     151        updateRubberBandingState();
    152152        return true;
    153153    }
     
    155155    if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) {
    156156        snapRubberBand();
     157        updateRubberBandingState();
    157158        return true;
    158159    }
     
    318319    }
    319320
     321    updateRubberBandingState();
     322
    320323    return handled;
    321324}
     
    413416                m_startStretch = { };
    414417                m_origVelocity = { };
     418
     419                updateRubberBandingState();
    415420                return;
    416421            }
     
    453458        m_startTime = MonotonicTime::now();
    454459        m_startStretch = { };
    455         if (!isRubberBandInProgress())
     460        if (!isRubberBandInProgressInternal())
    456461            stopSnapRubberbandTimer();
    457462    }
    458 }
    459 #endif
     463
     464    updateRubberBandingState();
     465}
     466#endif
     467
     468void ScrollController::scrollPositionChanged()
     469{
     470#if ENABLE(RUBBER_BANDING)
     471    updateRubberBandingState();
     472#endif
     473}
    460474
    461475bool ScrollController::usesScrollSnap() const
     
    480494{
    481495#if ENABLE(RUBBER_BANDING) && PLATFORM(MAC)
    482     if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimer)
    483         return false;
    484 
    485     return !m_client.stretchAmount().isZero();
     496    return m_isRubberBanding;
    486497#else
    487498    return false;
     
    518529{
    519530    m_client.didStopRubberbandSnapAnimation();
    520    
     531
    521532    if (m_snapRubberbandTimer) {
    522533        m_snapRubberbandTimer->stop();
    523534        m_snapRubberbandTimer = nullptr;
    524535    }
    525    
     536
    526537    m_client.removeWheelEventTestCompletionDeferralForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
    527538}
     
    555566{
    556567    return m_client.shouldRubberBandInDirection(direction);
     568}
     569
     570bool ScrollController::isRubberBandInProgressInternal() const
     571{
     572    if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimer)
     573        return false;
     574
     575    return !m_client.stretchAmount().isZero();
     576}
     577
     578void ScrollController::updateRubberBandingState()
     579{
     580    bool isRubberBanding = isRubberBandInProgressInternal();
     581    if (isRubberBanding == m_isRubberBanding)
     582        return;
     583   
     584    m_isRubberBanding = isRubberBanding;
     585    m_client.rubberBandingStateChanged(m_isRubberBanding);
    557586}
    558587
     
    718747    else if (wheelEvent.isEndOfNonMomentumScroll() || wheelEvent.isGestureCancel() || wheelEvent.isEndOfMomentumScroll())
    719748        m_inScrollGesture = false;
     749
     750    updateRubberBandingState();
    720751}
    721752
  • branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.cpp

    r267634 r267673  
    19111911        return false;
    19121912
     1913    if (auto scrollingCoordinator = page().scrollingCoordinator()) {
     1914        if (scrollingCoordinator->isRubberBandInProgress(scrollingNodeID()))
     1915            return true;
     1916    }
     1917
    19131918    if (auto scrollAnimator = existingScrollAnimator())
    19141919        return scrollAnimator->isRubberBandInProgress();
     
    39153920#endif
    39163921
    3917     if (!box->isHTMLMarquee() && !isRubberBandInProgress()) {
     3922    if (!box->isHTMLMarquee() && !isRubberBandInProgress() && !isUserScrollInProgress()) {
    39183923        // Layout may cause us to be at an invalid scroll position. In this case we need
    39193924        // to pull our scroll offsets back to the max (or push them up to the min).
  • branches/safari-610-branch/Source/WebKit/ChangeLog

    r267672 r267673  
     12020-09-27  Alan Coon  <alancoon@apple.com>
     2
     3        Cherry-pick r267002. rdar://problem/69594199
     4
     5    Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     6    https://bugs.webkit.org/show_bug.cgi?id=216463
     7    <rdar://problem/67095741>
     8   
     9    Reviewed by Darin Adler.
     10   
     11    When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     12    If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     13    clamp the scroll offset, causing the rubberband to collapse which interferes with
     14    the user interaction. This happend on Gmail when composing a reply.
     15   
     16    Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     17    query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     18    already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     19    and isScrollSnapInProgress() work.
     20   
     21    This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     22    was just based on when the timer was started and stopped, which did not match the
     23    implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     24    correctly notifies its clients when the rubberbanding state changes by updating that
     25    state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     26   
     27    Source/WebCore:
     28   
     29    I tried to make tests for this, but the timing of wheel and scroll event delivery makes
     30    reliable detection of interrupted rubberbands impossible in WebKitTestRunner.
     31   
     32    * page/FrameView.cpp:
     33    (WebCore::FrameView::isRubberBandInProgress const):
     34    * page/scrolling/AsyncScrollingCoordinator.cpp:
     35    (WebCore::AsyncScrollingCoordinator::isRubberBandInProgress const):
     36    * page/scrolling/AsyncScrollingCoordinator.h:
     37    * page/scrolling/ScrollingCoordinator.h:
     38    (WebCore::ScrollingCoordinator::isRubberBandInProgress const):
     39    * page/scrolling/ScrollingTree.cpp:
     40    (WebCore::ScrollingTree::isRubberBandInProgressForNode):
     41    (WebCore::ScrollingTree::setRubberBandingInProgressForNode):
     42    (WebCore::ScrollingTree::isRubberBandInProgress): Deleted.
     43    (WebCore::ScrollingTree::setMainFrameIsRubberBanding): Deleted.
     44    * page/scrolling/ScrollingTree.h:
     45    * page/scrolling/ScrollingTreeScrollingNode.cpp:
     46    (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
     47    * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     48    (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
     49    (WebCore::ScrollingTreeFrameScrollingNodeMac::updateMainFramePinAndRubberbandState):
     50    * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
     51    * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
     52    (WebCore::ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged):
     53    * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
     54    * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
     55    (WebCore::ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged):
     56    (WebCore::ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress const):
     57    (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation):
     58    (WebCore::ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged):
     59    * platform/ScrollAnimator.cpp:
     60    (WebCore::ScrollAnimator::notifyPositionChanged):
     61    * platform/cocoa/ScrollController.h:
     62    (WebCore::ScrollControllerClient::rubberBandingStateChanged):
     63    * platform/cocoa/ScrollController.mm:
     64    (WebCore::ScrollController::handleWheelEvent):
     65    (WebCore::ScrollController::snapRubberBandTimerFired):
     66    (WebCore::ScrollController::scrollPositionChanged):
     67    (WebCore::ScrollController::isRubberBandInProgress const):
     68    (WebCore::ScrollController::stopSnapRubberbandTimer):
     69    (WebCore::ScrollController::isRubberBandInProgressInternal const):
     70    (WebCore::ScrollController::updateRubberBandingState):
     71    (WebCore::ScrollController::updateGestureInProgressState):
     72    * rendering/RenderLayer.cpp:
     73    (WebCore::RenderLayer::isRubberBandInProgress const):
     74    (WebCore::RenderLayer::updateScrollInfoAfterLayout):
     75   
     76    Source/WebKit:
     77   
     78    * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
     79    * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
     80    (WebKit::RemoteScrollingCoordinator::isRubberBandInProgress const):
     81    (WebKit::RemoteScrollingCoordinator::scrollingStateInUIProcessChanged):
     82   
     83   
     84    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267002 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     85
     86    2020-09-13  Simon Fraser  <simon.fraser@apple.com>
     87
     88            Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     89            https://bugs.webkit.org/show_bug.cgi?id=216463
     90            <rdar://problem/67095741>
     91
     92            Reviewed by Darin Adler.
     93
     94            When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     95            If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     96            clamp the scroll offset, causing the rubberband to collapse which interferes with
     97            the user interaction. This happend on Gmail when composing a reply.
     98
     99            Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     100            query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     101            already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     102            and isScrollSnapInProgress() work.
     103
     104            This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     105            was just based on when the timer was started and stopped, which did not match the
     106            implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     107            correctly notifies its clients when the rubberbanding state changes by updating that
     108            state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     109
     110            * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
     111            * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
     112            (WebKit::RemoteScrollingCoordinator::isRubberBandInProgress const):
     113            (WebKit::RemoteScrollingCoordinator::scrollingStateInUIProcessChanged):
     114
    11152020-09-27  Alan Coon  <alancoon@apple.com>
    2116
  • branches/safari-610-branch/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h

    r264704 r267673  
    6666    void scheduleTreeStateCommit() override;
    6767
    68     bool isRubberBandInProgress() const override;
    69 
     68    bool isRubberBandInProgress(WebCore::ScrollingNodeID) const final;
    7069    bool isUserScrollInProgress(WebCore::ScrollingNodeID) const final;
    7170#if ENABLE(CSS_SCROLL_SNAP)
     
    8483    WebPage* m_webPage;
    8584
     85    HashSet<WebCore::ScrollingNodeID> m_nodesWithActiveRubberBanding;
    8686    HashSet<WebCore::ScrollingNodeID> m_nodesWithActiveScrollSnap;
    8787    HashSet<WebCore::ScrollingNodeID> m_nodesWithActiveUserScrolls;
  • branches/safari-610-branch/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm

    r264704 r267673  
    7373}
    7474
    75 bool RemoteScrollingCoordinator::isRubberBandInProgress() const
     75bool RemoteScrollingCoordinator::isRubberBandInProgress(ScrollingNodeID nodeID) const
    7676{
    77     // FIXME: need to maintain state in the web process?
    78     return false;
     77    return m_nodesWithActiveRubberBanding.contains(nodeID);
    7978}
    8079
     
    113112void RemoteScrollingCoordinator::scrollingStateInUIProcessChanged(const RemoteScrollingUIState& uiState)
    114113{
     114    // FIXME: Also track m_nodesWithActiveRubberBanding.
    115115    if (uiState.changes().contains(RemoteScrollingUIState::Changes::ScrollSnapNodes))
    116116        m_nodesWithActiveScrollSnap = uiState.nodesWithActiveScrollSnap();
Note: See TracChangeset for help on using the changeset viewer.