| Differences between
and this patch
- a/Source/WebCore/ChangeLog +17 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2021-06-16  Martin Robinson  <mrobinson@igalia.com>
2
3
        CSS scroll snap should allow scrolling to the middle of snap areas that overflow the snapport
4
        https://bugs.webkit.org/show_bug.cgi?id=223021
5
        <rdar://problem/75518606>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        No new tests. This is covered by existing tests and, in particular, a WPT test:
10
            - web-platform-tests/css/css-scroll-snap/overflowing-snap-areas.html
11
12
        * page/scrolling/ScrollSnapOffsetsInfo.cpp:
13
        (WebCore::searchForPotentialSnapPoints): Record when the target snap offset happens to
14
        fall in the interior of a snap area that overflows the snap port.
15
        (WebCore::closestSnapOffsetWithInfoAndAxis): When this happens and we are in a spec-compliant
16
        sitaution, just snap to the original target offset.
17
1
2021-06-25  Martin Robinson  <mrobinson@webkit.org>
18
2021-06-25  Martin Robinson  <mrobinson@webkit.org>
2
19
3
        [css-scroll-snap] Simplify snap point selection helpers
20
        [css-scroll-snap] Simplify snap point selection helpers
- a/Source/WebCore/page/scrolling/ScrollSnapOffsetsInfo.cpp -5 / +22 lines
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;
- a/LayoutTests/ChangeLog +18 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2021-06-16  Martin Robinson  <mrobinson@igalia.com>
2
3
        CSS scroll snap should allow scrolling to the middle of snap areas that overflow the snapport
4
        https://bugs.webkit.org/show_bug.cgi?id=223021
5
        <rdar://problem/75518606>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Update some existing tests that were relying on non-spec compliant behavior. These tests
10
        used snap areas that were larger than the snapport and didn't expect that the parent
11
        scroller could scroll into them.
12
13
        * css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html: This test used snap areas that
14
        overflow the snapport, thus meant that it relied on non-spec compliant behavior. Rework it so
15
        that the snap areas do not overflow, maintaining the existing behavior.
16
        * tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html: Ditto.
17
        * tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html: Ditto.
18
1
2021-06-14  Sergio Villar Senin  <svillar@igalia.com>
19
2021-06-14  Sergio Villar Senin  <svillar@igalia.com>
2
20
3
        [css-flexbox] Do not clamp flex base size with {min|max}-{height|width}
21
        [css-flexbox] Do not clamp flex base size with {min|max}-{height|width}
- a/LayoutTests/imported/w3c/ChangeLog +11 lines
Lines 1-3 a/LayoutTests/imported/w3c/ChangeLog_sec1
1
2021-06-16  Martin Robinson  <mrobinson@igalia.com>
2
3
        CSS scroll snap should allow scrolling to the middle of snap areas that overflow the snapport
4
        https://bugs.webkit.org/show_bug.cgi?id=223021
5
        <rdar://problem/75518606>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt: Update test
10
        expectations to reflect newly passing tests.
11
1
2021-06-25  Ziran Sun  <zsun@igalia.com>
12
2021-06-25  Ziran Sun  <zsun@igalia.com>
2
13
3
        Resync web-platform-tests/css/css-grid tests from upstream
14
        Resync web-platform-tests/css/css-grid tests from upstream
- a/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html -13 / +28 lines
Lines 34-54 a/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html_sec1
34
                scroll-snap-type: both mandatory;
34
                scroll-snap-type: both mandatory;
35
            }
35
            }
36
36
37
            .block {
38
                height: 1000px;
39
                width: 250px;
40
                scroll-snap-align: start;
41
            }
42
43
            .horizontal-drawer {
37
            .horizontal-drawer {
44
                height: 100%;
38
                height: 100%;
45
                width: 2000px;
39
                width: 2000px;
46
            }
40
            }
47
41
48
            .horizontal-drawer .block {
42
            .horizontal-drawer > div {
49
                width: 1000px;
43
                float: left;
50
                height: 250px;
44
                width: 990px;
45
                height: 100%;
46
            }
47
48
            .horizontal-drawer > div.snap-point {
49
                scroll-snap-align: start;
50
                width: 10px;
51
             }
52
53
            #vertical-container > div {
54
                width: 100%;
55
                height: 990px;
56
            }
57
58
            #vertical-container > div.snap-point {
59
                scroll-snap-align: start;
60
                height: 10px;
51
            }
