Changeset 293260 in webkit


Ignore:
Timestamp:
Apr 22, 2022 3:52:23 PM (3 months ago)
Author:
Simon Fraser
Message:

Focusing scroll container before scrolling breaks smooth scrolling
https://bugs.webkit.org/show_bug.cgi?id=239605

Reviewed by Wenson Hsieh.

Source/WebCore:

If script calls focus() and then scrollTo({ behavior: smooth }) in the same runloop, the
scrollToFocusedElementInternal() that happens on a zero-delay timer in FrameView will stop
the animated scroll.

Fix by having programmatic scrolls on Element and DOMWindow cancel any pending focus-related
scroll.

Test: fast/scrolling/programmatic-smooth-scroll-after-focus.html

  • dom/Element.cpp:

(WebCore::Element::scrollTo):

  • page/DOMWindow.cpp:

(WebCore::DOMWindow::scrollTo const):

  • page/FrameView.cpp:

(WebCore::FrameView::maintainScrollPositionAtAnchor):
(WebCore::FrameView::setScrollPosition):
(WebCore::FrameView::cancelScheduledScrollToFocusedElement):
(WebCore::FrameView::scrollToAnchor):
(WebCore::FrameView::setWasScrolledByUser):

  • page/FrameView.h:

LayoutTests:

  • fast/scrolling/programmatic-smooth-scroll-after-focus-expected.txt: Added.
  • fast/scrolling/programmatic-smooth-scroll-after-focus.html: Added.
  • platform/win/TestExpectations:
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r293254 r293260  
     12022-04-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Focusing scroll container before scrolling breaks smooth scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=239605
     5
     6        Reviewed by Wenson Hsieh.
     7
     8        * fast/scrolling/programmatic-smooth-scroll-after-focus-expected.txt: Added.
     9        * fast/scrolling/programmatic-smooth-scroll-after-focus.html: Added.
     10        * platform/win/TestExpectations:
     11
    1122022-04-22  Matteo Flores  <matteo_flores@apple.com>
    213
  • trunk/LayoutTests/platform/win/TestExpectations

    r293006 r293260  
    534534webkit.org/b/208559 fast/scrolling/rtl-point-in-iframe.html [ Skip ]
    535535fast/scrolling/rtl-scrollbars-alternate-iframe-body-dir-attr-does-not-update-scrollbar-placement.html [ ImageOnlyFailure ]
     536
     537# waitForScrollCompletion() not supported
     538fast/scrolling/programmatic-smooth-scroll-after-focus.html [ Skip ]
    536539
    537540# TODO Needs testRunner.enableAutoResizeMode()
  • trunk/Source/WebCore/ChangeLog

    r293251 r293260  
     12022-04-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Focusing scroll container before scrolling breaks smooth scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=239605
     5
     6        Reviewed by Wenson Hsieh.
     7
     8        If script calls focus() and then scrollTo({ behavior: smooth }) in the same runloop, the
     9        scrollToFocusedElementInternal() that happens on a zero-delay timer in FrameView will stop
     10        the animated scroll.
     11
     12        Fix by having programmatic scrolls on Element and DOMWindow cancel any pending focus-related
     13        scroll.
     14
     15        Test: fast/scrolling/programmatic-smooth-scroll-after-focus.html
     16
     17        * dom/Element.cpp:
     18        (WebCore::Element::scrollTo):
     19        * page/DOMWindow.cpp:
     20        (WebCore::DOMWindow::scrollTo const):
     21        * page/FrameView.cpp:
     22        (WebCore::FrameView::maintainScrollPositionAtAnchor):
     23        (WebCore::FrameView::setScrollPosition):
     24        (WebCore::FrameView::cancelScheduledScrollToFocusedElement):
     25        (WebCore::FrameView::scrollToAnchor):
     26        (WebCore::FrameView::setWasScrolledByUser):
     27        * page/FrameView.h:
     28
    1292022-04-22  Alan Bujtas  <zalan@apple.com>
    230
  • trunk/Source/WebCore/dom/Element.cpp

    r293059 r293260  
    11011101            return;
    11021102    }
     1103   
     1104    if (auto* view = document().view())
     1105        view->cancelScheduledScrollToFocusedElement();
    11031106
    11041107    document().updateLayoutIgnorePendingStylesheets();
  • trunk/Source/WebCore/page/DOMWindow.cpp

    r292677 r293260  
    17391739    }
    17401740
     1741    view->cancelScheduledScrollToFocusedElement();
    17411742    document()->updateLayoutIgnorePendingStylesheets();
    17421743
  • trunk/Source/WebCore/page/FrameView.cpp

    r292512 r293260  
    23302330    if (!m_maintainScrollPositionAnchor)
    23312331        return;
    2332     m_shouldScrollToFocusedElement = false;
    2333     m_delayedScrollToFocusedElementTimer.stop();
     2332
     2333    cancelScheduledScrollToFocusedElement();
    23342334
    23352335    // We need to update the layout before scrolling, otherwise we could
     
    23642364
    23652365    m_maintainScrollPositionAnchor = nullptr;
    2366     m_shouldScrollToFocusedElement = false;
    2367     m_delayedScrollToFocusedElementTimer.stop();
     2366    cancelScheduledScrollToFocusedElement();
     2367
    23682368    Page* page = frame().page();
    23692369    if (page && page->isMonitoringWheelEvents())
     
    24112411    m_shouldScrollToFocusedElement = true;
    24122412    m_delayedScrollToFocusedElementTimer.startOneShot(0_s);
     2413}
     2414
     2415void FrameView::cancelScheduledScrollToFocusedElement()
     2416{
     2417    m_shouldScrollToFocusedElement = false;
     2418    m_delayedScrollToFocusedElementTimer.stop();
    24132419}
    24142420
     
    32893295        return;
    32903296
    3291     m_shouldScrollToFocusedElement = false;
    3292     m_delayedScrollToFocusedElementTimer.stop();
     3297    cancelScheduledScrollToFocusedElement();
    32933298
    32943299    LayoutRect rect;
     
    33143319    LOG_WITH_STREAM(Scrolling, stream << " restoring anchor node to " << anchorNode.get());
    33153320    m_maintainScrollPositionAnchor = anchorNode;
    3316     m_shouldScrollToFocusedElement = false;
    3317     m_delayedScrollToFocusedElementTimer.stop();
     3321    cancelScheduledScrollToFocusedElement();
    33183322}
    33193323
     
    43234327    LOG(Scrolling, "FrameView::setWasScrolledByUser at %d", wasScrolledByUser);
    43244328
    4325     m_shouldScrollToFocusedElement = false;
    4326     m_delayedScrollToFocusedElementTimer.stop();
     4329    cancelScheduledScrollToFocusedElement();
    43274330    if (currentScrollType() == ScrollType::Programmatic)
    43284331        return;
  • trunk/Source/WebCore/page/FrameView.h

    r292042 r293260  
    267267    void restoreScrollbar();
    268268    void scheduleScrollToFocusedElement(SelectionRevealMode);
     269    void cancelScheduledScrollToFocusedElement();
    269270    void scrollToFocusedElementImmediatelyIfNeeded();
    270271    void updateLayerPositionsAfterScrolling() final;
Note: See TracChangeset for help on using the changeset viewer.