Changeset 280171 in webkit


Ignore:
Timestamp:
Jul 22, 2021 2:00:27 AM (12 months ago)
Author:
Martin Robinson
Message:

[css-scroll-snap] Pass the full target point when selecting a snap offset
https://bugs.webkit.org/show_bug.cgi?id=228023

Reviewed by Frédéric Wang.

Source/WebCore:

Pass the full proposed destination scroll offset when calling closestSnapOffset. For
now, only the component in the scroll direction is used, but eventually the other
component will be used to avoid snapping to snap areas that are entirely off the screen.

No new tests. This change is simply a refactor in preparation for a behavior
change and shouldn't change behavior itself.

  • page/scrolling/ScrollSnapOffsetsInfo.cpp:

(WebCore::closestSnapOffsetWithInfoAndAxis):
(WebCore::LayoutScrollSnapOffsetsInfo::closestSnapOffset const):
(WebCore::FloatScrollSnapOffsetsInfo::closestSnapOffset const):

  • page/scrolling/ScrollSnapOffsetsInfo.h:
  • page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp:

(WebCore::ScrollingTreeScrollingNodeDelegateNicosia::handleWheelEvent):

  • platform/ScrollAnimator.cpp:

(WebCore::ScrollAnimator::scroll):
(WebCore::ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded):

  • platform/ScrollAnimator.h:
  • platform/ScrollController.cpp:

(WebCore::ScrollController::setNearestScrollSnapIndexForAxisAndOffset):
(WebCore::ScrollController::adjustScrollDestination):
(WebCore::ScrollController::updateActiveScrollSnapIndexForClientOffset):
(WebCore::ScrollController::resnapAfterLayout):

  • platform/ScrollController.h:
  • platform/ScrollSnapAnimatorState.cpp:

(WebCore::ScrollSnapAnimatorState::setupAnimationForState):
(WebCore::ScrollSnapAnimatorState::targetOffsetForStartOffset const):

  • platform/ScrollSnapAnimatorState.h:
  • platform/ScrollableArea.cpp:

(WebCore::ScrollableArea::doPostThumbMoveSnapping):

Source/WebKit:

  • UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
  • UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:

(WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping):
(WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling const):

  • UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:

(-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):

