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

Changeset 267002 in webkit


Ignore:
Timestamp:
Sep 13, 2020, 1:30:59 PM (6 years ago)
Author:
Simon Fraser
Message:

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):

Location:
trunk/Source
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r267001 r267002  
     12020-09-13  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=216463
     5        <rdar://problem/67095741>
     6
     7        Reviewed by Darin Adler.
     8
     9        When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     10        If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     11        clamp the scroll offset, causing the rubberband to collapse which interferes with
     12        the user interaction. This happend on Gmail when composing a reply.
     13       
     14        Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     15        query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     16        already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     17        and isScrollSnapInProgress() work.
     18       
     19        This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     20        was just based on when the timer was started and stopped, which did not match the
     21        implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     22        correctly notifies its clients when the rubberbanding state changes by updating that
     23        state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     24
     25        I tried to make tests for this, but the timing of wheel and scroll event delivery makes
     26        reliable detection of interrupted rubberbands impossible in WebKitTestRunner.
     27
     28        * page/FrameView.cpp:
     29        (WebCore::FrameView::isRubberBandInProgress const):
     30        * page/scrolling/AsyncScrollingCoordinator.cpp:
     31        (WebCore::AsyncScrollingCoordinator::isRubberBandInProgress const):
     32        * page/scrolling/AsyncScrollingCoordinator.h:
     33        * page/scrolling/ScrollingCoordinator.h:
     34        (WebCore::ScrollingCoordinator::isRubberBandInProgress const):
     35        * page/scrolling/ScrollingTree.cpp:
     36        (WebCore::ScrollingTree::isRubberBandInProgressForNode):
     37        (WebCore::ScrollingTree::setRubberBandingInProgressForNode):
     38        (WebCore::ScrollingTree::isRubberBandInProgress): Deleted.
     39        (WebCore::ScrollingTree::setMainFrameIsRubberBanding): Deleted.
     40        * page/scrolling/ScrollingTree.h:
     41        * page/scrolling/ScrollingTreeScrollingNode.cpp:
     42        (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
     43        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     44        (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
     45        (WebCore::ScrollingTreeFrameScrollingNodeMac::updateMainFramePinAndRubberbandState):
     46        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
     47        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
     48        (WebCore::ScrollingTreeOverflowScrollingNodeMac::currentScrollPositionChanged):
     49        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
     50        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
     51        (WebCore::ScrollingTreeScrollingNodeDelegateMac::currentScrollPositionChanged):
     52        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isRubberBandInProgress const):
     53        (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation):
     54        (WebCore::ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged):
     55        * platform/ScrollAnimator.cpp:
     56        (WebCore::ScrollAnimator::notifyPositionChanged):
     57        * platform/cocoa/ScrollController.h:
     58        (WebCore::ScrollControllerClient::rubberBandingStateChanged):
     59        * platform/cocoa/ScrollController.mm:
     60        (WebCore::ScrollController::handleWheelEvent):
     61        (WebCore::ScrollController::snapRubberBandTimerFired):
     62        (WebCore::ScrollController::scrollPositionChanged):
     63        (WebCore::ScrollController::isRubberBandInProgress const):
     64        (WebCore::ScrollController::stopSnapRubberbandTimer):
     65        (WebCore::ScrollController::isRubberBandInProgressInternal const):
     66        (WebCore::ScrollController::updateRubberBandingState):
     67        (WebCore::ScrollController::updateGestureInProgressState):
     68        * rendering/RenderLayer.cpp:
     69        (WebCore::RenderLayer::isRubberBandInProgress const):
     70        (WebCore::RenderLayer::updateScrollInfoAfterLayout):
     71
    1722020-09-13  Zalan Bujtas  <zalan@apple.com>
    273
  • trunk/Source/WebCore/page/FrameView.cpp

    r266691 r267002  
    26332633    if (auto scrollingCoordinator = this->scrollingCoordinator()) {
    26342634        if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously(*this))
    2635             return scrollingCoordinator->isRubberBandInProgress();
     2635            return scrollingCoordinator->isRubberBandInProgress(scrollingNodeID());
    26362636    }
    26372637
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r266846 r267002  
    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;
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h

    r266846 r267002  
    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)
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h

    r266846 r267002  
    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; }
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp

    r266336 r267002  
    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
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.h

    r266292 r267002  
    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   
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r266390 r267002  
    5555
    5656    if (state.hasChangedProperty(ScrollingStateScrollingNode::TotalContentsSize)) {
    57         if (scrollingTree().isRubberBandInProgress())
     57        if (scrollingTree().isRubberBandInProgressForNode(scrollingNodeID()))
    5858            m_totalContentsSizeForRubberBand = m_totalContentsSize;
    5959        else
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm

    r264008 r267002  
    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
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h

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

    r264008 r267002  
    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{
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h

    r264008 r267002  
    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
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm

    r266333 r267002  
    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{
     
    313323void ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation()
    314324{
    315     scrollingTree().setMainFrameIsRubberBanding(false);
    316 
    317325    // Since the rubberband timer has stopped, totalContentsSizeForRubberBand can be synchronized with totalContentsSize.
    318326    scrollingNode().setTotalContentsSizeForRubberBand(totalContentsSize());
     327}
     328
     329void ScrollingTreeScrollingNodeDelegateMac::rubberBandingStateChanged(bool inRubberBand)
     330{
     331    scrollingTree().setRubberBandingInProgressForNode(scrollingNode().scrollingNodeID(), inRubberBand);
    319332}
    320333
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r266390 r267002  
    223223    // FIXME: need to not map back and forth all the time.
    224224    m_scrollableArea.setScrollOffsetFromAnimation(m_scrollableArea.scrollOffsetFromPosition(roundedIntPoint(currentPosition())));
     225
     226#if ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)
     227    m_scrollController.scrollPositionChanged();
     228#endif
    225229}
    226230
  • trunk/Source/WebCore/platform/cocoa/ScrollController.h

    r264891 r267002  
    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
  • trunk/Source/WebCore/platform/cocoa/ScrollController.mm

    r266337 r267002  
    149149
    150150        stopSnapRubberbandTimer();
    151 
     151        updateRubberBandingState();
    152152        return true;
    153153    }
     
    155155    if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) {
    156156        snapRubberBand();
     157        updateRubberBandingState();
    157158        return true;
    158159    }
     
    322323    }
    323324
     325    updateRubberBandingState();
     326
    324327    return handled;
    325328}
     
    417420                m_startStretch = { };
    418421                m_origVelocity = { };
     422
     423                updateRubberBandingState();
    419424                return;
    420425            }
     
    457462        m_startTime = MonotonicTime::now();
    458463        m_startStretch = { };
    459         if (!isRubberBandInProgress())
     464        if (!isRubberBandInProgressInternal())
    460465            stopSnapRubberbandTimer();
    461466    }
    462 }
    463 #endif
     467
     468    updateRubberBandingState();
     469}
     470#endif
     471
     472void ScrollController::scrollPositionChanged()
     473{
     474#if ENABLE(RUBBER_BANDING)
     475    updateRubberBandingState();
     476#endif
     477}
    464478
    465479bool ScrollController::usesScrollSnap() const
     
    484498{
    485499#if ENABLE(RUBBER_BANDING) && PLATFORM(MAC)
    486     if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimer)
    487         return false;
    488 
    489     return !m_client.stretchAmount().isZero();
     500    return m_isRubberBanding;
    490501#else
    491502    return false;
     
    522533{
    523534    m_client.didStopRubberbandSnapAnimation();
    524    
     535
    525536    if (m_snapRubberbandTimer) {
    526537        m_snapRubberbandTimer->stop();
    527538        m_snapRubberbandTimer = nullptr;
    528539    }
    529    
     540
    530541    m_client.removeWheelEventTestCompletionDeferralForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
    531542}
     
    559570{
    560571    return m_client.shouldRubberBandInDirection(direction);
     572}
     573
     574bool ScrollController::isRubberBandInProgressInternal() const
     575{
     576    if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimer)
     577        return false;
     578
     579    return !m_client.stretchAmount().isZero();
     580}
     581
     582void ScrollController::updateRubberBandingState()
     583{
     584    bool isRubberBanding = isRubberBandInProgressInternal();
     585    if (isRubberBanding == m_isRubberBanding)
     586        return;
     587   
     588    m_isRubberBanding = isRubberBanding;
     589    m_client.rubberBandingStateChanged(m_isRubberBanding);
    561590}
    562591
     
    722751    else if (wheelEvent.isEndOfNonMomentumScroll() || wheelEvent.isGestureCancel() || wheelEvent.isEndOfMomentumScroll())
    723752        m_inScrollGesture = false;
     753
     754    updateRubberBandingState();
    724755}
    725756
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r266677 r267002  
    19101910        return false;
    19111911
     1912    if (auto scrollingCoordinator = page().scrollingCoordinator()) {
     1913        if (scrollingCoordinator->isRubberBandInProgress(scrollingNodeID()))
     1914            return true;
     1915    }
     1916
    19121917    if (auto scrollAnimator = existingScrollAnimator())
    19131918        return scrollAnimator->isRubberBandInProgress();
     
    39143919#endif
    39153920
    3916     if (!box->isHTMLMarquee() && !isRubberBandInProgress()) {
     3921    if (!box->isHTMLMarquee() && !isRubberBandInProgress() && !isUserScrollInProgress()) {
    39173922        // Layout may cause us to be at an invalid scroll position. In this case we need
    39183923        // to pull our scroll offsets back to the max (or push them up to the min).
  • trunk/Source/WebKit/ChangeLog

    r266993 r267002  
     12020-09-13  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Overflow:scroll rubberbanding is interrupted by post-layout scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=216463
     5        <rdar://problem/67095741>
     6
     7        Reviewed by Darin Adler.
     8
     9        When rubberbanding overflow:scroll RenderLayer has an overscrolled scroll offset.
     10        If RenderLayer::updateScrollInfoAfterLayout() happens when in this state, it can
     11        clamp the scroll offset, causing the rubberband to collapse which interferes with
     12        the user interaction. This happend on Gmail when composing a reply.
     13       
     14        Fix by tracking the rubberbanding state in the scrolling tree, and having RenderLayer
     15        query this state via the ScrollingCoordinator. RenderLayer::updateScrollInfoAfterLayout()
     16        already tested isRubberBandInProgress(). This is similar to how isUserScrollInProgress()
     17        and isScrollSnapInProgress() work.
     18       
     19        This patch also fixes the tracking of rubberbanding state. Previously setMainFrameIsRubberBanding()
     20        was just based on when the timer was started and stopped, which did not match the
     21        implementation of ScrollController::isRubberBandInProgress(). Now ScrollController
     22        correctly notifies its clients when the rubberbanding state changes by updating that
     23        state whenever any of the conditions consulted in isRubberBandInProgressInternal() change.
     24
     25        * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
     26        * WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
     27        (WebKit::RemoteScrollingCoordinator::isRubberBandInProgress const):
     28        (WebKit::RemoteScrollingCoordinator::scrollingStateInUIProcessChanged):
     29
    1302020-09-13  Wenson Hsieh  <wenson_hsieh@apple.com>
    231
  • trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h

    r264704 r267002  
    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;
  • trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm

    r264704 r267002  
    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.