Add support for scroll behavior relies on ScrollAnimation of the Web process
authorcathiechen@igalia.com <cathiechen@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Jan 2020 12:25:14 +0000 (12:25 +0000)
committercathiechen@igalia.com <cathiechen@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Jan 2020 12:25:14 +0000 (12:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204882

Reviewed by Frédéric Wang

Based on the patch by Frédéric Wang.

LayoutTests/imported/w3c:

Enable CSSOMViewSmoothScrollingEnabled on scroll behavior tests and update expectations.

* web-platform-tests/css/cssom-view/scroll-behavior-default-css-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-default-css.html:
* web-platform-tests/css/cssom-view/scroll-behavior-element-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-element.html:
* web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html:
* web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html:
* web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested.html:
* web-platform-tests/css/cssom-view/scroll-behavior-smooth-positions.html:
* web-platform-tests/css/cssom-view/scroll-behavior-subframe-root-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html:
* web-platform-tests/css/cssom-view/scroll-behavior-subframe-window-expected.txt:
* web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html:

Source/WebCore:

This patch introduces a programmatic smooth scrolling in WebKit from the CSSOM View
specification [1]. To use this effect, web developers can pass a behavior parameter (auto,
smooth, or instant) to Element.scroll, Element.scrollTo, Element.scrollBy,
Element.scrollIntoView, Window.scroll, Window.scrollTo or Window.scrollBy [2]. When behavior
is auto, the instant/smooth characteristic is actually taken from the value of a new CSS
scroll-behavior property [3]. Both the new CSS and DOM behavior are protected by a runtime
flag.

[1] https://drafts.csswg.org/cssom-view
[2] https://drafts.csswg.org/cssom-view/#dictdef-scrolloptions
[3] https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior

Tests: imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-default-css.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-element.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-smooth-positions.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html
       imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html
* Sources.txt: Build ScrollAnimationSmooth.cpp on all platforms.
* SourcesGTK.txt: Remove ScrollAnimationSmooth.cpp since it is built on all platforms now.
* dom/Element.cpp:
(WebCore::Element::scrollIntoView): Pass scroll behavior, if any.
(WebCore::Element::scrollBy):
(WebCore::Element::scrollTo): Handle the case when scroll behavior is smooth.
(WebCore::Element::setScrollLeft): Handle the case when scroll behavior is smooth.
(WebCore::Element::setScrollTop): Handle the case when scroll behavior is smooth.
* page/DOMWindow.cpp:
(WebCore::DOMWindow::scrollBy const):
(WebCore::DOMWindow::scrollTo const): Handle the case when scroll behavior is smooth.
The optimization of cancel (0, 0) scrolling is skipped if an animated scroll is in progress.
Otherwise, the previous scroll won't be stopped by a follow-up scroll.
* page/FrameView.cpp:
(WebCore::FrameView::setScrollPosition):
(WebCore::FrameView::scrollToOffsetWithAnimation): Start an animated scroll.
* page/FrameView.h:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
* platform/ScrollAnimation.h:
(WebCore::ScrollAnimation::scroll): Function to animate scrolling to a specified position.
* platform/ScrollAnimationSmooth.cpp: Build this file on all platforms. Add a
smoothFactorForProgrammaticScroll parameter to slow down the smooth scrolling.
(WebCore::ScrollAnimationSmooth::scroll):
(WebCore::ScrollAnimationSmooth::updatePerAxisData): Scale the time parameters of the
animation so that it looks smoother.
* platform/ScrollAnimationSmooth.h: Declare the class on all platforms.
* platform/ScrollAnimator.cpp:
(WebCore::ScrollAnimator::ScrollAnimator): Initialize animation member for programmatic scrolling.
(WebCore::ScrollAnimator::scrollToOffset): Animate scrolling to the specified position.
(WebCore::ScrollAnimator::cancelAnimations): Copy logic from ScrollAnimationSmooth.cpp.
(WebCore::ScrollAnimator::serviceScrollAnimations): Ditto.
(WebCore::ScrollAnimator::willEndLiveResize): Ditto.
(WebCore::ScrollAnimator::didAddVerticalScrollbar): Ditto.
(WebCore::ScrollAnimator::didAddHorizontalScrollbar): Ditto.
* platform/ScrollAnimator.h: New animation member for smooth programmatic scrolling.
(WebCore::ScrollAnimator::ScrollAnimator::cancelAnimations): Deleted.
(WebCore::ScrollAnimator::ScrollAnimator::serviceScrollAnimations): Deleted.
(WebCore::ScrollAnimator::ScrollAnimator::willEndLiveResize): Deleted.
(WebCore::ScrollAnimator::ScrollAnimator::didAddVerticalScrollbar): Deleted.
(WebCore::ScrollAnimator::ScrollAnimator::didAddHorizontalScrollbar): Deleted.
* platform/ScrollTypes.h: Add ScrollBehaviorStatus to indicate the status of scrolling.
* platform/ScrollView.cpp:
(WebCore::ScrollView::setScrollPosition): Follow the CSSOM View spec: If a scroll is in
progress, we interrupt it and continue the scroll call (even when we are at the final position).
* platform/ScrollView.h:
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::scrollToOffsetWithAnimation):
(WebCore::ScrollableArea::setScrollOffsetFromInternals):
(WebCore::ScrollableArea::setScrollOffsetFromAnimation): To avoid iterate calling,
move the requestScrollPositionUpdate(position) checking out of setScrollOffsetFromAnimation().
* platform/ScrollableArea.h:
(WebCore::ScrollableArea::currentScrollBehaviorStatus const): Maintain currentScrollBehaviorStatus.
(WebCore::ScrollableArea::setScrollBehaviorStatus):
* platform/generic/ScrollAnimatorGeneric.cpp:
(WebCore::ScrollAnimatorGeneric::updatePosition):
* platform/mac/ScrollAnimatorMac.mm:
(WebCore::ScrollAnimatorMac::cancelAnimations): Call parent member to handle programmatic scrolling.
* rendering/RenderBox.cpp:
(WebCore::RenderBox::setScrollLeft): Add flag to indicate animated or not.
(WebCore::RenderBox::setScrollTop): Ditto.
(WebCore::RenderBox::setScrollPosition):
* rendering/RenderBox.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollToXPosition): Ditto.
(WebCore::RenderLayer::scrollToYPosition): Ditto.
(WebCore::RenderLayer::scrollToPosition):
(WebCore::RenderLayer::scrollToOffset): Follow the CSSOM View spec: If a scroll is in
progress, we interrupt it and continue the scroll call (even when we are at the final
position). It's ScrollBehaviorType::Instant scroll.
(WebCore::RenderLayer::requestScrollPositionUpdate):
(WebCore::RenderLayer::scrollToOffsetWithAnimation): Ditto. This is similar to scrollToOffset
but animates the scroll. It's ScrollBehaviorType::Smooth scroll.
(WebCore::RenderLayer::scrollTo):
(WebCore::RenderLayer::scrollRectToVisible): Again don't do an early return if scroll is in
progress. We call scrollToOffsetWithAnimation instead of scrollToOffset when appropriate.
Note that this function may not work well for several nested scroll boxes with at least one
element with smooth behavior. It will handled in bug Follow.
* rendering/RenderLayer.h: Add scroll behavior to ScrollTectToVisibleOptions.
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::setScrollLeft): Add animated flag.
(WebCore::RenderListBox::setScrollTop): Ditto.
* rendering/RenderListBox.h:
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::setScrollLeft):
(WebCore::RenderTextControlSingleLine::setScrollTop):
* rendering/RenderTextControlSingleLine.h:
* testing/Internals.cpp:
(WebCore::Internals::unconstrainedScrollTo):

LayoutTests:

* platform/mac-wk1/TestExpectations: Skip these tests on WK1 as they don't work for now.

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

46 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-default-css-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-default-css.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-element-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-element.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-smooth-positions.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html
LayoutTests/platform/mac-wk1/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/SourcesGTK.txt
Source/WebCore/dom/Element.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/platform/ScrollAnimation.h
Source/WebCore/platform/ScrollAnimationSmooth.cpp
Source/WebCore/platform/ScrollAnimationSmooth.h
Source/WebCore/platform/ScrollAnimator.cpp
Source/WebCore/platform/ScrollAnimator.h
Source/WebCore/platform/ScrollTypes.h
Source/WebCore/platform/ScrollView.cpp
Source/WebCore/platform/ScrollView.h
Source/WebCore/platform/ScrollableArea.cpp
Source/WebCore/platform/ScrollableArea.h
Source/WebCore/platform/generic/ScrollAnimatorGeneric.cpp
Source/WebCore/platform/mac/ScrollAnimatorMac.mm
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderListBox.cpp
Source/WebCore/rendering/RenderListBox.h
Source/WebCore/rendering/RenderTextControlSingleLine.cpp
Source/WebCore/rendering/RenderTextControlSingleLine.h
Source/WebCore/testing/Internals.cpp