61
            }
62
52
        </style>
63
        </style>
53
        <script src="../../resources/js-test.js"></script>
64
        <script src="../../resources/js-test.js"></script>
54
        <script src="../../resources/ui-helper.js"></script>
65
        <script src="../../resources/ui-helper.js"></script>
Lines 87-99 a/LayoutTests/css3/scroll-snap/scroll-snap-click-scrollbar-gutter.html_sec2
87
    <body onload="onLoad();">
98
    <body onload="onLoad();">
88
        <div id="horizontal-container" class="container">
99
        <div id="horizontal-container" class="container">
89
            <div class="horizontal-drawer">
100
            <div class="horizontal-drawer">
90
                <div class="block" style="float: left; background: #80475E"></div>
101
                <div class="snap-point" style="background: #80475E"></div>
91
                <div class="block" style="width: 450px; float: left; background: #CC5A71"></div>
102
                <div></div>
103
                <div class="snap-point" style="background: #CC5A71"></div>
104
                <div></div>
92
            </div>
105
            </div>
93
        </div>
106
        </div>
94
        <div id="vertical-container" class="container">
107
        <div id="vertical-container" class="container">
95
            <div class="block" style="background: #80475E"></div>
108
            <div class="snap-point" style="background: #80475E"></div>
96
            <div class="block" style="height: 450px; background: #CC5A71"></div>
109
            <div></div>
110
            <div class="snap-point" style="background: #CC5A71"></div>
111
            <div></div>
97
        </div>
112
        </div>
98
        <p id="console"></p>
113
        <p id="console"></p>
99
        <script>
114
        <script>
- a/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt -8 / +8 lines
Lines 1-13 a/LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/overflowing-snap-areas-expected.txt_sec1
1
1
2
PASS Snaps to the snap position if the snap area doesn't cover the snapport on x.
2
PASS Snaps to the snap position if the snap area doesn't cover the snapport on x.
3
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
3
PASS Snaps to the snap position if the snap area covers the snapport on x on the right border.
4
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
4
PASS Snaps to the snap position if the snap area covers the snapport on x on the left border.
5
PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on x.
5
PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on x.
6
PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on y.
6
PASS Snaps if the distance between the previous(400) and next(800) snap positions is smaller than snapport(500) on y.
7
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
7
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).
8
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
8
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).
9
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
9
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.
10
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
10
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.
11
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
11
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
12
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
12
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.
13
13
- a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html -1 / +2 lines
Lines 4-9 a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html_sec1
4
        <style>
4
        <style>
5
            html {
5
            html {
6
                scroll-snap-type: y mandatory;
6
                scroll-snap-type: y mandatory;
7
                margin: 0;
7
            }
8
            }
8
            .verticalGallery {
9
            .verticalGallery {
9
                width: 100vw;
10
                width: 100vw;
Lines 12-18 a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical-then-horizontal.html_sec2
12
                padding: 0;
13
                padding: 0;
13
            }
14
            }
14
            .colorBox {
15
            .colorBox {
15
                height: 100vh;
16
                height: 90vh;
16
                width: 100vw;
17
                width: 100vw;
17
                float: left;
18
                float: left;
18
                scroll-snap-align: start;
19
                scroll-snap-align: start;
- a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html -7 / +2 lines
Lines 13-33 a/LayoutTests/tiled-drawing/scrolling/scroll-snap/scroll-snap-proximity-overflow.html_sec1
13
                position: absolute;
13
                position: absolute;
14
                top: 0;
14
                top: 0;
15
                left: 0;
15
                left: 0;
16
                overflow-x: none;
17
                overflow-y: scroll;
16
                overflow-y: scroll;
18
                scroll-snap-type: y proximity;
17
                scroll-snap-type: y proximity;
19
                -webkit-scroll-snap-type: proximity;
20
                scroll-snap-type: proximity;
21
                opacity: 0.5;
18
                opacity: 0.5;
22
            }
19
            }
23
20
24
            .area {
21
            .area {
25
                height: 600px;
22
                height: 100%;
26
                width: 600px;
23
                width: 100%;
27
                float: left;
24
                float: left;
28
                scroll-snap-align: start;
25
                scroll-snap-align: start;
29
                -webkit-scroll-snap-coordinate: 0 0;
30
                scroll-snap-coordinate: 0 0;
31
            }
26
            }
32
        </style>
27
        </style>
33
        <script>
28
        <script>

Return to Bug 223021