Changeset 271439 in webkit


Ignore:
Timestamp:
Jan 13, 2021 6:18:03 AM (18 months ago)
Author:
commit-queue@webkit.org
Message:

Scroll-snap points should be triggered during programmatic scroll
https://bugs.webkit.org/show_bug.cgi?id=145330
<rdar://problem/21467780>

Patch by Martin Robinson <mrobinson@igalia.com> on 2021-01-13
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

Update test expectations for newly passing tests and tests that now
fail in a different way.

  • web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt:
  • web-platform-tests/css/css-scroll-snap/scroll-margin-expected.txt:
  • web-platform-tests/css/css-scroll-snap/scroll-padding-expected.txt:
  • web-platform-tests/css/css-scroll-snap/scroll-snap-stop-expected.txt:
  • web-platform-tests/css/css-scroll-snap/scroll-snap-type-expected.txt:
  • web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-after-relayout/adding-snap-area-while-snapped-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-after-relayout/changing-scroll-snap-align-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-after-relayout/move-current-target-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-after-relayout/remove-current-target-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-area-capturing-add-scroll-container-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-area-capturing-remove-scroll-container-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-inline-block-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-transformed-target-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-both-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-both-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-x-axis-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-y-axis-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-x-axis-expected.txt:
  • web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-y-axis-expected.txt:
  • web-platform-tests/css/css-scroll-snap/unreachable-snap-positions-expected.txt:

Source/WebCore:

Add support for scroll snapping when scroll via DOM APIs. This change also
introduces ScrollPositionChangeOptions which holds common parameters for
operations that from DOM that set scroll position.

  • dom/Element.cpp:

(WebCore::Element::scrollBy): When calling scrollTo mark that this call is a "directional"
scroll, so that directional scroll snapping is done.
(WebCore::Element::scrollTo): Accept the new enum argument marking directional scroll
and also properly set up the ScrollPositionChangeOptions.
(WebCore::Element::setScrollLeft): Use ScrollPositionChangeOptions.
(WebCore::Element::setScrollTop): Ditto.

  • dom/Element.h: Update method definitions.
  • page/DOMWindow.cpp:

(WebCore::DOMWindow::scrollBy const): Pass the new ScrollSnapPointSelectionMethod argument
to scrollTo.
(WebCore::DOMWindow::scrollTo const): Accept the new argument and also properly instantiate
a ScrollPositionChangeOptions argument doing the scroll operation.

  • page/DOMWindow.h: Update method definitions.
  • page/FrameView.cpp:

(WebCore::FrameView::setScrollPosition): Accept the new ScrollPositionChangeOptions argument
and also properly snap the destination location based on scroll snapping rules.

  • page/FrameView.h: Update method definition.
  • page/ScrollBehavior.cpp:

(WebCore::useSmoothScrolling): Move the check which translates the scrollingElement to the
root document element here to avoid as much repetition.

  • page/scrolling/ScrollSnapOffsetsInfo.cpp:

(WebCore::closestSnapOffset): Modify argument names to clarify that this function takes
scroll offsets.

  • page/scrolling/ScrollSnapOffsetsInfo.h: ditto.
  • platform/ScrollAnimator.cpp:

(WebCore::ScrollAnimator::scroll): Change to reflect rename of adjustScrollDestinationForDirectionalSnapping.
(WebCore::ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded): Added this helper which does
snapping in both the x and the y axis.

  • platform/ScrollAnimator.h: Update method definitions.
  • platform/ScrollTypes.h: Added ScrollPositionChangeOptions and ScrollSnapPointSelectionMethod.

(WebCore::ScrollPositionChangeOptions::createProgrammatic): Added.
(WebCore::ScrollPositionChangeOptions::createUser): Added.
(WebCore::ScrollPositionChangeOptions::createProgrammaticUnclamped): Added.
(WebCore::ScrollPositionChangeOptions::setAnimated): Added.
(WebCore::ScrollPositionChangeOptions::enableDirectionalScrollSnapping): Added.

  • platform/ScrollView.cpp:

(WebCore::ScrollView::setContentsScrollPosition): Update to reflect ScrollPositionChangeOptions.
(WebCore::ScrollView::setScrollPosition): Ditto.

  • platform/ScrollView.h: Ditto.
  • platform/cocoa/ScrollController.h: Rename adjustScrollDestinationForDirectionalSnapping to

adjustScrollDestination and allow it to do non-directional snapping.

  • platform/cocoa/ScrollController.mm:

(WebCore::ScrollController::adjustScrollDestination):
(WebCore::ScrollController::adjustScrollDestinationForDirectionalSnapping): Deleted.

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::setScrollLeft): Update to reflect ScrollPositionChangeOptions.
(WebCore::RenderBox::setScrollTop): Ditto.
(WebCore::RenderBox::setScrollPosition): Ditto.

  • rendering/RenderBox.h:
  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::scrollToXPosition): Ditto.
(WebCore::RenderLayer::scrollToYPosition): Ditto.
(WebCore::RenderLayer::setScrollPosition): Ditto.
(WebCore::RenderLayer::scrollToOffset): Combine with scrollToOffset and also start doing
snapping during this operation.
(WebCore::RenderLayer::scrollRectToVisible): Create ScrollPositionChangeOptions when doing
scrolling operations.
(WebCore::RenderLayer::scrollToOffsetWithAnimation): Deleted.

  • rendering/RenderLayer.h: Update method definitions.
  • rendering/RenderListBox.cpp:

(WebCore::RenderListBox::setScrollLeft): Update to use ScrollPositionChangeOptions.
(WebCore::RenderListBox::setScrollTop): Ditto.

  • rendering/RenderListBox.h: Ditto.
  • rendering/RenderMarquee.cpp: Ditto.

(WebCore::RenderMarquee::start): Ditto.

  • rendering/RenderTextControlSingleLine.cpp: Ditto.

(WebCore::RenderTextControlSingleLine::setScrollLeft): Ditto.
(WebCore::RenderTextControlSingleLine::setScrollTop): Ditto.

  • rendering/RenderTextControlSingleLine.h: Ditto.

Source/WebKitLegacy/mac:

  • DOM/DOMHTML.mm:

(-[DOMHTMLElement setScrollXOffset:scrollYOffset:adjustForIOSCaret:]): Update to use
ScrollPositionChangeOptions.

LayoutTests:

  • platform/ios-wk2/imported/w3c/web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt: Update expectation.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-script-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-script.html: Added.