index aaa238b..749fb41 100644 (file)
@@ -1,3 +1,14 @@
+2020-01-21  Cathie Chen  <cathiechen@igalia.com>
+
+        Add support for scroll behavior relies on ScrollAnimation of the Web process
+        https://bugs.webkit.org/show_bug.cgi?id=204882
+
+        Reviewed by Frédéric Wang
+
+        Based on the patch by Frédéric Wang.
+
+        * platform/mac-wk1/TestExpectations: Skip these tests on WK1 as they don't work for now.
+
 2020-01-20  Diego Pino Garcia  <dpino@igalia.com>
 
         [GTK] Gardening, update TestExpectations and baselines
index 5e9b820..e57b537 100644 (file)
@@ -1,3 +1,30 @@
+2020-01-21  Cathie Chen  <cathiechen@igalia.com>
+
+        Add support for scroll behavior relies on ScrollAnimation of the Web process
+        https://bugs.webkit.org/show_bug.cgi?id=204882
+
+        Reviewed by Frédéric Wang
+
+        Based on the patch by Frédéric Wang.
+
+        Enable CSSOMViewSmoothScrollingEnabled on scroll behavior tests and update expectations.
+
+        * web-platform-tests/css/cssom-view/scroll-behavior-default-css-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-default-css.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-element-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-element.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-smooth-positions.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-subframe-root-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html:
+        * web-platform-tests/css/cssom-view/scroll-behavior-subframe-window-expected.txt:
+        * web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html:
+
 2020-01-20  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         Unreviewed, rolling out r254807.
index 9068b79..8d4ca64 100644 (file)
@@ -1,4 +1,4 @@
 
 PASS Instant scrolling of an element with default scroll-behavior 
-FAIL Smooth scrolling of an element with default scroll-behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Smooth scrolling of an element with default scroll-behavior 
 
index 8606b1f..eed63a0 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing default value of scroll-behavior</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index 85c489c..6b4704b 100644 (file)
@@ -2,39 +2,39 @@
 PASS Element with auto scroll-behavior ; scroll() with default behavior 
 PASS Element with auto scroll-behavior ; scroll() with auto behavior 
 PASS Element with auto scroll-behavior ; scroll() with instant behavior 
-FAIL Element with auto scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scroll() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scroll() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with auto scroll-behavior ; scroll() with smooth behavior 
+PASS Element with smooth scroll-behavior ; scroll() with default behavior 
+PASS Element with smooth scroll-behavior ; scroll() with auto behavior 
 PASS Element with smooth scroll-behavior ; scroll() with instant behavior 
-FAIL Element with smooth scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with smooth scroll-behavior ; scroll() with smooth behavior 
 PASS Element with auto scroll-behavior ; scrollTo() with default behavior 
 PASS Element with auto scroll-behavior ; scrollTo() with auto behavior 
 PASS Element with auto scroll-behavior ; scrollTo() with instant behavior 
-FAIL Element with auto scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollTo() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollTo() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with auto scroll-behavior ; scrollTo() with smooth behavior 
+PASS Element with smooth scroll-behavior ; scrollTo() with default behavior 
+PASS Element with smooth scroll-behavior ; scrollTo() with auto behavior 
 PASS Element with smooth scroll-behavior ; scrollTo() with instant behavior 
-FAIL Element with smooth scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with smooth scroll-behavior ; scrollTo() with smooth behavior 
 PASS Element with auto scroll-behavior ; scrollBy() with default behavior 
 PASS Element with auto scroll-behavior ; scrollBy() with auto behavior 
 PASS Element with auto scroll-behavior ; scrollBy() with instant behavior 
-FAIL Element with auto scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollBy() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollBy() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with auto scroll-behavior ; scrollBy() with smooth behavior 
+PASS Element with smooth scroll-behavior ; scrollBy() with default behavior 
+PASS Element with smooth scroll-behavior ; scrollBy() with auto behavior 
 PASS Element with smooth scroll-behavior ; scrollBy() with instant behavior 
-FAIL Element with smooth scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with smooth scroll-behavior ; scrollBy() with smooth behavior 
 PASS Element with auto scroll-behavior ; scrollIntoView() with default behavior 
 PASS Element with auto scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Element with auto scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Element with auto scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollIntoView() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Element with smooth scroll-behavior ; scrollIntoView() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with auto scroll-behavior ; scrollIntoView() with smooth behavior 
+PASS Element with smooth scroll-behavior ; scrollIntoView() with default behavior 
+PASS Element with smooth scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Element with smooth scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Element with smooth scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Element with smooth scroll-behavior ; scrollIntoView() with smooth behavior 
 PASS Set scrollLeft to element with auto scroll-behavior 
-FAIL Set scrollLeft to element with smooth scroll-behavior assert_less_than: Shouldn't set scroll attribute immediately expected a number less than 500 but got 500
+PASS Set scrollLeft to element with smooth scroll-behavior 
 PASS Set scrollTop to element with auto scroll-behavior 
-FAIL Set scrollTop to element with smooth scroll-behavior assert_less_than: Shouldn't set scroll attribute immediately expected a number less than 250 but got 250
+PASS Set scrollTop to element with smooth scroll-behavior 
 PASS Aborting an ongoing smooth scrolling on an element with another smooth scrolling 
 PASS Aborting an ongoing smooth scrolling on an element with an instant scrolling 
 
index c598d97..73e66d2 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior for Element.scroll* and scroll-behavior on an element</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index c3333d5..43a2078 100644 (file)
@@ -3,39 +3,39 @@ PASS Page loaded
 PASS Main frame with auto scroll-behavior ; scroll() with default behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scroll() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scroll() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scroll() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scroll() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scrollTo() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scrollBy() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollIntoView() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollIntoView() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollIntoView() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scrollIntoView() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollIntoView() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scrollIntoView() with smooth behavior 
 PASS Set scrollLeft to frame with auto scroll-behavior 
-FAIL Set scrollLeft to frame with smooth scroll-behavior assert_less_than: Shouldn't set scroll attribute immediately expected a number less than 2430 but got 2430
+PASS Set scrollLeft to frame with smooth scroll-behavior 
 PASS Set scrollTop to frame with auto scroll-behavior 
-FAIL Set scrollTop to frame with smooth scroll-behavior assert_less_than: Shouldn't set scroll attribute immediately expected a number less than 2480 but got 2480
+PASS Set scrollTop to frame with smooth scroll-behavior 
 PASS Aborting an ongoing smooth scrolling on the main frame with another smooth scrolling 
 PASS Aborting an ongoing smooth scrolling on the main frame with an instant scrolling 
 
index 8aef869..4e7b7c5 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior for Element.scroll* and scroll-behavior on the root of the main frame</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index c6be966..382385a 100644 (file)
@@ -3,27 +3,27 @@ PASS Page loaded
 PASS Main frame with auto scroll-behavior ; scroll() with default behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scroll() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scroll() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scroll() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scroll() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scrollTo() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with auto scroll-behavior ; scrollBy() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 2430 but got 2430
+PASS Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior 
 PASS Aborting an ongoing smooth scrolling on the main frame with another smooth scrolling 
 PASS Aborting an ongoing smooth scrolling on the main frame with an instant scrolling 
 
index 8024d53..9c38e16 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior for Element.scroll* on the window of the main frame</title>
 <meta name="timeout" content="long"/>
 <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
index 7ce10c0..443a820 100644 (file)
@@ -1,3 +1,3 @@
 
-FAIL scrollIntoView with nested elements with different scroll-behavior assert_less_than: Element with smooth behavior should not scroll immediately expected a number less than 500 but got 500
+PASS scrollIntoView with nested elements with different scroll-behavior 
 
index 2a97e06..ece539b 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior with scrollIntoView for nested scrolling nodes</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index 97905bb..b371c4a 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scroll positions when scrolling an element with smooth behavior</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index 88a7362..d669baa 100644 (file)
@@ -3,39 +3,39 @@ PASS iframe loaded
 PASS Subframe with auto scroll-behavior ; scroll() with default behavior 
 PASS Subframe with auto scroll-behavior ; scroll() with auto behavior 
 PASS Subframe with auto scroll-behavior ; scroll() with instant behavior 
-FAIL Subframe with auto scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scroll() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scroll() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with auto scroll-behavior ; scroll() with smooth behavior 
+PASS Subframe with smooth scroll-behavior ; scroll() with default behavior 
+PASS Subframe with smooth scroll-behavior ; scroll() with auto behavior 
 PASS Subframe with smooth scroll-behavior ; scroll() with instant behavior 
-FAIL Subframe with smooth scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with smooth scroll-behavior ; scroll() with smooth behavior 
 PASS Subframe with auto scroll-behavior ; scrollTo() with default behavior 
 PASS Subframe with auto scroll-behavior ; scrollTo() with auto behavior 
 PASS Subframe with auto scroll-behavior ; scrollTo() with instant behavior 
-FAIL Subframe with auto scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollTo() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollTo() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with auto scroll-behavior ; scrollTo() with smooth behavior 
+PASS Subframe with smooth scroll-behavior ; scrollTo() with default behavior 
+PASS Subframe with smooth scroll-behavior ; scrollTo() with auto behavior 
 PASS Subframe with smooth scroll-behavior ; scrollTo() with instant behavior 
