WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-223175-20210315140440.patch (text/plain), 77.18 KB, created by
Martin Robinson
on 2021-03-15 06:04:41 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Martin Robinson
Created:
2021-03-15 06:04:41 PDT
Size:
77.18 KB
patch
obsolete
>Subversion Revision: 274413 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 58a2371cca152bfd8449674265735afaf77c9d5e..22b355de97188548d0a5f63b1d43098ac5e5cb3d 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,66 @@ >+2021-03-15 Martin Robinson <mrobinson@webkit.org> >+ >+ [css-scroll-snap] Properly handle overflowing snap areas >+ https://bugs.webkit.org/show_bug.cgi?id=223175 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Properly handle overflowing snap areas. This requires rewriting the snapping >+ algorithm. ScrollSnapOffsetsInfo now store snap area rectangles, which are >+ used to handle overflowing snap areas. In addition, snap offset ranges are no >+ longer kept to handle proximity. Instead this is done when choosing candidate >+ snap offsets. >+ >+ Because ScrollSnapOffsetsInfo now contains a rectangle type, its template needs >+ this type as well. In order to make it simpler to use ScrollSnapOffsetsInfo this >+ change exposes two type aliases, FloatScrollSnapOffsetsInfo and LayoutScrollSnapOffsetsInfo >+ which are used everywhere. >+ >+ No new tests. This change fixes the WPT test: >+ imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas.html >+ >+ * page/scrolling/AsyncScrollingCoordinator.cpp: Use the new type aliases. >+ * page/scrolling/ScrollSnapOffsetsInfo.cpp: >+ (WebCore::findFirstSnapStopOffsetBetweenOriginAndDestination): Updated to return an offset/index >+ pair so the return type of this function is compatible with that of calculateClosestSnapOffset. >+ (WebCore::updateSnapOffsetsForScrollableArea): No longer store offset ranges for proximity snapping >+ and also store snap areas converted to "offset" coordinates. >+ (WebCore::convertOffsetInfo): No longer need to convert offset ranges, but this does now >+ require converting offset areas. >+ (WebCore::FloatScrollSnapOffsetsInfo::convertUnits const): Use the new type aliases. >+ (WebCore::LayoutScrollSnapOffsetsInfo::convertUnits const): Ditto. >+ (WebCore::maxForAxis): Added this helper which gets the maximum in a particular axis given the axis. >+ (WebCore::minForAxis): Ditto. >+ (WebCore::isNearEnoughToOffsetForProximity): Added this helper which replaces computeAxisProximitySnapOffsetRanges. >+ (WebCore::calculateClosestSnapOffset): This replaces closestSnapOffsetWithOffsetsAndRanges, but also >+ and indicesOfNearestSnapOffsets. Now written using snap areas from the data structure as well as >+ with proper handling for overflowing snap areas. >+ (WebCore::LayoutScrollSnapOffsetsInfo::closestSnapOffset const): Update for new method names and type aliases. >+ (WebCore::FloatScrollSnapOffsetsInfo::closestSnapOffset const): Ditto. >+ * page/scrolling/ScrollSnapOffsetsInfo.h: >+ (WebCore::ScrollSnapOffsetsInfo::isEqual const): No longer look at snap offset ranges, but do take into >+ consideration the snap areas. >+ (WebCore::ScrollSnapOffsetsInfo::offsetsForAxis const): Renamed the template argument. >+ (WebCore::operator<<): Removed. >+ * page/scrolling/ScrollingStateScrollingNode.cpp: Use the new type alias. >+ * page/scrolling/ScrollingStateScrollingNode.h: Ditto. >+ * page/scrolling/ScrollingTreeScrollingNode.cpp: Ditto. >+ * page/scrolling/ScrollingTreeScrollingNode.h: Ditto. >+ * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm: >+ (WebCore::ScrollingTreeScrollingNodeDelegateMac::updateFromStateNode): convertUnits now takes two template arguments. >+ * platform/ScrollController.cpp: >+ (WebCore::ScrollController::updateScrollSnapPoints): Pass in the viewport size when selecting snap points. >+ (WebCore::ScrollController::adjustScrollDestination): Ditto. >+ * platform/ScrollController.h: Use the new type alias. >+ * platform/ScrollSnapAnimatorState.cpp: >+ (WebCore::ScrollSnapAnimatorState::setupAnimationForState): Pass viewport size to targetOffsetForStartOffset. >+ (WebCore::ScrollSnapAnimatorState::targetOffsetForStartOffset const): Ditto. >+ (WebCore::operator<<): No longer print snap offset ranges. >+ * platform/ScrollSnapAnimatorState.h: Removed method dealing with ranges. Now pass viewport size to targetOffsetForStartOffset. >+ * platform/ScrollableArea.cpp: Use the new type aliases. >+ * platform/ScrollableArea.h: Ditto. >+ * platform/mac/ScrollAnimatorMac.mm: Ditto. >+ > 2021-03-10 Sergio Villar Senin <svillar@igalia.com> > > Do not shrink radio buttons bellow its size >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index ce543af6409610968d39a6fd903f0404b241b9a7..3b02a599f1f3149fd618806a84eba87b79d64063 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,26 @@ >+2021-03-15 Martin Robinson <mrobinson@webkit.org> >+ >+ [css-scroll-snap] Properly handle overflowing snap areas >+ https://bugs.webkit.org/show_bug.cgi?id=223175 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ ScrollSnapOffsetsInfo no longer holds snap offset ranges, but is also templated off >+ of a rect type. In WebKit we switch to using the FloatScrollSnapOffsetsInfo alias. >+ Additionally, we need to pass in the viewport size when requesting a snap offset >+ position. >+ >+ * Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp: >+ (ArgumentCoder<ScrollingStateScrollingNode>::decode): Switch to using the FloatScrollSnapOffsetsInfo alias. >+ (ArgumentCoder<FloatScrollSnapOffsetsInfo>::encode): Ditto. Also we no longer need to encode the ranges. >+ (ArgumentCoder<FloatScrollSnapOffsetsInfo>::decode): Ditto. >+ * Shared/WebCoreArgumentCoders.cpp: Ditto. >+ * Shared/WebCoreArgumentCoders.h: Ditto. >+ * UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm: >+ (WebKit::RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling const): Pass in the viewport size now. >+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm: >+ (-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]): Ditto. >+ > 2021-03-15 Kimmo Kinnunen <kkinnunen@apple.com> > > RemoteRenderingBackend commands are not processed in order if GPU process is waiting for replies >diff --git a/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp b/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp >index 58480a2d7a8f8acbc0dc6e3d15847400479b7c97..480fe95d82b2914979fa059b66b93e71a8f7811f 100644 >--- a/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp >+++ b/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp >@@ -92,15 +92,15 @@ void AsyncScrollingCoordinator::handleWheelEventPhase(ScrollingNodeID nodeID, Pl > #endif > > #if ENABLE(CSS_SCROLL_SNAP) >-static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, const ScrollSnapOffsetsInfo<LayoutUnit>* offsetInfo, float deviceScaleFactor) >+static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, const LayoutScrollSnapOffsetsInfo* offsetInfo, float deviceScaleFactor) > { > if (!offsetInfo) { >- node.setSnapOffsetsInfo(ScrollSnapOffsetsInfo<float>()); >+ node.setSnapOffsetsInfo(FloatScrollSnapOffsetsInfo()); > return; > } > > // FIXME: Incorporate current page scale factor in snapping to device pixel. Perhaps we should just convert to float here and let UI process do the pixel snapping? >- node.setSnapOffsetsInfo(offsetInfo->convertUnits<float>(deviceScaleFactor)); >+ node.setSnapOffsetsInfo(offsetInfo->convertUnits<float, FloatRect>(deviceScaleFactor)); > } > #endif > >diff --git a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp b/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp >index acfed0f38378eb4e2ec2a51b41028f5203d57cb4..01021a4cc3fd034b6d61104a3236375271673185 100644 >--- a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp >+++ b/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp >@@ -41,68 +41,10 @@ > > namespace WebCore { > >-template <typename LayoutType> >-static void indicesOfNearestSnapOffsetRanges(LayoutType offset, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, unsigned& lowerIndex, unsigned& upperIndex) >+template <typename UnitType> >+static Optional<std::pair<UnitType, unsigned>> findFirstSnapStopOffsetBetweenOriginAndDestination(const Vector<SnapOffset<UnitType>>& snapOffsets, UnitType scrollOriginOffset, UnitType scrollDestinationOffset) > { >- if (snapOffsetRanges.isEmpty()) { >- lowerIndex = invalidSnapOffsetIndex; >- upperIndex = invalidSnapOffsetIndex; >- return; >- } >- >- int lowerIndexAsInt = -1; >- int upperIndexAsInt = snapOffsetRanges.size(); >- do { >- int middleIndex = (lowerIndexAsInt + upperIndexAsInt) / 2; >- auto& range = snapOffsetRanges[middleIndex]; >- if (range.start < offset && offset < range.end) { >- lowerIndexAsInt = middleIndex; >- upperIndexAsInt = middleIndex; >- break; >- } >- >- if (offset > range.end) >- lowerIndexAsInt = middleIndex; >- else >- upperIndexAsInt = middleIndex; >- } while (lowerIndexAsInt < upperIndexAsInt - 1); >- >- if (offset <= snapOffsetRanges.first().start) >- lowerIndex = invalidSnapOffsetIndex; >- else >- lowerIndex = lowerIndexAsInt; >- >- if (offset >= snapOffsetRanges.last().end) >- upperIndex = invalidSnapOffsetIndex; >- else >- upperIndex = upperIndexAsInt; >-} >- >-template <typename LayoutType> >-static void indicesOfNearestSnapOffsets(LayoutType offset, const Vector<SnapOffset<LayoutType>>& snapOffsets, unsigned& lowerIndex, unsigned& upperIndex) >-{ >- lowerIndex = 0; >- upperIndex = snapOffsets.size() - 1; >- while (lowerIndex < upperIndex - 1) { >- int middleIndex = (lowerIndex + upperIndex) / 2; >- auto middleOffset = snapOffsets[middleIndex].offset; >- if (offset == middleOffset) { >- upperIndex = middleIndex; >- lowerIndex = middleIndex; >- break; >- } >- >- if (offset > middleOffset) >- lowerIndex = middleIndex; >- else >- upperIndex = middleIndex; >- } >-} >- >-template <typename LayoutType> >-static Optional<unsigned> findFirstSnapStopOffsetBetweenOriginAndDestination(const Vector<SnapOffset<LayoutType>>& snapOffsets, LayoutType scrollOriginOffset, LayoutType scrollDestinationOffset) >-{ >- LayoutType difference = scrollDestinationOffset - scrollOriginOffset; >+ UnitType difference = scrollDestinationOffset - scrollOriginOffset; > if (!difference) > return WTF::nullopt; > >@@ -113,7 +55,7 @@ static Optional<unsigned> findFirstSnapStopOffsetBetweenOriginAndDestination(con > iteration = -1; > } > >- auto isPast = [difference](LayoutType mark, LayoutType candidate) { >+ auto isPast = [difference](UnitType mark, UnitType candidate) { > return (difference > 0 && candidate > mark) || (difference < 0 && candidate < mark); > }; > >@@ -124,65 +66,12 @@ static Optional<unsigned> findFirstSnapStopOffsetBetweenOriginAndDestination(con > if (snapOffsets[i].stop != ScrollSnapStop::Always) > continue; > if (isPast(scrollOriginOffset, offset)) >- return i; >+ return std::make_pair(offset, static_cast<unsigned>(i)); > } > > return WTF::nullopt; > } > >-template <typename LayoutType> >-static std::pair<LayoutType, unsigned> closestSnapOffsetWithOffsetsAndRanges(const Vector<SnapOffset<LayoutType>>& snapOffsets, const Vector<ScrollOffsetRange<LayoutType>>& snapOffsetRanges, LayoutType scrollDestinationOffset, float velocity, Optional<LayoutType> originalOffsetForDirectionalSnapping) >-{ >- if (snapOffsets.isEmpty()) >- return std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex); >- >- if (originalOffsetForDirectionalSnapping.hasValue()) { >- auto firstSnapStopOffsetIndex = findFirstSnapStopOffsetBetweenOriginAndDestination(snapOffsets, *originalOffsetForDirectionalSnapping, scrollDestinationOffset); >- if (firstSnapStopOffsetIndex.hasValue()) >- return std::make_pair(snapOffsets[*firstSnapStopOffsetIndex].offset, *firstSnapStopOffsetIndex); >- } >- >- unsigned lowerSnapOffsetRangeIndex; >- unsigned upperSnapOffsetRangeIndex; >- indicesOfNearestSnapOffsetRanges<LayoutType>(scrollDestinationOffset, snapOffsetRanges, lowerSnapOffsetRangeIndex, upperSnapOffsetRangeIndex); >- if (lowerSnapOffsetRangeIndex == upperSnapOffsetRangeIndex && upperSnapOffsetRangeIndex != invalidSnapOffsetIndex) >- return std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex); >- >- if (scrollDestinationOffset <= snapOffsets.first().offset) >- return std::make_pair(snapOffsets.first().offset, 0u); >- >- if (scrollDestinationOffset >= snapOffsets.last().offset) >- return std::make_pair(snapOffsets.last().offset, snapOffsets.size() - 1); >- >- unsigned lowerIndex; >- unsigned upperIndex; >- indicesOfNearestSnapOffsets<LayoutType>(scrollDestinationOffset, snapOffsets, lowerIndex, upperIndex); >- LayoutType lowerSnapPosition = snapOffsets[lowerIndex].offset; >- LayoutType upperSnapPosition = snapOffsets[upperIndex].offset; >- if (!std::abs(velocity)) { >- bool isCloserToLowerSnapPosition = scrollDestinationOffset - lowerSnapPosition <= upperSnapPosition - scrollDestinationOffset; >- return isCloserToLowerSnapPosition ? std::make_pair(lowerSnapPosition, lowerIndex) : std::make_pair(upperSnapPosition, upperIndex); >- } >- >- // 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 >- // 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 >- // 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. >- // This allows directional scrolling to escape snap points. >- if (velocity < 0) { >- if (lowerSnapOffsetRangeIndex == invalidSnapOffsetIndex || lowerSnapPosition >= snapOffsetRanges[lowerSnapOffsetRangeIndex].end) >- return std::make_pair(lowerSnapPosition, lowerIndex); >- if (!originalOffsetForDirectionalSnapping.hasValue() || *originalOffsetForDirectionalSnapping > upperSnapPosition) >- return std::make_pair(upperSnapPosition, upperIndex); >- } else { >- if (upperSnapOffsetRangeIndex == invalidSnapOffsetIndex || snapOffsetRanges[upperSnapOffsetRangeIndex].start >= upperSnapPosition) >- return std::make_pair(upperSnapPosition, upperIndex); >- if (!originalOffsetForDirectionalSnapping.hasValue() || *originalOffsetForDirectionalSnapping < lowerSnapPosition) >- return std::make_pair(lowerSnapPosition, lowerIndex); >- } >- >- return std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex); >-} >- > enum class InsetOrOutset { > Inset, > Outset >@@ -219,30 +108,6 @@ static LayoutUnit computeScrollSnapAlignOffset(LayoutUnit minLocation, LayoutUni > } > } > >-static void computeAxisProximitySnapOffsetRanges(const Vector<SnapOffset<LayoutUnit>>& snapOffsets, Vector<ScrollOffsetRange<LayoutUnit>>& offsetRanges, LayoutUnit scrollPortAxisLength) >-{ >- // This is an arbitrary choice for what it means to be "in proximity" of a snap offset. We should play around with >- // this and see what feels best. >- static const float ratioOfScrollPortAxisLengthToBeConsideredForProximity = 0.3; >- if (snapOffsets.size() < 2) >- return; >- >- // The extra rule accounting for scroll offset ranges in between the scroll destination and a potential snap offset >- // handles the corner case where the user scrolls with momentum very lightly away from a snap offset, such that the >- // predicted scroll destination is still within proximity of the snap offset. In this case, the regular (mandatory >- // scroll snapping) behavior would be to snap to the next offset in the direction of momentum scrolling, but >- // instead, it is more intuitive to either return to the original snap position (which we arbitrarily choose here) >- // or scroll just outside of the snap offset range. This is another minor behavior tweak that we should play around >- // with to see what feels best. >- LayoutUnit proximityDistance { ratioOfScrollPortAxisLengthToBeConsideredForProximity * scrollPortAxisLength }; >- for (size_t index = 1; index < snapOffsets.size(); ++index) { >- auto startOffset = snapOffsets[index - 1].offset + proximityDistance; >- auto endOffset = snapOffsets[index].offset - proximityDistance; >- if (startOffset < endOffset) >- offsetRanges.append({ startOffset, endOffset }); >- } >-} >- > void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle, LayoutRect viewportRectInBorderBoxCoordinates) > { > auto scrollSnapType = scrollingElementStyle.scrollSnapType(); >@@ -262,6 +127,7 @@ void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, const Re > > HashMap<float, SnapOffset<LayoutUnit>> verticalSnapOffsetsMap; > HashMap<float, SnapOffset<LayoutUnit>> horizontalSnapOffsetsMap; >+ Vector<LayoutRect> snapAreas; > bool hasHorizontalSnapOffsets = scrollSnapType.axis == ScrollSnapAxis::Both || scrollSnapType.axis == ScrollSnapAxis::XAxis || scrollSnapType.axis == ScrollSnapAxis::Inline; > bool hasVerticalSnapOffsets = scrollSnapType.axis == ScrollSnapAxis::Both || scrollSnapType.axis == ScrollSnapAxis::YAxis || scrollSnapType.axis == ScrollSnapAxis::Block; > >@@ -288,17 +154,29 @@ void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, const Re > > scrollSnapArea = computeScrollSnapPortOrAreaRect(scrollSnapArea, child->style().scrollMargin(), InsetOrOutset::Outset); > LOG_WITH_STREAM(ScrollSnap, stream << " Considering scroll snap target area " << scrollSnapArea); >+ > auto alignment = child->style().scrollSnapAlign(); >+ bool snapsHorizontally = hasHorizontalSnapOffsets && alignment.x != ScrollSnapAxisAlignType::None; >+ bool snapsVertically = hasVerticalSnapOffsets && alignment.y != ScrollSnapAxisAlignType::None; >+ if (!snapsHorizontally && !snapsVertically) >+ continue; >+ >+ // The scroll snap area is defined via its scroll position, so convert everything to scroll offetss here. >+ auto snapAreaOriginRelativeToBorderEdge = scrollSnapArea.location() - scrollSnapPort.location(); >+ LayoutRect scrollSnapAreaAsOffsets(scrollableArea.scrollOffsetFromPosition(roundedIntPoint(snapAreaOriginRelativeToBorderEdge)), scrollSnapArea.size()); >+ snapAreas.append(scrollSnapAreaAsOffsets); >+ unsigned snapAreaIndex = snapAreas.size() - 1; >+ > auto stop = child->style().scrollSnapStop(); >- if (hasHorizontalSnapOffsets && alignment.x != ScrollSnapAxisAlignType::None) { >+ if (snapsHorizontally) { > auto absoluteScrollXPosition = computeScrollSnapAlignOffset(scrollSnapArea.x(), scrollSnapArea.maxX(), alignment.x, scrollerIsRTL) - computeScrollSnapAlignOffset(scrollSnapPort.x(), scrollSnapPort.maxX(), alignment.x, scrollerIsRTL); > auto absoluteScrollOffset = clampTo<int>(scrollableArea.scrollOffsetFromPosition({ roundToInt(absoluteScrollXPosition), 0 }).x(), 0, maxScrollOffset.x()); >- addOrUpdateStopForSnapOffset(horizontalSnapOffsetsMap, { absoluteScrollOffset, stop }); >+ addOrUpdateStopForSnapOffset(horizontalSnapOffsetsMap, { absoluteScrollOffset, stop, snapAreaIndex }); > } >- if (hasVerticalSnapOffsets && alignment.y != ScrollSnapAxisAlignType::None) { >+ if (snapsVertically) { > auto absoluteScrollYPosition = computeScrollSnapAlignOffset(scrollSnapArea.y(), scrollSnapArea.maxY(), alignment.y, false) - computeScrollSnapAlignOffset(scrollSnapPort.y(), scrollSnapPort.maxY(), alignment.y, false); > auto absoluteScrollOffset = clampTo<int>(scrollableArea.scrollOffsetFromPosition({ 0, roundToInt(absoluteScrollYPosition) }).y(), 0, maxScrollOffset.y()); >- addOrUpdateStopForSnapOffset(verticalSnapOffsetsMap, { absoluteScrollOffset, stop }); >+ addOrUpdateStopForSnapOffset(verticalSnapOffsetsMap, { absoluteScrollOffset, stop, snapAreaIndex }); > } > } > >@@ -308,32 +186,25 @@ void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, const Re > }; > > Vector<SnapOffset<LayoutUnit>> horizontalSnapOffsets = copyToVector(horizontalSnapOffsetsMap.values()); >- Vector<ScrollOffsetRange<LayoutUnit>> horizontalSnapOffsetRanges; > if (!horizontalSnapOffsets.isEmpty()) { > std::sort(horizontalSnapOffsets.begin(), horizontalSnapOffsets.end(), compareSnapOffsets); >- if (scrollSnapType.strictness == ScrollSnapStrictness::Proximity) >- computeAxisProximitySnapOffsetRanges(horizontalSnapOffsets, horizontalSnapOffsetRanges, scrollSnapPort.width()); >- > LOG_WITH_STREAM(ScrollSnap, stream << " => Computed horizontal scroll snap offsets: " << horizontalSnapOffsets); >- LOG_WITH_STREAM(ScrollSnap, stream << " => Computed horizontal scroll snap offset ranges: " << horizontalSnapOffsetRanges); > } > > Vector<SnapOffset<LayoutUnit>> verticalSnapOffsets = copyToVector(verticalSnapOffsetsMap.values()); >- Vector<ScrollOffsetRange<LayoutUnit>> verticalSnapOffsetRanges; > if (!verticalSnapOffsets.isEmpty()) { > std::sort(verticalSnapOffsets.begin(), verticalSnapOffsets.end(), compareSnapOffsets); >- if (scrollSnapType.strictness == ScrollSnapStrictness::Proximity) >- computeAxisProximitySnapOffsetRanges(verticalSnapOffsets, verticalSnapOffsetRanges, scrollSnapPort.height()); >- > LOG_WITH_STREAM(ScrollSnap, stream << " => Computed vertical scroll snap offsets: " << verticalSnapOffsets); >- LOG_WITH_STREAM(ScrollSnap, stream << " => Computed vertical scroll snap offset ranges: " << verticalSnapOffsetRanges); > } > >+ if (!snapAreas.isEmpty()) >+ LOG_WITH_STREAM(ScrollSnap, stream << " => Computed snap areas: " << snapAreas); >+ > scrollableArea.setScrollSnapOffsetInfo({ >+ scrollSnapType.strictness, > horizontalSnapOffsets, > verticalSnapOffsets, >- horizontalSnapOffsetRanges, >- verticalSnapOffsetRanges >+ snapAreas, > }); > } > >@@ -347,57 +218,179 @@ static LayoutUnit convertOffsetUnit(float input, float /* scaleFactor */) > return LayoutUnit(input); > } > >-template <typename InputType, typename OutputType> >-static ScrollSnapOffsetsInfo<OutputType> convertOffsetInfo(const ScrollSnapOffsetsInfo<InputType>& input, float scaleFactor = 0.0) >+template <typename InputType, typename InputRectType, typename OutputType, typename OutputRectType> >+static ScrollSnapOffsetsInfo<OutputType, OutputRectType> convertOffsetInfo(const ScrollSnapOffsetsInfo<InputType, InputRectType>& input, float scaleFactor = 0.0) > { > auto convertOffsets = [scaleFactor](const Vector<SnapOffset<InputType>>& input) > { > Vector<SnapOffset<OutputType>> output; > output.reserveInitialCapacity(input.size()); > for (auto& offset : input) >- output.uncheckedAppend({ convertOffsetUnit(offset.offset, scaleFactor), offset.stop }); >+ output.uncheckedAppend({ convertOffsetUnit(offset.offset, scaleFactor), offset.stop, offset.snapAreaIndex }); > return output; > }; > >- auto convertOffsetRanges = [scaleFactor](const Vector<ScrollOffsetRange<InputType>>& input) >+ auto convertRects = [scaleFactor](const Vector<InputRectType>& input) > { >- Vector<ScrollOffsetRange<OutputType>> output; >+ Vector<OutputRectType> output; > output.reserveInitialCapacity(input.size()); >- for (auto& range : input) >- output.uncheckedAppend({ convertOffsetUnit(range.start, scaleFactor), convertOffsetUnit(range.end, scaleFactor) }); >+ for (auto& rect : input) { >+ OutputRectType outputRect( >+ convertOffsetUnit(rect.x(), scaleFactor), convertOffsetUnit(rect.y(), scaleFactor), >+ convertOffsetUnit(rect.width(), scaleFactor), convertOffsetUnit(rect.height(), scaleFactor)); >+ output.uncheckedAppend(outputRect); >+ } > return output; > }; > > return { >+ input.strictness, > convertOffsets(input.horizontalSnapOffsets), > convertOffsets(input.verticalSnapOffsets), >- convertOffsetRanges(input.horizontalSnapOffsetRanges), >- convertOffsetRanges(input.verticalSnapOffsetRanges) >+ convertRects(input.snapAreas), > }; > } > > template <> template <> >-ScrollSnapOffsetsInfo<LayoutUnit> ScrollSnapOffsetsInfo<float>::convertUnits(float /* unusedScaleFactor */) const >+LayoutScrollSnapOffsetsInfo FloatScrollSnapOffsetsInfo::convertUnits(float /* unusedScaleFactor */) const > { >- return convertOffsetInfo<float, LayoutUnit>(*this); >+ return convertOffsetInfo<float, FloatRect, LayoutUnit, LayoutRect>(*this); > } > > template <> template <> >-ScrollSnapOffsetsInfo<float> ScrollSnapOffsetsInfo<LayoutUnit>::convertUnits(float deviceScaleFactor) const >+FloatScrollSnapOffsetsInfo LayoutScrollSnapOffsetsInfo::convertUnits(float deviceScaleFactor) const > { >- return convertOffsetInfo<LayoutUnit, float>(*this, deviceScaleFactor); >+ return convertOffsetInfo<LayoutUnit, LayoutRect, float, FloatRect>(*this, deviceScaleFactor); > } > >-template <> >-std::pair<LayoutUnit, unsigned> ScrollSnapOffsetsInfo<LayoutUnit>::closestSnapOffset(ScrollEventAxis axis, LayoutUnit scrollDestinationOffset, float velocity, Optional<LayoutUnit> originalPositionForDirectionalSnapping) const >+template <typename UnitType, typename RectType> >+static UnitType maxForAxis(RectType rect, ScrollEventAxis axis) > { >- return closestSnapOffsetWithOffsetsAndRanges(offsetsForAxis(axis), offsetRangesForAxis(axis), scrollDestinationOffset, velocity, originalPositionForDirectionalSnapping); >+ return axis == ScrollEventAxis::Horizontal ? rect.maxX() : rect.maxY(); > } > >-template <> >-std::pair<float, unsigned> ScrollSnapOffsetsInfo<float>::closestSnapOffset(ScrollEventAxis axis, float scrollDestinationOffset, float velocity, Optional<float> originalPositionForDirectionalSnapping) const >+template <typename UnitType, typename RectType> >+static UnitType minForAxis(RectType rect, ScrollEventAxis axis) >+{ >+ return axis == ScrollEventAxis::Horizontal ? rect.x() : rect.y(); >+} >+ >+template <typename UnitType> >+static bool isNearEnoughToOffsetForProximity(ScrollSnapStrictness strictness, UnitType scrollDestination, UnitType candidateSnapOffset, UnitType viewportLength) >+{ >+ if (strictness != ScrollSnapStrictness::Proximity) >+ return true; >+ >+ // This is an arbitrary choice for what it means to be "in proximity" of a snap offset. We should play around with >+ // this and see what feels best. >+ static const float ratioOfScrollPortAxisLengthToBeConsideredForProximity = 0.3; >+ return std::abs(float {candidateSnapOffset - scrollDestination}) <= (viewportLength * ratioOfScrollPortAxisLengthToBeConsideredForProximity); >+} >+ >+template <typename UnitType, typename RectType, typename SizeType> >+static std::pair<UnitType, unsigned> calculateClosestSnapOffset(const ScrollSnapOffsetsInfo<UnitType, RectType>& info, ScrollEventAxis axis, const SizeType& viewportSize, UnitType scrollDestinationOffset, float velocity, Optional<UnitType> originalOffset) >+{ >+ const auto& snapOffsets = info.offsetsForAxis(axis); >+ auto pairForNoSnapping = std::make_pair(scrollDestinationOffset, invalidSnapOffsetIndex); >+ if (snapOffsets.isEmpty()) >+ return pairForNoSnapping; >+ >+ // The first snap point with `scroll-snap-stop: always` between the original position and destination takes precedence. >+ if (originalOffset) { >+ if (auto firstSnapStopOffset = findFirstSnapStopOffsetBetweenOriginAndDestination(snapOffsets, *originalOffset, scrollDestinationOffset)) >+ return *firstSnapStopOffset; >+ } >+ >+ auto viewportLength = axis == ScrollEventAxis::Horizontal ? viewportSize.width() : viewportSize.height(); >+ bool landedInsideSnapAreaThatConsumesViewport = false; >+ Optional<std::pair<UnitType, unsigned>> previous, next; >+ Optional<RectType> previousSnapArea, nextSnapArea; >+ for (unsigned i = 0; i < snapOffsets.size(); i++) { >+ const auto& snapArea = info.snapAreas[snapOffsets[i].snapAreaIndex]; >+ landedInsideSnapAreaThatConsumesViewport |= (minForAxis<UnitType>(snapArea, axis) <= scrollDestinationOffset && maxForAxis<UnitType>(snapArea, axis) >= (scrollDestinationOffset + viewportLength)); >+ // If the scroll landed exactly on a snap offset, choose that one. >+ UnitType potentialSnapOffset = snapOffsets[i].offset; >+ if (potentialSnapOffset == scrollDestinationOffset) >+ return std::make_pair(potentialSnapOffset, i); >+ >+ if (potentialSnapOffset < scrollDestinationOffset) { >+ previous = std::make_pair(potentialSnapOffset, i); >+ previousSnapArea = snapArea; >+ } else if (!next && potentialSnapOffset > scrollDestinationOffset) { >+ next = std::make_pair(potentialSnapOffset, i); >+ nextSnapArea = snapArea; >+ } >+ } >+ >+ // From https://www.w3.org/TR/css-scroll-snap-1/#snap-overflow >+ // "If the snap area is larger than the snapport in a particular axis, then any scroll position >+ // in which the snap area covers the snapport, and the distance between the geometrically >+ // previous and subsequent snap positions in that axis is larger than size of the snapport in >+ // that axis, is a valid snap position in that axis. The UA may use the specified alignment as a >+ // more precise target for certain scroll operations (e.g. explicit paging)." >+ if (landedInsideSnapAreaThatConsumesViewport && (!previous || !next || ((*next).first - (*previous).first) >= viewportLength)) >+ return pairForNoSnapping; >+ >+ if (originalOffset) { >+ // If this is a directional scroll and there are no scroll stops in a particular direction, >+ // don't scroll past the edge of the scroll area. >+ if (!next && previous) >+ return std::make_pair(std::max((*previous).first, maxForAxis<UnitType>(*previousSnapArea, axis) - viewportLength), invalidSnapOffsetIndex); >+ if (!previous && next) >+ return std::make_pair(minForAxis<UnitType>(*nextSnapArea, axis), invalidSnapOffsetIndex); >+ >+ // From https://www.w3.org/TR/css-scroll-snap-1/#choosing >+ // "User agents must ensure that a user can âescapeâ a snap position, regardless of the scroll >+ // method. For example, if the snap type is mandatory and the next snap position is more than >+ // two screen-widths away, a naïve âalways snap to nearestâ selection algorithm might âtrapâ the >+ // user if their end position was only one screen-width away. Instead, a smarter algorithm that >+ // only returned to the starting snap position if the end-point was a fairly small distance from >+ // it, and otherwise ignored the starting snap position, would give better behavior." >+ // We only do this if we are in a situation where we are choosing between two compatible >+ // snap offsets. >+ if (*originalOffset < scrollDestinationOffset && (*previous).first <= *originalOffset) >+ previous.reset(); >+ if (*originalOffset > scrollDestinationOffset && (*next).first >= *originalOffset) >+ next.reset(); >+ } >+ >+ if (next && !isNearEnoughToOffsetForProximity(info.strictness, scrollDestinationOffset, (*next).first, viewportLength)) >+ next.reset(); >+ if (previous && !isNearEnoughToOffsetForProximity(info.strictness, scrollDestinationOffset, (*previous).first, viewportLength)) >+ previous.reset(); >+ >+ // If we don't have compatible offsets to choose between, just do the obvious thing >+ // and do no snapping or only select the single compatible offset. >+ if (!previous && !next) >+ return pairForNoSnapping; >+ if (!previous) >+ return *next; >+ if (!next) >+ return *previous; >+ >+ // If this scroll isn't directional, then choose whatever snap point is closer. >+ UnitType previousSnapOffset = (*previous).first; >+ UnitType nextSnapOffset = (*next).first; >+ if (!std::abs(velocity)) { >+ bool isCloserToPreviousSnapIndex = scrollDestinationOffset - previousSnapOffset <= nextSnapOffset - scrollDestinationOffset; >+ return isCloserToPreviousSnapIndex ? *previous : *next; >+ } >+ >+ // Finally, if we have a directional scroll prefer the snap point that is in the scroll direction. >+ return velocity < 0 ? *previous : *next; >+} >+ >+ >+template <> template <> >+std::pair<LayoutUnit, unsigned> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const LayoutSize& viewportSize, LayoutUnit scrollDestinationOffset, float velocity, Optional<LayoutUnit> originalOffsetForDirectionalSnapping) const >+{ >+ return calculateClosestSnapOffset<LayoutUnit, LayoutRect, LayoutSize>(*this, axis, viewportSize, scrollDestinationOffset, velocity, originalOffsetForDirectionalSnapping); >+} >+ >+template <> template <> >+std::pair<float, unsigned> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis axis, const FloatSize& viewportSize, float scrollDestinationOffset, float velocity, Optional<float> originalOffsetForDirectionalSnapping) const > { >- return closestSnapOffsetWithOffsetsAndRanges(offsetsForAxis(axis), offsetRangesForAxis(axis), scrollDestinationOffset, velocity, originalPositionForDirectionalSnapping); >+ return calculateClosestSnapOffset<float, FloatRect, FloatSize>(*this, axis, viewportSize, scrollDestinationOffset, velocity, originalOffsetForDirectionalSnapping); > } > > } >diff --git a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h b/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h >index 20a647fea12c6cc8b55579c51bd0a3605fdce5e6..b992bafe077c762f52ee8d4b7b4d01d304744fd4 100644 >--- a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h >+++ b/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.h >@@ -27,6 +27,10 @@ > > #if ENABLE(CSS_SCROLL_SNAP) > >+#include "FloatRect.h" >+#include "FloatSize.h" >+#include "LayoutRect.h" >+#include "LayoutSize.h" > #include "LayoutUnit.h" > #include "ScrollTypes.h" > #include "StyleScrollSnapPoints.h" >@@ -35,39 +39,29 @@ > > namespace WebCore { > >-class LayoutRect; > class ScrollableArea; > class RenderBox; > class RenderStyle; > >-template <typename T> >+template <typename OffsetType> > struct SnapOffset { >- T offset; >+ OffsetType offset; > ScrollSnapStop stop; >+ unsigned snapAreaIndex; > }; > >-template <typename T> >-struct ScrollOffsetRange { >- T start; >- T end; >-}; >- >-template <typename T> >+template <typename OffsetType, typename RectType> > struct ScrollSnapOffsetsInfo { > WTF_MAKE_STRUCT_FAST_ALLOCATED; >- Vector<SnapOffset<T>> horizontalSnapOffsets; >- Vector<SnapOffset<T>> verticalSnapOffsets; >+ ScrollSnapStrictness strictness; > >- // Snap offset ranges represent non-empty ranges of scroll offsets in which scrolling may rest after scroll snapping. >- // These are used in two cases: (1) for proximity scroll snapping, where portions of areas between adjacent snap offsets >- // may emit snap offset ranges, and (2) in the case where the snap area is larger than the snap port, in which case areas >- // where the snap port fits within the snap area are considered to be valid snap positions. >- Vector<ScrollOffsetRange<T>> horizontalSnapOffsetRanges; >- Vector<ScrollOffsetRange<T>> verticalSnapOffsetRanges; >+ Vector<SnapOffset<OffsetType>> horizontalSnapOffsets; >+ Vector<SnapOffset<OffsetType>> verticalSnapOffsets; >+ Vector<RectType> snapAreas; > >- bool isEqual(const ScrollSnapOffsetsInfo<T>& other) const >+ bool isEqual(const ScrollSnapOffsetsInfo<OffsetType, RectType>& other) const > { >- return horizontalSnapOffsets == other.horizontalSnapOffsets && verticalSnapOffsets == other.verticalSnapOffsets && horizontalSnapOffsetRanges == other.horizontalSnapOffsetRanges && verticalSnapOffsetRanges == other.verticalSnapOffsetRanges; >+ return strictness == other.strictness && horizontalSnapOffsets == other.horizontalSnapOffsets && verticalSnapOffsets == other.verticalSnapOffsets && snapAreas == other.snapAreas; > } > > bool isEmpty() const >@@ -75,29 +69,27 @@ struct ScrollSnapOffsetsInfo { > return horizontalSnapOffsets.isEmpty() && verticalSnapOffsets.isEmpty(); > } > >- Vector<SnapOffset<T>> offsetsForAxis(ScrollEventAxis axis) const >+ Vector<SnapOffset<OffsetType>> offsetsForAxis(ScrollEventAxis axis) const > { > return axis == ScrollEventAxis::Vertical ? verticalSnapOffsets : horizontalSnapOffsets; > } > >- Vector<ScrollOffsetRange<T>> offsetRangesForAxis(ScrollEventAxis axis) const >- { >- return axis == ScrollEventAxis::Vertical ? verticalSnapOffsetRanges : horizontalSnapOffsetRanges; >- } >- >- template<typename OutputType> ScrollSnapOffsetsInfo<OutputType> convertUnits(float deviceScaleFactor = 0.0) const; >- WEBCORE_EXPORT std::pair<T, unsigned> closestSnapOffset(ScrollEventAxis, T scrollDestinationOffset, float velocity, Optional<T> originalPositionForDirectionalSnapping = WTF::nullopt) const; >+ template<typename OutputType, typename OutputRectType> ScrollSnapOffsetsInfo<OutputType, OutputRectType> convertUnits(float deviceScaleFactor = 0.0) const; >+ template<typename SizeType> WEBCORE_EXPORT std::pair<OffsetType, unsigned> closestSnapOffset(ScrollEventAxis, const SizeType& viewportSize, OffsetType scrollDestinationOffset, float velocity, Optional<OffsetType> originalPositionForDirectionalSnapping = WTF::nullopt) const; > }; > >+using LayoutScrollSnapOffsetsInfo = ScrollSnapOffsetsInfo<LayoutUnit, LayoutRect>; >+using FloatScrollSnapOffsetsInfo = ScrollSnapOffsetsInfo<float, FloatRect>; >+ > template <> template <> >-ScrollSnapOffsetsInfo<LayoutUnit> ScrollSnapOffsetsInfo<float>::convertUnits(float /* unusedScaleFactor */) const; >-template <> >-WEBCORE_EXPORT std::pair<float, unsigned> ScrollSnapOffsetsInfo<float>::closestSnapOffset(ScrollEventAxis, float scrollDestinationOffset, float velocity, Optional<float> originalPositionForDirectionalSnapping) const; >+LayoutScrollSnapOffsetsInfo FloatScrollSnapOffsetsInfo::convertUnits(float /* unusedScaleFactor */) const; >+template <> template <> >+WEBCORE_EXPORT std::pair<float, unsigned> FloatScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const FloatSize& viewportSize, float scrollDestinationOffset, float velocity, Optional<float> originalPositionForDirectionalSnapping) const; > > template <> template <> >-ScrollSnapOffsetsInfo<float> ScrollSnapOffsetsInfo<LayoutUnit>::convertUnits(float deviceScaleFactor) const; >-template <> >-WEBCORE_EXPORT std::pair<LayoutUnit, unsigned> ScrollSnapOffsetsInfo<LayoutUnit>::closestSnapOffset(ScrollEventAxis, LayoutUnit scrollDestinationOffset, float velocity, Optional<LayoutUnit> originalPositionForDirectionalSnapping) const; >+FloatScrollSnapOffsetsInfo LayoutScrollSnapOffsetsInfo::convertUnits(float deviceScaleFactor) const; >+template <> template <> >+WEBCORE_EXPORT std::pair<LayoutUnit, unsigned> LayoutScrollSnapOffsetsInfo::closestSnapOffset(ScrollEventAxis, const LayoutSize& viewportSize, LayoutUnit scrollDestinationOffset, float velocity, Optional<LayoutUnit> originalPositionForDirectionalSnapping) const; > > const unsigned invalidSnapOffsetIndex = UINT_MAX; > >@@ -106,7 +98,7 @@ const unsigned invalidSnapOffsetIndex = UINT_MAX; > // the scrolling container's border box. > void updateSnapOffsetsForScrollableArea(ScrollableArea&, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle, LayoutRect viewportRectInBorderBoxCoordinates); > >-template <typename T> WTF::TextStream& operator<<(WTF::TextStream& ts, SnapOffset<T> offset) >+template <typename OffsetType> WTF::TextStream& operator<<(WTF::TextStream& ts, SnapOffset<OffsetType> offset) > { > ts << offset.offset; > if (offset.stop == ScrollSnapStop::Always) >@@ -114,13 +106,6 @@ template <typename T> WTF::TextStream& operator<<(WTF::TextStream& ts, SnapOffse > return ts; > } > >-template<typename T> >-TextStream& operator<<(TextStream& ts, const ScrollOffsetRange<T>& range) >-{ >- ts << "start: " << range.start << " end: " << range.end; >- return ts; >-} >- > }; // namespace WebCore > > #endif // ENABLE(CSS_SCROLL_SNAP) >diff --git a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp >index f40819afe3cefd3481806f41799e9059875f80e1..8432881c89f16c57b4674c24bb4a98386d7ac923 100644 >--- a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp >+++ b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp >@@ -157,7 +157,7 @@ void ScrollingStateScrollingNode::setScrollOrigin(const IntPoint& scrollOrigin) > } > > #if ENABLE(CSS_SCROLL_SNAP) >-void ScrollingStateScrollingNode::setSnapOffsetsInfo(const ScrollSnapOffsetsInfo<float>& info) >+void ScrollingStateScrollingNode::setSnapOffsetsInfo(const FloatScrollSnapOffsetsInfo& info) > { > if (m_snapOffsetsInfo.isEqual(info)) > return; >diff --git a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h >index bd4e97b9c5efdf9129def8b6bb230d37b4164044..c5d7639cf1cae0c7e037fc3599f22581baadabe8 100644 >--- a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h >+++ b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h >@@ -71,8 +71,8 @@ public: > WEBCORE_EXPORT void setScrollOrigin(const IntPoint&); > > #if ENABLE(CSS_SCROLL_SNAP) >- const ScrollSnapOffsetsInfo<float>& snapOffsetsInfo() const { return m_snapOffsetsInfo; } >- WEBCORE_EXPORT void setSnapOffsetsInfo(const ScrollSnapOffsetsInfo<float>& newOffsetsInfo); >+ const FloatScrollSnapOffsetsInfo& snapOffsetsInfo() const { return m_snapOffsetsInfo; } >+ WEBCORE_EXPORT void setSnapOffsetsInfo(const FloatScrollSnapOffsetsInfo& newOffsetsInfo); > > unsigned currentHorizontalSnapPointIndex() const { return m_currentHorizontalSnapPointIndex; } > WEBCORE_EXPORT void setCurrentHorizontalSnapPointIndex(unsigned); >@@ -130,7 +130,7 @@ private: > IntPoint m_scrollOrigin; > > #if ENABLE(CSS_SCROLL_SNAP) >- ScrollSnapOffsetsInfo<float> m_snapOffsetsInfo; >+ FloatScrollSnapOffsetsInfo m_snapOffsetsInfo; > unsigned m_currentHorizontalSnapPointIndex { 0 }; > unsigned m_currentVerticalSnapPointIndex { 0 }; > #endif >diff --git a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >index 130e73edbc28c0828831a58c22f3c51ce67d10e7..8b634e1ad64f2419bf2ba908431c837c97d6f45c 100644 >--- a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >+++ b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >@@ -327,7 +327,7 @@ void ScrollingTreeScrollingNode::dumpProperties(TextStream& ts, ScrollingStateTr > } > > #if ENABLE(CSS_SCROLL_SNAP) >-const ScrollSnapOffsetsInfo<float>& ScrollingTreeScrollingNode::snapOffsetsInfo() const >+const FloatScrollSnapOffsetsInfo& ScrollingTreeScrollingNode::snapOffsetsInfo() const > { > return m_snapOffsetsInfo; > } >diff --git a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >index be49d0b125f01b71ed6d8bcae4f6e27750c384b6..55bced3e0e612106d93f852eef7d464210525438 100644 >--- a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >+++ b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >@@ -95,7 +95,7 @@ public: > bool canHaveScrollbars() const { return m_scrollableAreaParameters.horizontalScrollbarMode != ScrollbarAlwaysOff || m_scrollableAreaParameters.verticalScrollbarMode != ScrollbarAlwaysOff; } > > #if ENABLE(CSS_SCROLL_SNAP) >- const ScrollSnapOffsetsInfo<float>& snapOffsetsInfo() const; >+ const FloatScrollSnapOffsetsInfo& snapOffsetsInfo() const; > unsigned currentHorizontalSnapPointIndex() const { return m_currentHorizontalSnapPointIndex; } > unsigned currentVerticalSnapPointIndex() const { return m_currentVerticalSnapPointIndex; } > void setCurrentHorizontalSnapPointIndex(unsigned index) { m_currentHorizontalSnapPointIndex = index; } >@@ -159,7 +159,7 @@ private: > FloatPoint m_currentScrollPosition; > IntPoint m_scrollOrigin; > #if ENABLE(CSS_SCROLL_SNAP) >- ScrollSnapOffsetsInfo<float> m_snapOffsetsInfo; >+ FloatScrollSnapOffsetsInfo m_snapOffsetsInfo; > unsigned m_currentHorizontalSnapPointIndex { 0 }; > unsigned m_currentVerticalSnapPointIndex { 0 }; > #endif >diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm >index a5b48c203415ab7b09ce9c3fa99c15ea63740e45..3e24574ab00eff45e0f8ca10f130851a81aea767 100644 >--- a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm >+++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm >@@ -65,7 +65,7 @@ void ScrollingTreeScrollingNodeDelegateMac::updateFromStateNode(const ScrollingS > > #if ENABLE(CSS_SCROLL_SNAP) > if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::Property::SnapOffsetsInfo)) >- m_scrollController.updateScrollSnapPoints(scrollingStateNode.snapOffsetsInfo().convertUnits<LayoutUnit>()); >+ m_scrollController.updateScrollSnapPoints(scrollingStateNode.snapOffsetsInfo().convertUnits<LayoutUnit, LayoutRect>()); > > if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::Property::CurrentHorizontalSnapOffsetIndex)) > m_scrollController.setActiveScrollSnapIndexForAxis(ScrollEventAxis::Horizontal, scrollingStateNode.currentHorizontalSnapPointIndex()); >diff --git a/Source/WebCore/platform/ScrollController.cpp b/Source/WebCore/platform/ScrollController.cpp >index c3ec6c441d312f5852bbd6f2b490e27cb5e313ae..65500d10fef38107422e29fb99c056e06125db29 100644 >--- a/Source/WebCore/platform/ScrollController.cpp >+++ b/Source/WebCore/platform/ScrollController.cpp >@@ -67,7 +67,7 @@ void ScrollController::updateScrollSnapState(const ScrollableArea& scrollableAre > updateScrollSnapPoints(*snapOffsetInfo); > } > >-void ScrollController::updateScrollSnapPoints(const ScrollSnapOffsetsInfo<LayoutUnit>& snapOffsetInfo) >+void ScrollController::updateScrollSnapPoints(const LayoutScrollSnapOffsetsInfo& snapOffsetInfo) > { > if (snapOffsetInfo.isEmpty()) { > m_scrollSnapState = nullptr; >@@ -115,8 +115,8 @@ void ScrollController::setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis > return; > > LayoutUnit clampedOffset = std::min(std::max(LayoutUnit(offset / scaleFactor), snapOffsets.first().offset), snapOffsets.last().offset); >- >- unsigned activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, clampedOffset, 0).second; >+ LayoutSize viewportSize(m_client.viewportSize().width(), m_client.viewportSize().height()); >+ unsigned activeIndex = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, clampedOffset, 0).second; > if (activeIndex == activeScrollSnapIndexForAxis(axis)) > return; > >@@ -137,7 +137,9 @@ float ScrollController::adjustScrollDestination(ScrollEventAxis axis, float dest > Optional<LayoutUnit> originalOffsetInLayoutUnits; > if (originalOffset.hasValue()) > originalOffsetInLayoutUnits = LayoutUnit(*originalOffset / m_client.pageScaleFactor()); >- LayoutUnit offset = snapState.snapOffsetInfo().closestSnapOffset(axis, LayoutUnit(destinationOffset / m_client.pageScaleFactor()), velocity, originalOffsetInLayoutUnits).first; >+ >+ LayoutSize viewportSize(m_client.viewportSize().width(), m_client.viewportSize().height()); >+ LayoutUnit offset = snapState.snapOffsetInfo().closestSnapOffset(axis, viewportSize, LayoutUnit(destinationOffset / m_client.pageScaleFactor()), velocity, originalOffsetInLayoutUnits).first; > return offset * m_client.pageScaleFactor(); > } > >diff --git a/Source/WebCore/platform/ScrollController.h b/Source/WebCore/platform/ScrollController.h >index d925fd45584c0111c9ef0c2891f7c7516610eb7b..dd53ada90a2f5f2908801023c3e5a3c431ef6162 100644 >--- a/Source/WebCore/platform/ScrollController.h >+++ b/Source/WebCore/platform/ScrollController.h >@@ -132,7 +132,7 @@ public: > void scrollPositionChanged(); > > #if ENABLE(CSS_SCROLL_SNAP) >- void updateScrollSnapPoints(const ScrollSnapOffsetsInfo<LayoutUnit>&); >+ void updateScrollSnapPoints(const LayoutScrollSnapOffsetsInfo&); > void setActiveScrollSnapIndexForAxis(ScrollEventAxis, unsigned); > void setActiveScrollSnapIndicesForOffset(ScrollOffset); > bool activeScrollSnapIndexDidChange() const { return m_activeScrollSnapIndexDidChange; } >diff --git a/Source/WebCore/platform/ScrollSnapAnimatorState.cpp b/Source/WebCore/platform/ScrollSnapAnimatorState.cpp >index 7d68d50dde76e89096cd3e58f3fc391ffc67177c..1ee74167b81983f4702d836a6f97707724720915 100644 >--- a/Source/WebCore/platform/ScrollSnapAnimatorState.cpp >+++ b/Source/WebCore/platform/ScrollSnapAnimatorState.cpp >@@ -51,8 +51,8 @@ void ScrollSnapAnimatorState::setupAnimationForState(ScrollSnapState state, cons > > m_momentumCalculator = ScrollingMomentumCalculator::create(viewportSize, contentSize, initialOffset, initialDelta, initialVelocity); > auto predictedScrollTarget = m_momentumCalculator->predictedDestinationOffset(); >- float targetOffsetX = targetOffsetForStartOffset(ScrollEventAxis::Horizontal, contentSize.width() - viewportSize.width(), initialOffset.x(), predictedScrollTarget.width(), pageScale, initialDelta.width(), m_activeSnapIndexX); >- float targetOffsetY = targetOffsetForStartOffset(ScrollEventAxis::Vertical, contentSize.height() - viewportSize.height(), initialOffset.y(), predictedScrollTarget.height(), pageScale, initialDelta.height(), m_activeSnapIndexY); >+ float targetOffsetX = targetOffsetForStartOffset(ScrollEventAxis::Horizontal, viewportSize, contentSize.width() - viewportSize.width(), initialOffset.x(), predictedScrollTarget.width(), pageScale, initialDelta.width(), m_activeSnapIndexX); >+ float targetOffsetY = targetOffsetForStartOffset(ScrollEventAxis::Vertical, viewportSize, contentSize.height() - viewportSize.height(), initialOffset.y(), predictedScrollTarget.height(), pageScale, initialDelta.height(), m_activeSnapIndexY); > m_momentumCalculator->setRetargetedScrollOffset({ targetOffsetX, targetOffsetY }); > m_startTime = MonotonicTime::now(); > m_currentState = state; >@@ -91,10 +91,11 @@ FloatPoint ScrollSnapAnimatorState::currentAnimatedScrollOffset(bool& isAnimatio > return m_momentumCalculator->scrollOffsetAfterElapsedTime(elapsedTime); > } > >-float ScrollSnapAnimatorState::targetOffsetForStartOffset(ScrollEventAxis axis, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta, unsigned& outActiveSnapIndex) const >+float ScrollSnapAnimatorState::targetOffsetForStartOffset(ScrollEventAxis axis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta, unsigned& outActiveSnapIndex) const > { > LayoutUnit proposedOffset; >- std::tie(proposedOffset, outActiveSnapIndex) = m_snapOffsetsInfo.closestSnapOffset(axis, LayoutUnit(predictedOffset / pageScale), initialDelta); >+ LayoutSize viewportLayoutSize(viewportSize.width(), viewportSize.height()); >+ std::tie(proposedOffset, outActiveSnapIndex) = m_snapOffsetsInfo.closestSnapOffset(axis, viewportLayoutSize, LayoutUnit(predictedOffset / pageScale), initialDelta); > if (outActiveSnapIndex != invalidSnapOffsetIndex) > return pageScale * proposedOffset; > return clampTo<float>(startOffset, 0, maxScrollOffset); >@@ -105,11 +106,6 @@ TextStream& operator<<(TextStream& ts, const ScrollSnapAnimatorState& state) > ts << "ScrollSnapAnimatorState"; > ts.dumpProperty("snap offsets x", state.snapOffsetsForAxis(ScrollEventAxis::Horizontal)); > ts.dumpProperty("snap offsets y", state.snapOffsetsForAxis(ScrollEventAxis::Vertical)); >- if (!state.snapOffsetRangesForAxis(ScrollEventAxis::Horizontal).isEmpty()) >- ts.dumpProperty("snap offsets ranges x", state.snapOffsetRangesForAxis(ScrollEventAxis::Horizontal)); >- if (!state.snapOffsetRangesForAxis(ScrollEventAxis::Vertical).isEmpty()) >- ts.dumpProperty("snap offsets ranges y", state.snapOffsetRangesForAxis(ScrollEventAxis::Vertical)); >- > ts.dumpProperty("active snap index x", state.activeSnapIndexForAxis(ScrollEventAxis::Horizontal)); > ts.dumpProperty("active snap index y", state.activeSnapIndexForAxis(ScrollEventAxis::Vertical)); > >diff --git a/Source/WebCore/platform/ScrollSnapAnimatorState.h b/Source/WebCore/platform/ScrollSnapAnimatorState.h >index 3feb1ac3b59aaee44c639b4aff0c242695821499..6b6d2275cfa345b9a2b6a69ea8189d665d614cdc 100644 >--- a/Source/WebCore/platform/ScrollSnapAnimatorState.h >+++ b/Source/WebCore/platform/ScrollSnapAnimatorState.h >@@ -57,24 +57,8 @@ public: > return axis == ScrollEventAxis::Horizontal ? m_snapOffsetsInfo.horizontalSnapOffsets : m_snapOffsetsInfo.verticalSnapOffsets; > } > >- const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRangesForAxis(ScrollEventAxis axis) const >- { >- return axis == ScrollEventAxis::Horizontal ? m_snapOffsetsInfo.horizontalSnapOffsetRanges : m_snapOffsetsInfo.verticalSnapOffsetRanges; >- } >- >- const ScrollSnapOffsetsInfo<LayoutUnit>& snapOffsetInfo() const { return m_snapOffsetsInfo; } >- void setSnapOffsetInfo(const ScrollSnapOffsetsInfo<LayoutUnit>& newInfo) { m_snapOffsetsInfo = newInfo; } >- >- void setSnapOffsetsAndPositionRangesForAxis(ScrollEventAxis axis, const Vector<SnapOffset<LayoutUnit>>& snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>& snapOffsetRanges) >- { >- if (axis == ScrollEventAxis::Horizontal) { >- m_snapOffsetsInfo.horizontalSnapOffsets = snapOffsets; >- m_snapOffsetsInfo.horizontalSnapOffsetRanges = snapOffsetRanges; >- } else { >- m_snapOffsetsInfo.verticalSnapOffsets = snapOffsets; >- m_snapOffsetsInfo.verticalSnapOffsetRanges = snapOffsetRanges; >- } >- } >+ const LayoutScrollSnapOffsetsInfo& snapOffsetInfo() const { return m_snapOffsetsInfo; } >+ void setSnapOffsetInfo(const LayoutScrollSnapOffsetsInfo& newInfo) { m_snapOffsetsInfo = newInfo; } > > ScrollSnapState currentState() const { return m_currentState; } > >@@ -100,13 +84,13 @@ public: > void transitionToDestinationReachedState(); > > private: >- float targetOffsetForStartOffset(ScrollEventAxis, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta, unsigned& outActiveSnapIndex) const; >+ float targetOffsetForStartOffset(ScrollEventAxis, const FloatSize& viewportSize, float maxScrollOffset, float startOffset, float predictedOffset, float pageScale, float initialDelta, unsigned& outActiveSnapIndex) const; > void teardownAnimationForState(ScrollSnapState); > void setupAnimationForState(ScrollSnapState, const FloatSize& contentSize, const FloatSize& viewportSize, float pageScale, const FloatPoint& initialOffset, const FloatSize& initialVelocity, const FloatSize& initialDelta); > > ScrollSnapState m_currentState { ScrollSnapState::UserInteraction }; > >- ScrollSnapOffsetsInfo<LayoutUnit> m_snapOffsetsInfo; >+ LayoutScrollSnapOffsetsInfo m_snapOffsetsInfo; > > unsigned m_activeSnapIndexX { 0 }; > unsigned m_activeSnapIndexY { 0 }; >diff --git a/Source/WebCore/platform/ScrollableArea.cpp b/Source/WebCore/platform/ScrollableArea.cpp >index 79f9e98098a8ddca2b49ce977d2143e1cb6caf85..132aea289e097722693d12ce07006a5916961f6b 100644 >--- a/Source/WebCore/platform/ScrollableArea.cpp >+++ b/Source/WebCore/platform/ScrollableArea.cpp >@@ -479,19 +479,19 @@ String ScrollableArea::verticalScrollbarStateForTesting() const > } > > #if ENABLE(CSS_SCROLL_SNAP) >-ScrollSnapOffsetsInfo<LayoutUnit>& ScrollableArea::ensureSnapOffsetsInfo() >+LayoutScrollSnapOffsetsInfo& ScrollableArea::ensureSnapOffsetsInfo() > { > if (!m_snapOffsetsInfo) >- m_snapOffsetsInfo = makeUnique<ScrollSnapOffsetsInfo<LayoutUnit>>(); >+ m_snapOffsetsInfo = makeUnique<LayoutScrollSnapOffsetsInfo>(); > return *m_snapOffsetsInfo; > } > >-const ScrollSnapOffsetsInfo<LayoutUnit>* ScrollableArea::snapOffsetInfo() const >+const LayoutScrollSnapOffsetsInfo* ScrollableArea::snapOffsetInfo() const > { > return m_snapOffsetsInfo.get(); > } > >-void ScrollableArea::setScrollSnapOffsetInfo(const ScrollSnapOffsetsInfo<LayoutUnit>& info) >+void ScrollableArea::setScrollSnapOffsetInfo(const LayoutScrollSnapOffsetsInfo& info) > { > if (info.isEmpty()) { > clearSnapOffsets(); >diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h >index 7eb7b540282840ab7b5f31fdfa6b2bfd58eb19dc..3587179cdb7f679398a7c877312ed497c16fe8d9 100644 >--- a/Source/WebCore/platform/ScrollableArea.h >+++ b/Source/WebCore/platform/ScrollableArea.h >@@ -91,9 +91,9 @@ public: > bool usesScrollSnap() const; > > #if ENABLE(CSS_SCROLL_SNAP) >- WEBCORE_EXPORT const ScrollSnapOffsetsInfo<LayoutUnit>* snapOffsetInfo() const; >+ WEBCORE_EXPORT const LayoutScrollSnapOffsetsInfo* snapOffsetInfo() const; > virtual void updateSnapOffsets() { }; >- void setScrollSnapOffsetInfo(const ScrollSnapOffsetsInfo<LayoutUnit>&); >+ void setScrollSnapOffsetInfo(const LayoutScrollSnapOffsetsInfo&); > void clearSnapOffsets(); > unsigned currentHorizontalSnapPointIndex() const { return m_currentHorizontalSnapPointIndex; } > void setCurrentHorizontalSnapPointIndex(unsigned index) { m_currentHorizontalSnapPointIndex = index; } >@@ -385,8 +385,8 @@ private: > mutable std::unique_ptr<ScrollAnimator> m_scrollAnimator; > > #if ENABLE(CSS_SCROLL_SNAP) >- ScrollSnapOffsetsInfo<LayoutUnit>& ensureSnapOffsetsInfo(); >- std::unique_ptr<ScrollSnapOffsetsInfo<LayoutUnit>> m_snapOffsetsInfo; >+ LayoutScrollSnapOffsetsInfo& ensureSnapOffsetsInfo(); >+ std::unique_ptr<LayoutScrollSnapOffsetsInfo> m_snapOffsetsInfo; > unsigned m_currentHorizontalSnapPointIndex { 0 }; > unsigned m_currentVerticalSnapPointIndex { 0 }; > #endif >diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm >index c095cd66f5956f8b89aacb33d5b7f80230a9a7b5..d4521d658c33fad6e396f61a807e98533198bfb3 100644 >--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm >+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm >@@ -1278,7 +1278,7 @@ bool ScrollAnimatorMac::isPinnedForScrollDelta(const FloatSize& delta) const > } > > #if ENABLE(CSS_SCROLL_SNAP) >-static bool gestureShouldBeginSnap(const PlatformWheelEvent& wheelEvent, ScrollEventAxis axis, const ScrollSnapOffsetsInfo<LayoutUnit>* offsetInfo) >+static bool gestureShouldBeginSnap(const PlatformWheelEvent& wheelEvent, ScrollEventAxis axis, const LayoutScrollSnapOffsetsInfo* offsetInfo) > { > if (!offsetInfo) > return false; >diff --git a/Source/WebKit/Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp b/Source/WebKit/Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp >index 3e380fd145d7225bac057330c19d6ca88a0e0cd2..523af4422e325c4262b92f5b7cee339e3230cceb 100644 >--- a/Source/WebKit/Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp >+++ b/Source/WebKit/Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp >@@ -98,9 +98,9 @@ template<> struct ArgumentCoder<RequestedScrollData> { > static WARN_UNUSED_RETURN bool decode(Decoder&, RequestedScrollData&); > }; > >-template<> struct ArgumentCoder<ScrollSnapOffsetsInfo<float>> { >- static void encode(Encoder&, const ScrollSnapOffsetsInfo<float>&); >- static WARN_UNUSED_RETURN bool decode(Decoder&, ScrollSnapOffsetsInfo<float>&); >+template<> struct ArgumentCoder<FloatScrollSnapOffsetsInfo> { >+ static void encode(Encoder&, const FloatScrollSnapOffsetsInfo&); >+ static WARN_UNUSED_RETURN bool decode(Decoder&, FloatScrollSnapOffsetsInfo&); > }; > > template<> struct ArgumentCoder<SnapOffset<float>> { >@@ -311,7 +311,7 @@ bool ArgumentCoder<ScrollingStateScrollingNode>::decode(Decoder& decoder, Scroll > SCROLLING_NODE_DECODE(ScrollingStateNode::Property::ScrollPosition, FloatPoint, setScrollPosition); > SCROLLING_NODE_DECODE(ScrollingStateNode::Property::ScrollOrigin, IntPoint, setScrollOrigin); > #if ENABLE(CSS_SCROLL_SNAP) >- SCROLLING_NODE_DECODE(ScrollingStateNode::Property::SnapOffsetsInfo, ScrollSnapOffsetsInfo<float>, setSnapOffsetsInfo); >+ SCROLLING_NODE_DECODE(ScrollingStateNode::Property::SnapOffsetsInfo, FloatScrollSnapOffsetsInfo, setSnapOffsetsInfo); > SCROLLING_NODE_DECODE(ScrollingStateNode::Property::CurrentHorizontalSnapOffsetIndex, unsigned, setCurrentHorizontalSnapPointIndex); > SCROLLING_NODE_DECODE(ScrollingStateNode::Property::CurrentVerticalSnapOffsetIndex, unsigned, setCurrentVerticalSnapPointIndex); > #endif >@@ -544,23 +544,20 @@ bool ArgumentCoder<SnapOffset<float>>::decode(Decoder& decoder, SnapOffset<float > } > > >-void ArgumentCoder<ScrollSnapOffsetsInfo<float>>::encode(Encoder& encoder, const ScrollSnapOffsetsInfo<float>& info) >+void ArgumentCoder<FloatScrollSnapOffsetsInfo>::encode(Encoder& encoder, const FloatScrollSnapOffsetsInfo& info) > { > encoder << info.horizontalSnapOffsets; > encoder << info.verticalSnapOffsets; >- encoder << info.horizontalSnapOffsetRanges; >- encoder << info.verticalSnapOffsetRanges; >+ encoder << info.snapAreas; > } > >-bool ArgumentCoder<ScrollSnapOffsetsInfo<float>>::decode(Decoder& decoder, ScrollSnapOffsetsInfo<float>& info) >+bool ArgumentCoder<FloatScrollSnapOffsetsInfo>::decode(Decoder& decoder, FloatScrollSnapOffsetsInfo& info) > { > if (!decoder.decode(info.horizontalSnapOffsets)) > return false; > if (!decoder.decode(info.verticalSnapOffsets)) > return false; >- if (!decoder.decode(info.horizontalSnapOffsetRanges)) >- return false; >- if (!decoder.decode(info.verticalSnapOffsetRanges)) >+ if (!decoder.decode(info.snapAreas)) > return false; > return true; > } >diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >index 38dd9d31e6c7cf794956e7730b107de4947a4b87..87e4d460ee3e41cc7986964c31485ed356f0d7b5 100644 >--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >@@ -2805,32 +2805,6 @@ bool ArgumentCoder<ServiceWorkerOrClientIdentifier>::decode(Decoder& decoder, Se > } > #endif > >-#if ENABLE(CSS_SCROLL_SNAP) >- >-void ArgumentCoder<ScrollOffsetRange<float>>::encode(Encoder& encoder, const ScrollOffsetRange<float>& range) >-{ >- encoder << range.start; >- encoder << range.end; >-} >- >-auto ArgumentCoder<ScrollOffsetRange<float>>::decode(Decoder& decoder) -> Optional<WebCore::ScrollOffsetRange<float>> >-{ >- WebCore::ScrollOffsetRange<float> range; >- float start; >- if (!decoder.decode(start)) >- return WTF::nullopt; >- >- float end; >- if (!decoder.decode(end)) >- return WTF::nullopt; >- >- range.start = start; >- range.end = end; >- return range; >-} >- >-#endif >- > void ArgumentCoder<MediaSelectionOption>::encode(Encoder& encoder, const MediaSelectionOption& option) > { > encoder << option.displayName; >diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.h b/Source/WebKit/Shared/WebCoreArgumentCoders.h >index 928da7560c3e89bd41d518a6b62e54e8a4eef5a8..e3ebd33c0e69cc234f1c6d5814e7b4779fa66f66 100644 >--- a/Source/WebKit/Shared/WebCoreArgumentCoders.h >+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.h >@@ -743,15 +743,6 @@ template<> struct ArgumentCoder<WebCore::ServiceWorkerOrClientIdentifier> { > > #endif > >-#if ENABLE(CSS_SCROLL_SNAP) >- >-template<> struct ArgumentCoder<WebCore::ScrollOffsetRange<float>> { >- static void encode(Encoder&, const WebCore::ScrollOffsetRange<float>&); >- static Optional<WebCore::ScrollOffsetRange<float>> decode(Decoder&); >-}; >- >-#endif >- > template<> struct ArgumentCoder<WebCore::MediaSelectionOption> { > static void encode(Encoder&, const WebCore::MediaSelectionOption&); > static Optional<WebCore::MediaSelectionOption> decode(Decoder&); >diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm >index 11675f3245ba11ac398fdba2fce363babf0aa454..0464108fd8fad48b2bd4e38f80f9c6b2a5802935 100644 >--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm >+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm >@@ -223,14 +223,12 @@ bool RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling(ScrollEven > > float RemoteScrollingCoordinatorProxy::closestSnapOffsetForMainFrameScrolling(ScrollEventAxis axis, float scrollDestination, float velocity, unsigned& currentIndex) const > { >- ScrollingTreeNode* root = m_scrollingTree->rootNode(); >- ASSERT(root && root->isFrameScrollingNode()); >- ScrollingTreeFrameScrollingNode* rootScrollingNode = static_cast<ScrollingTreeFrameScrollingNode*>(root); >+ ScrollingTreeFrameScrollingNode* rootScrollingNode = m_scrollingTree->rootNode(); > const auto& snapOffsetsInfo = rootScrollingNode->snapOffsetsInfo(); > > float scaledScrollDestination = scrollDestination / m_webPageProxy.displayedContentScale(); > float rawClosestSnapOffset; >- std::tie(rawClosestSnapOffset, currentIndex) = snapOffsetsInfo.closestSnapOffset(axis, scaledScrollDestination, velocity); >+ std::tie(rawClosestSnapOffset, currentIndex) = snapOffsetsInfo.closestSnapOffset(axis, rootScrollingNode->layoutViewport().size(), scaledScrollDestination, velocity); > return rawClosestSnapOffset * m_webPageProxy.displayedContentScale(); > } > >diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm >index 880c03195f89c4bd13dd6a646523f1df84c9564e..8fc6615f76f3c9fad00f594b34b13dd44c923cd0 100644 >--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm >+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm >@@ -106,16 +106,17 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi > unsigned originalHorizontalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentHorizontalSnapPointIndex(); > unsigned originalVerticalSnapPosition = _scrollingTreeNodeDelegate->scrollingNode().currentVerticalSnapPointIndex(); > >+ WebCore::FloatSize viewportSize(static_cast<float>(CGRectGetWidth([scrollView bounds])), static_cast<float>(CGRectGetHeight([scrollView bounds]))); > const auto& snapOffsetsInfo = _scrollingTreeNodeDelegate->scrollingNode().snapOffsetsInfo(); > if (!snapOffsetsInfo.horizontalSnapOffsets.isEmpty()) { >- auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Horizontal, horizontalTarget, velocity.x); >+ auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Horizontal, viewportSize, horizontalTarget, velocity.x); > _scrollingTreeNodeDelegate->scrollingNode().setCurrentHorizontalSnapPointIndex(index); > if (horizontalTarget >= 0 && horizontalTarget <= scrollView.contentSize.width) > targetContentOffset->x = potentialSnapPosition; > } > > if (!snapOffsetsInfo.verticalSnapOffsets.isEmpty()) { >- auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Vertical, verticalTarget, velocity.x); >+ auto [potentialSnapPosition, index] = snapOffsetsInfo.closestSnapOffset(WebCore::ScrollEventAxis::Vertical, viewportSize, verticalTarget, velocity.x); > _scrollingTreeNodeDelegate->scrollingNode().setCurrentVerticalSnapPointIndex(index); > if (verticalTarget >= 0 && verticalTarget <= scrollView.contentSize.height) > targetContentOffset->y = potentialSnapPosition; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 7f8a9e0f6d6ac6c8e8c00551dbd63bbc05907c02..d494bece2667cba6cab2f7b970e4910cbcd10696 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,16 @@ >+2021-03-15 Martin Robinson <mrobinson@webkit.org> >+ >+ [css-scroll-snap] Properly handle overflowing snap areas >+ https://bugs.webkit.org/show_bug.cgi?id=223175 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html: This test used snap areas that >+ overflow the snapport, thus meant that it relied on non-spec compliant behavior. Rework it so >+ that the snap areas do not overflow, maintaining the existing behavior. >+ * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html: Ditto. >+ * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html: Ditto. >+ > 2021-03-14 Yusuke Suzuki <ysuzuki@apple.com> > > Prevent dynamic import in service worker >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index 1ae326c3cb0b2c4ce35683b7d8a86e5d3db25e59..54738bbd1d95967c892094641593e9a3553acdea 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,13 @@ >+2021-03-15 Martin Robinson <mrobinson@webkit.org> >+ >+ [css-scroll-snap] Properly handle overflowing snap areas >+ https://bugs.webkit.org/show_bug.cgi?id=223175 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt: Update expectations to >+ show that this test is now passing. >+ > 2021-03-10 Sergio Villar Senin <svillar@igalia.com> > > Do not shrink radio buttons bellow its size >diff --git a/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html b/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html >index 7b3526cc4dd07d51c9ec93dc89d4902bf0bd4632..94da8be531bfdeb94205f7e8ec21261d1df86bf8 100644 >--- a/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html >+++ b/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html >@@ -34,21 +34,32 @@ > scroll-snap-type: both mandatory; > } > >- .block { >- height: 1000px; >- width: 250px; >- scroll-snap-align: start; >- } >- > .horizontal-drawer { > height: 100%; > width: 2000px; > } > >- .horizontal-drawer .block { >- width: 1000px; >- height: 250px; >+ .horizontal-drawer > div { >+ float: left; >+ width: 990px; >+ height: 100%; >+ } >+ >+ .horizontal-drawer > div.snap-point { >+ scroll-snap-align: start; >+ width: 10px; >+ } >+ >+ #vertical-container > div { >+ width: 100%; >+ height: 990px; >+ } >+ >+ #vertical-container > div.snap-point { >+ scroll-snap-align: start; >+ height: 10px; > } >+ > </style> > <script src="../../resources/js-test.js"></script> > <script src="../../resources/ui-helper.js"></script> >@@ -87,13 +98,17 @@ > <body onload="onLoad();"> > <div id="horizontal-container" class="container"> > <div class="horizontal-drawer"> >- <div class="block" style="float: left; background: #80475E"></div> >- <div class="block" style="width: 450px; float: left; background: #CC5A71"></div> >+ <div class="snap-point" style="background: #80475E"></div> >+ <div></div> >+ <div class="snap-point" style="background: #CC5A71"></div> >+ <div></div> > </div> > </div> > <div id="vertical-container" class="container"> >- <div class="block" style="background: #80475E"></div> >- <div class="block" style="height: 450px; background: #CC5A71"></div> >+ <div class="snap-point" style="background: #80475E"></div> >+ <div></div> >+ <div class="snap-point" style="background: #CC5A71"></div> >+ <div></div> > </div> > <p id="console"></p> > <script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt >index a45d2adcddf6cf03df39863c36365933b88e281e..259cd980c549a058a08fffa7f24321f6ac583227 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt >@@ -1,13 +1,13 @@ > > PASS Snaps to the snap position if the snap area doesn't cover the snapport on x. >-FAIL 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 >-FAIL 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 >+PASS Snaps to the snap position if the snap area covers the snapport on x on the right border. >+PASS Snaps to the snap position if the snap area covers the snapport on x on the left border. > PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on x. > PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on y. >-FAIL 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 >-FAIL 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 >-FAIL 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 >-FAIL 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 >-FAIL 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 >-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 10 but got 0 >+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). >+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). >+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. >+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. >+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 >+PASS 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. > >diff --git a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html b/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html >index 6427a114e48b26be65b55e7b868df8675691a9f8..94dad2168c60de915476b1d010a643d04fe920e7 100644 >--- a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html >+++ b/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html >@@ -4,6 +4,7 @@ > <style> > html { > scroll-snap-type: y mandatory; >+ margin: 0; > } > .verticalGallery { > width: 100vw; >@@ -12,7 +13,7 @@ > padding: 0; > } > .colorBox { >- height: 100vh; >+ height: 90vh; > width: 100vw; > float: left; > scroll-snap-align: start; >diff --git a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html b/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html >index 5b052fdbf94c84a3d8e0d1a28fcb52202aef9f2f..1531e1e3ab225e502b3b720d1d061b8be30ff62c 100644 >--- a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html >+++ b/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html >@@ -13,21 +13,16 @@ > position: absolute; > top: 0; > left: 0; >- overflow-x: none; > overflow-y: scroll; > scroll-snap-type: y proximity; >- -webkit-scroll-snap-type: proximity; >- scroll-snap-type: proximity; > opacity: 0.5; > } > > .area { >- height: 600px; >- width: 600px; >+ height: 100%; >+ width: 100%; > float: left; > scroll-snap-align: start; >- -webkit-scroll-snap-coordinate: 0 0; >- scroll-snap-coordinate: 0 0; > } > </style> > <script>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 223175
:
423157
|
423166
|
423189
|
423311