Changeset 270838 in webkit


Ignore:
Timestamp:
Dec 15, 2020 6:34:27 AM (19 months ago)
Author:
Martin Robinson
Message:

CSS Scroll Snap is not in effect when the user scrolls via the keyboard
https://bugs.webkit.org/show_bug.cgi?id=198566
<rdar://problem/51488088>

Reviewed by Simon Fraser.

Add support for scroll snap for keyboard scrolling

This change adds support for the concept of directional scroll snapping,
which will never snap to a snap point that is away from the original
scroll offset in the opposite direction of the scroll direction. This
allows escaping snap points.

Source/WebCore:

Tests: tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled.html

tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard.html
tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled.html
tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard.html
tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard.html
tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard.html
tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard.html

  • page/FrameView.cpp:

(WebCore::FrameView::pageScaleFactor const): Added.

  • page/FrameView.h: Added scale factor getter.
  • page/scrolling/ScrollSnapOffsetsInfo.cpp:

(WebCore::closestSnapOffset): Added a new optional argument that signals
directional snapping. This changes the behavior when choosing a snap offset
that is in the opposite direction as the scroll direction.

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

(WebCore::ScrollAnimator::scroll):

  • page/scrolling/ScrollSnapOffsetsInfo.h:

(WebCore::ScrollAnimator::scroll): No longer use the granularity argument.
(WebCore::ScrollAnimator::scrollWithoutAnimation): Remove the unused ScrollGranularity
argument and use the new positionFromStep helper.
(WebCore::ScrollAnimator::scrollWithDirectionalSnapping): Added.
(WebCore::ScrollAnimator::positionFromStep): Added this helper.
(WebCore::ScrollAnimator::handleWheelEvent): Remove the granularity argument.
(WebCore::ScrollAnimator::pageScaleFactor const): Added this implementation
of a ScrollControllerClient method.

  • platform/ScrollAnimator.h: Update method declarations.
  • platform/ScrollableArea.cpp:

(WebCore::ScrollableArea::scroll): Use the new argument to the scroll method.

  • platform/cocoa/ScrollController.h: Added new method.

(WebCore::ScrollableArea::pageScaleFactor const):

  • platform/cocoa/ScrollController.h:
  • platform/cocoa/ScrollController.mm:

(WebCore::ScrollController::adjustScrollDestinationForDirectionalSnapping): Added.

  • platform/mac/ScrollAnimatorMac.h:
  • platform/mac/ScrollAnimatorMac.mm:

(WebCore::ScrollAnimatorMac::scroll): Use new positionFromStep helper.

LayoutTests:

  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard.html: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard-expected.txt: Added.
  • tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard.html: Added.