-FAIL Subframe with smooth scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with smooth scroll-behavior ; scrollTo() with smooth behavior 
 PASS Subframe with auto scroll-behavior ; scrollBy() with default behavior 
 PASS Subframe with auto scroll-behavior ; scrollBy() with auto behavior 
 PASS Subframe with auto scroll-behavior ; scrollBy() with instant behavior 
-FAIL Subframe with auto scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollBy() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollBy() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with auto scroll-behavior ; scrollBy() with smooth behavior 
+PASS Subframe with smooth scroll-behavior ; scrollBy() with default behavior 
+PASS Subframe with smooth scroll-behavior ; scrollBy() with auto behavior 
 PASS Subframe with smooth scroll-behavior ; scrollBy() with instant behavior 
-FAIL Subframe with smooth scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with smooth scroll-behavior ; scrollBy() with smooth behavior 
 PASS Subframe with auto scroll-behavior ; scrollIntoView() with default behavior 
 PASS Subframe with auto scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Subframe with auto scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Subframe with auto scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollIntoView() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Subframe with smooth scroll-behavior ; scrollIntoView() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with auto scroll-behavior ; scrollIntoView() with smooth behavior 
+PASS Subframe with smooth scroll-behavior ; scrollIntoView() with default behavior 
+PASS Subframe with smooth scroll-behavior ; scrollIntoView() with auto behavior 
 PASS Subframe with smooth scroll-behavior ; scrollIntoView() with instant behavior 
-FAIL Subframe with smooth scroll-behavior ; scrollIntoView() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe with smooth scroll-behavior ; scrollIntoView() with smooth behavior 
 PASS Subframe setting scrollLeft with auto scroll-behavior 
-FAIL Subframe setting scrollLeft with smooth scroll-behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Subframe setting scrollLeft with smooth scroll-behavior 
 PASS Subframe setting scrollTop with auto scroll-behavior 
-FAIL Subframe setting scrollTop with smooth scroll-behavior assert_less_than: Should not set scrollTop immediately expected a number less than 250 but got 250
+PASS Subframe setting scrollTop with smooth scroll-behavior 
 PASS Aborting an ongoing smooth scrolling on a subframe with another smooth scrolling 
 PASS Aborting an ongoing smooth scrolling on a subframe with an instant scrolling 
 
index 050817d..dac8bca 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior for Element.scroll* and scroll-behavior on the root of a subframe</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index cc665eb..05eb327 100644 (file)
@@ -3,27 +3,27 @@ PASS iframe loaded
 PASS Main frame with auto scroll-behavior ; scroll() with default behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scroll() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scroll() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with auto scroll-behavior ; scroll() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scroll() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scroll() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scroll() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with smooth scroll-behavior ; scroll() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with auto scroll-behavior ; scrollTo() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollTo() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollTo() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with default behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with auto scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with auto scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with default behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with auto behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with auto scroll-behavior ; scrollBy() with smooth behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with default behavior 
+PASS Main frame with smooth scroll-behavior ; scrollBy() with auto behavior 
 PASS Main frame with smooth scroll-behavior ; scrollBy() with instant behavior 
-FAIL Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior assert_less_than: Should not set scrollLeft immediately expected a number less than 500 but got 500
+PASS Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior 
 PASS Aborting an ongoing smooth scrolling on the main frame with another smooth scrolling 
 PASS Aborting an ongoing smooth scrolling on the main frame with an instant scrolling 
 
index 0a8ed39..74aec54 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSOMViewSmoothScrollingEnabled=true ] -->
 <title>Testing scrollOptions' behavior for Element.scroll* and scroll-behavior on the root of a subframe</title>
 <meta name="timeout" content="long"/>
 <link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
index 69458c4..9b4c4a1 100644 (file)
@@ -749,6 +749,12 @@ webkit.org/b/189594 imported/w3c/web-platform-tests/css/css-animations/pending-s
 
 webkit.org/b/188070 imported/w3c/web-platform-tests/streams/piping/error-propagation-backward.html [ Pass Failure ]
 
+# Tests for smooth scroll behavior do not all work and they are slow, so let's just skip them.
+webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html [ Skip ]
+webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html [ Skip ]
+webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html [ Skip ]
+webkit.org/b/191357 imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html [ Skip ]
+
 webkit.org/b/189908 imported/w3c/web-platform-tests/resource-timing/resource_timing.worker.html [ Failure ]
 
 webkit.org/b/189756 [ Mojave+ ] compositing/filters/opacity-change-on-filtered-paints-into-ancestor.html [ Pass ImageOnlyFailure ]
index 414f00c..9b0fbf7 100644 (file)
@@ -1,3 +1,122 @@
+2020-01-21  Cathie Chen  <cathiechen@igalia.com>
+
+        Add support for scroll behavior relies on ScrollAnimation of the Web process
+        https://bugs.webkit.org/show_bug.cgi?id=204882
+
+        Reviewed by Frédéric Wang
+
+        Based on the patch by Frédéric Wang.
+
+        This patch introduces a programmatic smooth scrolling in WebKit from the CSSOM View
+        specification [1]. To use this effect, web developers can pass a behavior parameter (auto,
+        smooth, or instant) to Element.scroll, Element.scrollTo, Element.scrollBy,
+        Element.scrollIntoView, Window.scroll, Window.scrollTo or Window.scrollBy [2]. When behavior
+        is auto, the instant/smooth characteristic is actually taken from the value of a new CSS
+        scroll-behavior property [3]. Both the new CSS and DOM behavior are protected by a runtime
+        flag.
+
+        [1] https://drafts.csswg.org/cssom-view
+        [2] https://drafts.csswg.org/cssom-view/#dictdef-scrolloptions
+        [3] https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior
+
+        Tests: imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-default-css.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-element.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-root.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-main-frame-window.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-scrollintoview-nested.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-smooth-positions.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-root.html
+               imported/w3c/web-platform-tests/css/cssom-view/scroll-behavior-subframe-window.html
+        * Sources.txt: Build ScrollAnimationSmooth.cpp on all platforms.
+        * SourcesGTK.txt: Remove ScrollAnimationSmooth.cpp since it is built on all platforms now.
+        * dom/Element.cpp:
+        (WebCore::Element::scrollIntoView): Pass scroll behavior, if any.
+        (WebCore::Element::scrollBy):
+        (WebCore::Element::scrollTo): Handle the case when scroll behavior is smooth.
+        (WebCore::Element::setScrollLeft): Handle the case when scroll behavior is smooth.
+        (WebCore::Element::setScrollTop): Handle the case when scroll behavior is smooth.
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::scrollBy const):
+        (WebCore::DOMWindow::scrollTo const): Handle the case when scroll behavior is smooth.
+        The optimization of cancel (0, 0) scrolling is skipped if an animated scroll is in progress.
+        Otherwise, the previous scroll won't be stopped by a follow-up scroll.
+        * page/FrameView.cpp:
+        (WebCore::FrameView::setScrollPosition):
+        (WebCore::FrameView::scrollToOffsetWithAnimation): Start an animated scroll.
+        * page/FrameView.h:
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
+        * platform/ScrollAnimation.h:
+        (WebCore::ScrollAnimation::scroll): Function to animate scrolling to a specified position.
+        * platform/ScrollAnimationSmooth.cpp: Build this file on all platforms. Add a
+        smoothFactorForProgrammaticScroll parameter to slow down the smooth scrolling.
+        (WebCore::ScrollAnimationSmooth::scroll):
+        (WebCore::ScrollAnimationSmooth::updatePerAxisData): Scale the time parameters of the
+        animation so that it looks smoother.
+        * platform/ScrollAnimationSmooth.h: Declare the class on all platforms.
+        * platform/ScrollAnimator.cpp:
+        (WebCore::ScrollAnimator::ScrollAnimator): Initialize animation member for programmatic scrolling.
+        (WebCore::ScrollAnimator::scrollToOffset): Animate scrolling to the specified position.
+        (WebCore::ScrollAnimator::cancelAnimations): Copy logic from ScrollAnimationSmooth.cpp.
+        (WebCore::ScrollAnimator::serviceScrollAnimations): Ditto.
+        (WebCore::ScrollAnimator::willEndLiveResize): Ditto.
+        (WebCore::ScrollAnimator::didAddVerticalScrollbar): Ditto.
+        (WebCore::ScrollAnimator::didAddHorizontalScrollbar): Ditto.
+        * platform/ScrollAnimator.h: New animation member for smooth programmatic scrolling.
+        (WebCore::ScrollAnimator::ScrollAnimator::cancelAnimations): Deleted.
+        (WebCore::ScrollAnimator::ScrollAnimator::serviceScrollAnimations): Deleted.
+        (WebCore::ScrollAnimator::ScrollAnimator::willEndLiveResize): Deleted.
+        (WebCore::ScrollAnimator::ScrollAnimator::didAddVerticalScrollbar): Deleted.
+        (WebCore::ScrollAnimator::ScrollAnimator::didAddHorizontalScrollbar): Deleted.
+        * platform/ScrollTypes.h: Add ScrollBehaviorStatus to indicate the status of scrolling.
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::setScrollPosition): Follow the CSSOM View spec: If a scroll is in
+        progress, we interrupt it and continue the scroll call (even when we are at the final position).
+        * platform/ScrollView.h:
+        * platform/ScrollableArea.cpp:
+        (WebCore::ScrollableArea::scrollToOffsetWithAnimation):
+        (WebCore::ScrollableArea::setScrollOffsetFromInternals):
+        (WebCore::ScrollableArea::setScrollOffsetFromAnimation): To avoid iterate calling,
+        move the requestScrollPositionUpdate(position) checking out of setScrollOffsetFromAnimation().
+        * platform/ScrollableArea.h:
+        (WebCore::ScrollableArea::currentScrollBehaviorStatus const): Maintain currentScrollBehaviorStatus.
+        (WebCore::ScrollableArea::setScrollBehaviorStatus):
+        * platform/generic/ScrollAnimatorGeneric.cpp:
+        (WebCore::ScrollAnimatorGeneric::updatePosition):
+        * platform/mac/ScrollAnimatorMac.mm:
+        (WebCore::ScrollAnimatorMac::cancelAnimations): Call parent member to handle programmatic scrolling.
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::setScrollLeft): Add flag to indicate animated or not.
+        (WebCore::RenderBox::setScrollTop): Ditto.
+        (WebCore::RenderBox::setScrollPosition):
+        * rendering/RenderBox.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::scrollToXPosition): Ditto.
+        (WebCore::RenderLayer::scrollToYPosition): Ditto.
+        (WebCore::RenderLayer::scrollToPosition):
+        (WebCore::RenderLayer::scrollToOffset): Follow the CSSOM View spec: If a scroll is in
+        progress, we interrupt it and continue the scroll call (even when we are at the final
+        position). It's ScrollBehaviorType::Instant scroll.
+        (WebCore::RenderLayer::requestScrollPositionUpdate):
+        (WebCore::RenderLayer::scrollToOffsetWithAnimation): Ditto. This is similar to scrollToOffset
+        but animates the scroll. It's ScrollBehaviorType::Smooth scroll.
+        (WebCore::RenderLayer::scrollTo):
+        (WebCore::RenderLayer::scrollRectToVisible): Again don't do an early return if scroll is in
+        progress. We call scrollToOffsetWithAnimation instead of scrollToOffset when appropriate.
+        Note that this function may not work well for several nested scroll boxes with at least one
+        element with smooth behavior. It will handled in bug Follow.
+        * rendering/RenderLayer.h: Add scroll behavior to ScrollTectToVisibleOptions.
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::setScrollLeft): Add animated flag.
+        (WebCore::RenderListBox::setScrollTop): Ditto.
+        * rendering/RenderListBox.h:
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::setScrollLeft):
+        (WebCore::RenderTextControlSingleLine::setScrollTop):
+        * rendering/RenderTextControlSingleLine.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::unconstrainedScrollTo):
+
 2020-01-20  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         EXIF orientation is ignored for some CSS images