Location:
trunk
Files:
2 added
52 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r271436 r271439  
     12021-01-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Scroll-snap points should be triggered during programmatic scroll
     4        https://bugs.webkit.org/show_bug.cgi?id=145330
     5        <rdar://problem/21467780>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * platform/ios-wk2/imported/w3c/web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt: Update expectation.
     10        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-script-expected.txt: Added.
     11        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-script.html: Added.
     12
    1132021-01-13  Sergio Villar Senin  <svillar@igalia.com>
    214
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r271435 r271439  
     12021-01-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Scroll-snap points should be triggered during programmatic scroll
     4        https://bugs.webkit.org/show_bug.cgi?id=145330
     5        <rdar://problem/21467780>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Update test expectations for newly passing tests and tests that now
     10        fail in a different way.
     11
     12        * web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt:
     13        * web-platform-tests/css/css-scroll-snap/scroll-margin-expected.txt:
     14        * web-platform-tests/css/css-scroll-snap/scroll-padding-expected.txt:
     15        * web-platform-tests/css/css-scroll-snap/scroll-snap-stop-expected.txt:
     16        * web-platform-tests/css/css-scroll-snap/scroll-snap-type-expected.txt:
     17        * web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt:
     18        * web-platform-tests/css/css-scroll-snap/snap-after-relayout/adding-snap-area-while-snapped-expected.txt:
     19        * web-platform-tests/css/css-scroll-snap/snap-after-relayout/changing-scroll-snap-align-expected.txt:
     20        * web-platform-tests/css/css-scroll-snap/snap-after-relayout/move-current-target-expected.txt:
     21        * web-platform-tests/css/css-scroll-snap/snap-after-relayout/remove-current-target-expected.txt:
     22        * web-platform-tests/css/css-scroll-snap/snap-area-capturing-add-scroll-container-expected.txt:
     23        * web-platform-tests/css/css-scroll-snap/snap-area-capturing-remove-scroll-container-expected.txt:
     24        * web-platform-tests/css/css-scroll-snap/snap-inline-block-expected.txt:
     25        * web-platform-tests/css/css-scroll-snap/snap-to-transformed-target-expected.txt:
     26        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-both-expected.txt:
     27        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-both-expected.txt:
     28        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-x-axis-expected.txt:
     29        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-y-axis-expected.txt:
     30        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-x-axis-expected.txt:
     31        * web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-y-axis-expected.txt:
     32        * web-platform-tests/css/css-scroll-snap/unreachable-snap-positions-expected.txt:
     33
    1342021-01-12  Antoine Quint  <graouts@webkit.org>
    235
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps to the snap position if the snap area doesn't cover the snapport on x. assert_equals: expected 200 but got 10
    3 PASS Snaps to the snap position if the snap area covers the snapport on x on the right border.
    4 PASS Snaps to the snap position if the snap area covers the snapport on x on the left border.
    5 FAIL Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on x. assert_equals: expected 400 but got 500
    6 FAIL Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on y. assert_equals: expected 400 but got 500
    7 PASS Snap to current scroll position which is a valid snap position, as the snap area covers snapport on x and the distance between the previous(800) and next(1400) is larger than snapport(500).
    8 PASS Snap to current scroll position which is a valid snap position, as the snap area covers snapport on y and the distance between the previous(800) and next(1400) is larger than snapport(500).
    9 PASS Snap to current scroll position which is a valid snap position, as the snap area covers snapport on x and there is no subsequent snap positions.
    10 PASS Snap to current scroll position which is a valid snap position, as the snap area covers snapport on y and there is no subsequent snap positions.
    11 PASS Don't snap back even if scrollTo tries to scroll to positions which are outside of the scroll range and if a snap target element covers the snaport
    12 FAIL Snap to current scroll position on x as the area is covering x axis.However, we snap to the specified snap position on y as the area is not covering y axis. assert_equals: expected 200 but got 100
     2PASS Snaps to the snap position if the snap area doesn't cover the snapport on x.
     3FAIL Snaps to the snap position if the snap area covers the snapport on x on the right border. assert_equals: expected 2715 but got 200
     4FAIL Snaps to the snap position if the snap area covers the snapport on x on the left border. assert_equals: expected 200 but got 2715
     5PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on x.
     6PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on y.
     7FAIL Snap to current scroll position which is a valid snap position, as the snap area covers snapport on x and the distance between the previous(800) and next(1400) is larger than snapport(500). assert_equals: expected 900 but got 800
     8FAIL Snap to current scroll position which is a valid snap position, as the snap area covers snapport on y and the distance between the previous(800) and next(1400) is larger than snapport(500). assert_equals: expected 900 but got 800
     9FAIL Snap to current scroll position which is a valid snap position, as the snap area covers snapport on x and there is no subsequent snap positions. assert_equals: expected 1500 but got 1400
     10FAIL Snap to current scroll position which is a valid snap position, as the snap area covers snapport on y and there is no subsequent snap positions. assert_equals: expected 1500 but got 1400
     11FAIL Don't snap back even if scrollTo tries to scroll to positions which are outside of the scroll range and if a snap target element covers the snaport assert_equals: expected 3715 but got 2200
     12FAIL Snap to current scroll position on x as the area is covering x axis.However, we snap to the specified snap position on y as the area is not covering y axis. assert_equals: expected 10 but got 0
    1313
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-margin-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps to the positions adjusted by scroll-margin assert_equals: expected 200 but got 0
    3 FAIL scroll-margin doesn't contribute to the snap position of the element if it's outside of the scroll port assert_equals: expected 0 but got 150
     2PASS Snaps to the positions adjusted by scroll-margin
     3PASS scroll-margin doesn't contribute to the snap position of the element if it's outside of the scroll port
    44
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-padding-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps to the positions adjusted by scroll-padding assert_equals: expected 200 but got 0
     2PASS Snaps to the positions adjusted by scroll-padding
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-snap-stop-expected.txt

    r268250 r271439  
    11
    2 FAIL A scroll with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 300
    3 FAIL A scroll with intended end position should always choose the closest snap position regardless of the scroll-snap-stop value. assert_equals: expected 200 but got 300
    4 FAIL A scroll outside bounds in the snapping axis with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 1715
    5 FAIL A scroll outside bounds in the non-snapping axis with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 300
     2FAIL A scroll with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 200
     3PASS A scroll with intended end position should always choose the closest snap position regardless of the scroll-snap-stop value.
     4FAIL A scroll outside bounds in the snapping axis with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 200
     5FAIL A scroll outside bounds in the non-snapping axis with intended direction and end position should not pass a snap area with scroll-snap-stop: always. assert_equals: expected 100 but got 200
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-snap-type-expected.txt

    r268250 r271439  
    11
    2 FAIL mandatory scroll-snap-type should snap as long as the element is visible. assert_equals: expected 1000 but got 625
     2PASS mandatory scroll-snap-type should snap as long as the element is visible.
    33PASS proximity scroll-snap-type shouldn't snap if the snap position is too far away.
    4 FAIL proximity scroll-snap-type should snap if the snap position is close. assert_equals: expected 1000 but got 995
     4PASS proximity scroll-snap-type should snap if the snap position is close.
    55PASS none scroll-snap-type shouldn't snap.
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt

    r268250 r271439  
    11
    2 FAIL assign scrollLeft and scrollTop for {left: 800} on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     2PASS assign scrollLeft and scrollTop for {left: 800} on div lands on (1000, 0)
    33FAIL assign scrollLeft and scrollTop for {left: 800} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    4 FAIL scrollTo({left: 800}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
    5 FAIL scrollBy({left: 800}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     4PASS scrollTo({left: 800}) on div lands on (1000, 0)
     5PASS scrollBy({left: 800}) on div lands on (1000, 0)
    66FAIL scrollTo({left: 800}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    77FAIL scrollBy({left: 800}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    88FAIL scrollTo({left: 800}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    99FAIL scrollBy({left: 800}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    10 FAIL assign scrollLeft and scrollTop for {top: 900} on div lands on (0, 1000) assert_equals: expected 1000 but got 900
     10PASS assign scrollLeft and scrollTop for {top: 900} on div lands on (0, 1000)
    1111FAIL assign scrollLeft and scrollTop for {top: 900} on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    12 FAIL scrollTo({top: 900}) on div lands on (0, 1000) assert_equals: expected 1000 but got 900
    13 FAIL scrollBy({top: 900}) on div lands on (0, 1000) assert_equals: expected 1000 but got 900
     12PASS scrollTo({top: 900}) on div lands on (0, 1000)
     13PASS scrollBy({top: 900}) on div lands on (0, 1000)
    1414FAIL scrollTo({top: 900}) on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    1515FAIL scrollBy({top: 900}) on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    1616FAIL scrollTo({top: 900}) on window lands on (0, 1000) assert_equals: expected 1000 but got 900
    1717FAIL scrollBy({top: 900}) on window lands on (0, 1000) assert_equals: expected 1000 but got 900
    18 FAIL assign scrollLeft and scrollTop for {left: 900, top: 800} on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
     18PASS assign scrollLeft and scrollTop for {left: 900, top: 800} on div lands on (1000, 1000)
    1919FAIL assign scrollLeft and scrollTop for {left: 900, top: 800} on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    20 FAIL scrollTo({left: 900, top: 800}) on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
    21 FAIL scrollBy({left: 900, top: 800}) on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
     20PASS scrollTo({left: 900, top: 800}) on div lands on (1000, 1000)
     21PASS scrollBy({left: 900, top: 800}) on div lands on (1000, 1000)
    2222FAIL scrollTo({left: 900, top: 800}) on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2323FAIL scrollBy({left: 900, top: 800}) on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2424FAIL scrollTo({left: 900, top: 800}) on window lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2525FAIL scrollBy({left: 900, top: 800}) on window lands on (1000, 1000) assert_equals: expected 1000 but got 900
    26 FAIL assign scrollLeft and scrollTop for {left: 800, top: -100} on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     26PASS assign scrollLeft and scrollTop for {left: 800, top: -100} on div lands on (1000, 0)
    2727FAIL assign scrollLeft and scrollTop for {left: 800, top: -100} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    28 FAIL scrollTo({left: 800, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
    29 FAIL scrollBy({left: 800, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     28PASS scrollTo({left: 800, top: -100}) on div lands on (1000, 0)
     29PASS scrollBy({left: 800, top: -100}) on div lands on (1000, 0)
    3030FAIL scrollTo({left: 800, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    3131FAIL scrollBy({left: 800, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    3232FAIL scrollTo({left: 800, top: -100}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    3333FAIL scrollBy({left: 800, top: -100}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    34 FAIL assign scrollLeft and scrollTop for {left: 10000, top: -100} on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
     34PASS assign scrollLeft and scrollTop for {left: 10000, top: -100} on div lands on (1000, 0)
    3535FAIL assign scrollLeft and scrollTop for {left: 10000, top: -100} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 3215
    36 FAIL scrollTo({left: 10000, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
    37 FAIL scrollBy({left: 10000, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
     36PASS scrollTo({left: 10000, top: -100}) on div lands on (1000, 0)
     37PASS scrollBy({left: 10000, top: -100}) on div lands on (1000, 0)
    3838FAIL scrollTo({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 3215
    3939FAIL scrollBy({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 3215
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/adding-snap-area-while-snapped-expected.txt

    r268250 r271439  
    11
    2 FAIL Adding a new snap area while already snapped should not make the scroller snap to it. assert_equals: expected 100 but got 0
     2PASS Adding a new snap area while already snapped should not make the scroller snap to it.
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/changing-scroll-snap-align-expected.txt

    r268856 r271439  
    11
    2 FAIL Changing the current target's snap alignment should make the scroller resnap to it even if another snap position is closer to the current offset assert_equals: expected 100 but got 0
    3 FAIL Removing the current target's snap alignment should make the scroller resnap to a new snap area. assert_equals: expected 100 but got 0
     2PASS Changing the current target's snap alignment should make the scroller resnap to it even if another snap position is closer to the current offset
     3PASS Removing the current target's snap alignment should make the scroller resnap to a new snap area.
    44PASS Changing an element snap alignment from none to start should make thescroller resnap.
    55PASS Changing an element snap alignment from none to start by adding a class should make the scroller resnap.
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/move-current-target-expected.txt

    r268250 r271439  
    11
    2 FAIL Moving the current snap target should make the scroller resnap to it. assert_equals: expected 100 but got 0
    3 FAIL Changing the layout of other elements should be able to cause resnapping to the target. assert_equals: expected 100 but got 0
    4 FAIL Transforming the current snap target should make the scroller resnap to it. assert_equals: expected 100 but got 0
    5 FAIL Applying two property changes that do not change the visual offset of the target should not change the scroll offset. assert_equals: expected 200 but got 0
     2PASS Moving the current snap target should make the scroller resnap to it.
     3PASS Changing the layout of other elements should be able to cause resnapping to the target.
     4PASS Transforming the current snap target should make the scroller resnap to it.
     5PASS Applying two property changes that do not change the visual offset of the target should not change the scroll offset.
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/remove-current-target-expected.txt

    r268250 r271439  
    11
    2 FAIL Removing the current snap target should make the scroller snap to a new target. assert_equals: expected 100 but got 0
     2PASS Removing the current snap target should make the scroller snap to a new target.
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-area-capturing-add-scroll-container-expected.txt

    r268250 r271439  
    11
    2 FAIL Making an element scrollable should make it capture the correct descendant snap areas' snap points. assert_equals: expected 500 but got 10
    3 FAIL Attaching a new element that is scrollable should assign the correct snap areas to it. assert_equals: expected 300 but got 10
     2PASS Making an element scrollable should make it capture the correct descendant snap areas' snap points.
     3PASS Attaching a new element that is scrollable should assign the correct snap areas to it.
    44
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-area-capturing-remove-scroll-container-expected.txt

    r268856 r271439  
    11
    2 FAIL Making a snap container not scrollable should promote the next scrollable ancestor to become a snap container. assert_equals: expected 300 but got 310
     2PASS Making a snap container not scrollable should promote the next scrollable ancestor to become a snap container.
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-inline-block-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps correctly for horizontal-tb writing mode with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected 300 but got 0
    3 FAIL Snaps correctly for vertical-lr writing mode with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected 115 but got 0
    4 FAIL Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected -315 but got -500
     2FAIL Snaps correctly for horizontal-tb writing mode with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected 300 but got 115
     3PASS Snaps correctly for vertical-lr writing mode with 'scroll-snap-align: end start' alignment
     4FAIL Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected -315 but got -485
    55FAIL Snaps correctly for horizontal-tb writing mode with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected 115 but got 0
    66FAIL Snaps correctly for vertical-lr writing mode with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected 300 but got 0
    7 FAIL Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on y expected 165 but got 0
    8 FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on y expected 165 but got 0
    9 FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected -315 but got -500
     7FAIL Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected -500 but got -300
     8FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected -500 but got -300
     9FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected -315 but got -485
    1010
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-transformed-target-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps to the transformed snap start position assert_equals: expected 350 but got 10
    3 FAIL Snaps to the transformed snap end position assert_equals: expected 50 but got 10
    4 FAIL Snaps to visible top left position of the transformed box assert_equals: expected 0 but got 10
     2PASS Snaps to the transformed snap start position
     3PASS Snaps to the transformed snap end position
     4PASS Snaps to visible top left position of the transformed box
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-both-expected.txt

    r268250 r271439  
    11
    2 FAIL Only snap to visible areas in the case where taking the closest snap point of   each axis does not snap to a visible area assert_equals: expected 0 but got 500
     2FAIL Only snap to visible areas in the case where taking the closest snap point of   each axis does not snap to a visible area assert_equals: expected 0 but got 800
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-both-expected.txt

    r268250 r271439  
    11
    2 FAIL Snap to area such that only the scroll margin from both axes' areas are visible assert_equals: expected 800 but got 500
     2PASS Snap to area such that only the scroll margin from both axes' areas are visible
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-x-axis-expected.txt

    r268250 r271439  
    11
    2 FAIL Scroll margin should be considered when calculating snap area visibilty while snapping on the x-axis assert_equals: expected 700 but got 500
     2PASS Scroll margin should be considered when calculating snap area visibilty while snapping on the x-axis
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-margin-y-axis-expected.txt

    r268250 r271439  
    11
    2 FAIL Scroll margin should be considered when calculating snap area visibilty while snapping on the y-axis assert_equals: expected 700 but got 500
     2PASS Scroll margin should be considered when calculating snap area visibilty while snapping on the y-axis
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-x-axis-expected.txt

    r268250 r271439  
    11
    2 FAIL Only snap to visible area on X axis, even when the non-visible ones are closer assert_equals: expected 800 but got 500
     2FAIL Only snap to visible area on X axis, even when the non-visible ones are closer assert_equals: expected 800 but got 700
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-to-visible-areas-y-axis-expected.txt

    r268250 r271439  
    11
    2 FAIL Only snap to visible area on Y axis, even when the non-visible ones are closer assert_equals: expected 800 but got 500
     2FAIL Only snap to visible area on Y axis, even when the non-visible ones are closer assert_equals: expected 800 but got 700
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/unreachable-snap-positions-expected.txt

    r268250 r271439  
    11
    2 FAIL Snaps to the positions defined by the element as much as possible assert_equals: expected 0 but got 100
     2PASS Snaps to the positions defined by the element as much as possible
    33
  • trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/css/css-scroll-snap/scrollTo-scrollBy-snaps-expected.txt

    r268250 r271439  
    11
    2 FAIL assign scrollLeft and scrollTop for {left: 800} on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     2PASS assign scrollLeft and scrollTop for {left: 800} on div lands on (1000, 0)
    33FAIL assign scrollLeft and scrollTop for {left: 800} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    4 FAIL scrollTo({left: 800}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
    5 FAIL scrollBy({left: 800}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     4PASS scrollTo({left: 800}) on div lands on (1000, 0)
     5PASS scrollBy({left: 800}) on div lands on (1000, 0)
    66FAIL scrollTo({left: 800}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    77FAIL scrollBy({left: 800}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    88FAIL scrollTo({left: 800}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    99FAIL scrollBy({left: 800}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    10 FAIL assign scrollLeft and scrollTop for {top: 900} on div lands on (0, 1000) assert_equals: expected 1000 but got 900
     10PASS assign scrollLeft and scrollTop for {top: 900} on div lands on (0, 1000)
    1111FAIL assign scrollLeft and scrollTop for {top: 900} on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    12 FAIL scrollTo({top: 900}) on div lands on (0, 1000) assert_equals: expected 1000 but got 900
    13 FAIL scrollBy({top: 900}) on div lands on (0, 1000) assert_equals: expected 1000 but got 900
     12PASS scrollTo({top: 900}) on div lands on (0, 1000)
     13PASS scrollBy({top: 900}) on div lands on (0, 1000)
    1414FAIL scrollTo({top: 900}) on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    1515FAIL scrollBy({top: 900}) on viewport-defining element lands on (0, 1000) assert_equals: expected 1000 but got 900
    1616FAIL scrollTo({top: 900}) on window lands on (0, 1000) assert_equals: expected 1000 but got 900
    1717FAIL scrollBy({top: 900}) on window lands on (0, 1000) assert_equals: expected 1000 but got 900
    18 FAIL assign scrollLeft and scrollTop for {left: 900, top: 800} on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
     18PASS assign scrollLeft and scrollTop for {left: 900, top: 800} on div lands on (1000, 1000)
    1919FAIL assign scrollLeft and scrollTop for {left: 900, top: 800} on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    20 FAIL scrollTo({left: 900, top: 800}) on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
    21 FAIL scrollBy({left: 900, top: 800}) on div lands on (1000, 1000) assert_equals: expected 1000 but got 900
     20PASS scrollTo({left: 900, top: 800}) on div lands on (1000, 1000)
     21PASS scrollBy({left: 900, top: 800}) on div lands on (1000, 1000)
    2222FAIL scrollTo({left: 900, top: 800}) on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2323FAIL scrollBy({left: 900, top: 800}) on viewport-defining element lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2424FAIL scrollTo({left: 900, top: 800}) on window lands on (1000, 1000) assert_equals: expected 1000 but got 900
    2525FAIL scrollBy({left: 900, top: 800}) on window lands on (1000, 1000) assert_equals: expected 1000 but got 900
    26 FAIL assign scrollLeft and scrollTop for {left: 800, top: -100} on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     26PASS assign scrollLeft and scrollTop for {left: 800, top: -100} on div lands on (1000, 0)
    2727FAIL assign scrollLeft and scrollTop for {left: 800, top: -100} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    28 FAIL scrollTo({left: 800, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
    29 FAIL scrollBy({left: 800, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 800
     28PASS scrollTo({left: 800, top: -100}) on div lands on (1000, 0)
     29PASS scrollBy({left: 800, top: -100}) on div lands on (1000, 0)
    3030FAIL scrollTo({left: 800, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    3131FAIL scrollBy({left: 800, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 800
    3232FAIL scrollTo({left: 800, top: -100}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    3333FAIL scrollBy({left: 800, top: -100}) on window lands on (1000, 0) assert_equals: expected 1000 but got 800
    34 FAIL assign scrollLeft and scrollTop for {left: 10000, top: -100} on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
     34PASS assign scrollLeft and scrollTop for {left: 10000, top: -100} on div lands on (1000, 0)
    3535FAIL assign scrollLeft and scrollTop for {left: 10000, top: -100} on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 10000
    36 FAIL scrollTo({left: 10000, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
    37 FAIL scrollBy({left: 10000, top: -100}) on div lands on (1000, 0) assert_equals: expected 1000 but got 3215
     36PASS scrollTo({left: 10000, top: -100}) on div lands on (1000, 0)
     37PASS scrollBy({left: 10000, top: -100}) on div lands on (1000, 0)
    3838FAIL scrollTo({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 10000
    3939FAIL scrollBy({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0) assert_equals: expected 1000 but got 10000
  • trunk/Source/WebCore/ChangeLog

    r271437 r271439  
     12021-01-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Scroll-snap points should be triggered during programmatic scroll
     4        https://bugs.webkit.org/show_bug.cgi?id=145330
     5        <rdar://problem/21467780>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Add support for scroll snapping when scroll via DOM APIs. This change also
     10        introduces ScrollPositionChangeOptions which holds common parameters for
     11        operations that from DOM that set scroll position.
     12
     13        * dom/Element.cpp:
     14        (WebCore::Element::scrollBy): When calling scrollTo mark that this call is a "directional"
     15        scroll, so that directional scroll snapping is done.
     16        (WebCore::Element::scrollTo): Accept the new enum argument marking directional scroll
     17        and also properly set up the ScrollPositionChangeOptions.
     18        (WebCore::Element::setScrollLeft): Use ScrollPositionChangeOptions.
     19        (WebCore::Element::setScrollTop): Ditto.
     20        * dom/Element.h: Update method definitions.
     21        * page/DOMWindow.cpp:
     22        (WebCore::DOMWindow::scrollBy const): Pass the new ScrollSnapPointSelectionMethod argument
     23        to scrollTo.
     24        (WebCore::DOMWindow::scrollTo const): Accept the new argument and also properly instantiate
     25        a ScrollPositionChangeOptions argument doing the scroll operation.
     26        * page/DOMWindow.h: Update method definitions.
     27        * page/FrameView.cpp:
     28        (WebCore::FrameView::setScrollPosition): Accept the new ScrollPositionChangeOptions argument
     29        and also properly snap the destination location based on scroll snapping rules.
     30        * page/FrameView.h: Update method definition.
     31        * page/ScrollBehavior.cpp:
     32        (WebCore::useSmoothScrolling): Move the check which translates the scrollingElement to the
     33        root document element here to avoid as much repetition.
     34        * page/scrolling/ScrollSnapOffsetsInfo.cpp:
     35        (WebCore::closestSnapOffset): Modify argument names to clarify that this function takes
     36        scroll offsets.
     37        * page/scrolling/ScrollSnapOffsetsInfo.h: ditto.
     38        * platform/ScrollAnimator.cpp:
     39        (WebCore::ScrollAnimator::scroll): Change to reflect rename of adjustScrollDestinationForDirectionalSnapping.
     40        (WebCore::ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded): Added this helper which does
     41        snapping in both the x and the y axis.
     42        * platform/ScrollAnimator.h: Update method definitions.
     43        * platform/ScrollTypes.h: Added ScrollPositionChangeOptions and ScrollSnapPointSelectionMethod.
     44        (WebCore::ScrollPositionChangeOptions::createProgrammatic): Added.
     45        (WebCore::ScrollPositionChangeOptions::createUser): Added.
     46        (WebCore::ScrollPositionChangeOptions::createProgrammaticUnclamped): Added.
     47        (WebCore::ScrollPositionChangeOptions::setAnimated): Added.
     48        (WebCore::ScrollPositionChangeOptions::enableDirectionalScrollSnapping): Added.
     49        * platform/ScrollView.cpp:
     50        (WebCore::ScrollView::setContentsScrollPosition): Update to reflect ScrollPositionChangeOptions.
     51        (WebCore::ScrollView::setScrollPosition): Ditto.
     52        * platform/ScrollView.h: Ditto.
     53        * platform/cocoa/ScrollController.h: Rename adjustScrollDestinationForDirectionalSnapping to
     54        adjustScrollDestination and allow it to do non-directional snapping.
     55        * platform/cocoa/ScrollController.mm:
     56        (WebCore::ScrollController::adjustScrollDestination):
     57        (WebCore::ScrollController::adjustScrollDestinationForDirectionalSnapping): Deleted.
     58        * rendering/RenderBox.cpp:
     59        (WebCore::RenderBox::setScrollLeft): Update to reflect ScrollPositionChangeOptions.
     60        (WebCore::RenderBox::setScrollTop): Ditto.
     61        (WebCore::RenderBox::setScrollPosition): Ditto.
     62        * rendering/RenderBox.h:
     63        * rendering/RenderLayer.cpp:
     64        (WebCore::RenderLayer::scrollToXPosition): Ditto.
     65        (WebCore::RenderLayer::scrollToYPosition): Ditto.
     66        (WebCore::RenderLayer::setScrollPosition): Ditto.
     67        (WebCore::RenderLayer::scrollToOffset): Combine with scrollToOffset and also start doing
     68        snapping during this operation.
     69        (WebCore::RenderLayer::scrollRectToVisible): Create ScrollPositionChangeOptions when doing
     70        scrolling operations.
     71        (WebCore::RenderLayer::scrollToOffsetWithAnimation): Deleted.
     72        * rendering/RenderLayer.h: Update method definitions.
     73        * rendering/RenderListBox.cpp:
     74        (WebCore::RenderListBox::setScrollLeft): Update to use ScrollPositionChangeOptions.
     75        (WebCore::RenderListBox::setScrollTop): Ditto.
     76        * rendering/RenderListBox.h: Ditto.
     77        * rendering/RenderMarquee.cpp: Ditto.
     78        (WebCore::RenderMarquee::start): Ditto.
     79        * rendering/RenderTextControlSingleLine.cpp: Ditto.
     80        (WebCore::RenderTextControlSingleLine::setScrollLeft): Ditto.
     81        (WebCore::RenderTextControlSingleLine::setScrollTop): Ditto.
     82        * rendering/RenderTextControlSingleLine.h: Ditto.
     83
    1842021-01-13  Xabier Rodriguez Calvar  <calvaris@igalia.com>
    285
  • trunk/Source/WebCore/dom/Element.cpp

    r271435 r271439  
    949949    scrollToOptions.left.value() += scrollLeft();
    950950    scrollToOptions.top.value() += scrollTop();
    951     scrollTo(scrollToOptions);
     951    scrollTo(scrollToOptions, ScrollClamping::Clamped, ScrollSnapPointSelectionMethod::Directional);
    952952}
    953953
     
    957957}
    958958
    959 void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping)
     959void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping, ScrollSnapPointSelectionMethod snapPointSelectionMethod)
    960960{
    961961    if (!document().settings().CSSOMViewScrollingAPIEnabled()) {
     
    976976            return;
    977977
    978         window->scrollTo(options, clamping);
     978        window->scrollTo(options, clamping, snapPointSelectionMethod);
    979979        return;
    980980    }
     
    986986        return;
    987987
    988     ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options,
     988    auto scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options,
    989989        adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer),
    990990        adjustForAbsoluteZoom(renderer->scrollTop(), *renderer)
     
    994994        clampToInteger(scrollToOptions.top.value() * renderer->style().effectiveZoom())
    995995    );
    996     AnimatedScroll animated = useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), this) ? AnimatedScroll::Yes : AnimatedScroll::No;
    997     renderer->setScrollPosition(scrollPosition, ScrollType::Programmatic, clamping, animated);
     996
     997    auto animated = useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), this) ? AnimatedScroll::Yes : AnimatedScroll::No;
     998    auto scrollPositionChangeOptions = ScrollPositionChangeOptions::createProgrammaticWithOptions(clamping, animated, snapPointSelectionMethod);
     999    renderer->setScrollPosition(scrollPosition, scrollPositionChangeOptions);
    9981000}
    9991001
     
    13211323    document().updateLayoutIgnorePendingStylesheets();
    13221324
     1325    auto options = ScrollPositionChangeOptions::createProgrammatic();
     1326    options.animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? AnimatedScroll::Yes : AnimatedScroll::No;
     1327
    13231328    if (document().scrollingElement() == this) {
    13241329        if (auto* frame = documentFrameWithNonNullView()) {
    1325             // FIXME: Should we use document()->scrollingElement()?
    1326             // See https://bugs.webkit.org/show_bug.cgi?id=205059
    1327             AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, document().documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No;
    13281330            IntPoint position(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY());
    1329             frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated);
     1331            frame->view()->setScrollPosition(position, options);
    13301332        }
    13311333        return;
     
    13341336    if (auto* renderer = renderBox()) {
    13351337        int clampedLeft = clampToInteger(newLeft * renderer->style().effectiveZoom());
    1336         AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? AnimatedScroll::Yes : AnimatedScroll::No;
    1337         renderer->setScrollLeft(clampedLeft, ScrollType::Programmatic, ScrollClamping::Clamped, animated);
     1338        renderer->setScrollLeft(clampedLeft, options);
    13381339        if (auto* scrollableArea = renderer->layer())
    13391340            scrollableArea->setScrollShouldClearLatchedState(true);
     
    13451346    document().updateLayoutIgnorePendingStylesheets();
    13461347
     1348    auto options = ScrollPositionChangeOptions::createProgrammatic();
     1349    options.animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? AnimatedScroll::Yes : AnimatedScroll::No;
     1350
    13471351    if (document().scrollingElement() == this) {
    13481352        if (auto* frame = documentFrameWithNonNullView()) {
    1349             // FIXME: Should we use document()->scrollingElement()?
    1350             // See https://bugs.webkit.org/show_bug.cgi?id=205059
    1351             AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, document().documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No;
    13521353            IntPoint position(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor()));
    1353             frame->view()->setScrollPosition(position, ScrollClamping::Clamped, animated);
     1354            frame->view()->setScrollPosition(position, options);
    13541355        }
    13551356        return;
     
    13581359    if (auto* renderer = renderBox()) {
    13591360        int clampedTop = clampToInteger(newTop * renderer->style().effectiveZoom());
    1360         AnimatedScroll animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? AnimatedScroll::Yes : AnimatedScroll::No;
    1361         renderer->setScrollTop(clampedTop, ScrollType::Programmatic, ScrollClamping::Clamped, animated);
     1361        renderer->setScrollTop(clampedTop, options);
    13621362        if (auto* scrollableArea = renderer->layer())
    13631363            scrollableArea->setScrollShouldClearLatchedState(true);
  • trunk/Source/WebCore/dom/Element.h

    r271435 r271439  
    159159    void scrollBy(const ScrollToOptions&);
    160160    void scrollBy(double x, double y);
    161     virtual void scrollTo(const ScrollToOptions&, ScrollClamping = ScrollClamping::Clamped);
     161    virtual void scrollTo(const ScrollToOptions&, ScrollClamping = ScrollClamping::Clamped, ScrollSnapPointSelectionMethod = ScrollSnapPointSelectionMethod::Closest);
    162162    void scrollTo(double x, double y);
    163163
  • trunk/Source/WebCore/page/DOMWindow.cpp

    r271059 r271439  
    9191#include "ScheduledAction.h"
    9292#include "Screen.h"
     93#include "ScrollAnimator.h"
    9394#include "SecurityOrigin.h"
    9495#include "SecurityOriginData.h"
     
    16751676    scrollToOptions.left.value() += view->mapFromLayoutToCSSUnits(view->contentsScrollPosition().x());
    16761677    scrollToOptions.top.value() += view->mapFromLayoutToCSSUnits(view->contentsScrollPosition().y());
    1677     scrollTo(scrollToOptions);
     1678    scrollTo(scrollToOptions, ScrollClamping::Clamped, ScrollSnapPointSelectionMethod::Directional);
    16781679}
    16791680
     
    16831684}
    16841685
    1685 void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping clamping) const
     1686void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping clamping, ScrollSnapPointSelectionMethod snapPointSelectionMethod) const
    16861687{
    16871688    if (!isCurrentlyDisplayedInFrame())
     
    17071708    // FIXME: Should we use document()->scrollingElement()?
    17081709    // See https://bugs.webkit.org/show_bug.cgi?id=205059
    1709     AnimatedScroll animated = useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), document()->documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No;
    1710 
    1711     view->setContentsScrollPosition(layoutPos, clamping, animated);
     1710    auto animated = useSmoothScrolling(scrollToOptions.behavior.valueOr(ScrollBehavior::Auto), document()->documentElement()) ? AnimatedScroll::Yes : AnimatedScroll::No;
     1711    auto scrollPositionChangeOptions = ScrollPositionChangeOptions::createProgrammaticWithOptions(clamping, animated, snapPointSelectionMethod);
     1712    view->setContentsScrollPosition(layoutPos, scrollPositionChangeOptions);
    17121713}
    17131714
  • trunk/Source/WebCore/page/DOMWindow.h

    r260800 r271439  
    281281    void scrollBy(const ScrollToOptions&) const;
    282282    void scrollBy(double x, double y) const;
    283     void scrollTo(const ScrollToOptions&, ScrollClamping = ScrollClamping::Clamped) const;
     283    void scrollTo(const ScrollToOptions&, ScrollClamping = ScrollClamping::Clamped, ScrollSnapPointSelectionMethod = ScrollSnapPointSelectionMethod::Closest) const;
    284284    void scrollTo(double x, double y, ScrollClamping = ScrollClamping::Clamped) const;
    285285
  • trunk/Source/WebCore/page/FrameView.cpp

    r271019 r271439  
    23122312}
    23132313
    2314 void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll animated)
     2314void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, const ScrollPositionChangeOptions& options)
    23152315{
    23162316    LOG_WITH_STREAM(Scrolling, stream << "FrameView::setScrollPosition " << scrollPosition << " , clearing anchor");
    23172317
    23182318    auto oldScrollType = currentScrollType();
    2319     setCurrentScrollType(ScrollType::Programmatic);
     2319    setCurrentScrollType(options.type);
    23202320
    23212321    m_maintainScrollPositionAnchor = nullptr;
     
    23252325    if (page && page->isMonitoringWheelEvents())
    23262326        scrollAnimator().setWheelEventTestMonitor(page->wheelEventTestMonitor());
    2327     if (animated == AnimatedScroll::Yes)
    2328         scrollToOffsetWithAnimation(scrollOffsetFromPosition(scrollPosition), currentScrollType(), clamping);
     2327
     2328    ScrollOffset snappedOffset = ceiledIntPoint(scrollAnimator().adjustScrollOffsetForSnappingIfNeeded(scrollOffsetFromPosition(scrollPosition), options.snapPointSelectionMethod));
     2329
     2330    if (options.animated == AnimatedScroll::Yes)
     2331        scrollToOffsetWithAnimation(snappedOffset, currentScrollType(), options.clamping);
    23292332    else
    2330         ScrollView::setScrollPosition(scrollPosition, clamping);
     2333        ScrollView::setScrollPosition(scrollPositionFromOffset(snappedOffset), options);
    23312334
    23322335    setCurrentScrollType(oldScrollType);
  • trunk/Source/WebCore/page/FrameView.h

    r271019 r271439  
    240240    WEBCORE_EXPORT void setFixedVisibleContentRect(const IntRect&) final;
    241241#endif
    242     WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No) final;
     242    WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, const ScrollPositionChangeOptions& = ScrollPositionChangeOptions::createProgrammatic()) final;
    243243    void restoreScrollbar();
    244244    void scheduleScrollToFocusedElement(SelectionRevealMode);
  • trunk/Source/WebCore/page/ScrollBehavior.cpp

    r255957 r271439  
    3636bool useSmoothScrolling(ScrollBehavior behavior, Element* associatedElement)
    3737{
     38    // FIXME: Should we use document()->scrollingElement()?
     39    // See https://bugs.webkit.org/show_bug.cgi?id=205059
     40    if (associatedElement == associatedElement->document().scrollingElement())
     41        associatedElement = associatedElement->document().documentElement();
     42
    3843    if (!associatedElement
    3944        || !associatedElement->renderer()
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp

    r270838 r271439  
    101101
    102102template <typename LayoutType>
    103 static LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, LayoutType scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<LayoutType> originalPositionForDirectionalSnapping)
     103static LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, LayoutType scrollDestinationOffset, float velocity, unsigned& activeSnapIndex, Optional<LayoutType> originalOffsetForDirectionalSnapping)
    104104{
    105105    ASSERT(snapOffsets.size());
     
    108108    unsigned lowerSnapOffsetRangeIndex;
    109109    unsigned upperSnapOffsetRangeIndex;
    110     indicesOfNearestSnapOffsetRanges<LayoutType>(scrollDestination, snapOffsetRanges, lowerSnapOffsetRangeIndex, upperSnapOffsetRangeIndex);
     110    indicesOfNearestSnapOffsetRanges<LayoutType>(scrollDestinationOffset, snapOffsetRanges, lowerSnapOffsetRangeIndex, upperSnapOffsetRangeIndex);
    111111    if (lowerSnapOffsetRangeIndex == upperSnapOffsetRangeIndex && upperSnapOffsetRangeIndex != invalidSnapOffsetIndex) {
    112112        activeSnapIndex = invalidSnapOffsetIndex;
    113         return scrollDestination;
    114     }
    115 
    116     if (scrollDestination <= snapOffsets.first())
     113        return scrollDestinationOffset;
     114    }
     115
     116    if (scrollDestinationOffset <= snapOffsets.first())
    117117        return snapOffsets.first();
    118118
    119119    activeSnapIndex = snapOffsets.size() - 1;
    120     if (scrollDestination >= snapOffsets.last())
     120    if (scrollDestinationOffset >= snapOffsets.last())
    121121        return snapOffsets.last();
    122122
    123123    unsigned lowerIndex;
    124124    unsigned upperIndex;
    125     indicesOfNearestSnapOffsets<LayoutType>(scrollDestination, snapOffsets, lowerIndex, upperIndex);
     125    indicesOfNearestSnapOffsets<LayoutType>(scrollDestinationOffset, snapOffsets, lowerIndex, upperIndex);
    126126    LayoutType lowerSnapPosition = snapOffsets[lowerIndex];
    127127    LayoutType upperSnapPosition = snapOffsets[upperIndex];
    128128    if (!std::abs(velocity)) {
    129         bool isCloserToLowerSnapPosition = scrollDestination - lowerSnapPosition <= upperSnapPosition - scrollDestination;
     129        bool isCloserToLowerSnapPosition = scrollDestinationOffset - lowerSnapPosition <= upperSnapPosition - scrollDestinationOffset;
    130130        activeSnapIndex = isCloserToLowerSnapPosition ? lowerIndex : upperIndex;
    131131        return isCloserToLowerSnapPosition ? lowerSnapPosition : upperSnapPosition;
     
    142142        }
    143143
    144         if (!originalPositionForDirectionalSnapping.hasValue() || *originalPositionForDirectionalSnapping > upperSnapPosition) {
     144        if (!originalOffsetForDirectionalSnapping.hasValue() || *originalOffsetForDirectionalSnapping > upperSnapPosition) {
    145145            activeSnapIndex = upperIndex;
    146146            return upperSnapPosition;
     
    152152        }
    153153
    154         if (!originalPositionForDirectionalSnapping.hasValue() || *originalPositionForDirectionalSnapping < lowerSnapPosition) {
     154        if (!originalOffsetForDirectionalSnapping.hasValue() || *originalOffsetForDirectionalSnapping < lowerSnapPosition) {
    155155            activeSnapIndex = lowerIndex;
    156156            return lowerSnapPosition;
     
    159159
    160160    activeSnapIndex = invalidSnapOffsetIndex;
    161     return scrollDestination;
    162 }
    163 
    164 LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<LayoutUnit> originalPositionForDirectionalSnapping)
    165 {
    166     return closestSnapOffset<LayoutUnit>(snapOffsets, snapOffsetRanges, scrollDestination, velocity, activeSnapIndex, originalPositionForDirectionalSnapping);
    167 }
    168 
    169 float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<float> originalPositionForDirectionalSnapping)
    170 {
    171     return closestSnapOffset<float>(snapOffsets, snapOffsetRanges, scrollDestination, velocity, activeSnapIndex, originalPositionForDirectionalSnapping);
     161    return scrollDestinationOffset;
     162}
     163
     164LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestinationOffset, float velocity, unsigned& activeSnapIndex, Optional<LayoutUnit> originalOffsetForDirectionalSnapping)
     165{
     166    return closestSnapOffset<LayoutUnit>(snapOffsets, snapOffsetRanges, scrollDestinationOffset, velocity, activeSnapIndex, originalOffsetForDirectionalSnapping);
     167}
     168
     169float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestinationOffset, float velocity, unsigned& activeSnapIndex, Optional<float> originalOffsetForDirectionalSnapping)
     170{
     171    return closestSnapOffset<float>(snapOffsets, snapOffsetRanges, scrollDestinationOffset, velocity, activeSnapIndex, originalOffsetForDirectionalSnapping);
    172172}
    173173
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h

    r270838 r271439  
    6767void updateSnapOffsetsForScrollableArea(ScrollableArea&, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle, LayoutRect viewportRectInBorderBoxCoordinates);
    6868
    69 WEBCORE_EXPORT LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<LayoutUnit> originalPositionForDirectionalSnapping = WTF::nullopt);
    70 WEBCORE_EXPORT float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<float> originalPositionForDirectionalSnapping = WTF::nullopt);
     69WEBCORE_EXPORT LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestinationOffset, float velocity, unsigned& activeSnapIndex, Optional<LayoutUnit> originalPositionForDirectionalSnapping = WTF::nullopt);
     70WEBCORE_EXPORT float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestinationOffset, float velocity, unsigned& activeSnapIndex, Optional<float> originalPositionForDirectionalSnapping = WTF::nullopt);
    7171
    7272}; // namespace WebCore
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r270838 r271439  
    9292    auto currentOffset = ScrollableArea::scrollOffsetFromPosition(this->currentPosition(), scrollOrigin);
    9393    if (orientation == HorizontalScrollbar) {
    94         newOffset.setX(m_scrollController.adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis::Horizontal, newOffset.x(), multiplier, currentOffset.x()));
     94        newOffset.setX(m_scrollController.adjustScrollDestination(ScrollEventAxis::Horizontal, newOffset.x(), multiplier, currentOffset.x()));
    9595        newPosition = ScrollableArea::scrollPositionFromOffset(newOffset, scrollOrigin);
    9696        return scroll(HorizontalScrollbar, granularity, newPosition.x() - this->currentPosition().x(), 1.0);
    9797    }
    9898
    99     newOffset.setY(m_scrollController.adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis::Vertical, newPosition.y(), multiplier, currentOffset.y()));
     99    newOffset.setY(m_scrollController.adjustScrollDestination(ScrollEventAxis::Vertical, newPosition.y(), multiplier, currentOffset.y()));
    100100    newPosition = ScrollableArea::scrollPositionFromOffset(newOffset, scrollOrigin);
    101101    return scroll(VerticalScrollbar, granularity, newPosition.y() - this->currentPosition().y(), 1.0);
     
    355355}
    356356
     357FloatPoint ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded(const FloatPoint& offset, ScrollSnapPointSelectionMethod method)
     358{
     359#if ENABLE(CSS_SCROLL_SNAP)
     360    if (!m_scrollController.usesScrollSnap())
     361        return offset;
     362
     363    Optional<float> originalXOffset, originalYOffset;
     364    FloatSize velocity;
     365    if (method == ScrollSnapPointSelectionMethod::Directional) {
     366        FloatSize scrollOrigin = toFloatSize(m_scrollableArea.scrollOrigin());
     367        auto currentOffset = ScrollableArea::scrollOffsetFromPosition(this->currentPosition(), scrollOrigin);
     368        originalXOffset = currentOffset.x();
     369        originalYOffset = currentOffset.y();
     370        velocity = { offset.x() - currentOffset.x(), offset.y() - currentOffset.y() };
     371    }
     372
     373    FloatPoint newOffset = offset;
     374    newOffset.setX(m_scrollController.adjustScrollDestination(ScrollEventAxis::Horizontal, newOffset.x(), velocity.width(), originalXOffset));
     375    newOffset.setY(m_scrollController.adjustScrollDestination(ScrollEventAxis::Vertical, newOffset.y(), velocity.height(), originalYOffset));
     376    return newOffset;
     377#else
     378    return offset;
     379#endif
     380}
     381
     382
    357383} // namespace WebCore
  • trunk/Source/WebCore/platform/ScrollAnimator.h

    r270838 r271439  
    3838#include <wtf/FastMalloc.h>
    3939#include <wtf/Forward.h>
     40#include <wtf/Optional.h>
    4041
    4142#if ENABLE(RUBBER_BANDING) || ENABLE(CSS_SCROLL_SNAP)
     
    139140    void setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&& testMonitor) { m_wheelEventTestMonitor = testMonitor; }
    140141
     142    FloatPoint adjustScrollOffsetForSnappingIfNeeded(const FloatPoint& offset, ScrollSnapPointSelectionMethod);
     143
    141144#if ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)
    142145    std::unique_ptr<ScrollControllerTimer> createTimer(Function<void()>&&) final;
  • trunk/Source/WebCore/platform/ScrollTypes.h

    r270613 r271439  
    2626#pragma once
    2727
     28#include "FloatPoint.h"
    2829#include "IntPoint.h"
    2930#include <cstdint>
     
    250251};
    251252
     253// This value controls the method used to select snap points during scrolling. This may either
     254// be "directional" or "closest." The directional method only chooses snap points that are at or
     255// beyond the scroll destination in the direction of the scroll. The "closest" method does not
     256// have this constraint.
     257enum class ScrollSnapPointSelectionMethod : uint8_t {
     258    Directional,
     259    Closest,
     260};
     261
    252262using ScrollbarControlState = unsigned;
    253263using ScrollbarControlPartMask = unsigned;
     
    257267WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollClamping);
    258268WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollBehaviorForFixedElements);
     269
     270struct ScrollPositionChangeOptions {
     271    ScrollType type;
     272    ScrollClamping clamping = ScrollClamping::Clamped;
     273    AnimatedScroll animated = AnimatedScroll::No;
     274    ScrollSnapPointSelectionMethod snapPointSelectionMethod = ScrollSnapPointSelectionMethod::Closest;
     275
     276    static ScrollPositionChangeOptions createProgrammatic()
     277    {
     278        return { ScrollType::Programmatic };
     279    }
     280
     281    static ScrollPositionChangeOptions createProgrammaticWithOptions(ScrollClamping clamping, AnimatedScroll animated, ScrollSnapPointSelectionMethod snapPointSelectionMethod)
     282    {
     283        return { ScrollType::Programmatic, clamping, animated, snapPointSelectionMethod };
     284    }
     285
     286    static ScrollPositionChangeOptions createUser()
     287    {
     288        return { ScrollType::User };
     289    }
     290
     291    static ScrollPositionChangeOptions createProgrammaticUnclamped()
     292    {
     293        return { ScrollType::Programmatic, ScrollClamping::Unclamped };
     294    }
     295};
    259296
    260297} // namespace WebCore
  • trunk/Source/WebCore/platform/ScrollView.cpp

    r264627 r271439  
    208208}
    209209
    210 void ScrollView::setContentsScrollPosition(const IntPoint& position, ScrollClamping clamping, AnimatedScroll animated)
     210void ScrollView::setContentsScrollPosition(const IntPoint& position, const ScrollPositionChangeOptions& options)
    211211{
    212212#if PLATFORM(IOS_FAMILY)
     
    214214        setActualScrollPosition(position);
    215215#endif
    216     setScrollPosition(position, clamping, animated);
     216    setScrollPosition(position, options);
    217217}
    218218
     
    515515}
    516516
    517 void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping, AnimatedScroll/* animated*/)
     517void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, const ScrollPositionChangeOptions& options)
    518518{
    519519    LOG_WITH_STREAM(Scrolling, stream << "ScrollView::setScrollPosition " << scrollPosition);
     
    530530        scrollAnimator().cancelAnimations();
    531531
    532     ScrollPosition newScrollPosition = (!delegatesScrolling() && clamping == ScrollClamping::Clamped) ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
     532    ScrollPosition newScrollPosition = (!delegatesScrolling() && options.clamping == ScrollClamping::Clamped) ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
    533533    if ((!delegatesScrolling() || currentScrollType() == ScrollType::User) && currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation && newScrollPosition == this->scrollPosition())
    534534        return;
    535535
    536     if (!requestScrollPositionUpdate(newScrollPosition, currentScrollType(), clamping))
     536    if (!requestScrollPositionUpdate(newScrollPosition, currentScrollType(), options.clamping))
    537537        updateScrollbars(newScrollPosition);
    538538
  • trunk/Source/WebCore/platform/ScrollView.h

    r264627 r271439  
    245245    // Scroll position used by web-exposed features (has legacy iOS behavior).
    246246    WEBCORE_EXPORT IntPoint contentsScrollPosition() const;
    247     void setContentsScrollPosition(const IntPoint&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
     247    void setContentsScrollPosition(const IntPoint&, const ScrollPositionChangeOptions& = ScrollPositionChangeOptions::createProgrammatic());
    248248
    249249#if PLATFORM(IOS_FAMILY)
     
    275275
    276276    // Functions for scrolling the view.
    277     virtual void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
     277    virtual void setScrollPosition(const ScrollPosition&, const ScrollPositionChangeOptions& = ScrollPositionChangeOptions::createProgrammatic());
    278278
    279279    void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); }
  • trunk/Source/WebCore/platform/cocoa/ScrollController.h

    r271081 r271439  
    167167    void updateScrollSnapState(const ScrollableArea&);
    168168    void updateGestureInProgressState(const PlatformWheelEvent&);
    169     float adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis, float destination, float velocity, float originalPosition);
     169    float adjustScrollDestination(ScrollEventAxis, float destinationOffset, float velocity, Optional<float> originalOffset);
    170170#if PLATFORM(MAC)
    171171    // Returns true if handled.
  • trunk/Source/WebCore/platform/cocoa/ScrollController.mm

    r271081 r271439  
    905905}
    906906
    907 float ScrollController::adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis axis, float destination, float velocity, float originalPosition)
     907float ScrollController::adjustScrollDestination(ScrollEventAxis axis, float destinationOffset, float velocity, Optional<float> originalOffset)
    908908{
    909909    if (!usesScrollSnap())
    910         return destination;
     910        return destinationOffset;
    911911
    912912    ScrollSnapAnimatorState& snapState = *m_scrollSnapState;
    913913    auto snapOffsets = snapState.snapOffsetsForAxis(axis);
    914914    if (!snapOffsets.size())
    915         return destination;
     915        return destinationOffset;
    916916
    917917    unsigned snapIndex;
    918     LayoutUnit offset = closestSnapOffset(snapState.snapOffsetsForAxis(axis), snapState.snapOffsetRangesForAxis(axis), LayoutUnit(destination / m_client.pageScaleFactor()), velocity, snapIndex, LayoutUnit(originalPosition / m_client.pageScaleFactor()));
     918    Optional<LayoutUnit> originalOffsetInLayoutUnits;
     919    if (originalOffset.hasValue())
     920        originalOffsetInLayoutUnits = LayoutUnit(*originalOffset / m_client.pageScaleFactor());
     921    LayoutUnit offset = closestSnapOffset(snapState.snapOffsetsForAxis(axis), snapState.snapOffsetRangesForAxis(axis), LayoutUnit(destinationOffset / m_client.pageScaleFactor()), velocity, snapIndex, originalOffsetInLayoutUnits);
    919922    return offset * m_client.pageScaleFactor();
    920923}
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r271375 r271439  
    594594}
    595595
    596 void RenderBox::setScrollLeft(int newLeft, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
     596void RenderBox::setScrollLeft(int newLeft, const ScrollPositionChangeOptions& options)
    597597{
    598598    if (!hasOverflowClip() || !layer())
    599599        return;
    600600    setupWheelEventMonitor(*layer());
    601     layer()->scrollToXPosition(newLeft, scrollType, clamping, animated);
    602 }
    603 
    604 void RenderBox::setScrollTop(int newTop, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
     601    layer()->scrollToXPosition(newLeft, options);
     602}
     603
     604void RenderBox::setScrollTop(int newTop, const ScrollPositionChangeOptions& options)
    605605{
    606606    if (!hasOverflowClip() || !layer())
    607607        return;
    608608    setupWheelEventMonitor(*layer());
    609     layer()->scrollToYPosition(newTop, scrollType, clamping, animated);
    610 }
    611 
    612 void RenderBox::setScrollPosition(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
     609    layer()->scrollToYPosition(newTop, options);
     610}
     611
     612void RenderBox::setScrollPosition(const ScrollPosition& position, const ScrollPositionChangeOptions& options)
    613613{
    614614    if (!hasOverflowClip() || !layer())
    615615        return;
    616616    setupWheelEventMonitor(*layer());
    617     layer()->setScrollPosition(position, scrollType, clamping, animated);
     617    layer()->setScrollPosition(position, options);
    618618}
    619619
  • trunk/Source/WebCore/rendering/RenderBox.h

    r271375 r271439  
    2626#include "RenderBoxModelObject.h"
    2727#include "RenderOverflow.h"
     28#include "ScrollSnapOffsetsInfo.h"
    2829#include "ScrollTypes.h"
    2930#include "ShapeOutsideInfo.h"
     
    250251    virtual int scrollWidth() const;
    251252    virtual int scrollHeight() const;
    252     virtual void setScrollLeft(int, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
    253     virtual void setScrollTop(int, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
    254     void setScrollPosition(const ScrollPosition&, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
     253    virtual void setScrollLeft(int, const ScrollPositionChangeOptions&);
     254    virtual void setScrollTop(int, const ScrollPositionChangeOptions&);
     255    void setScrollPosition(const ScrollPosition&, const ScrollPositionChangeOptions&);
    255256
    256257    LayoutUnit marginTop() const override { return m_marginBox.top(); }
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r270850 r271439  
    25982598}
    25992599
    2600 void RenderLayer::scrollToXPosition(int x, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
     2600void RenderLayer::scrollToXPosition(int x, const ScrollPositionChangeOptions& options)
    26012601{
    26022602    ScrollPosition position(x, m_scrollPosition.y());
    2603     setScrollPosition(position, scrollType, clamping, animated);
    2604 }
    2605 
    2606 void RenderLayer::scrollToYPosition(int y, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
     2603    setScrollPosition(position, options);
     2604}
     2605
     2606void RenderLayer::scrollToYPosition(int y, const ScrollPositionChangeOptions& options)
    26072607{
    26082608    ScrollPosition position(m_scrollPosition.x(), y);
    2609     setScrollPosition(position, scrollType, clamping, animated);
    2610 }
    2611 
    2612 void RenderLayer::setScrollPosition(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping, AnimatedScroll animated)
    2613 {
    2614     if (animated == AnimatedScroll::Yes)
    2615         scrollToOffsetWithAnimation(scrollOffsetFromPosition(position), scrollType, clamping);
    2616     else
    2617         scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
     2609    setScrollPosition(position, options);
     2610}
     2611
     2612void RenderLayer::setScrollPosition(const ScrollPosition& position, const ScrollPositionChangeOptions& options)
     2613{
     2614    scrollToOffset(scrollOffsetFromPosition(position), options);
    26182615}
    26192616
     
    26342631}
    26352632
    2636 void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType scrollType, ScrollClamping clamping)
     2633void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, const ScrollPositionChangeOptions& options)
    26372634{
    26382635    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
    26392636        scrollAnimator().cancelAnimations();
    26402637
    2641     ScrollOffset clampedScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset;
     2638    ScrollOffset clampedScrollOffset = options.clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset;
    26422639    if (clampedScrollOffset == this->scrollOffset())
    26432640        return;
    26442641
    26452642    auto previousScrollType = currentScrollType();
    2646     setCurrentScrollType(scrollType);
    2647 
    2648     if (!requestScrollPositionUpdate(scrollPositionFromOffset(clampedScrollOffset), scrollType, clamping))
    2649         scrollToOffsetWithoutAnimation(clampedScrollOffset, clamping);
    2650     setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
    2651 
    2652     setCurrentScrollType(previousScrollType);
    2653 }
    2654 
    2655 void RenderLayer::scrollToOffsetWithAnimation(const ScrollOffset& offset, ScrollType scrollType, ScrollClamping clamping)
    2656 {
    2657     auto previousScrollType = currentScrollType();
    2658     setCurrentScrollType(scrollType);
    2659 
    2660     ScrollOffset newScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(offset) : offset;
    2661     if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
    2662         scrollAnimator().cancelAnimations();
    2663     if (newScrollOffset != this->scrollOffset())
    2664         ScrollableArea::scrollToOffsetWithAnimation(newScrollOffset);
     2643    setCurrentScrollType(options.type);
     2644
     2645    ScrollOffset snappedOffset = ceiledIntPoint(scrollAnimator().adjustScrollOffsetForSnappingIfNeeded(clampedScrollOffset, options.snapPointSelectionMethod));
     2646    if (options.animated == AnimatedScroll::Yes)
     2647        ScrollableArea::scrollToOffsetWithAnimation(snappedOffset);
     2648    else {
     2649        auto snappedPosition = scrollPositionFromOffset(snappedOffset);
     2650        if (!requestScrollPositionUpdate(snappedPosition, options.type, options.clamping))
     2651            scrollToOffsetWithoutAnimation(snappedOffset, options.clamping);
     2652        setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
     2653    }
    26652654
    26662655    setCurrentScrollType(previousScrollType);
     
    28232812    auto* parentLayer = enclosingContainingBlockLayer(*this, CrossFrameBoundaries::No);
    28242813
    2825     auto shouldUseAnimatedScroll = [this](Element* element, ScrollBehavior behavior)
     2814    auto scrollPositionChangeOptionsForElement = [this, options](Element* element)
    28262815    {
    2827         bool useAnimatedScrolling = !renderer().frame().eventHandler().autoscrollInProgress()
    2828             && element && useSmoothScrolling(behavior, element);
    2829         return useAnimatedScrolling ? AnimatedScroll::Yes : AnimatedScroll::No;
     2816        auto scrollPositionOptions = ScrollPositionChangeOptions::createProgrammatic();
     2817        if (!renderer().frame().eventHandler().autoscrollInProgress() && element && useSmoothScrolling(options.behavior, element))
     2818            scrollPositionOptions.animated = AnimatedScroll::Yes;
     2819        return scrollPositionOptions;
    28302820    };
    28312821
     
    28532843        if (clampedScrollOffset != scrollOffset() || currentScrollBehaviorStatus() != ScrollBehaviorStatus::NotInAnimation) {
    28542844            ScrollOffset oldScrollOffset = scrollOffset();
    2855             auto animated = shouldUseAnimatedScroll(box->element(), options.behavior);
    2856             setScrollPosition(scrollPositionFromOffset(clampedScrollOffset), ScrollType::Programmatic, ScrollClamping::Clamped, animated);
     2845            scrollToOffset(clampedScrollOffset, scrollPositionChangeOptionsForElement(box->element()));
    28572846            IntSize scrollOffsetDifference = clampedScrollOffset - oldScrollOffset;
    28582847            localExposeRect.move(-scrollOffsetDifference);
     
    28792868
    28802869                LayoutRect exposeRect = getRectToExpose(viewRect, newRect, insideFixed, options.alignX, options.alignY);
    2881 
    28822870                IntPoint scrollPosition(roundedIntPoint(exposeRect.location()));
     2871
    28832872                // Adjust offsets if they're outside of the allowable range.
    28842873                scrollPosition = scrollPosition.constrainedBetween(IntPoint(), IntPoint(frameView.contentsSize()));
     2874
    28852875                // FIXME: Should we use contentDocument()->scrollingElement()?
    28862876                // See https://bugs.webkit.org/show_bug.cgi?id=205059
    2887                 auto animated = shouldUseAnimatedScroll(element, options.behavior);
    2888                 frameView.setScrollPosition(scrollPosition, ScrollClamping::Clamped, animated);
     2877                frameView.setScrollPosition(scrollPosition, scrollPositionChangeOptionsForElement(element));
    28892878
    28902879                if (options.shouldAllowCrossOriginScrolling == ShouldAllowCrossOriginScrolling::Yes || frameView.safeToPropagateScrollToParent()) {
     
    29292918            // Avoid scrolling to the rounded value of revealRect.location() if we don't actually need to scroll
    29302919            if (revealRect != viewRect) {
    2931                 ScrollOffset clampedScrollPosition = roundedIntPoint(revealRect.location()).constrainedBetween(minScrollPosition, maxScrollPosition);
    29322920                // FIXME: Should we use document()->scrollingElement()?
    29332921                // See https://bugs.webkit.org/show_bug.cgi?id=205059
    2934                 auto animated = shouldUseAnimatedScroll(element, options.behavior);
    2935                 frameView.setScrollPosition(clampedScrollPosition, ScrollClamping::Clamped, animated);
     2922                ScrollOffset clampedScrollPosition = roundedIntPoint(revealRect.location()).constrainedBetween(minScrollPosition, maxScrollPosition);
     2923                frameView.setScrollPosition(clampedScrollPosition, scrollPositionChangeOptionsForElement(element));
    29362924            }
    29372925
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r270850 r271439  
    448448    bool requestScrollPositionUpdate(const ScrollPosition&, ScrollType = ScrollType::User, ScrollClamping = ScrollClamping::Clamped) final;
    449449
    450     WEBCORE_EXPORT void scrollToOffset(const ScrollOffset&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped);
    451     WEBCORE_EXPORT void scrollToOffsetWithAnimation(const ScrollOffset&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped);
    452 
    453     void scrollToXPosition(int x, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
    454     void scrollToYPosition(int y, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
    455     void setScrollPosition(const ScrollPosition&, ScrollType, ScrollClamping = ScrollClamping::Clamped, AnimatedScroll = AnimatedScroll::No);
     450    WEBCORE_EXPORT void scrollToOffset(const ScrollOffset&, const ScrollPositionChangeOptions& = ScrollPositionChangeOptions::createProgrammatic());
     451
     452    void scrollToXPosition(int x, const ScrollPositionChangeOptions&);
     453    void scrollToYPosition(int y, const ScrollPositionChangeOptions&);
     454    void setScrollPosition(const ScrollPosition&, const ScrollPositionChangeOptions&);
    456455
    457456    // These are only used by marquee.
    458     void scrollToXOffset(int x) { scrollToOffset(ScrollOffset(x, scrollOffset().y()), ScrollType::Programmatic, ScrollClamping::Unclamped); }
    459     void scrollToYOffset(int y) { scrollToOffset(ScrollOffset(scrollOffset().x(), y), ScrollType::Programmatic, ScrollClamping::Unclamped); }
     457    void scrollToXOffset(int x) { scrollToOffset(ScrollOffset(x, scrollOffset().y()), ScrollPositionChangeOptions::createProgrammaticUnclamped()); }
     458    void scrollToYOffset(int y) { scrollToOffset(ScrollOffset(scrollOffset().x(), y), ScrollPositionChangeOptions::createProgrammaticUnclamped()); }
    460459
    461460    void setPostLayoutScrollPosition(Optional<ScrollPosition>);
  • trunk/Source/WebCore/rendering/RenderListBox.cpp

    r271003 r271439  
    744744}
    745745
    746 void RenderListBox::setScrollLeft(int, ScrollType, ScrollClamping, AnimatedScroll)
     746void RenderListBox::setScrollLeft(int, const ScrollPositionChangeOptions&)
    747747{
    748748}
     
    761761}
    762762
    763 void RenderListBox::setScrollTop(int newTop, ScrollType, ScrollClamping, AnimatedScroll)
     763void RenderListBox::setScrollTop(int newTop, const ScrollPositionChangeOptions&)
    764764{
    765765    // Determine an index and scroll to it.   
  • trunk/Source/WebCore/rendering/RenderListBox.h

    r260981 r271439  
    107107    int scrollWidth() const override;
    108108    int scrollHeight() const override;
    109     void setScrollLeft(int, ScrollType, ScrollClamping, AnimatedScroll) override;
    110     void setScrollTop(int, ScrollType, ScrollClamping, AnimatedScroll) override;
     109    void setScrollLeft(int, const ScrollPositionChangeOptions&) override;
     110    void setScrollTop(int, const ScrollPositionChangeOptions&) override;
    111111
    112112    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
  • trunk/Source/WebCore/rendering/RenderMarquee.cpp

    r243926 r271439  
    172172        return;
    173173
     174    auto details = ScrollPositionChangeOptions::createProgrammaticUnclamped();
    174175    if (!m_suspended && !m_stopped) {
    175176        if (isHorizontal())
    176             m_layer->scrollToOffset(ScrollOffset(m_start, 0), ScrollType::Programmatic, ScrollClamping::Unclamped);
     177            m_layer->scrollToOffset(ScrollOffset(m_start, 0), details);
    177178        else
    178             m_layer->scrollToOffset(ScrollOffset(0, m_start), ScrollType::Programmatic, ScrollClamping::Unclamped);
     179            m_layer->scrollToOffset(ScrollOffset(0, m_start), details);
    179180    } else {
    180181        m_suspended = false;
  • trunk/Source/WebCore/rendering/RenderTextControlSingleLine.cpp

    r265746 r271439  
    384384}
    385385
    386 void RenderTextControlSingleLine::setScrollLeft(int newLeft, ScrollType, ScrollClamping, AnimatedScroll)
     386void RenderTextControlSingleLine::setScrollLeft(int newLeft, const ScrollPositionChangeOptions&)
    387387{
    388388    if (innerTextElement())
     
    390390}
    391391
    392 void RenderTextControlSingleLine::setScrollTop(int newTop, ScrollType, ScrollClamping, AnimatedScroll)
     392void RenderTextControlSingleLine::setScrollTop(int newTop, const ScrollPositionChangeOptions&)
    393393{
    394394    if (innerTextElement())
  • trunk/Source/WebCore/rendering/RenderTextControlSingleLine.h

    r259846 r271439  
    5858    int scrollWidth() const override;
    5959    int scrollHeight() const override;
    60     void setScrollLeft(int, ScrollType, ScrollClamping, AnimatedScroll) override;
    61     void setScrollTop(int, ScrollType, ScrollClamping, AnimatedScroll) override;
     60    void setScrollLeft(int, const ScrollPositionChangeOptions&) override;
     61    void setScrollTop(int, const ScrollPositionChangeOptions&) override;
    6262    bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = nullptr, RenderBox* startBox = nullptr, const IntPoint& wheelEventAbsolutePoint = IntPoint()) final;
    6363    bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = 0) final;
  • trunk/Source/WebKitLegacy/mac/ChangeLog

    r271430 r271439  
     12021-01-13  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Scroll-snap points should be triggered during programmatic scroll
     4        https://bugs.webkit.org/show_bug.cgi?id=145330
     5        <rdar://problem/21467780>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * DOM/DOMHTML.mm:
     10        (-[DOMHTMLElement setScrollXOffset:scrollYOffset:adjustForIOSCaret:]): Update to use
     11        ScrollPositionChangeOptions.
     12
    1132021-01-12  Tim Horton  <timothy_horton@apple.com>
    214
  • trunk/Source/WebKitLegacy/mac/DOM/DOMHTML.mm

    r265084 r271439  
    114114    if (adjustForIOSCaret)
    115115        layer->setAdjustForIOSCaretWhenScrolling(true);
    116     layer->scrollToOffset(WebCore::ScrollOffset(x, y), WebCore::ScrollType::Programmatic, WebCore::ScrollClamping::Unclamped);
     116
     117    auto scrollPositionChangeOptions = WebCore::ScrollPositionChangeOptions::createProgrammatic();
     118    scrollPositionChangeOptions.clamping = WebCore::ScrollClamping::Unclamped;
     119    layer->scrollToOffset(WebCore::ScrollOffset(x, y), scrollPositionChangeOptions);
    117120    if (adjustForIOSCaret)
    118121        layer->setAdjustForIOSCaretWhenScrolling(false);
Note: See TracChangeset for help on using the changeset viewer.