Location:
trunk
Files:
14 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r270837 r270838  
     12020-12-15  Martin Robinson  <mrobinson@webkit.org>
     2
     3        CSS Scroll Snap is not in effect when the user scrolls via the keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=198566
     5        <rdar://problem/51488088>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Add support for scroll snap for keyboard scrolling
     10
     11        This change adds support for the concept of directional scroll snapping,
     12        which will never snap to a snap point that is away from the original
     13        scroll offset in the opposite direction of the scroll direction. This
     14        allows escaping snap points.
     15
     16        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-expected.txt: Added.
     17        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled-expected.txt: Added.
     18        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled.html: Added.
     19        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard.html: Added.
     20        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-expected.txt: Added.
     21        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled-expected.txt: Added.
     22        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled.html: Added.
     23        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard.html: Added.
     24        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard-expected.txt: Added.
     25        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard.html: Added.
     26        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard-expected.txt: Added.
     27        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard.html: Added.
     28        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard-expected.txt: Added.
     29        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard.html: Added.
     30
    1312020-12-15  Antoine Quint  <graouts@webkit.org>
    232
  • trunk/Source/WebCore/ChangeLog

    r270837 r270838  
     12020-12-15  Martin Robinson  <mrobinson@webkit.org>
     2
     3        CSS Scroll Snap is not in effect when the user scrolls via the keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=198566
     5        <rdar://problem/51488088>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Add support for scroll snap for keyboard scrolling
     10
     11        This change adds support for the concept of directional scroll snapping,
     12        which will never snap to a snap point that is away from the original
     13        scroll offset in the opposite direction of the scroll direction. This
     14        allows escaping snap points.
     15
     16        Tests: tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard-scaled.html
     17               tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-horizontal-with-keyboard.html
     18               tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard-scaled.html
     19               tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-with-keyboard.html
     20               tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-horizontal-with-keyboard.html
     21               tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-mainframe-vertical-with-keyboard.html
     22               tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow-rtl-with-keyboard.html
     23
     24        * page/FrameView.cpp:
     25        (WebCore::FrameView::pageScaleFactor const): Added.
     26        * page/FrameView.h: Added scale factor getter.
     27        * page/scrolling/ScrollSnapOffsetsInfo.cpp:
     28        (WebCore::closestSnapOffset): Added a new optional argument that signals
     29        directional snapping. This changes the behavior when choosing a snap offset
     30        that is in the opposite direction as the scroll direction.
     31        * page/scrolling/ScrollSnapOffsetsInfo.h:
     32        * platform/ScrollAnimator.cpp:
     33        (WebCore::ScrollAnimator::scroll):
     34        * page/scrolling/ScrollSnapOffsetsInfo.h:
     35        (WebCore::ScrollAnimator::scroll): No longer use the granularity argument.
     36        (WebCore::ScrollAnimator::scrollWithoutAnimation): Remove the unused ScrollGranularity
     37        argument and use the new positionFromStep helper.
     38        (WebCore::ScrollAnimator::scrollWithDirectionalSnapping): Added.
     39        (WebCore::ScrollAnimator::positionFromStep): Added this helper.
     40        (WebCore::ScrollAnimator::handleWheelEvent): Remove the granularity argument.
     41        (WebCore::ScrollAnimator::pageScaleFactor const): Added this implementation
     42        of a ScrollControllerClient method.
     43        * platform/ScrollAnimator.h: Update method declarations.
     44        * platform/ScrollableArea.cpp:
     45        (WebCore::ScrollableArea::scroll): Use the new argument to the scroll method.
     46        * platform/cocoa/ScrollController.h: Added new method.
     47        (WebCore::ScrollableArea::pageScaleFactor const):
     48        * platform/cocoa/ScrollController.h:
     49        * platform/cocoa/ScrollController.mm:
     50        (WebCore::ScrollController::adjustScrollDestinationForDirectionalSnapping): Added.
     51        * platform/mac/ScrollAnimatorMac.h:
     52        * platform/mac/ScrollAnimatorMac.mm:
     53        (WebCore::ScrollAnimatorMac::scroll): Use new positionFromStep helper.
     54
    1552020-12-15  Antoine Quint  <graouts@webkit.org>
    256
  • trunk/Source/WebCore/page/FrameView.cpp

    r270557 r270838  
    55335533}
    55345534
     5535float FrameView::pageScaleFactor() const
     5536{
     5537    return frame().frameScaleFactor();
     5538}
     5539
    55355540} // namespace WebCore
    55365541
  • trunk/Source/WebCore/page/FrameView.h

    r270557 r270838  
    849849    void didFinishProhibitingScrollingWhenChangingContentSize() final;
    850850
     851    // ScrollableArea.
     852    float pageScaleFactor() const override;
     853
    851854    static MonotonicTime sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
    852855
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp

    r270390 r270838  
    101101
    102102template <typename LayoutType>
    103 LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, LayoutType scrollDestination, float velocity, unsigned& activeSnapIndex)
     103static LayoutType closestSnapOffset(const Vector<LayoutType>& snapOffsets, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, LayoutType scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<LayoutType> originalPositionForDirectionalSnapping)
    104104{
    105105    ASSERT(snapOffsets.size());
     
    133133
    134134    // Non-zero velocity indicates a flick gesture. Even if another snap point is closer, we should choose the one in the direction of the flick gesture
    135     // as long as a scroll snap offset range does not lie between the scroll destination and the targeted snap offset.
     135    // as long as a scroll snap offset range does not lie between the scroll destination and the targeted snap offset. If we are doing directional
     136    // snapping, we should never snap to a point that was on the other side of the original position in the opposite direction of this scroll.
     137    // This allows directional scrolling to escape snap points.
    136138    if (velocity < 0) {
    137         if (lowerSnapOffsetRangeIndex != invalidSnapOffsetIndex && lowerSnapPosition < snapOffsetRanges[lowerSnapOffsetRangeIndex].end) {
     139        if (lowerSnapOffsetRangeIndex == invalidSnapOffsetIndex || lowerSnapPosition >= snapOffsetRanges[lowerSnapOffsetRangeIndex].end) {
     140            activeSnapIndex = lowerIndex;
     141            return lowerSnapPosition;
     142        }
     143
     144        if (!originalPositionForDirectionalSnapping.hasValue() || *originalPositionForDirectionalSnapping > upperSnapPosition) {
    138145            activeSnapIndex = upperIndex;
    139146            return upperSnapPosition;
    140147        }
    141         activeSnapIndex = lowerIndex;
    142         return lowerSnapPosition;
    143     }
    144 
    145     if (upperSnapOffsetRangeIndex != invalidSnapOffsetIndex && snapOffsetRanges[upperSnapOffsetRangeIndex].start < upperSnapPosition) {
    146         activeSnapIndex = lowerIndex;
    147         return lowerSnapPosition;
    148     }
    149     activeSnapIndex = upperIndex;
    150     return upperSnapPosition;
    151 }
    152 
    153 LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestination, float velocity, unsigned& activeSnapIndex)
    154 {
    155     return closestSnapOffset<LayoutUnit>(snapOffsets, snapOffsetRanges, scrollDestination, velocity, activeSnapIndex);
    156 }
    157 
    158 float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestination, float velocity, unsigned& activeSnapIndex)
    159 {
    160     return closestSnapOffset<float>(snapOffsets, snapOffsetRanges, scrollDestination, velocity, activeSnapIndex);
     148    } else {
     149        if (upperSnapOffsetRangeIndex == invalidSnapOffsetIndex || snapOffsetRanges[upperSnapOffsetRangeIndex].start >= upperSnapPosition) {
     150            activeSnapIndex = upperIndex;
     151            return upperSnapPosition;
     152        }
     153
     154        if (!originalPositionForDirectionalSnapping.hasValue() || *originalPositionForDirectionalSnapping < lowerSnapPosition) {
     155            activeSnapIndex = lowerIndex;
     156            return lowerSnapPosition;
     157        }
     158    }
     159
     160    activeSnapIndex = invalidSnapOffsetIndex;
     161    return scrollDestination;
     162}
     163
     164LayoutUnit 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
     169float 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);
    161172}
    162173
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h

    r270390 r270838  
    3030#include "LayoutUnit.h"
    3131#include "StyleScrollSnapPoints.h"
     32#include <wtf/Optional.h>
    3233#include <wtf/Vector.h>
    3334
     
    6667void updateSnapOffsetsForScrollableArea(ScrollableArea&, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle, LayoutRect viewportRectInBorderBoxCoordinates);
    6768
    68 WEBCORE_EXPORT LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestination, float velocity, unsigned& activeSnapIndex);
    69 WEBCORE_EXPORT float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestination, float velocity, unsigned& activeSnapIndex);
     69WEBCORE_EXPORT LayoutUnit closestSnapOffset(const Vector<LayoutUnit>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges, LayoutUnit scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<LayoutUnit> originalPositionForDirectionalSnapping = WTF::nullopt);
     70WEBCORE_EXPORT float closestSnapOffset(const Vector<float>& snapOffsets, const Vector<ScrollOffsetRange<float>>& snapOffsetRanges, float scrollDestination, float velocity, unsigned& activeSnapIndex, Optional<float> originalPositionForDirectionalSnapping = WTF::nullopt);
    7071
    7172}; // namespace WebCore
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r269659 r270838  
    8181}
    8282
    83 bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
    84 {
    85     return scrollWithoutAnimation(orientation, granularity, step, multiplier);
    86 }
    87 
    88 bool ScrollAnimator::scrollWithoutAnimation(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier)
     83bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier, ScrollBehavior behavior)
     84{
     85#if ENABLE(CSS_SCROLL_SNAP)
     86    if (behavior != ScrollBehavior::DoDirectionalSnapping)
     87        return scrollWithoutAnimation(orientation, step, multiplier);
     88
     89    FloatSize scrollOrigin = toFloatSize(m_scrollableArea.scrollOrigin());
     90    FloatPoint newPosition = positionFromStep(orientation, step, multiplier);
     91    auto newOffset = ScrollableArea::scrollOffsetFromPosition(newPosition, scrollOrigin);
     92    auto currentOffset = ScrollableArea::scrollOffsetFromPosition(this->currentPosition(), scrollOrigin);
     93    if (orientation == HorizontalScrollbar) {
     94        newOffset.setX(m_scrollController.adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis::Horizontal, newOffset.x(), multiplier, currentOffset.x()));
     95        newPosition = ScrollableArea::scrollPositionFromOffset(newOffset, scrollOrigin);
     96        return scroll(HorizontalScrollbar, granularity, newPosition.x() - this->currentPosition().x(), 1.0);
     97    }
     98
     99    newOffset.setY(m_scrollController.adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis::Vertical, newPosition.y(), multiplier, currentOffset.y()));
     100    newPosition = ScrollableArea::scrollPositionFromOffset(newOffset, scrollOrigin);
     101    return scroll(VerticalScrollbar, granularity, newPosition.y() - this->currentPosition().y(), 1.0);
     102#else
     103    UNUSED_PARAM(granularity);
     104    UNUSED_PARAM(behavior);
     105    return scrollWithoutAnimation(orientation, step, multiplier);
     106#endif
     107}
     108
     109bool ScrollAnimator::scrollWithoutAnimation(ScrollbarOrientation orientation, float step, float multiplier)
    89110{
    90111    FloatPoint currentPosition = this->currentPosition();
     112    FloatPoint newPosition = positionFromStep(orientation, step, multiplier);
     113    newPosition = newPosition.constrainedBetween(m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition());
     114    if (currentPosition == newPosition)
     115        return false;
     116
     117    m_currentPosition = newPosition;
     118    notifyPositionChanged(newPosition - currentPosition);
     119    return true;
     120}
     121
     122void ScrollAnimator::scrollToOffset(const FloatPoint& offset)
     123{
     124    m_animationProgrammaticScroll->setCurrentPosition(m_currentPosition);
     125    auto newPosition = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
     126    m_animationProgrammaticScroll->scroll(newPosition);
     127    m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::InNonNativeAnimation);
     128}
     129
     130void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping)
     131{
     132    FloatPoint newPosition = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
     133    FloatSize delta = newPosition - currentPosition();
     134    m_currentPosition = newPosition;
     135    notifyPositionChanged(delta);
     136    updateActiveScrollSnapIndexForOffset();
     137}
     138
     139FloatPoint ScrollAnimator::positionFromStep(ScrollbarOrientation orientation, float step, float multiplier)
     140{
    91141    FloatSize delta;
    92142    if (orientation == HorizontalScrollbar)
     
    94144    else
    95145        delta.setHeight(step * multiplier);
    96 
    97     FloatPoint newPosition = FloatPoint(currentPosition + delta).constrainedBetween(m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition());
    98     if (currentPosition == newPosition)
    99         return false;
    100 
    101     m_currentPosition = newPosition;
    102     notifyPositionChanged(newPosition - currentPosition);
    103     return true;
    104 }
    105 
    106 void ScrollAnimator::scrollToOffset(const FloatPoint& offset)
    107 {
    108     m_animationProgrammaticScroll->setCurrentPosition(m_currentPosition);
    109     auto newPosition = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
    110     m_animationProgrammaticScroll->scroll(newPosition);
    111     m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::InNonNativeAnimation);
    112 }
    113 
    114 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping)
    115 {
    116     FloatPoint newPosition = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
    117     FloatSize delta = newPosition - currentPosition();
    118     m_currentPosition = newPosition;
    119     notifyPositionChanged(delta);
    120     updateActiveScrollSnapIndexForOffset();
     146    return this->currentPosition() + delta;
    121147}
    122148
     
    183209            }
    184210            if (e.hasPreciseScrollingDeltas())
    185                 scrollWithoutAnimation(VerticalScrollbar, granularity, verticalScrollbar->pixelStep(), -deltaY);
     211                scrollWithoutAnimation(VerticalScrollbar, verticalScrollbar->pixelStep(), -deltaY);
    186212            else
    187213                scroll(VerticalScrollbar, granularity, verticalScrollbar->pixelStep(), -deltaY);
     
    196222            }
    197223            if (e.hasPreciseScrollingDeltas())
    198                 scrollWithoutAnimation(HorizontalScrollbar, granularity, horizontalScrollbar->pixelStep(), -deltaX);
     224                scrollWithoutAnimation(HorizontalScrollbar, horizontalScrollbar->pixelStep(), -deltaX);
    199225            else
    200226                scroll(HorizontalScrollbar, granularity, horizontalScrollbar->pixelStep(), -deltaX);
     
    272298}
    273299
     300float ScrollAnimator::pageScaleFactor() const
     301{
     302    return m_scrollableArea.pageScaleFactor();
     303}
    274304#endif
    275305
  • trunk/Source/WebCore/platform/ScrollAnimator.h

    r269143 r270838  
    6868    virtual ~ScrollAnimator();
    6969
     70    enum ScrollBehavior {
     71        Default,
     72        DoDirectionalSnapping,
     73    };
     74
    7075    // Computes a scroll destination for the given parameters.  Returns false if
    7176    // already at the destination.  Otherwise, starts scrolling towards the
    7277    // destination and returns true.  Scrolling may be immediate or animated.
    7378    // The base class implementation always scrolls immediately, never animates.
    74     virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
    75     bool scrollWithoutAnimation(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
     79    virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier, ScrollBehavior = ScrollBehavior::Default);
     80    bool scrollWithoutAnimation(ScrollbarOrientation, float step, float multiplier);
    7681
    7782    void scrollToOffset(const FloatPoint&);
     
    134139    void setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&& testMonitor) { m_wheelEventTestMonitor = testMonitor; }
    135140
    136 #if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
    137     void deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const override;
    138     void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const override;
    139 #endif
    140 
    141141#if ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)
    142142    std::unique_ptr<ScrollControllerTimer> createTimer(Function<void()>&&) final;
     
    148148#endif
    149149    void updateScrollSnapState();
     150    bool activeScrollSnapIndexDidChange() const;
     151    unsigned activeScrollSnapIndexForAxis(ScrollEventAxis) const;
     152#endif
     153
     154    // ScrollControllerClient.
     155#if ENABLE(CSS_SCROLL_SNAP)
    150156    FloatPoint scrollOffset() const override;
    151157    void immediateScrollOnAxis(ScrollEventAxis, float delta) override;
    152     bool activeScrollSnapIndexDidChange() const;
    153     unsigned activeScrollSnapIndexForAxis(ScrollEventAxis) const;
     158    float pageScaleFactor() const override;
    154159    LayoutSize scrollExtent() const override;
    155160    FloatSize viewportSize() const override;
     161#endif
     162#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
     163    void deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const override;
     164    void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const override;
    156165#endif
    157166
     
    159168    virtual void notifyPositionChanged(const FloatSize& delta);
    160169    void updateActiveScrollSnapIndexForOffset();
     170    FloatPoint positionFromStep(ScrollbarOrientation, float step, float multiplier);
    161171
    162172    ScrollableArea& m_scrollableArea;
  • trunk/Source/WebCore/platform/ScrollableArea.cpp

    r270389 r270838  
    141141
    142142    step = adjustScrollStepForFixedContent(step, orientation, granularity);
    143     return scrollAnimator().scroll(orientation, granularity, step, multiplier);
     143    return scrollAnimator().scroll(orientation, granularity, step, multiplier, ScrollAnimator::ScrollBehavior::DoDirectionalSnapping);
    144144}
    145145
  • trunk/Source/WebCore/platform/ScrollableArea.h

    r270390 r270838  
    356356    virtual String debugDescription() const = 0;
    357357
     358    virtual float pageScaleFactor() const
     359    {
     360        return 1.0f;
     361    }
     362
    358363protected:
    359364    WEBCORE_EXPORT ScrollableArea();
  • trunk/Source/WebCore/platform/cocoa/ScrollController.h

    r269559 r270838  
    109109    virtual void didStopScrollSnapAnimation() { }
    110110
    111     virtual float pageScaleFactor() const
    112     {
    113         return 1.0f;
    114     }
     111    virtual float pageScaleFactor() const = 0;
    115112
    116113    virtual unsigned activeScrollOffsetIndex(ScrollEventAxis) const
     
    168165    unsigned activeScrollSnapIndexForAxis(ScrollEventAxis) const;
    169166    void updateScrollSnapState(const ScrollableArea&);
    170 
    171167    void updateGestureInProgressState(const PlatformWheelEvent&);
    172 
     168    float adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis, float destination, float velocity, float originalPosition);
    173169#if PLATFORM(MAC)
    174170    bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
  • trunk/Source/WebCore/platform/cocoa/ScrollController.mm

    r270389 r270838  
    906906}
    907907
     908float ScrollController::adjustScrollDestinationForDirectionalSnapping(ScrollEventAxis axis, float destination, float velocity, float originalPosition)
     909{
     910    if (!usesScrollSnap())
     911        return destination;
     912
     913    ScrollSnapAnimatorState& snapState = *m_scrollSnapState;
     914    auto snapOffsets = snapState.snapOffsetsForAxis(axis);
     915    if (!snapOffsets.size())
     916        return destination;
     917
     918    unsigned snapIndex;
     919    LayoutUnit offset = closestSnapOffset(snapState.snapOffsetsForAxis(axis), snapState.snapOffsetRangesForAxis(axis), LayoutUnit(destination / m_client.pageScaleFactor()), velocity, snapIndex, LayoutUnit(originalPosition / m_client.pageScaleFactor()));
     920    return offset * m_client.pageScaleFactor();
     921}
     922
     923
    908924void ScrollController::setActiveScrollSnapIndicesForOffset(ScrollOffset offset)
    909925{
  • trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.cpp

    r268522 r270838  
    9595
    9696#if ENABLE(SMOOTH_SCROLLING)
    97 bool ScrollAnimatorGeneric::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
     97bool ScrollAnimatorGeneric::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier, ScrollBehavior behavior)
    9898{
    9999    if (!m_scrollableArea.scrollAnimatorEnabled())
    100100        return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
     101
     102    // This method doesn't do directional snapping, but our base class does. It will call into
     103    // ScrollAnimatorGeneric::scroll again with the snapped positions and ScrollBehavior::Default.
     104    if (behavior == ScrollBehavior::DoDirectionalSnapping)
     105        return ScrollAnimator::scroll(orientation, granularity, step, multiplier, behavior);
    101106
    102107    ensureSmoothScrollingAnimation();
  • trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.h

    r259112 r270838  
    4646private:
    4747#if ENABLE(SMOOTH_SCROLLING)
    48     bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
     48    bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier, ScrollBehavior) override;
    4949#endif
    5050    void scrollToOffsetWithoutAnimation(const FloatPoint&, ScrollClamping) override;
  • trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.h

    r269373 r270838  
    8080    FloatSize m_contentAreaScrolledTimerScrollDelta;
    8181
    82     bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
     82    bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier, ScrollBehavior) override;
    8383    void scrollToOffsetWithoutAnimation(const FloatPoint&, ScrollClamping) override;
    8484
  • trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm

    r269659 r270838  
    780780#endif
    781781
    782 bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
     782bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier, ScrollBehavior behavior)
    783783{
    784784    m_haveScrolledSincePageLoad = true;
    785785
    786786    if (!scrollAnimationEnabledForSystem() || !m_scrollableArea.scrollAnimatorEnabled())
    787         return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
     787        return ScrollAnimator::scroll(orientation, granularity, step, multiplier, behavior);
    788788
    789789    if (granularity == ScrollByPixel)
    790         return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
     790        return ScrollAnimator::scroll(orientation, granularity, step, multiplier, behavior);
     791
     792    // This method doesn't do directional snapping, but our base class does. It will call into
     793    // ScrollAnimatorMac::scroll again with the snapped positions and ScrollBehavior::Default.
     794    if (behavior == ScrollBehavior::DoDirectionalSnapping)
     795        return ScrollAnimator::scroll(orientation, granularity, step, multiplier, behavior);
    791796
    792797    FloatPoint currentPosition = this->currentPosition();
    793     FloatSize delta;
    794     if (orientation == HorizontalScrollbar)
    795         delta.setWidth(step * multiplier);
    796     else
    797         delta.setHeight(step * multiplier);
    798 
    799     FloatPoint newPosition = FloatPoint(currentPosition + delta).constrainedBetween(m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition());
     798    FloatPoint newPosition = positionFromStep(orientation, step, multiplier);
     799    newPosition = newPosition.constrainedBetween(m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition());
    800800    if (currentPosition == newPosition)
    801801        return false;
Note: See TracChangeset for help on using the changeset viewer.