index cd567af..9850736 100644 (file)
@@ -1763,6 +1763,7 @@ platform/RemoteCommandListener.cpp
 platform/RuntimeApplicationChecks.cpp
 platform/SSLKeyGenerator.cpp
 platform/ScrollAnimator.cpp
+platform/ScrollAnimationSmooth.cpp
 platform/ScrollView.cpp
 platform/ScrollableArea.cpp
 platform/Scrollbar.cpp
index 7205e20..6de6532 100644 (file)
@@ -63,7 +63,6 @@ page/scrolling/nicosia/ScrollingTreeStickyNode.cpp
 page/scrolling/generic/ScrollingThreadGeneric.cpp
 
 platform/ScrollAnimationKinetic.cpp
-platform/ScrollAnimationSmooth.cpp
 platform/UserAgentQuirks.cpp
 
 platform/generic/ScrollAnimatorGeneric.cpp
index ff98eee..dea8c0c 100644 (file)
@@ -840,7 +840,6 @@ void Element::scrollIntoView(Optional<Variant<bool, ScrollIntoViewOptions>>&& ar
     bool insideFixed;
     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
 
-    // FIXME(webkit.org/b/188043): Support ScrollBehavior.
     ScrollIntoViewOptions options;
     if (arg) {
         auto value = arg.value();
@@ -859,7 +858,8 @@ void Element::scrollIntoView(Optional<Variant<bool, ScrollIntoViewOptions>>&& ar
         SelectionRevealMode::Reveal,
         isHorizontal ? alignX : alignY,
         isHorizontal ? alignY : alignX,
-        ShouldAllowCrossOriginScrolling::No
+        ShouldAllowCrossOriginScrolling::No,
+        options.behavior.valueOr(ScrollBehavior::Auto)
     };
     renderer()->scrollRectToVisible(absoluteBounds, insideFixed, visibleOptions);
 }
@@ -920,7 +920,7 @@ void Element::scrollBy(const ScrollToOptions& options)
 
 void Element::scrollBy(double x, double y)
 {
-    scrollBy({ x, y });
+    scrollBy(ScrollToOptions(x, y));
 }
 
 void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping)
@@ -956,13 +956,17 @@ void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping)
         adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer),
         adjustForAbsoluteZoom(renderer->scrollTop(), *renderer)
     );
-    renderer->setScrollLeft(clampToInteger(scrollToOptions.left.value() * renderer->style().effectiveZoom()), ScrollType::Programmatic, clamping);
-    renderer->setScrollTop(clampToInteger(scrollToOptions.top.value() * renderer->style().effectiveZoom()), ScrollType::Programmatic, clamping);
+    IntPoint scrollPosition(
+        clampToInteger(scrollToOptions.left.value() * renderer->style().effectiveZoom()),
+        clampToInteger(scrollToOptions.top.value() * renderer->style().effectiveZoom())
+    );
+    bool animated = useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), *this);
+    renderer->setScrollPosition(scrollPosition, ScrollType::Programmatic, animated, clamping);
 }
 
 void Element::scrollTo(double x, double y)
 {
-    scrollTo({ x, y });
+    scrollTo(ScrollToOptions(x, y));
 }
 
 void Element::scrollByUnits(int units, ScrollGranularity granularity)
@@ -1296,13 +1300,19 @@ void Element::setScrollLeft(int newLeft)
     document().updateLayoutIgnorePendingStylesheets();
 
     if (document().scrollingElement() == this) {
-        if (auto* frame = documentFrameWithNonNullView())
-            frame->view()->setScrollPosition(IntPoint(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY()));
+        if (auto* frame = documentFrameWithNonNullView()) {
+            // FIXME: Should we use document()->scrollingElement()?
+            // See https://bugs.webkit.org/show_bug.cgi?id=205059
+            bool animated = document().documentElement() && useSmoothScrolling(ScrollBehavior::Auto, *document().documentElement());
+            frame->view()->setScrollPosition(IntPoint(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY()), animated);
+        }
         return;
     }
 
     if (auto* renderer = renderBox()) {
-        renderer->setScrollLeft(static_cast<int>(newLeft * renderer->style().effectiveZoom()), ScrollType::Programmatic);
+        int clampedLeft = clampToInteger(newLeft * renderer->style().effectiveZoom());
+        bool animated = useSmoothScrolling(ScrollBehavior::Auto, *this);
+        renderer->setScrollLeft(clampedLeft, ScrollType::Programmatic, animated);
         if (auto* scrollableArea = renderer->layer())
             scrollableArea->setScrollShouldClearLatchedState(true);
     }
@@ -1313,13 +1323,19 @@ void Element::setScrollTop(int newTop)
     document().updateLayoutIgnorePendingStylesheets();
 
     if (document().scrollingElement() == this) {
-        if (auto* frame = documentFrameWithNonNullView())
-            frame->view()->setScrollPosition(IntPoint(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
+        if (auto* frame = documentFrameWithNonNullView()) {
+            // FIXME: Should we use document()->scrollingElement()?
+            // See https://bugs.webkit.org/show_bug.cgi?id=205059
+            bool animated = document().documentElement() && useSmoothScrolling(ScrollBehavior::Auto, *document().documentElement());
+            frame->view()->setScrollPosition(IntPoint(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor())), animated);
+        }
         return;
     }
 
     if (auto* renderer = renderBox()) {
-        renderer->setScrollTop(static_cast<int>(newTop * renderer->style().effectiveZoom()), ScrollType::Programmatic);
+        int clampedTop = clampToInteger(newTop * renderer->style().effectiveZoom());
+        bool animated = useSmoothScrolling(ScrollBehavior::Auto, *this);
+        renderer->setScrollTop(clampedTop, ScrollType::Programmatic, animated);
         if (auto* scrollableArea = renderer->layer())
             scrollableArea->setScrollShouldClearLatchedState(true);
     }
index 743b6e8..2c4576f 100644 (file)
@@ -1650,7 +1650,7 @@ double DOMWindow::devicePixelRatio() const
 
 void DOMWindow::scrollBy(double x, double y) const
 {
-    scrollBy({ x, y });
+    scrollBy(ScrollToOptions(x, y));
 }
 
 void DOMWindow::scrollBy(const ScrollToOptions& options) const
@@ -1672,10 +1672,10 @@ void DOMWindow::scrollBy(const ScrollToOptions& options) const
 
 void DOMWindow::scrollTo(double x, double y, ScrollClamping clamping) const
 {
-    scrollTo({ x, y }, clamping);
+    scrollTo(ScrollToOptions(x, y), clamping);
 }
 
-void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping) const
+void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping clamping) const
 {
     if (!isCurrentlyDisplayedInFrame())
         return;
@@ -1688,12 +1688,22 @@ void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping) const
         view->contentsScrollPosition().x(), view->contentsScrollPosition().y()
     );
 
