Changeset 278862 in webkit
- Timestamp:
- Jun 15, 2021 12:08:07 AM (13 months ago)
- Location:
- trunk
- Files:
-
- 17 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp (modified) (4 diffs)
-
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp (modified) (1 diff)
-
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h (modified) (1 diff)
-
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (modified) (1 diff)
-
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (modified) (1 diff)
-
Source/WebCore/platform/ScrollAnimator.cpp (modified) (2 diffs)
-
Source/WebCore/platform/ScrollAnimator.h (modified) (1 diff)
-
Source/WebCore/platform/ScrollController.cpp (modified) (4 diffs)
-
Source/WebCore/platform/ScrollController.h (modified) (2 diffs)
-
Source/WebCore/platform/ScrollSnapAnimatorState.cpp (modified) (1 diff)
-
Source/WebCore/platform/ScrollSnapAnimatorState.h (modified) (1 diff)
-
Source/WebCore/platform/ScrollableArea.cpp (modified) (3 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r278861 r278862 1 2021-06-15 Martin Robinson <mrobinson@webkit.org> 2 3 [css-scroll-snap] New snap containers always snap to the first scroll position 4 https://bugs.webkit.org/show_bug.cgi?id=226630 5 6 Reviewed by Simon Fraser. 7 8 * TestExpectations: Mark two WPT tests as passing. 9 1 10 2021-06-14 Youenn Fablet <youenn@apple.com> 2 11 -
trunk/LayoutTests/TestExpectations
r278825 r278862 4554 4554 imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-snap-001.html [ ImageOnlyFailure ] 4555 4555 imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-snap-002.html [ ImageOnlyFailure ] 4556 imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-snap-003.html [ ImageOnlyFailure ]4557 4556 imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html [ ImageOnlyFailure ] 4558 imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html [ ImageOnlyFailure ]4559 4557 imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-writing-mode-000.html [ ImageOnlyFailure ] 4560 4558 webkit.org/b/218325 imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-margin-001.html [ Pass ImageOnlyFailure ] -
trunk/Source/WebCore/ChangeLog
r278858 r278862 1 2021-06-15 Martin Robinson <mrobinson@webkit.org> 2 3 [css-scroll-snap] New snap containers always snap to the first scroll position 4 https://bugs.webkit.org/show_bug.cgi?id=226630 5 6 Reviewed by Simon Fraser. 7 8 There are two situations where we should not immediately snap to the first snap position 9 of a scroller after initial layout: 10 1. If that scroll is right-to-left. In this case the last snap position is closest to 11 the origin. 12 2. If the scroller uses proximity snapping and the first snap position is far enough 13 away from the origin that it isn't yet active. 14 Previously, WebKit was always snapping to the first position. The change fixes that by 15 not snapping to the 0 index snap point immediately after initial layout and only snapping 16 to an eligible snap positions after running a snap point search. 17 18 No new tests. This change fixes two existing WPT tests: 19 - imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-snap-003.htm 20 - imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.htm 21 22 * page/scrolling/ScrollSnapOffsetsInfo.cpp: 23 (WebCore::closestSnapOffsetWithInfoAndAxis): Pull in isNearEnoughToOffsetForProximity as 24 an anonymous function and use it to avoid snapping to the first and last position if 25 they are too far for proximity snapping. 26 * page/scrolling/ScrollingStateScrollingNode.cpp: 27 (WebCore::ScrollingStateScrollingNode::dumpProperties const): Use invalidSnapOffsetIndex as 28 the default for the snap index property. Interpret 0 as a valid snap position. 29 * page/scrolling/ScrollingStateScrollingNode.h: Ditto. 30 * page/scrolling/ScrollingTreeScrollingNode.cpp: 31 (WebCore::ScrollingTreeScrollingNode::dumpProperties const): Ditto. 32 * page/scrolling/ScrollingTreeScrollingNode.h: Ditto. 33 * platform/ScrollAnimator.cpp: 34 (WebCore::ScrollAnimator::resnapAfterLayout): Added this method that passes through to ScrollController. 35 (WebCore::ScrollAnimator::updateActiveScrollSnapIndexForOffset): Simplified setActiveScrollSnapIndicesForOffset 36 into updateActiveScrollSnapIndexForClientOffset. 37 * platform/ScrollAnimator.h: Added method definition. 38 * platform/ScrollController.cpp: 39 (WebCore::ScrollController::setSnapOffsetsInfo): Use updateActiveScrollSnapIndexForClientOffset now. 40 (WebCore::ScrollController::activeScrollSnapIndexForAxis const): Return invalidSnapOffsetIndex 41 when snapping is disabled. 42 (WebCore::ScrollController::setNearestScrollSnapIndexForAxisAndOffset): No longer clamp the scroll 43 position to the first and last snap points. We might be scrolling to a position before or after 44 them that isn't subject to proximity snapping. 45 (WebCore::ScrollController::updateActiveScrollSnapIndexForClientOffset): Renamed from setActiveScrollSnapIndicesForOffset 46 because it always just took the client's current offset. 47 (WebCore::ScrollController::resnapAfterLayout): Added this helper which snaps in axes that aren't currently 48 snapped to a snap position after a layout. 49 * platform/ScrollController.h: Removed unused method that used 0 incorrectly as an invalid snap position. 50 Update method definitions. 51 * platform/ScrollSnapAnimatorState.h: Use invalidSnapOffsetIndex to signify no snapping. 52 * platform/ScrollSnapAnimatorState.cpp: 53 (WebCore::ScrollSnapAnimatorState::targetOffsetForStartOffset const): No longer clamp offsets to first and 54 last scroll snap offsets. 55 * platform/ScrollableArea.cpp: 56 (WebCore::ScrollableArea::currentHorizontalSnapPointIndex const): Ditto. 57 (WebCore::ScrollableArea::currentVerticalSnapPointIndex const): Ditto. 58 (WebCore::ScrollableArea::resnapAfterLayout): Call into ScrollController::resnapAfterLayout. 59 1 60 2021-06-14 Myles C. Maxfield <mmaxfield@apple.com> 2 61 -
trunk/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp
r278350 r278862 43 43 namespace WebCore { 44 44 45 template <typename UnitType>46 static bool isNearEnoughToOffsetForProximity(ScrollSnapStrictness strictness, UnitType scrollDestination, UnitType candidateSnapOffset, UnitType viewportLength)47 {48 if (strictness != ScrollSnapStrictness::Proximity)49 return true;50 51 // This is an arbitrary choice for what it means to be "in proximity" of a snap offset. We should play around with52 // this and see what feels best.53 static const float ratioOfScrollPortAxisLengthToBeConsideredForProximity = 0.3;54 return std::abs(float {candidateSnapOffset - scrollDestination}) <= (viewportLength * ratioOfScrollPortAxisLengthToBeConsideredForProximity);55 }56 57 45 template <typename LayoutType> 58 46 static void indicesOfNearestSnapOffsets(LayoutType offset, const Vector<SnapOffset<LayoutType>>& snapOffsets, unsigned& lowerIndex, unsigned& upperIndex) … … 111 99 { 112 100 const auto& snapOffsets = info.offsetsForAxis(axis); 101 auto pairForNoSnapping = std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex); 113 102 if (snapOffsets.isEmpty()) 114 return std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex);103 return pairForNoSnapping; 115 104 116 105 if (originalOffsetForDirectionalSnapping) { … … 119 108 } 120 109 110 auto viewportLength = axis == ScrollEventAxis::Horizontal ? viewportSize.width() : viewportSize.height(); 111 auto isNearEnoughToOffsetForProximity = [&](LayoutType candidateSnapOffset) { 112 if (info.strictness != ScrollSnapStrictness::Proximity) 113 return true; 114 115 // This is an arbitrary choice for what it means to be "in proximity" of a snap offset. We should play around with 116 // this and see what feels best. 117 static const float ratioOfScrollPortAxisLengthToBeConsideredForProximity = 0.3; 118 return std::abs(float {candidateSnapOffset - scrollDestinationOffset}) <= (viewportLength * ratioOfScrollPortAxisLengthToBeConsideredForProximity); 119 }; 120 121 121 if (scrollDestinationOffset <= snapOffsets.first().offset) 122 return std::make_pair(snapOffsets.first().offset, 0u); 123 124 if (scrollDestinationOffset >= snapOffsets.last().offset) 125 return std::make_pair(snapOffsets.last().offset, snapOffsets.size() - 1); 122 return isNearEnoughToOffsetForProximity(snapOffsets.first().offset) ? std::make_pair(snapOffsets.first().offset, 0u) : pairForNoSnapping; 123 124 if (scrollDestinationOffset >= snapOffsets.last().offset) { 125 unsigned lastIndex = static_cast<unsigned>(snapOffsets.size() - 1); 126 return isNearEnoughToOffsetForProximity(snapOffsets.last().offset) ? std::make_pair(snapOffsets.last().offset, lastIndex) : pairForNoSnapping; 127 } 126 128 127 129 unsigned lowerIndex; … … 131 133 LayoutType upperSnapPosition = snapOffsets[upperIndex].offset; 132 134 133 auto viewportLength = axis == ScrollEventAxis::Horizontal ? viewportSize.width() : viewportSize.height(); 134 if (!isNearEnoughToOffsetForProximity<LayoutType>(info.strictness, scrollDestinationOffset, lowerSnapPosition, viewportLength)) { 135 if (!isNearEnoughToOffsetForProximity(lowerSnapPosition)) { 135 136 lowerSnapPosition = scrollDestinationOffset; 136 137 lowerIndex = invalidSnapOffsetIndex; 137 138 } 138 139 139 if (!isNearEnoughToOffsetForProximity <LayoutType>(info.strictness, scrollDestinationOffset, upperSnapPosition, viewportLength)) {140 if (!isNearEnoughToOffsetForProximity(upperSnapPosition)) { 140 141 upperSnapPosition = scrollDestinationOffset; 141 142 upperIndex = invalidSnapOffsetIndex; 142 143 } 144 143 145 if (!std::abs(velocity)) { 144 146 bool isCloserToLowerSnapPosition = (upperIndex == invalidSnapOffsetIndex) -
trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
r275354 r278862 314 314 ts.dumpProperty("vertical snap offsets", m_snapOffsetsInfo.verticalSnapOffsets); 315 315 316 if (m_currentHorizontalSnapPointIndex )316 if (m_currentHorizontalSnapPointIndex != invalidSnapOffsetIndex) 317 317 ts.dumpProperty("current horizontal snap point index", m_currentHorizontalSnapPointIndex); 318 318 319 if (m_currentVerticalSnapPointIndex )319 if (m_currentVerticalSnapPointIndex != invalidSnapOffsetIndex) 320 320 ts.dumpProperty("current vertical snap point index", m_currentVerticalSnapPointIndex); 321 321 #endif -
trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
r275354 r278862 132 132 #if ENABLE(CSS_SCROLL_SNAP) 133 133 FloatScrollSnapOffsetsInfo m_snapOffsetsInfo; 134 unsigned m_currentHorizontalSnapPointIndex { 0};135 unsigned m_currentVerticalSnapPointIndex { 0};134 unsigned m_currentHorizontalSnapPointIndex { invalidSnapOffsetIndex }; 135 unsigned m_currentVerticalSnapPointIndex { invalidSnapOffsetIndex }; 136 136 #endif 137 137 -
trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp
r278253 r278862 319 319 ts.dumpProperty("vertical snap offsets", m_snapOffsetsInfo.verticalSnapOffsets); 320 320 321 if (m_currentHorizontalSnapPointIndex )321 if (m_currentHorizontalSnapPointIndex != invalidSnapOffsetIndex) 322 322 ts.dumpProperty("current horizontal snap point index", m_currentHorizontalSnapPointIndex); 323 323 324 if (m_currentVerticalSnapPointIndex )324 if (m_currentVerticalSnapPointIndex != invalidSnapOffsetIndex) 325 325 ts.dumpProperty("current vertical snap point index", m_currentVerticalSnapPointIndex); 326 326 -
trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
r278253 r278862 161 161 #if ENABLE(CSS_SCROLL_SNAP) 162 162 FloatScrollSnapOffsetsInfo m_snapOffsetsInfo; 163 unsigned m_currentHorizontalSnapPointIndex { 0};164 unsigned m_currentVerticalSnapPointIndex { 0};163 unsigned m_currentHorizontalSnapPointIndex { invalidSnapOffsetIndex }; 164 unsigned m_currentVerticalSnapPointIndex { invalidSnapOffsetIndex }; 165 165 #endif 166 166 ScrollableAreaParameters m_scrollableAreaParameters; -
trunk/Source/WebCore/platform/ScrollAnimator.cpp
r278484 r278862 194 194 return m_scrollController.setActiveScrollSnapIndexForAxis(axis, index); 195 195 } 196 197 void ScrollAnimator::resnapAfterLayout() 198 { 199 m_scrollController.resnapAfterLayout(); 200 } 196 201 #endif 197 202 … … 274 279 { 275 280 #if ENABLE(CSS_SCROLL_SNAP) 276 auto scrollOffset = m_scrollableArea.scrollOffsetFromPosition(roundedIntPoint(currentPosition())); 277 m_scrollController.setActiveScrollSnapIndicesForOffset(scrollOffset); 281 m_scrollController.updateActiveScrollSnapIndexForClientOffset(); 278 282 #endif 279 283 } -
trunk/Source/WebCore/platform/ScrollAnimator.h
r278484 r278862 162 162 void setSnapOffsetsInfo(const LayoutScrollSnapOffsetsInfo&); 163 163 const LayoutScrollSnapOffsetsInfo* snapOffsetsInfo() const; 164 void resnapAfterLayout(); 164 165 #endif 165 166 -
trunk/Source/WebCore/platform/ScrollController.cpp
r278484 r278862 114 114 115 115 if (shouldComputeCurrentSnapIndices) 116 setActiveScrollSnapIndicesForOffset(roundedIntPoint(m_client.scrollOffset()));116 updateActiveScrollSnapIndexForClientOffset(); 117 117 118 118 LOG_WITH_STREAM(ScrollSnap, stream << "ScrollController " << this << " setSnapOffsetsInfo new state: " << ValueOrNull(m_scrollSnapState.get())); … … 127 127 { 128 128 if (!usesScrollSnap()) 129 return 0;129 return invalidSnapOffsetIndex; 130 130 131 131 return m_scrollSnapState->activeSnapIndexForAxis(axis); … … 152 152 return; 153 153 154 LayoutUnit clampedOffset = std::min(std::max(LayoutUnit(offset / scaleFactor), snapOffsets.first().offset), snapOffsets.last().offset);155 156 154 LayoutSize viewportSize(m_client.viewportSize().width(), m_client.viewportSize().height()); 157 unsigned activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, clampedOffset, 0).second;155 unsigned activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, LayoutUnit(offset / scaleFactor), 0).second; 158 156 if (activeIndex == activeScrollSnapIndexForAxis(axis)) 159 157 return; … … 182 180 183 181 184 void ScrollController::setActiveScrollSnapIndicesForOffset(ScrollOffset offset) 185 { 186 if (!usesScrollSnap()) 187 return; 188 182 void ScrollController::updateActiveScrollSnapIndexForClientOffset() 183 { 184 if (!usesScrollSnap()) 185 return; 186 187 ScrollOffset offset = roundedIntPoint(m_client.scrollOffset()); 189 188 setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset.x()); 190 189 setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset.y()); 190 } 191 192 void ScrollController::resnapAfterLayout() 193 { 194 if (!usesScrollSnap()) 195 return; 196 197 // If we are already snapped in a particular axis, maintain that. Otherwise, snap to the nearest eligible snap point. 198 ScrollOffset offset = roundedIntPoint(m_client.scrollOffset()); 199 size_t activeHorizontalIndex = m_scrollSnapState->activeSnapIndexForAxis(ScrollEventAxis::Horizontal); 200 if (activeHorizontalIndex == invalidSnapOffsetIndex) 201 setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Horizontal, offset.x()); 202 size_t activeVerticalIndex = m_scrollSnapState->activeSnapIndexForAxis(ScrollEventAxis::Vertical); 203 if (activeVerticalIndex == invalidSnapOffsetIndex) 204 setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis::Vertical, offset.y()); 205 191 206 } 192 207 #endif -
trunk/Source/WebCore/platform/ScrollController.h
r278484 r278862 112 112 virtual void willStartScrollSnapAnimation() { } 113 113 virtual void didStopScrollSnapAnimation() { } 114 115 114 virtual float pageScaleFactor() const = 0; 116 117 virtual unsigned activeScrollOffsetIndex(ScrollEventAxis) const118 {119 return 0;120 }121 122 115 virtual LayoutSize scrollExtent() const = 0; 123 116 virtual FloatSize viewportSize() const = 0; … … 143 136 const LayoutScrollSnapOffsetsInfo* snapOffsetsInfo() const; 144 137 void setActiveScrollSnapIndexForAxis(ScrollEventAxis, unsigned); 145 void setActiveScrollSnapIndicesForOffset(ScrollOffset); 138 void updateActiveScrollSnapIndexForClientOffset(); 139 void resnapAfterLayout(); 146 140 bool activeScrollSnapIndexDidChange() const { return m_activeScrollSnapIndexDidChange; } 147 141 void setScrollSnapIndexDidChange(bool state) { m_activeScrollSnapIndexDidChange = state; } -
trunk/Source/WebCore/platform/ScrollSnapAnimatorState.cpp
r277350 r278862 101 101 102 102 float targetOffset = m_snapOffsetsInfo.closestSnapOffset(axis, LayoutSize { viewportSize }, LayoutUnit(predictedOffset / pageScale), initialDelta, LayoutUnit(startOffset / pageScale)).first; 103 float minimumTargetOffset = std::max<float>(0, snapOffsets.first().offset); 104 float maximumTargetOffset = std::min<float>(maxScrollOffset, snapOffsets.last().offset); 105 targetOffset = clampTo<float>(targetOffset, minimumTargetOffset, maximumTargetOffset); 106 return pageScale * targetOffset; 103 return pageScale * clampTo<float>(targetOffset, 0, maxScrollOffset); 107 104 } 108 105 -
trunk/Source/WebCore/platform/ScrollSnapAnimatorState.h
r277350 r278862 93 93 LayoutScrollSnapOffsetsInfo m_snapOffsetsInfo; 94 94 95 unsigned m_activeSnapIndexX { 0};96 unsigned m_activeSnapIndexY { 0};95 unsigned m_activeSnapIndexX { invalidSnapOffsetIndex }; 96 unsigned m_activeSnapIndexY { invalidSnapOffsetIndex }; 97 97 98 98 MonotonicTime m_startTime; -
trunk/Source/WebCore/platform/ScrollableArea.cpp
r278484 r278862 495 495 if (auto* scrollAnimator = existingScrollAnimator()) 496 496 return scrollAnimator->activeScrollSnapIndexForAxis(ScrollEventAxis::Horizontal); 497 return 0; // FIXME: This should really be invalidSnapOffsetIndex.497 return invalidSnapOffsetIndex; 498 498 } 499 499 … … 502 502 if (auto* scrollAnimator = existingScrollAnimator()) 503 503 return scrollAnimator->activeScrollSnapIndexForAxis(ScrollEventAxis::Vertical); 504 return 0; // FIXME: This should really be invalidSnapOffsetIndex.504 return invalidSnapOffsetIndex; 505 505 } 506 506 … … 519 519 LOG_WITH_STREAM(ScrollSnap, stream << *this << " updateScrollSnapState: isScrollSnapInProgress " << isScrollSnapInProgress() << " isUserScrollInProgress " << isUserScrollInProgress()); 520 520 521 if (!existingScrollAnimator() || isScrollSnapInProgress() || isUserScrollInProgress()) 521 ScrollAnimator* scrollAnimator = existingScrollAnimator(); 522 if (!scrollAnimator || isScrollSnapInProgress() || isUserScrollInProgress()) 522 523 return; 524 525 scrollAnimator->resnapAfterLayout(); 523 526 524 527 const auto* info = snapOffsetsInfo(); -
trunk/Source/WebKit/ChangeLog
r278849 r278862 1 2021-06-15 Martin Robinson <mrobinson@webkit.org> 2 3 [css-scroll-snap] New snap containers always snap to the first scroll position 4 https://bugs.webkit.org/show_bug.cgi?id=226630 5 6 Reviewed by Simon Fraser. 7 8 * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h: Use invalidSnapOffsetIndex 9 instead of 0 to initialize the snap position. 10 1 11 2021-06-14 Alex Christensen <achristensen@webkit.org> 2 12 -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
r278253 r278862 33 33 #include "RemoteScrollingUIState.h" 34 34 #include <WebCore/GraphicsLayer.h> 35 #include <WebCore/ScrollSnapOffsetsInfo.h> 35 36 #include <wtf/Noncopyable.h> 36 37 #include <wtf/RefPtr.h> … … 132 133 RemoteScrollingUIState m_uiState; 133 134 #if ENABLE(CSS_SCROLL_SNAP) 134 unsigned m_currentHorizontalSnapPointIndex { 0};135 unsigned m_currentVerticalSnapPointIndex { 0};135 unsigned m_currentHorizontalSnapPointIndex { WebCore::invalidSnapOffsetIndex }; 136 unsigned m_currentVerticalSnapPointIndex { WebCore::invalidSnapOffsetIndex }; 136 137 #endif 137 138 bool m_propagatesMainFrameScrolls { true };
Note: See TracChangeset
for help on using the changeset viewer.