Location:
trunk/Source
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r280158 r280171  
     12021-07-22  Martin Robinson  <mrobinson@webkit.org>
     2
     3        [css-scroll-snap] Pass the full target point when selecting a snap offset
     4        https://bugs.webkit.org/show_bug.cgi?id=228023
     5
     6        Reviewed by Frédéric Wang.
     7
     8        Pass the full proposed destination scroll offset when calling closestSnapOffset. For
     9        now, only the component in the scroll direction is used, but eventually the other
     10        component will be used to avoid snapping to snap areas that are entirely off the screen.
     11
     12        No new tests. This change is simply a refactor in preparation for a behavior
     13        change and shouldn't change behavior itself.
     14
     15        * page/scrolling/ScrollSnapOffsetsInfo.cpp:
     16        (WebCore::closestSnapOffsetWithInfoAndAxis):
     17        (WebCore::LayoutScrollSnapOffsetsInfo::closestSnapOffset const):
     18        (WebCore::FloatScrollSnapOffsetsInfo::closestSnapOffset const):
     19        * page/scrolling/ScrollSnapOffsetsInfo.h:
     20        * page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp:
     21        (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::handleWheelEvent):
     22        * platform/ScrollAnimator.cpp:
     23        (WebCore::ScrollAnimator::scroll):
     24        (WebCore::ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded):
     25        * platform/ScrollAnimator.h:
     26        * platform/ScrollController.cpp:
     27        (WebCore::ScrollController::setNearestScrollSnapIndexForAxisAndOffset):
     28        (WebCore::ScrollController::adjustScrollDestination):
     29        (WebCore::ScrollController::updateActiveScrollSnapIndexForClientOffset):
     30        (WebCore::ScrollController::resnapAfterLayout):
     31        * platform/ScrollController.h:
     32        * platform/ScrollSnapAnimatorState.cpp:
     33        (WebCore::ScrollSnapAnimatorState::setupAnimationForState):
     34        (WebCore::ScrollSnapAnimatorState::targetOffsetForStartOffset const):
     35        * platform/ScrollSnapAnimatorState.h:
     36        * platform/ScrollableArea.cpp:
     37        (WebCore::ScrollableArea::doPostThumbMoveSnapping):
     38
    1392021-07-21  Alex Christensen  <achristensen@webkit.org>
    240
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp

    r279714 r280171  
    9191}
    9292
    93 template <typename InfoType, typename SizeType, typename LayoutType>
    94 static std::pair<LayoutType, std::optional<unsigned>> closestSnapOffsetWithInfoAndAxis(const InfoType& info, ScrollEventAxis axis, const SizeType& viewportSize, LayoutType scrollDestinationOffset, float velocity, std::optional<LayoutType> originalOffsetForDirectionalSnapping)
    95 {
     93template <typename InfoType, typename SizeType, typename LayoutType, typename PointType>
     94static std::pair<LayoutType, std::optional<unsigned>> closestSnapOffsetWithInfoAndAxis(const InfoType& info, ScrollEventAxis axis, const SizeType& viewportSize, PointType scrollDestinationOffsetPoint, float velocity, std::optional<LayoutType> originalOffsetForDirectionalSnapping)
     95{
     96    auto scrollDestinationOffset = axis == ScrollEventAxis::Horizontal ? scrollDestinationOffsetPoint.x() : scrollDestinationOffsetPoint.y();
    9697    const auto& snapOffsets = info.offsetsForAxis(axis);
    9798    auto pairForNoSnapping = std::make_pair(scrollDestinationOffset, std::nullopt);
     
    389390
    390391template <> template <>
    391 std::pair<LayoutUnit, std::optional<unsigned>> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const LayoutSize& viewportSize, LayoutUnit scrollDestinationOffset, float velocity, std::optional<LayoutUnit> originalPositionForDirectionalSnapping) const
     392std::pair<LayoutUnit, std::optional<unsigned>> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const LayoutSize& viewportSize, LayoutPoint scrollDestinationOffset, float velocity, std::optional<LayoutUnit> originalPositionForDirectionalSnapping) const
    392393{
    393394    return closestSnapOffsetWithInfoAndAxis(*this, axis, viewportSize, scrollDestinationOffset, velocity, originalPositionForDirectionalSnapping);
     
    395396
    396397template <> template<>
    397 std::pair<float, std::optional<unsigned>> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const FloatSize& viewportSize, float scrollDestinationOffset, float velocity, std::optional<float> originalPositionForDirectionalSnapping) const
     398std::pair<float, std::optional<unsigned>> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const FloatSize& viewportSize, FloatPoint scrollDestinationOffset, float velocity, std::optional<float> originalPositionForDirectionalSnapping) const
    398399{
    399400    return closestSnapOffsetWithInfoAndAxis(*this, axis, viewportSize, scrollDestinationOffset, velocity, originalPositionForDirectionalSnapping);
  • trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h

    r279218 r280171  
    7171
    7272    template<typename OutputType> OutputType convertUnits(float deviceScaleFactor = 0.0) const;
    73     template<typename SizeType>
    74     WEBCORE_EXPORT std::pair<UnitType, std::optional<unsigned>> closestSnapOffset(ScrollEventAxis, const SizeType& viewportSize, UnitType scrollDestinationOffset, float velocity, std::optional<UnitType> originalPositionForDirectionalSnapping = std::nullopt) const;
     73    template<typename SizeType, typename PointType>
     74    WEBCORE_EXPORT std::pair<UnitType, std::optional<unsigned>> closestSnapOffset(ScrollEventAxis, const SizeType& viewportSize, PointType scrollDestinationOffset, float velocity, std::optional<UnitType> originalPositionForDirectionalSnapping = std::nullopt) const;
    7575};
    7676
     
    8181LayoutScrollSnapOffsetsInfo FloatScrollSnapOffsetsInfo::convertUnits(float /* unusedScaleFactor */) const;
    8282template <> template <>
    83 WEBCORE_EXPORT std::pair<float, std::optional<unsigned>> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const FloatSize& viewportSize, float scrollDestinationOffset, float velocity, std::optional<float> originalPositionForDirectionalSnapping) const;
     83WEBCORE_EXPORT std::pair<float, std::optional<unsigned>> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const FloatSize& viewportSize, FloatPoint scrollDestinationOffset, float velocity, std::optional<float> originalPositionForDirectionalSnapping) const;
    8484
    8585
     
    8787FloatScrollSnapOffsetsInfo LayoutScrollSnapOffsetsInfo::convertUnits(float deviceScaleFactor) const;
    8888template <> template <>
    89 WEBCORE_EXPORT std::pair<LayoutUnit, std::optional<unsigned>> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const LayoutSize& viewportSize, LayoutUnit scrollDestinationOffset, float velocity, std::optional<LayoutUnit> originalPositionForDirectionalSnapping) const;
     89WEBCORE_EXPORT std::pair<LayoutUnit, std::optional<unsigned>> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const LayoutSize& viewportSize, LayoutPoint scrollDestinationOffset, float velocity, std::optional<LayoutUnit> originalPositionForDirectionalSnapping) const;
    9090
    9191// Update the snap offsets for this scrollable area, given the RenderBox of the scroll container, the RenderStyle
  • trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp

    r279218 r280171  
    170170        float scale = pageScaleFactor();
    171171        FloatPoint originalOffset = LayoutPoint(scrollingNode().currentScrollOffset().x() / scale, scrollingNode().currentScrollOffset().y() / scale);
    172         FloatPoint newFloatOffset = scrollingNode().currentScrollOffset() + FloatSize(deltaX, deltaY);
    173         auto newOffset = LayoutPoint(newFloatOffset.x() / scale, newFloatOffset.y() / scale);
    174 
    175         auto offsetX = scrollingNode().snapOffsetsInfo().closestSnapOffset(ScrollEventAxis::Horizontal, scrollableAreaSize(), newOffset.x(), deltaX, originalOffset.x()).first;
    176         auto offsetY = scrollingNode().snapOffsetsInfo().closestSnapOffset(ScrollEventAxis::Vertical, scrollableAreaSize(), newOffset.y(), deltaY, originalOffset.y()).first;
     172        auto newOffset = (scrollingNode().currentScrollOffset() + FloatSize(deltaX, deltaY));
     173        newOffset.scale(1.0 / scale);
     174
     175        auto offsetX = scrollingNode().snapOffsetsInfo().closestSnapOffset(ScrollEventAxis::Horizontal, scrollableAreaSize(), newOffset, deltaX, originalOffset.x()).first;
     176        auto offsetY = scrollingNode().snapOffsetsInfo().closestSnapOffset(ScrollEventAxis::Vertical, scrollableAreaSize(), newOffset, deltaY, originalOffset.y()).first;
    177177
    178178        deltaX = (offsetX - originalOffset.x()) * scale;
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r279564 r280171  
    8787        auto newOffset = currentOffset + delta;
    8888        if (orientation == HorizontalScrollbar)
    89             newOffset.setX(m_scrollController.adjustScrollDestination(ScrollEventAxis::Horizontal, newOffset.x(), multiplier, currentOffset.x()));
     89            newOffset.setX(m_scrollController.adjustScrollDestination(ScrollEventAxis::Horizontal, newOffset, multiplier, currentOffset.x()));
    9090        else
    91             newOffset.setY(m_scrollController.adjustScrollDestination(ScrollEventAxis::Vertical, newOffset.y(), multiplier, currentOffset.y()));
     91            newOffset.setY(m_scrollController.adjustScrollDestination(ScrollEventAxis::Vertical, newOffset, multiplier, currentOffset.y()));
    9292        auto newDelta = newOffset - currentOffset;
    9393
     
    398398
    399399    FloatPoint newOffset = offset;
    400     newOffset.setX(adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Horizontal, newOffset.x(), method));
    401     newOffset.setY(adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Vertical, newOffset.y(), method));
     400    newOffset.setX(adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Horizontal, newOffset, method));
     401    newOffset.setY(adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Vertical, newOffset, method));
    402402    return newOffset;
    403403}
    404404
    405 float ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis axis, float newOffset, ScrollSnapPointSelectionMethod method)
     405float ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis axis, const FloatPoint& newOffset, ScrollSnapPointSelectionMethod method)
    406406{
    407407    if (!m_scrollController.usesScrollSnap())
    408         return newOffset;
     408        return axis == ScrollEventAxis::Horizontal ? newOffset.x() : newOffset.y();
    409409
    410410    std::optional<float> originalOffset;
    411     float velocity = 0.;
     411    float velocityInScrollAxis = 0.;
    412412    if (method == ScrollSnapPointSelectionMethod::Directional) {
    413413        FloatSize scrollOrigin = toFloatSize(m_scrollableArea.scrollOrigin());
    414414        auto currentOffset = ScrollableArea::scrollOffsetFromPosition(this->currentPosition(), scrollOrigin);
     415        auto velocity = newOffset - currentOffset;
    415416        originalOffset = axis == ScrollEventAxis::Horizontal ? currentOffset.x() : currentOffset.y();
    416         velocity = newOffset - (axis == ScrollEventAxis::Horizontal ? currentOffset.x() : currentOffset.y());
     417        velocityInScrollAxis = axis == ScrollEventAxis::Horizontal ? velocity.width() : velocity.height();
    417418    }
    418419
    419     return m_scrollController.adjustScrollDestination(axis, newOffset, velocity, originalOffset);
     420    return m_scrollController.adjustScrollDestination(axis, newOffset, velocityInScrollAxis, originalOffset);
    420421}
    421422
  • trunk/Source/WebCore/platform/ScrollAnimator.h

    r279564 r280171  
    135135
    136136    FloatPoint adjustScrollOffsetForSnappingIfNeeded(const FloatPoint& offset, ScrollSnapPointSelectionMethod);
    137     float adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis, float newOffset, ScrollSnapPointSelectionMethod);
     137    float adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis, const FloatPoint& newOffset, ScrollSnapPointSelectionMethod);
    138138
    139139    std::unique_ptr<ScrollControllerTimer> createTimer(Function<void()>&&) final;
  • trunk/Source/WebCore/platform/ScrollController.cpp

    r279218 r280171  
    128128}
    129129
    130 void ScrollController::setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis axis, int offset)
     130void ScrollController::setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis axis, ScrollOffset scrollOffset)
    131131{
    132132    if (!usesScrollSnap())
     
    134134
    135135    float scaleFactor = m_client.pageScaleFactor();
     136    LayoutPoint layoutScrollOffset(scrollOffset.x() / scaleFactor, scrollOffset.y() / scaleFactor);
    136137    ScrollSnapAnimatorState& snapState = *m_scrollSnapState;
    137138
     
    140141    std::optional<unsigned> activeIndex;
    141142    if (snapOffsets.size())
    142         activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, LayoutUnit(offset / scaleFactor), 0).second;
     143        activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, layoutScrollOffset, 0).second;
    143144
    144145    if (activeIndex == activeScrollSnapIndexForAxis(axis))
     
    149150}
    150151
    151 float ScrollController::adjustScrollDestination(ScrollEventAxis axis, float destinationOffset, float velocity, std::optional<float> originalOffset)
    152 {
    153     if (!usesScrollSnap())
    154         return destinationOffset;
     152float ScrollController::adjustScrollDestination(ScrollEventAxis axis, FloatPoint destinationOffset, float velocity, std::optional<float> originalOffset)
     153{
     154    if (!usesScrollSnap())
     155        return axis == ScrollEventAxis::Horizontal ? destinationOffset.x() : destinationOffset.y();
    155156
    156157    ScrollSnapAnimatorState& snapState = *m_scrollSnapState;
    157158    auto snapOffsets = snapState.snapOffsetsForAxis(axis);
    158159    if (!snapOffsets.size())
    159         return destinationOffset;
    160 
     160        return axis == ScrollEventAxis::Horizontal ? destinationOffset.x() : destinationOffset.y();
     161
     162    float scaleFactor = m_client.pageScaleFactor();
    161163    std::optional<LayoutUnit> originalOffsetInLayoutUnits;
    162164    if (originalOffset)
    163         originalOffsetInLayoutUnits = LayoutUnit(*originalOffset / m_client.pageScaleFactor());
     165        originalOffsetInLayoutUnits = LayoutUnit(*originalOffset / scaleFactor);
    164166    LayoutSize viewportSize(m_client.viewportSize().width(), m_client.viewportSize().height());
    165     LayoutUnit offset = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, LayoutUnit(destinationOffset / m_client.pageScaleFactor()), velocity, originalOffsetInLayoutUnits).first;
    166     return offset * m_client.pageScaleFactor();
     167    LayoutPoint layoutDestinationOffset(destinationOffset.x() / scaleFactor, destinationOffset.y() / scaleFactor);
     168    LayoutUnit offset = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, layoutDestinationOffset, velocity, originalOffsetInLayoutUnits).first;
     169    return offset * scaleFactor;
    167170}
    168171
     
    174177
    175178    ScrollOffset offset = roundedIntPoint(m_client.scrollOffset());
    176     setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset.x());
    177     setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset.y());
     179    setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset);
     180    setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset);
    178181}
    179182
     
    189192    auto activeHorizontalIndex = m_scrollSnapState->activeSnapIndexForAxis(ScrollEventAxis::Horizontal);
    190193    if (!activeHorizontalIndex || *activeHorizontalIndex >= snapState.snapOffsetsForAxis(ScrollEventAxis::Horizontal).size())
    191         setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset.x());
     194        setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset);
    192195
    193196    auto activeVerticalIndex = m_scrollSnapState->activeSnapIndexForAxis(ScrollEventAxis::Vertical);
    194197    if (!activeVerticalIndex || *activeVerticalIndex >= snapState.snapOffsetsForAxis(ScrollEventAxis::Vertical).size())
    195         setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset.y());
     198        setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset);
    196199
    197200}
  • trunk/Source/WebCore/platform/ScrollController.h

    r279218 r280171  
    136136    void updateScrollSnapState(const ScrollableArea&);
    137137    void updateGestureInProgressState(const PlatformWheelEvent&);
    138     float adjustScrollDestination(ScrollEventAxis, float destinationOffset, float velocity, std::optional<float> originalOffset);
     138    float adjustScrollDestination(ScrollEventAxis, FloatPoint destinationOffset, float velocity, std::optional<float> originalOffset);
    139139
    140140#if PLATFORM(MAC)
     
    160160
    161161private:
    162     void setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis, int);
     162    void setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis, ScrollOffset);
    163163
    164164    void updateScrollSnapAnimatingState(MonotonicTime);
  • trunk/Source/WebCore/platform/ScrollSnapAnimatorState.cpp

    r279218 r280171  
    4949
    5050    m_momentumCalculator = ScrollingMomentumCalculator::create(viewportSize, contentSize, initialOffset, initialDelta, initialVelocity);
    51     auto predictedScrollTarget = m_momentumCalculator->predictedDestinationOffset();
     51    FloatPoint predictedScrollTarget { m_momentumCalculator->predictedDestinationOffset() };
    5252
    5353    float targetOffsetX, targetOffsetY;
    54     std::tie(targetOffsetX, m_activeSnapIndexX) = targetOffsetForStartOffset(ScrollEventAxis::Horizontal, viewportSize, contentSize.width() - viewportSize.width(), initialOffset.x(), predictedScrollTarget.width(), pageScale, initialDelta.width());
    55     std::tie(targetOffsetY, m_activeSnapIndexY) = targetOffsetForStartOffset(ScrollEventAxis::Vertical, viewportSize, contentSize.height() - viewportSize.height(), initialOffset.y(), predictedScrollTarget.height(), pageScale, initialDelta.height());
     54    std::tie(targetOffsetX, m_activeSnapIndexX) = targetOffsetForStartOffset(ScrollEventAxis::Horizontal, viewportSize, contentSize.width() - viewportSize.width(), initialOffset.x(), predictedScrollTarget, pageScale, initialDelta.width());
     55    std::tie(targetOffsetY, m_activeSnapIndexY) = targetOffsetForStartOffset(ScrollEventAxis::Vertical, viewportSize, contentSize.height() - viewportSize.height(), initialOffset.y(), predictedScrollTarget, pageScale, initialDelta.height());
    5656    m_momentumCalculator->setRetargetedScrollOffset({ targetOffsetX, targetOffsetY });
    5757    m_startTime = MonotonicTime::now();
     
    9292}
    9393
    94 std::pair<float, std::optional<unsigned>> ScrollSnapAnimatorState::targetOffsetForStartOffset(ScrollEventAxis axis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta) const
     94std::pair<float, std::optional<unsigned>> ScrollSnapAnimatorState::targetOffsetForStartOffset(ScrollEventAxis axis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, FloatPoint predictedOffset, float pageScale, float initialDelta) const
    9595{
    9696    const auto& snapOffsets = m_snapOffsetsInfo.offsetsForAxis(axis);
    9797    if (snapOffsets.isEmpty())
    98         return std::make_pair(clampTo<float>(predictedOffset, 0, maxScrollOffset), std::nullopt);
     98        return std::make_pair(clampTo<float>(axis == ScrollEventAxis::Horizontal ? predictedOffset.x() : predictedOffset.y(), 0, maxScrollOffset), std::nullopt);
    9999
    100     auto [targetOffset, snapIndex] = m_snapOffsetsInfo.closestSnapOffset(axis, LayoutSize { viewportSize }, LayoutUnit(predictedOffset / pageScale), initialDelta, LayoutUnit(startOffset / pageScale));
     100    LayoutPoint predictedLayoutOffset(predictedOffset.x() / pageScale, predictedOffset.y() / pageScale);
     101    auto [targetOffset, snapIndex] = m_snapOffsetsInfo.closestSnapOffset(axis, LayoutSize { viewportSize }, predictedLayoutOffset, initialDelta, LayoutUnit(startOffset / pageScale));
    101102    return std::make_pair(pageScale * clampTo<float>(float { targetOffset }, 0, maxScrollOffset), snapIndex);
    102103}
  • trunk/Source/WebCore/platform/ScrollSnapAnimatorState.h

    r279218 r280171  
    8383
    8484private:
    85     std::pair<float, std::optional<unsigned>> targetOffsetForStartOffset(ScrollEventAxis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta) const;
     85    std::pair<float, std::optional<unsigned>> targetOffsetForStartOffset(ScrollEventAxis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, FloatPoint predictedOffset, float pageScale, float initialDelta) const;
    8686    void teardownAnimationForState(ScrollSnapState);
    8787    void setupAnimationForState(ScrollSnapState, const FloatSize& contentSize, const FloatSize& viewportSize, float pageScale, const FloatPoint& initialOffset, const FloatSize& initialVelocity, const FloatSize& initialDelta);
  • trunk/Source/WebCore/platform/ScrollableArea.cpp

    r279564 r280171  
    564564    auto newOffset = currentOffset;
    565565    if (orientation == HorizontalScrollbar)
    566         newOffset.setX(scrollAnimator->adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Horizontal, currentOffset.x(), ScrollSnapPointSelectionMethod::Closest));
     566        newOffset.setX(scrollAnimator->adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Horizontal, currentOffset, ScrollSnapPointSelectionMethod::Closest));
    567567    else
    568         newOffset.setY(scrollAnimator->adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Vertical, currentOffset.y(), ScrollSnapPointSelectionMethod::Closest));
     568        newOffset.setY(scrollAnimator->adjustScrollOffsetForSnappingIfNeeded(ScrollEventAxis::Vertical, currentOffset, ScrollSnapPointSelectionMethod::Closest));
    569569    if (newOffset == currentOffset)
    570570        return;
  • trunk/Source/WebKit/ChangeLog

    r280160 r280171  
     12021-07-22  Martin Robinson  <mrobinson@webkit.org>
     2
     3        [css-scroll-snap] Pass the full target point when selecting a snap offset
     4        https://bugs.webkit.org/show_bug.cgi?id=228023
     5
     6        Reviewed by Frédéric Wang.
     7
     8        * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
     9        * UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
     10        (WebKit::RemoteScrollingCoordinatorProxy::adjustTargetContentOffsetForSnapping):
     11        (WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling const):
     12        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
     13        (-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
     14
    1152021-07-21  Chris Dumez  <cdumez@apple.com>
    216
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h

    r279218 r280171  
    119119
    120120    bool shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis) const;
    121     std::pair<float, std::optional<unsigned>> closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis, float currentScrollOffset, float scrollDestination, float velocity) const;
     121    std::pair<float, std::optional<unsigned>> closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis, float currentScrollOffset, WebCore::FloatPoint scrollDestination, float velocity) const;
    122122
    123123    void sendUIStateChangedIfNecessary();
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm

    r279218 r280171  
    198198    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal)) {
    199199        float potentialSnapPosition;
    200         std::tie(potentialSnapPosition, m_currentHorizontalSnapPointIndex) = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal, currentContentOffset.x, targetContentOffset->x, velocity.x);
     200        std::tie(potentialSnapPosition, m_currentHorizontalSnapPointIndex) = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Horizontal, currentContentOffset.x, FloatPoint(*targetContentOffset), velocity.x);
    201201        if (targetContentOffset->x > 0 && targetContentOffset->x < maxScrollOffsets.width)
    202202            targetContentOffset->x = std::min<float>(maxScrollOffsets.width, potentialSnapPosition);
     
    205205    if (shouldSnapForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical)) {
    206206        float potentialSnapPosition;
    207         std::tie(potentialSnapPosition, m_currentVerticalSnapPointIndex) = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical, currentContentOffset.y + topInset, targetContentOffset->y, velocity.y);
     207        std::tie(potentialSnapPosition, m_currentVerticalSnapPointIndex) = closestSnapOffsetForMainFrameScrolling(WebCore::ScrollEventAxis::Vertical, currentContentOffset.y + topInset, FloatPoint(*targetContentOffset), velocity.y);
    208208        if (m_currentVerticalSnapPointIndex)
    209209            potentialSnapPosition -= topInset;
     
    229229}
    230230
    231 std::pair<float, std::optional<unsigned>> RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float currentScrollOffset, float scrollDestination, float velocity) const
     231std::pair<float, std::optional<unsigned>> RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float currentScrollOffset, FloatPoint scrollDestination, float velocity) const
    232232{
    233233    ScrollingTreeNode* root = m_scrollingTree->rootNode();
     
    236236    const auto& snapOffsetsInfo = rootScrollingNode->snapOffsetsInfo();
    237237
    238     float scaledScrollDestination = scrollDestination / m_webPageProxy.displayedContentScale();
     238    scrollDestination.scale(1.0 / m_webPageProxy.displayedContentScale());
    239239    float scaledCurrentScrollOffset = currentScrollOffset / m_webPageProxy.displayedContentScale();
    240     auto [rawClosestSnapOffset, newIndex] = snapOffsetsInfo.closestSnapOffset(axis, rootScrollingNode->layoutViewport().size(), scaledScrollDestination, velocity, scaledCurrentScrollOffset);
     240    auto [rawClosestSnapOffset, newIndex] = snapOffsetsInfo.closestSnapOffset(axis, rootScrollingNode->layoutViewport().size(), scrollDestination, velocity, scaledCurrentScrollOffset);
    241241    return std::make_pair(rawClosestSnapOffset * m_webPageProxy.displayedContentScale(), newIndex);
    242242}
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm

    r279218 r280171  
    9797    }
    9898
    99     CGFloat horizontalTarget = targetContentOffset->x;
    100     CGFloat verticalTarget = targetContentOffset->y;
    101 
    10299    std::optional<unsigned> originalHorizontalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex();
    103100    std::optional<unsigned> originalVerticalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex();
     
    106103    const auto& snapOffsetsInfo = _scrollingTreeNodeDelegate->scrollingNode().snapOffsetsInfo();
    107104    if (!snapOffsetsInfo.horizontalSnapOffsets.isEmpty()) {
    108         auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Horizontal, viewportSize, horizontalTarget, velocity.x, scrollView.contentOffset.x);
     105        auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Horizontal, viewportSize, WebCore::FloatPoint(*targetContentOffset), velocity.x, scrollView.contentOffset.x);
    109106        _scrollingTreeNodeDelegate->scrollingNode().setCurrentHorizontalSnapPointIndex(index);
    110         if (horizontalTarget >= 0 && horizontalTarget <= scrollView.contentSize.width)
     107        if (targetContentOffset->x >= 0 && targetContentOffset->x <= scrollView.contentSize.width)
    111108            targetContentOffset->x = potentialSnapPosition;
    112109    }
    113110
    114111    if (!snapOffsetsInfo.verticalSnapOffsets.isEmpty()) {
    115         auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Vertical, viewportSize, verticalTarget, velocity.y, scrollView.contentOffset.y);
     112        auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Vertical, viewportSize, WebCore::FloatPoint(*targetContentOffset), velocity.y, scrollView.contentOffset.y);
    116113        _scrollingTreeNodeDelegate->scrollingNode().setCurrentVerticalSnapPointIndex(index);
    117         if (verticalTarget >= 0 && verticalTarget <= scrollView.contentSize.height)
     114        if (targetContentOffset->y >= 0 && targetContentOffset->y <= scrollView.contentSize.height)
    118115            targetContentOffset->y = potentialSnapPosition;
    119116    }
Note: See TracChangeset for help on using the changeset viewer.