-    if (!scrollToOptions.left.value() && !scrollToOptions.top.value() && view->contentsScrollPosition() == IntPoint(0, 0))
+    // This is an optimization for the common case of scrolling to (0, 0) when the scroller is already at the origin.
+    // If an animated scroll is in progress, this optimization is skipped to ensure that the animated scroll is really stopped.
+    if (view->currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation && !scrollToOptions.left.value() && !scrollToOptions.top.value() && view->contentsScrollPosition() == IntPoint(0, 0))
         return;
 
     document()->updateLayoutIgnorePendingStylesheets();
 
     IntPoint layoutPos(view->mapFromCSSToLayoutUnits(scrollToOptions.left.value()), view->mapFromCSSToLayoutUnits(scrollToOptions.top.value()));
+
+    // FIXME: Should we use document()->scrollingElement()?
+    // See https://bugs.webkit.org/show_bug.cgi?id=205059
+    if (document()->documentElement() && useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), *document()->documentElement())) {
+        view->scrollToOffsetWithAnimation(layoutPos, ScrollType::Programmatic, clamping);
+        return;
+    }
+
     view->setContentsScrollPosition(layoutPos);
 }
 
index 225a5da..54cb41a 100644 (file)
@@ -2279,7 +2279,7 @@ void FrameView::scrollElementToRect(const Element& element, const IntRect& rect)
     setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
 }
 
-void FrameView::setScrollPosition(const ScrollPosition& scrollPosition)
+void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, bool animated)
 {
     LOG_WITH_STREAM(Scrolling, stream << "FrameView::setScrollPosition " << scrollPosition << " , clearing anchor");
 
@@ -2292,7 +2292,10 @@ void FrameView::setScrollPosition(const ScrollPosition& scrollPosition)
     Page* page = frame().page();
     if (page && page->isMonitoringWheelEvents())
         scrollAnimator().setWheelEventTestMonitor(page->wheelEventTestMonitor());
-    ScrollView::setScrollPosition(scrollPosition);
+    if (animated)
+        scrollToOffsetWithAnimation(scrollOffsetFromPosition(scrollPosition), currentScrollType());
+    else
+        ScrollView::setScrollPosition(scrollPosition);
 
     setCurrentScrollType(oldScrollType);
 }
@@ -3658,6 +3661,19 @@ void FrameView::scrollTo(const ScrollPosition& newPosition)
     didChangeScrollOffset();
 }
 
+void FrameView::scrollToOffsetWithAnimation(const ScrollOffset& offset, ScrollType scrollType, ScrollClamping)
+{
+    auto previousScrollType = currentScrollType();
+    setCurrentScrollType(scrollType);
+
+    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
+        scrollAnimator().cancelAnimations();
+    if (offset != this->scrollOffset())
+        ScrollableArea::scrollToOffsetWithAnimation(offset);
+
+    setCurrentScrollType(previousScrollType);
+}
+
 float FrameView::adjustScrollStepForFixedContent(float step, ScrollbarOrientation orientation, ScrollGranularity granularity)
 {
     if (granularity != ScrollByPage || orientation == HorizontalScrollbar)
index f34940d..50a5b0b 100644 (file)
@@ -223,7 +223,7 @@ public:
 #if USE(COORDINATED_GRAPHICS)
     WEBCORE_EXPORT void setFixedVisibleContentRect(const IntRect&) final;
 #endif
-    WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&) final;
+    WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, bool animated = false) final;
     void restoreScrollbar();
     void scheduleScrollToFocusedElement(SelectionRevealMode);
     void scrollToFocusedElementImmediatelyIfNeeded();
@@ -659,6 +659,8 @@ public:
 
     void renderLayerDidScroll(const RenderLayer&);
 
+    WEBCORE_EXPORT void scrollToOffsetWithAnimation(const ScrollOffset&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped);
+
 protected:
     bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) final;
     void scrollContentsSlowPath(const IntRect& updateRect) final;
index b7c1d24..523a77f 100644 (file)
@@ -32,12 +32,14 @@ namespace WebCore {
 
 class FloatPoint;
 class ScrollableArea;
+enum class ScrollClamping : uint8_t;
 
 class ScrollAnimation {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     virtual ~ScrollAnimation() { };
     virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float /* step */, float /* multiplier */) { return true; };
+    virtual void scroll(const FloatPoint&) { };
     virtual void stop() = 0;
     virtual void updateVisibleLengths() { };
     virtual void setCurrentPosition(const FloatPoint&) { };
index d064e69..2ca578a 100644 (file)
@@ -28,8 +28,6 @@
 #include "config.h"
 #include "ScrollAnimationSmooth.h"
 
-#if ENABLE(SMOOTH_SCROLLING)
-
 #include "FloatPoint.h"
 #include "ScrollableArea.h"
 
@@ -38,6 +36,7 @@ namespace WebCore {
 static const double frameRate = 60;
 static const Seconds tickTime = 1_s / frameRate;
 static const Seconds minimumTimerInterval { 1_ms };
+static const double smoothFactorForProgrammaticScroll = 5;
 
 ScrollAnimationSmooth::ScrollAnimationSmooth(ScrollableArea& scrollableArea, const FloatPoint& position, WTF::Function<void (FloatPoint&&)>&& notifyPositionChangedFunction)
     : ScrollAnimation(scrollableArea)
@@ -67,9 +66,22 @@ bool ScrollAnimationSmooth::scroll(ScrollbarOrientation orientation, ScrollGranu
     return needToScroll;
 }
 
+void ScrollAnimationSmooth::scroll(const FloatPoint& position)
+{
+    ScrollGranularity granularity = ScrollByPage;
+    bool needToScroll = updatePerAxisData(m_horizontalData, granularity, position.x() - m_horizontalData.currentPosition, m_scrollableArea.minimumScrollPosition().x(), m_scrollableArea.maximumScrollPosition().x(), smoothFactorForProgrammaticScroll);
+    needToScroll |=
+        updatePerAxisData(m_verticalData, granularity, position.y() - m_verticalData.currentPosition, m_scrollableArea.minimumScrollPosition().y(), m_scrollableArea.maximumScrollPosition().y(), smoothFactorForProgrammaticScroll);
+    if (needToScroll && !animationTimerActive()) {
+        m_startTime = m_horizontalData.startTime;
+        animationTimerFired();
+    }
+};
+
 void ScrollAnimationSmooth::stop()
 {
     m_animationTimer.stop();
+    m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
 }
 
 void ScrollAnimationSmooth::updateVisibleLengths()
@@ -247,7 +259,7 @@ static inline void getAnimationParametersForGranularity(ScrollGranularity granul
     }
 }
 
-bool ScrollAnimationSmooth::updatePerAxisData(PerAxisData& data, ScrollGranularity granularity, float delta, float minScrollPosition, float maxScrollPosition)
+bool ScrollAnimationSmooth::updatePerAxisData(PerAxisData& data, ScrollGranularity granularity, float delta, float minScrollPosition, float maxScrollPosition, double smoothFactor)
 {
     if (!data.startTime || !delta || (delta < 0) != (data.desiredPosition - data.currentPosition < 0)) {
         data.desiredPosition = data.currentPosition;
@@ -264,6 +276,12 @@ bool ScrollAnimationSmooth::updatePerAxisData(PerAxisData& data, ScrollGranulari
     Curve coastTimeCurve;
     getAnimationParametersForGranularity(granularity, animationTime, repeatMinimumSustainTime, attackTime, releaseTime, coastTimeCurve, maximumCoastTime);
 
+    animationTime *= smoothFactor;
+    repeatMinimumSustainTime *= smoothFactor;
+    attackTime *= smoothFactor;
+    releaseTime *= smoothFactor;
+    maximumCoastTime *= smoothFactor;
+
     data.desiredPosition = newPosition;
     if (!data.startTime)
         data.attackTime = attackTime;
@@ -392,6 +410,8 @@ void ScrollAnimationSmooth::animationTimerFired()
 
     if (continueAnimation)
         startNextTimer(std::max(minimumTimerInterval, deltaToNextFrame));
+    else
+        m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
 
     m_notifyPositionChangedFunction(FloatPoint(m_horizontalData.currentPosition, m_verticalData.currentPosition));
 }
@@ -407,5 +427,3 @@ bool ScrollAnimationSmooth::animationTimerActive() const
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(SMOOTH_SCROLLING)
index 02cc4ee..8173fa7 100644 (file)
 
 #include "ScrollAnimation.h"
 
-#if ENABLE(SMOOTH_SCROLLING)
-
 #include "Timer.h"
 
 namespace WebCore {
 
 class FloatPoint;
 class ScrollableArea;
+enum class ScrollClamping : uint8_t;
 
 class ScrollAnimationSmooth final: public ScrollAnimation {
 public:
@@ -51,6 +50,7 @@ public:
 
 private:
     bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
+    void scroll(const FloatPoint&) override;
     void stop() override;
     void updateVisibleLengths() override;
     void setCurrentPosition(const FloatPoint&) override;
@@ -89,7 +89,7 @@ private:
         int visibleLength { 0 };
     };
 
-    bool updatePerAxisData(PerAxisData&, ScrollGranularity, float delta, float minScrollPosition, float maxScrollPosition);
+    bool updatePerAxisData(PerAxisData&, ScrollGranularity, float delta, float minScrollPosition, float maxScrollPosition, double smoothFactor = 1);
     bool animateScroll(PerAxisData&, MonotonicTime currentTime);
 
     void requestAnimationTimerFired();
@@ -108,4 +108,3 @@ private:
 
 } // namespace WebCore
 
-#endif // ENABLE(SMOOTH_SCROLLING)
index a611868..4d598c7 100644 (file)
@@ -35,6 +35,7 @@
 #include "FloatPoint.h"
 #include "LayoutSize.h"
 #include "PlatformWheelEvent.h"
+#include "ScrollAnimationSmooth.h"
 #include "ScrollableArea.h"
 #include <algorithm>
 
@@ -52,6 +53,18 @@ ScrollAnimator::ScrollAnimator(ScrollableArea& scrollableArea)
 #if ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)
     , m_scrollController(*this)
 #endif
+    , m_animationProgrammaticScroll(makeUnique<ScrollAnimationSmooth>(scrollableArea, m_currentPosition, [this](FloatPoint&& position) {
+        auto previousScrollType = m_scrollableArea.currentScrollType();
+        m_scrollableArea.setCurrentScrollType(ScrollType::Programmatic);
+        bool updated = m_scrollableArea.requestScrollPositionUpdate(roundedIntPoint(position));
+        m_scrollableArea.setCurrentScrollType(previousScrollType);
+        if (updated)
+            return;
+
+        FloatSize delta = position - m_currentPosition;
+        m_currentPosition = WTFMove(position);
+        notifyPositionChanged(delta);
+    }))
 {
 }
 
@@ -75,6 +88,14 @@ bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity,
     return true;
 }
 
+void ScrollAnimator::scrollToOffset(const FloatPoint& offset)
+{
+    m_animationProgrammaticScroll->setCurrentPosition(m_currentPosition);
+    auto newPosition = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
+    m_animationProgrammaticScroll->scroll(newPosition);
+    m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::InNonNativeAnimation);
+}
+
 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping)
 {
     FloatPoint newPositon = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
@@ -245,4 +266,33 @@ void ScrollAnimator::removeWheelEventTestCompletionDeferralForReason(WheelEventT
 }
 #endif
 
+void ScrollAnimator::cancelAnimations()
+{
+#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
+    m_animationProgrammaticScroll->stop();
+#endif
+}
+
+void ScrollAnimator::serviceScrollAnimations()
+{
+#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
+    m_animationProgrammaticScroll->serviceAnimation();
+#endif
+}
+
+void ScrollAnimator::willEndLiveResize()
+{
+    m_animationProgrammaticScroll->updateVisibleLengths();
+}
+
+void ScrollAnimator::didAddVerticalScrollbar(Scrollbar*)
+{
+    m_animationProgrammaticScroll->updateVisibleLengths();
+}
+
+void ScrollAnimator::didAddHorizontalScrollbar(Scrollbar*)
+{
+    m_animationProgrammaticScroll->updateVisibleLengths();
+}
+
 } // namespace WebCore
