|
Lines 45-57
struct PotentialSnapPointSearchResult {
a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp_sec1
|
| 45 |
std::optional<std::pair<UnitType, unsigned>> previous; |
45 |
std::optional<std::pair<UnitType, unsigned>> previous; |
| 46 |
std::optional<std::pair<UnitType, unsigned>> next; |
46 |
std::optional<std::pair<UnitType, unsigned>> next; |
| 47 |
std::optional<std::pair<UnitType, unsigned>> snapStop; |
47 |
std::optional<std::pair<UnitType, unsigned>> snapStop; |
|
|
48 |
bool landedInsideSnapAreaThatConsumesViewport; |
| 48 |
}; |
49 |
}; |
| 49 |
|
50 |
|
| 50 |
template <typename InfoType, typename UnitType> |
51 |
template <typename InfoType, typename UnitType> |
| 51 |
static PotentialSnapPointSearchResult<UnitType> searchForPotentialSnapPoints(const InfoType& info, ScrollEventAxis axis, UnitType destinationOffset, std::optional<UnitType> originalOffset) |
52 |
static PotentialSnapPointSearchResult<UnitType> searchForPotentialSnapPoints(const InfoType& info, ScrollEventAxis axis, UnitType viewportLength, UnitType destinationOffset, std::optional<UnitType> originalOffset) |
| 52 |
{ |
53 |
{ |
| 53 |
const auto& snapOffsets = info.offsetsForAxis(axis); |
54 |
const auto& snapOffsets = info.offsetsForAxis(axis); |
| 54 |
std::optional<std::pair<UnitType, unsigned>> previous, next, exact, snapStop; |
55 |
std::optional<std::pair<UnitType, unsigned>> previous, next, exact, snapStop; |
|
|
56 |
bool landedInsideSnapAreaThatConsumesViewport = false; |
| 55 |
|
57 |
|
| 56 |
// A particular snap stop is better if it's between the original offset and destination offset and closer original |
58 |
// A particular snap stop is better if it's between the original offset and destination offset and closer original |
| 57 |
// offset than the previously selected snap stop. We always want to stop at the snap stop closest to the original offset. |
59 |
// offset than the previously selected snap stop. We always want to stop at the snap stop closest to the original offset. |
|
Lines 66-71
static PotentialSnapPointSearchResult<UnitType> searchForPotentialSnapPoints(con
a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp_sec2
|
| 66 |
|
68 |
|
| 67 |
for (unsigned i = 0; i < snapOffsets.size(); i++) { |
69 |
for (unsigned i = 0; i < snapOffsets.size(); i++) { |
| 68 |
UnitType potentialSnapOffset = snapOffsets[i].offset; |
70 |
UnitType potentialSnapOffset = snapOffsets[i].offset; |
|
|
71 |
|
| 72 |
const auto& snapArea = info.snapAreas[snapOffsets[i].snapAreaIndex]; |
| 73 |
auto snapAreaMin = axis == ScrollEventAxis::Horizontal ? snapArea.x() : snapArea.y(); |
| 74 |
auto snapAreaMax = axis == ScrollEventAxis::Horizontal ? snapArea.maxX() : snapArea.maxY(); |
| 75 |
landedInsideSnapAreaThatConsumesViewport |= snapAreaMin <= destinationOffset && snapAreaMax >= (destinationOffset + viewportLength); |
| 76 |
|
| 69 |
if (potentialSnapOffset == destinationOffset) |
77 |
if (potentialSnapOffset == destinationOffset) |
| 70 |
exact = std::make_pair(potentialSnapOffset, i); |
78 |
exact = std::make_pair(potentialSnapOffset, i); |
| 71 |
else if (potentialSnapOffset < destinationOffset) |
79 |
else if (potentialSnapOffset < destinationOffset) |
|
Lines 78-85
static PotentialSnapPointSearchResult<UnitType> searchForPotentialSnapPoints(con
a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp_sec3
|
| 78 |
} |
86 |
} |
| 79 |
|
87 |
|
| 80 |
if (exact) |
88 |
if (exact) |
| 81 |
return { exact, exact, snapStop }; |
89 |
return { exact, exact, snapStop, landedInsideSnapAreaThatConsumesViewport }; |
| 82 |
return { previous, next, snapStop }; |
90 |
return { previous, next, snapStop, landedInsideSnapAreaThatConsumesViewport }; |
| 83 |
} |
91 |
} |
| 84 |
|
92 |
|
| 85 |
template <typename InfoType, typename SizeType, typename LayoutType> |
93 |
template <typename InfoType, typename SizeType, typename LayoutType> |
|
Lines 90-100
static std::pair<LayoutType, std::optional<unsigned>> closestSnapOffsetWithInfoA
a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp_sec4
|
| 90 |
if (snapOffsets.isEmpty()) |
98 |
if (snapOffsets.isEmpty()) |
| 91 |
return pairForNoSnapping; |
99 |
return pairForNoSnapping; |
| 92 |
|
100 |
|
| 93 |
auto [previous, next, snapStop] = searchForPotentialSnapPoints(info, axis, scrollDestinationOffset, originalOffsetForDirectionalSnapping); |
101 |
auto viewportLength = axis == ScrollEventAxis::Horizontal ? viewportSize.width() : viewportSize.height(); |
|
|
102 |
auto [previous, next, snapStop, landedInsideSnapAreaThatConsumesViewport] = searchForPotentialSnapPoints(info, axis, viewportLength, scrollDestinationOffset, originalOffsetForDirectionalSnapping); |
| 94 |
if (snapStop) |
103 |
if (snapStop) |
| 95 |
return *snapStop; |
104 |
return *snapStop; |
| 96 |
|
105 |
|
| 97 |
auto viewportLength = axis == ScrollEventAxis::Horizontal ? viewportSize.width() : viewportSize.height(); |
106 |
// From https://www.w3.org/TR/css-scroll-snap-1/#snap-overflow |
|
|
107 |
// "If the snap area is larger than the snapport in a particular axis, then any scroll position |
| 108 |
// in which the snap area covers the snapport, and the distance between the geometrically |
| 109 |
// previous and subsequent snap positions in that axis is larger than size of the snapport in |
| 110 |
// that axis, is a valid snap position in that axis. The UA may use the specified alignment as a |
| 111 |
// more precise target for certain scroll operations (e.g. explicit paging)." |
| 112 |
if (landedInsideSnapAreaThatConsumesViewport && (!previous || !next || ((*next).first - (*previous).first) >= viewportLength)) |
| 113 |
return pairForNoSnapping; |
| 114 |
|
| 98 |
auto isNearEnoughToOffsetForProximity = [&](LayoutType candidateSnapOffset) { |
115 |
auto isNearEnoughToOffsetForProximity = [&](LayoutType candidateSnapOffset) { |
| 99 |
if (info.strictness != ScrollSnapStrictness::Proximity) |
116 |
if (info.strictness != ScrollSnapStrictness::Proximity) |
| 100 |
return true; |
117 |
return true; |