index a5c69c5..9b7c09b 100644 (file)
@@ -46,6 +46,7 @@ namespace WebCore {
 
 class FloatPoint;
 class PlatformTouchEvent;
+class ScrollAnimation;
 class ScrollableArea;
 class Scrollbar;
 class WheelEventTestMonitor;
@@ -68,6 +69,7 @@ public:
     // The base class implementation always scrolls immediately, never animates.
     virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
 
+    void scrollToOffset(const FloatPoint&);
     virtual void scrollToOffsetWithoutAnimation(const FloatPoint&, ScrollClamping = ScrollClamping::Clamped);
 
     ScrollableArea& scrollableArea() const { return m_scrollableArea; }
@@ -85,8 +87,8 @@ public:
     void setCurrentPosition(const FloatPoint&);
     const FloatPoint& currentPosition() const { return m_currentPosition; }
 
-    virtual void cancelAnimations() { }
-    virtual void serviceScrollAnimations() { }
+    virtual void cancelAnimations();
+    virtual void serviceScrollAnimations();
 
     virtual void contentAreaWillPaint() const { }
     virtual void mouseEnteredContentArea() { }
@@ -97,16 +99,16 @@ public:
     virtual void mouseIsDownInScrollbar(Scrollbar*, bool) const { }
     virtual void willStartLiveResize() { }
     virtual void contentsResized() const { }
-    virtual void willEndLiveResize() { }
+    virtual void willEndLiveResize();
     virtual void contentAreaDidShow() { }
     virtual void contentAreaDidHide() { }
 
     virtual void lockOverlayScrollbarStateToHidden(bool) { }
     virtual bool scrollbarsCanBeActive() const { return true; }
 
-    virtual void didAddVerticalScrollbar(Scrollbar*) { }
+    virtual void didAddVerticalScrollbar(Scrollbar*);
     virtual void willRemoveVerticalScrollbar(Scrollbar*) { }
-    virtual void didAddHorizontalScrollbar(Scrollbar*) { }
+    virtual void didAddHorizontalScrollbar(Scrollbar*);
     virtual void willRemoveHorizontalScrollbar(Scrollbar*) { }
 
     virtual void invalidateScrollbarPartLayers(Scrollbar*) { }
@@ -151,6 +153,8 @@ protected:
     ScrollController m_scrollController;
 #endif
     FloatPoint m_currentPosition;
+
+    std::unique_ptr<ScrollAnimation> m_animationProgrammaticScroll;
 };
 
 } // namespace WebCore
index 8911491..f457b15 100644 (file)
@@ -54,6 +54,13 @@ enum class ScrollPositionClamp : uint8_t {
     ToContentEdges,
 };
 
+// FIXME: Add another status InNativeAnimation to indicate native scrolling is in progress.
+// See: https://bugs.webkit.org/show_bug.cgi?id=204936
+enum class ScrollBehaviorStatus : uint8_t {
+    NotInAnimation,
+    InNonNativeAnimation,
+};
+
 inline ScrollDirection logicalToPhysical(ScrollLogicalDirection direction, bool isVertical, bool isFlipped)
 {
     switch (direction) {
index 4f2137d..2d3b6d2 100644 (file)
@@ -518,7 +518,7 @@ void ScrollView::completeUpdatesAfterScrollTo(const IntSize& scrollDelta)
     updateCompositingLayersAfterScrolling();
 }
 
-void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition)
+void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, bool/* animated*/)
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollView::setScrollPosition " << scrollPosition);
 
@@ -532,13 +532,16 @@ void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition)
 
     ScrollPosition newScrollPosition = !delegatesScrolling() ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
 
-    if ((!delegatesScrolling() || currentScrollType() == ScrollType::User) && newScrollPosition == this->scrollPosition())
+    if ((!delegatesScrolling() || currentScrollType() == ScrollType::User) && currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation && newScrollPosition == this->scrollPosition())
         return;
 
-    if (requestScrollPositionUpdate(newScrollPosition))
-        return;
+    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
+        scrollAnimator().cancelAnimations();
+
+    if (!requestScrollPositionUpdate(newScrollPosition))
+        updateScrollbars(newScrollPosition);
 
-    updateScrollbars(newScrollPosition);
+    setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
 }
 
 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
@@ -595,7 +598,8 @@ void ScrollView::updateScrollbars(const ScrollPosition& desiredPosition)
     
     if (!managesScrollbars()) {
         if (scrollOriginChanged()) {
-            ScrollableArea::scrollToOffsetWithoutAnimation(scrollOffsetFromPosition(desiredPosition));
+            if (!requestScrollPositionUpdate(desiredPosition))
+                ScrollableArea::scrollToOffsetWithoutAnimation(scrollOffsetFromPosition(desiredPosition));
             resetScrollOriginChanged();
         }
         return;
index c4aa592..1957ceb 100644 (file)
@@ -264,7 +264,7 @@ public:
     ScrollPosition cachedScrollPosition() const { return m_cachedScrollPosition; }
 
     // Functions for scrolling the view.
-    virtual void setScrollPosition(const ScrollPosition&);
+    virtual void setScrollPosition(const ScrollPosition&, bool animated = false);
     void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); }
 
     // This function scrolls by lines, pages or pixels.
index 0297295..cffea83 100644 (file)
@@ -71,6 +71,7 @@ ScrollableArea::ScrollableArea()
     , m_scrollOriginChanged(false)
     , m_currentScrollType(static_cast<unsigned>(ScrollType::User))
     , m_scrollShouldClearLatchedState(false)
+    , m_currentScrollBehaviorStatus(static_cast<unsigned>(ScrollBehaviorStatus::NotInAnimation))
 {
 }
 
@@ -142,6 +143,12 @@ bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granula
     return scrollAnimator().scroll(orientation, granularity, step, multiplier);
 }
 
+void ScrollableArea::scrollToOffsetWithAnimation(const FloatPoint& offset, ScrollClamping)
+{
+    LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea " << this << " scrollToOffsetWithAnimation " << offset);
+    scrollAnimator().scrollToOffset(offset);
+}
+
 void ScrollableArea::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping clamping)
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea " << this << " scrollToOffsetWithoutAnimation " << offset);
@@ -221,16 +228,15 @@ bool ScrollableArea::handleTouchEvent(const PlatformTouchEvent& touchEvent)
 // NOTE: Only called from Internals for testing.
 void ScrollableArea::setScrollOffsetFromInternals(const ScrollOffset& offset)
 {
+    if (requestScrollPositionUpdate(scrollPositionFromOffset(offset)))
+        return;
+
     setScrollOffsetFromAnimation(offset);
 }
 
 void ScrollableArea::setScrollOffsetFromAnimation(const ScrollOffset& offset)
 {
-    ScrollPosition position = scrollPositionFromOffset(offset);
-    if (requestScrollPositionUpdate(position))
-        return;
-
-    scrollPositionChanged(position);
+    scrollPositionChanged(scrollPositionFromOffset(offset));
 }
 
 void ScrollableArea::willStartLiveResize()
index b6d27fe..53779c3 100644 (file)
@@ -62,7 +62,11 @@ inline int offsetForOrientation(ScrollOffset offset, ScrollbarOrientation orient
 
 class ScrollableArea : public CanMakeWeakPtr<ScrollableArea> {
 public:
+    ScrollBehaviorStatus currentScrollBehaviorStatus() { return static_cast<ScrollBehaviorStatus>(m_currentScrollBehaviorStatus); }
+    void setScrollBehaviorStatus(ScrollBehaviorStatus status) { m_currentScrollBehaviorStatus = static_cast<unsigned>(status); }
+
     WEBCORE_EXPORT bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
+    WEBCORE_EXPORT void scrollToOffsetWithAnimation(const FloatPoint&, ScrollClamping = ScrollClamping::Clamped);
     WEBCORE_EXPORT void scrollToOffsetWithoutAnimation(const FloatPoint&, ScrollClamping = ScrollClamping::Clamped);
     void scrollToOffsetWithoutAnimation(ScrollbarOrientation, float offset);
 
@@ -404,6 +408,7 @@ private:
     unsigned m_scrollOriginChanged : 1;
     unsigned m_currentScrollType : 1; // ScrollType
     unsigned m_scrollShouldClearLatchedState : 1;
+    unsigned m_currentScrollBehaviorStatus : 1;
 };
 
 } // namespace WebCore
index 208af7b..ad332c3 100644 (file)
@@ -162,6 +162,8 @@ void ScrollAnimatorGeneric::willEndLiveResize()
 
 void ScrollAnimatorGeneric::updatePosition(FloatPoint&& position)
 {
+    if (m_scrollableArea.requestScrollPositionUpdate(roundedIntPoint(position)))
+        return;
     FloatSize delta = position - m_currentPosition;
     m_currentPosition = WTFMove(position);
     notifyPositionChanged(delta);
index 404261c..a415254 100644 (file)
@@ -1156,6 +1156,7 @@ void ScrollAnimatorMac::notifyContentAreaScrolled(const FloatSize& delta)
 
 void ScrollAnimatorMac::cancelAnimations()
 {
+    ScrollAnimator::cancelAnimations();
     m_haveScrolledSincePageLoad = false;
 
     if (scrollbarPaintTimerIsActive())
index 833e4df..6cc715a 100644 (file)
@@ -581,20 +581,28 @@ static void setupWheelEventMonitor(RenderLayer& layer)
     layer.scrollAnimator().setWheelEventTestMonitor(page.wheelEventTestMonitor());
 }
 
-void RenderBox::setScrollLeft(int newLeft, ScrollType scrollType, ScrollClamping clamping)
+void RenderBox::setScrollLeft(int newLeft, ScrollType scrollType, bool animated, ScrollClamping clamping)
 {
     if (!hasOverflowClip() || !layer())
         return;
     setupWheelEventMonitor(*layer());
-    layer()->scrollToXPosition(newLeft, scrollType, clamping);
+    layer()->scrollToXPosition(newLeft, scrollType, animated, clamping);
 }
 
-void RenderBox::setScrollTop(int newTop, ScrollType scrollType, ScrollClamping clamping)
+void RenderBox::setScrollTop(int newTop, ScrollType scrollType, bool animated, ScrollClamping clamping)
 {
     if (!hasOverflowClip() || !layer())
         return;
     setupWheelEventMonitor(*layer());
-    layer()->scrollToYPosition(newTop, scrollType, clamping);
+    layer()->scrollToYPosition(newTop, scrollType, animated, clamping);
+}
+
+void RenderBox::setScrollPosition(const ScrollPosition& position, ScrollType scrollType, bool animated, ScrollClamping clamping)
+{
+    if (!hasOverflowClip() || !layer())
+        return;
+    setupWheelEventMonitor(*layer());
+    layer()->scrollToPosition(position, scrollType, animated, clamping);
 }
 
 void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
index 4954814..2219280 100644 (file)
@@ -247,8 +247,9 @@ public:
     virtual int scrollTop() const;
     virtual int scrollWidth() const;
     virtual int scrollHeight() const;
-    virtual void setScrollLeft(int, ScrollType, ScrollClamping = ScrollClamping::Clamped);
-    virtual void setScrollTop(int, ScrollType, ScrollClamping = ScrollClamping::Clamped);
+    virtual void setScrollLeft(int, ScrollType, bool animated = false, ScrollClamping = ScrollClamping::Clamped);
+    virtual void setScrollTop(int, ScrollType, bool animated = false, ScrollClamping = ScrollClamping::Clamped);
+    void setScrollPosition(const ScrollPosition&, ScrollType, bool animated = false, ScrollClamping = ScrollClamping::Clamped);
 
     LayoutUnit marginTop() const override { return m_marginBox.top(); }
     LayoutUnit marginBottom() const override { return m_marginBox.bottom(); }
index d5b91b2..7f7784a 100644 (file)
@@ -2579,16 +2579,24 @@ void RenderLayer::applyPostLayoutScrollPositionIfNeeded()
     m_postLayoutScrollPosition = WTF::nullopt;
 }
 
-void RenderLayer::scrollToXPosition(int x, ScrollType scrollType, ScrollClamping clamping)
+void RenderLayer::scrollToXPosition(int x, ScrollType scrollType, bool animated, ScrollClamping clamping)
 {
     ScrollPosition position(x, m_scrollPosition.y());
-    scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
+    scrollToPosition(position, scrollType, animated, clamping);
 }
 
-void RenderLayer::scrollToYPosition(int y, ScrollType scrollType, ScrollClamping clamping)
+void RenderLayer::scrollToYPosition(int y, ScrollType scrollType, bool animated, ScrollClamping clamping)
 {
     ScrollPosition position(m_scrollPosition.x(), y);
-    scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
+    scrollToPosition(position, scrollType, animated, clamping);
+}
+
+void RenderLayer::scrollToPosition(const ScrollPosition& position, ScrollType scrollType, bool animated, ScrollClamping clamping)
+{
+    if (animated)
+        scrollToOffsetWithAnimation(scrollOffsetFromPosition(position), scrollType, clamping);
+    else
+        scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
 }
 
 ScrollOffset RenderLayer::clampScrollOffset(const ScrollOffset& scrollOffset) const
@@ -2598,6 +2606,9 @@ ScrollOffset RenderLayer::clampScrollOffset(const ScrollOffset& scrollOffset) co
 
 void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType scrollType, ScrollClamping clamping)
 {
+    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
+        scrollAnimator().cancelAnimations();
+
     ScrollOffset clampedScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset;
     if (clampedScrollOffset == this->scrollOffset())
         return;
@@ -2605,14 +2616,32 @@ void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType sc
     auto previousScrollType = currentScrollType();
     setCurrentScrollType(scrollType);
 
-    bool handled = false;
+    if (!requestScrollPositionUpdate(scrollPositionFromOffset(clampedScrollOffset)))
+        scrollToOffsetWithoutAnimation(clampedScrollOffset, clamping);
+    setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
+
+    setCurrentScrollType(previousScrollType);
+}
+
+bool RenderLayer::requestScrollPositionUpdate(const ScrollPosition& position)
+{
 #if ENABLE(ASYNC_SCROLLING)
     if (ScrollingCoordinator* scrollingCoordinator = page().scrollingCoordinator())
-        handled = scrollingCoordinator->requestScrollPositionUpdate(*this, scrollPositionFromOffset(clampedScrollOffset));
+        return scrollingCoordinator->requestScrollPositionUpdate(*this, position);
 #endif
+    return false;
+}
 
-    if (!handled)
-        scrollToOffsetWithoutAnimation(clampedScrollOffset, clamping);
+void RenderLayer::scrollToOffsetWithAnimation(const ScrollOffset& offset, ScrollType scrollType, ScrollClamping clamping)
+{
+    auto previousScrollType = currentScrollType();
+    setCurrentScrollType(scrollType);
+
+    ScrollOffset newScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(offset) : offset;
+    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
+        scrollAnimator().cancelAnimations();
+    if (newScrollOffset != this->scrollOffset())
+        ScrollableArea::scrollToOffsetWithAnimation(newScrollOffset);
 
     setCurrentScrollType(previousScrollType);
 }
@@ -2649,7 +2678,7 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
 #endif
     }
     
-    if (m_scrollPosition == newPosition) {
+    if (m_scrollPosition == newPosition && currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation) {
         // FIXME: Nothing guarantees we get a scrollTo() with an unchanged position at the end of a user gesture.
         // The ScrollingCoordinator probably needs to message the main thread when a gesture ends.
         if (requiresScrollPositionReconciliation()) {
@@ -2794,10 +2823,11 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
         LayoutRect revealRect = getRectToExpose(layerBounds, localExposeRect, insideFixed, options.alignX, options.alignY);
 
         ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(revealRect).location()));
-        if (clampedScrollOffset != scrollOffset()) {
+        if (currentScrollBehaviorStatus() != ScrollBehaviorStatus::NotInAnimation || clampedScrollOffset != scrollOffset()) {
             ScrollOffset oldScrollOffset = scrollOffset();
-            scrollToOffset(clampedScrollOffset);
-            IntSize scrollOffsetDifference = scrollOffset() - oldScrollOffset;
+            bool animated = (box->element() && useSmoothScrolling(options.behavior, *box->element()));
+            scrollToPosition(scrollPositionFromOffset(clampedScrollOffset), ScrollType::Programmatic, animated);
+            IntSize scrollOffsetDifference = clampedScrollOffset - oldScrollOffset;
             localExposeRect.move(-scrollOffsetDifference);
             newRect = LayoutRect(box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox());
         }
@@ -2817,10 +2847,13 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
                 LayoutRect viewRect = frameView.visibleContentRect(LegacyIOSDocumentVisibleRect);
                 LayoutRect exposeRect = getRectToExpose(viewRect, absoluteRect, insideFixed, options.alignX, options.alignY);
 
-                IntPoint scrollOffset(roundedIntPoint(exposeRect.location()));
+                IntPoint scrollPosition(roundedIntPoint(exposeRect.location()));
                 // Adjust offsets if they're outside of the allowable range.
-                scrollOffset = scrollOffset.constrainedBetween(IntPoint(), IntPoint(frameView.contentsSize()));
-                frameView.setScrollPosition(scrollOffset);
+                scrollPosition = scrollPosition.constrainedBetween(IntPoint(), IntPoint(frameView.contentsSize()));
+                // FIXME: Should we use contentDocument()->scrollingElement()?
+                // See https://bugs.webkit.org/show_bug.cgi?id=205059
+                bool animated = ownerElement->contentDocument() && ownerElement->contentDocument()->documentElement() && useSmoothScrolling(options.behavior, *ownerElement->contentDocument()->documentElement());
+                frameView.setScrollPosition(scrollPosition, animated);
 
                 if (options.shouldAllowCrossOriginScrolling == ShouldAllowCrossOriginScrolling::Yes || frameView.safeToPropagateScrollToParent()) {
                     parentLayer = ownerElement->renderer()->enclosingLayer();
@@ -2859,7 +2892,10 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
             // Avoid scrolling to the rounded value of revealRect.location() if we don't actually need to scroll
             if (revealRect != viewRect) {
                 ScrollOffset clampedScrollPosition = roundedIntPoint(revealRect.location()).constrainedBetween(minScrollPosition, maxScrollPosition);
-                frameView.setScrollPosition(clampedScrollPosition);
+                // FIXME: Should we use document()->scrollingElement()?
+                // See https://bugs.webkit.org/show_bug.cgi?id=205059
+                bool animated = renderer().document().documentElement() && useSmoothScrolling(options.behavior, *renderer().document().documentElement());
+                frameView.setScrollPosition(clampedScrollPosition, animated);
             }
 
             // This is the outermost view of a web page, so after scrolling this view we
index dcc345d..87b01cc 100644 (file)
@@ -50,6 +50,7 @@
 #include "PaintInfo.h"
 #include "RenderBox.h"
 #include "RenderPtr.h"
+#include "ScrollBehavior.h"
 #include "ScrollableArea.h"
 #include <memory>
 #include <wtf/WeakPtr.h>
@@ -134,6 +135,7 @@ struct ScrollRectToVisibleOptions {
     const ScrollAlignment& alignX { ScrollAlignment::alignCenterIfNeeded };
     const ScrollAlignment& alignY { ScrollAlignment::alignCenterIfNeeded };
     ShouldAllowCrossOriginScrolling shouldAllowCrossOriginScrolling { ShouldAllowCrossOriginScrolling::No };
+    ScrollBehavior behavior { ScrollBehavior::Auto };
 };
 
 DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(RenderLayer);
@@ -440,9 +442,13 @@ public:
     void scrollByRecursively(const IntSize& delta, ScrollableArea** scrolledArea = nullptr);
 
     WEBCORE_EXPORT void scrollToOffset(const ScrollOffset&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped);
+    WEBCORE_EXPORT void scrollToOffsetWithAnimation(const ScrollOffset&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped);
 
-    void scrollToXPosition(int x, ScrollType, ScrollClamping = ScrollClamping::Clamped);
-    void scrollToYPosition(int y, ScrollType, ScrollClamping = ScrollClamping::Clamped);
+    bool requestScrollPositionUpdate(const ScrollPosition&) override;
+
+    void scrollToXPosition(int x, ScrollType, bool animated, ScrollClamping = ScrollClamping::Clamped);
+    void scrollToYPosition(int y, ScrollType, bool animated, ScrollClamping = ScrollClamping::Clamped);
+    void scrollToPosition(const ScrollPosition&, ScrollType, bool animated, ScrollClamping = ScrollClamping::Clamped);
 
     // These are only used by marquee.
     void scrollToXOffset(int x) { scrollToOffset(ScrollOffset(x, scrollOffset().y()), ScrollType::Programmatic, ScrollClamping::Unclamped); }
index 25cd2d3..c33e906 100644 (file)
@@ -743,7 +743,7 @@ int RenderListBox::scrollLeft() const
     return 0;
 }
 
-void RenderListBox::setScrollLeft(int, ScrollType, ScrollClamping)
+void RenderListBox::setScrollLeft(int, ScrollType, bool, ScrollClamping)
 {
 }
 
@@ -760,7 +760,7 @@ static void setupWheelEventTestMonitor(RenderListBox& renderer)
     renderer.scrollAnimator().setWheelEventTestMonitor(renderer.page().wheelEventTestMonitor());
 }
 
-void RenderListBox::setScrollTop(int newTop, ScrollType, ScrollClamping)
+void RenderListBox::setScrollTop(int newTop, ScrollType, bool, ScrollClamping)
 {
     // Determine an index and scroll to it.    
     int index = newTop / itemHeight();
index 65d9226..25c9065 100644 (file)
@@ -106,8 +106,8 @@ private:
     int scrollTop() const override;
     int scrollWidth() const override;
     int scrollHeight() const override;
-    void setScrollLeft(int, ScrollType, ScrollClamping) override;
-    void setScrollTop(int, ScrollType, ScrollClamping) override;
+    void setScrollLeft(int, ScrollType, bool, ScrollClamping) override;
+    void setScrollTop(int, ScrollType, bool, ScrollClamping) override;
 
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
 
index 9ee8888..4df7d31 100644 (file)
@@ -376,13 +376,13 @@ int RenderTextControlSingleLine::scrollTop() const
     return RenderBlockFlow::scrollTop();
 }
 
-void RenderTextControlSingleLine::setScrollLeft(int newLeft, ScrollType, ScrollClamping)
+void RenderTextControlSingleLine::setScrollLeft(int newLeft, ScrollType, bool, ScrollClamping)
 {
     if (innerTextElement())
         innerTextElement()->setScrollLeft(newLeft);
 }
 
-void RenderTextControlSingleLine::setScrollTop(int newTop, ScrollType, ScrollClamping)
+void RenderTextControlSingleLine::setScrollTop(int newTop, ScrollType, bool, ScrollClamping)
 {
     if (innerTextElement())
         innerTextElement()->setScrollTop(newTop);
index 3f5786d..666aa31 100644 (file)
@@ -57,8 +57,8 @@ private:
     int scrollTop() const override;
     int scrollWidth() const override;
     int scrollHeight() const override;
-    void setScrollLeft(int, ScrollType, ScrollClamping) override;
-    void setScrollTop(int, ScrollType, ScrollClamping) override;
+    void setScrollLeft(int, ScrollType, bool, ScrollClamping) override;
+    void setScrollTop(int, ScrollType, bool, ScrollClamping) override;
     bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = nullptr, RenderBox* startBox = nullptr, const IntPoint& wheelEventAbsolutePoint = IntPoint()) final;
     bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = 0) final;
 
index 1cea774..a60f9cf 100644 (file)
@@ -1762,7 +1762,7 @@ ExceptionOr<void> Internals::unconstrainedScrollTo(Element& element, double x, d
     if (!document || !document->view())
         return Exception { InvalidAccessError };
 
-    element.scrollTo({ x, y }, ScrollClamping::Unclamped);
+    element.scrollTo(ScrollToOptions(x, y), ScrollClamping::Unclamped);
     return { };
 }