Bug 222968 - Implement CSS overscroll-behavior for synchronous scroll
Summary: Implement CSS overscroll-behavior for synchronous scroll
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Scrolling (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: cathiechen
URL:
Keywords: InRadar
Depends on:
Blocks: 176454 220139
  Show dependency treegraph
 
Reported: 2021-03-09 03:47 PST by cathiechen
Modified: 2022-02-03 13:34 PST (History)
19 users (show)

See Also:


Attachments
Patch (59.57 KB, patch)
2021-03-09 03:51 PST, cathiechen
no flags Details | Formatted Diff | Diff
Patch (59.42 KB, patch)
2021-03-15 06:04 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (59.56 KB, patch)
2021-03-15 06:19 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (60.84 KB, patch)
2021-03-15 22:43 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (61.87 KB, patch)
2021-03-18 03:34 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (60.39 KB, patch)
2021-03-22 08:38 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (60.29 KB, patch)
2021-03-24 10:59 PDT, cathiechen
no flags Details | Formatted Diff | Diff
Patch (34.72 KB, patch)
2021-12-02 16:57 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (37.86 KB, patch)
2021-12-03 14:02 PST, Nikos Mouchtaris
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (37.86 KB, patch)
2021-12-03 14:15 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (38.07 KB, patch)
2021-12-08 17:25 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (39.78 KB, patch)
2021-12-09 14:39 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (39.65 KB, patch)
2021-12-10 13:53 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (38.69 KB, patch)
2021-12-10 15:35 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (17.07 KB, patch)
2022-01-28 17:51 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff
Patch (36.83 KB, patch)
2022-01-28 21:09 PST, Nikos Mouchtaris
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (36.87 KB, patch)
2022-01-28 21:55 PST, Nikos Mouchtaris
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (37.69 KB, patch)
2022-01-28 23:04 PST, Nikos Mouchtaris
simon.fraser: review+
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (35.52 KB, patch)
2022-02-02 12:46 PST, Nikos Mouchtaris
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (35.75 KB, patch)
2022-02-02 12:57 PST, Nikos Mouchtaris
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (39.01 KB, patch)
2022-02-02 23:35 PST, Nikos Mouchtaris
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description cathiechen 2021-03-09 03:47:30 PST
Support CSS property overscroll-behavior for synchronous scroll.
Comment 1 cathiechen 2021-03-09 03:51:11 PST
Created attachment 422685 [details]
Patch
Comment 2 cathiechen 2021-03-15 06:04:20 PDT
Created attachment 423165 [details]
Patch
Comment 3 cathiechen 2021-03-15 06:19:20 PDT
Created attachment 423168 [details]
Patch
Comment 4 cathiechen 2021-03-15 22:43:27 PDT
Created attachment 423300 [details]
Patch
Comment 5 Radar WebKit Bug Importer 2021-03-16 04:48:17 PDT
<rdar://problem/75472790>
Comment 6 cathiechen 2021-03-18 03:34:11 PDT
Created attachment 423579 [details]
Patch
Comment 7 cathiechen 2021-03-22 08:38:30 PDT
Created attachment 423886 [details]
Patch
Comment 8 cathiechen 2021-03-22 20:36:36 PDT
Comment on attachment 423886 [details]
Patch

I think overscroll-behahvior of sync scroll is ready to review:)
Comment 9 cathiechen 2021-03-24 10:59:54 PDT
Created attachment 424158 [details]
Patch
Comment 10 Nikos Mouchtaris 2021-12-02 16:57:24 PST
Created attachment 445794 [details]
Patch
Comment 11 Nikos Mouchtaris 2021-12-03 14:02:04 PST
Created attachment 445896 [details]
Patch
Comment 12 Nikos Mouchtaris 2021-12-03 14:15:43 PST
Created attachment 445897 [details]
Patch
Comment 13 Nikos Mouchtaris 2021-12-08 17:25:25 PST
Created attachment 446466 [details]
Patch
Comment 14 Simon Fraser (smfr) 2021-12-09 11:20:33 PST
Comment on attachment 446466 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=446466&action=review

> Source/WebCore/page/EventHandler.cpp:2922
> +static bool shouldBlockScrollChainingWithScrollableArea(const ScrollableArea* scrollableArea, FloatSize& biasedDelta)

I don't like "scroll chaining".

> Source/WebCore/page/EventHandler.cpp:2930
> +        biasedDelta.setWidth(scrollableArea->horizontalOverscrollBehavior()!= OverscrollBehavior::Auto ? 0 : biasedDelta.width());
> +        biasedDelta.setHeight(scrollableArea->verticalOverscrollBehavior()!= OverscrollBehavior::Auto ? 0 : biasedDelta.height());

Spacing here.

> Source/WebCore/page/EventHandler.cpp:2943
> +    if (frameView && (frameView->horizontalOverscrollBehavior() != OverscrollBehavior::Auto || frameView->verticalOverscrollBehavior() != OverscrollBehavior::Auto)) {
> +        if (frameView->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && !biasedDelta.height() && biasedDelta.width())
> +            return true;
> +        if ((frameView->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && frameView->verticalOverscrollBehavior() != OverscrollBehavior::Auto) || (frameView->horizontalOverscrollBehavior()!= OverscrollBehavior::Auto && !biasedDelta.height()) || (frameView->verticalOverscrollBehavior()!= OverscrollBehavior::Auto && !biasedDelta.width()))
> +            return true;
> +        biasedDelta.setWidth(frameView->horizontalOverscrollBehavior()!= OverscrollBehavior::Auto ? 0 : biasedDelta.width());
> +        biasedDelta.setHeight(frameView->verticalOverscrollBehavior()!= OverscrollBehavior::Auto ? 0 : biasedDelta.height());

There are so many "horizontalOverscrollBehavior() != OverscrollBehavior::Auto" checks in this code. Maybe add a helper function that makes this more readable.

> Source/WebCore/page/EventHandler.cpp:3064
> +        adjustedWheelEvent = adjustedWheelEvent.copyWithDeltaAndVelocity(filteredDelta, adjustedWheelEvent.scrollingVelocity());
> +        handledEvent = processWheelEventForScrolling(adjustedWheelEvent, scrollableArea, handling);
> +        processWheelEventForScrollSnap(adjustedWheelEvent, scrollableArea);

I find it odd that this main thread code implements overscroll behavior by zeroing out the deltas on the events, but the scrolling thread code does it by cutting of the ancestor node traversal. Let's be consistent.
Comment 15 Nikos Mouchtaris 2021-12-09 14:39:45 PST
Created attachment 446608 [details]
Patch
Comment 16 Jon Lee 2021-12-10 12:29:36 PST
Comment on attachment 446608 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=446608&action=review

> Source/WebCore/page/EventHandler.cpp:3127
> +                if (boxScrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && !filteredPlatformDelta.height())

can this use hasHorizontalOverscrollBehavior?

> Source/WebCore/page/mac/EventHandlerMac.mm:818
> +        if ((scrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && scrollableArea->verticalOverscrollBehavior() != OverscrollBehavior::Auto) || (scrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && !wheelEvent.delta().height()) || (scrollableArea->verticalOverscrollBehavior() != OverscrollBehavior::Auto && !wheelEvent.delta().width()))

can this use has{Horizontal,Vertical}OverscrollBehavior?
Comment 17 Jon Lee 2021-12-10 12:29:37 PST
Comment on attachment 446608 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=446608&action=review

> Source/WebCore/page/EventHandler.cpp:3127
> +                if (boxScrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && !filteredPlatformDelta.height())

can this use hasHorizontalOverscrollBehavior?

> Source/WebCore/page/mac/EventHandlerMac.mm:818
> +        if ((scrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && scrollableArea->verticalOverscrollBehavior() != OverscrollBehavior::Auto) || (scrollableArea->horizontalOverscrollBehavior() != OverscrollBehavior::Auto && !wheelEvent.delta().height()) || (scrollableArea->verticalOverscrollBehavior() != OverscrollBehavior::Auto && !wheelEvent.delta().width()))

can this use has{Horizontal,Vertical}OverscrollBehavior?
Comment 18 Nikos Mouchtaris 2021-12-10 13:53:42 PST
Created attachment 446805 [details]
Patch
Comment 19 Nikos Mouchtaris 2021-12-10 13:57:03 PST
(In reply to Simon Fraser (smfr) from comment #14)
> Comment on attachment 446466 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=446466&action=review
> 
> > Source/WebCore/page/EventHandler.cpp:3064
> > +        adjustedWheelEvent = adjustedWheelEvent.copyWithDeltaAndVelocity(filteredDelta, adjustedWheelEvent.scrollingVelocity());
> > +        handledEvent = processWheelEventForScrolling(adjustedWheelEvent, scrollableArea, handling);
> > +        processWheelEventForScrollSnap(adjustedWheelEvent, scrollableArea);
> 
> I find it odd that this main thread code implements overscroll behavior by
> zeroing out the deltas on the events, but the scrolling thread code does it
> by cutting of the ancestor node traversal. Let's be consistent.

The traversal is getting cut off in EventHandler::handleWheelEventInAppropriateEnclosingBox based on the result of shouldBlockScrollPropogationWithScrollableArea.
Comment 20 Simon Fraser (smfr) 2021-12-10 14:16:12 PST
Comment on attachment 446805 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=446805&action=review

> Source/WebCore/page/EventHandler.cpp:2922
> +static bool shouldBlockScrollPropogationWithScrollableArea(const ScrollableArea* scrollableArea, FloatSize& biasedDelta)

"Propogation"

Maybe this should be a function on ScrollableArea? And can we find out how to do this without having to modify event deltas?
Comment 21 Nikos Mouchtaris 2021-12-10 15:35:05 PST
Created attachment 446830 [details]
Patch
Comment 22 Nikos Mouchtaris 2021-12-10 15:37:30 PST
(In reply to Simon Fraser (smfr) from comment #20)
> Comment on attachment 446805 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=446805&action=review
> 
> > Source/WebCore/page/EventHandler.cpp:2922
> > +static bool shouldBlockScrollPropogationWithScrollableArea(const ScrollableArea* scrollableArea, FloatSize& biasedDelta)
> 
> "Propogation"
> 
> Maybe this should be a function on ScrollableArea? And can we find out how
> to do this without having to modify event deltas?

I think we have to modify the deltas for the case where we are only blocking in one direction, we have to zero out the delta for that direction.
Comment 23 Simon Fraser (smfr) 2022-01-28 16:38:22 PST
Comment on attachment 446830 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=446830&action=review

> Source/WebCore/page/EventHandler.cpp:3029
> +    PlatformWheelEvent adjustedWheelEvent = PlatformWheelEvent(event);

auto

> Source/WebCore/page/EventHandler.cpp:3057
> +    FloatSize filteredDelta(wheelEvent.deltaX(), wheelEvent.deltaY());

auto filteredDelta = wheelEvent.delta()

> Source/WebCore/page/EventHandler.cpp:3058
> +    scrollableArea.shouldBlockScrollPropagation(filteredDelta);

That looks like a no-op until you notice that shouldBlockScrollPropagation() modifies the delta. Can we apply the same cleanup we did in bug 220139?

> Source/WebCore/page/EventHandler.cpp:3096
> +    FloatSize biasedDelta(wheelEvent.deltaX(), wheelEvent.deltaY());

auto biasedDelta = ....

> Source/WebCore/platform/ScrollableArea.cpp:811
> +bool ScrollableArea::shouldBlockScrollPropagation(FloatSize& biasedDelta) const

This code should be changed to be more similar to the async structure (separate out the question from the modification).

> LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element.html:1
> +<!doctype html>

Same comments about these tests as in bug 220139.
Comment 24 Nikos Mouchtaris 2022-01-28 17:51:10 PST
Created attachment 450298 [details]
Patch
Comment 25 Simon Fraser (smfr) 2022-01-28 20:33:47 PST
Comment on attachment 450298 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=450298&action=review

I'd like to see one more round. Also, we need to test this code path. You need some tests that either don't have async overflow scroll enabled.

> Source/WebCore/page/EventHandler.cpp:3103
> +                if (boxScrollableArea->hasHorizontalOverscrollBehavior() && !filteredPlatformDelta.height())

Need ScrollableArea::horizontalOverscrollBehaviorPreventsPropagation() etc just like the async code path.

Again here, the lack of symmetry between vertical and horizontal is confusing.

> Source/WebCore/page/FrameView.h:706
> +    bool hasHorizontalOverscrollBehavior() const final { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> +    bool hasVerticalOverscrollBehavior() const final { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }

Can't these live on ScrollableArea?

> Source/WebCore/page/mac/EventHandlerMac.mm:819
> +        if ((scrollableArea->hasHorizontalOverscrollBehavior() && scrollableArea->hasVerticalOverscrollBehavior()) || (scrollableArea->hasHorizontalOverscrollBehavior() && !wheelEvent.delta().height()) || (scrollableArea->hasVerticalOverscrollBehavior() && !wheelEvent.delta().width()))
> +            return nullptr;

I feel like this could be wrapped up a helper called something like overscrollBehaviorPreventsScrollPropagation(FloatSize delta). Also it should use horizontalOverscrollBehaviorPreventsPropagation() terminology.

> Source/WebCore/platform/ScrollableArea.cpp:821
> +bool ScrollableArea::shouldBlockScrollPropagation(const FloatSize& biasedDelta) const

Oh it's here. Why didn't EventHandlerMac call this?

> Source/WebCore/platform/ScrollableArea.h:375
> +    virtual bool hasHorizontalOverscrollBehavior() const { return false; }
> +    virtual bool hasVerticalOverscrollBehavior() const { return false; }

horizontalOverscrollBehaviorPreventsPropagation etc

> Source/WebCore/rendering/RenderLayer.cpp:2312
> +//                ASSERT_UNUSED(foundAncestor, foundAncestor);

Why? Also you can't land this.
Comment 26 Nikos Mouchtaris 2022-01-28 21:09:47 PST
Created attachment 450309 [details]
Patch
Comment 27 Nikos Mouchtaris 2022-01-28 21:55:55 PST
Created attachment 450311 [details]
Patch
Comment 28 Nikos Mouchtaris 2022-01-28 23:04:25 PST
Created attachment 450319 [details]
Patch
Comment 29 Simon Fraser (smfr) 2022-02-01 13:58:51 PST
Comment on attachment 450319 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=450319&action=review

I'd still like the tests to be rewritten.

> Source/WebCore/page/FrameView.h:706
> +    bool horizontalOverscrollBehaviorPreventsPropagation() const final { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> +    bool verticalOverscrollBehaviorPreventsPropagation() const final { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }

Why aren't these just on the base class? horizontalOverscrollBehavior() is virtual, so this doesn't need to be.

> Source/WebCore/page/mac/EventHandlerMac.mm:819
> +        if (scrollableArea->shouldBlockScrollPropagation(wheelEvent.delta()))
> +            return nullptr;

Is this the right place to call this, allowing a "over scroll-behavior: contain" scroller to rubberband?

> Source/WebCore/platform/ScrollableArea.cpp:822
> +    return ((horizontalOverscrollBehaviorPreventsPropagation() || verticalOverscrollBehaviorPreventsPropagation()) && ((horizontalOverscrollBehaviorPreventsPropagation() && verticalOverscrollBehaviorPreventsPropagation()) || (horizontalOverscrollBehaviorPreventsPropagation() && !biasedDelta.height()) || (verticalOverscrollBehaviorPreventsPropagation() && !biasedDelta.width())));

I'd wrap this line more.

> Source/WebCore/platform/ScrollableArea.h:378
> +    virtual bool horizontalOverscrollBehaviorPreventsPropagation() const { return false; }
> +    virtual bool verticalOverscrollBehaviorPreventsPropagation() const { return false; }

Can't these just be:

bool horizontalOverscrollBehaviorPreventsPropagation() const { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
bool verticalOverscrollBehaviorPreventsPropagation() const { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }

> Source/WebCore/rendering/RenderLayerScrollableArea.h:241
> +    bool horizontalOverscrollBehaviorPreventsPropagation() const final { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> +    bool verticalOverscrollBehaviorPreventsPropagation() const final { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }

And you can remove these.

> LayoutTests/platform/ios/TestExpectations:821
> +# Overscroll-behavior is not supported on iOS yet: https://bugs.webkit.org/show_bug.cgi?id=233788
> +fast/scrolling/sync-scroll-overscroll-behavior-element.html [ Skip ]
> +fast/scrolling/sync-scroll-overscroll-behavior-iframe.html [ Skip ]
> +fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html [ Skip ]
> +fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html [ Skip ]

Not true any more.
Comment 30 Nikos Mouchtaris 2022-02-02 12:46:52 PST
Created attachment 450690 [details]
Patch
Comment 31 Nikos Mouchtaris 2022-02-02 12:57:30 PST
Created attachment 450692 [details]
Patch
Comment 32 Nikos Mouchtaris 2022-02-02 13:01:37 PST
(In reply to Simon Fraser (smfr) from comment #29)
> Comment on attachment 450319 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=450319&action=review
> 
> I'd still like the tests to be rewritten.
Tracked in https://bugs.webkit.org/show_bug.cgi?id=235847.
> 
> > Source/WebCore/page/FrameView.h:706
> > +    bool horizontalOverscrollBehaviorPreventsPropagation() const final { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> > +    bool verticalOverscrollBehaviorPreventsPropagation() const final { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }
> 
> Why aren't these just on the base class? horizontalOverscrollBehavior() is
> virtual, so this doesn't need to be.
> 
Fixed.
> > Source/WebCore/page/mac/EventHandlerMac.mm:819
> > +        if (scrollableArea->shouldBlockScrollPropagation(wheelEvent.delta()))
> > +            return nullptr;
> 
> Is this the right place to call this, allowing a "over scroll-behavior:
> contain" scroller to rubberband?
Added similar code to async in handleWheelEventInAppropriateEnclosingBox to allow node to handle rubber banding.
> 
> > Source/WebCore/platform/ScrollableArea.cpp:822
> > +    return ((horizontalOverscrollBehaviorPreventsPropagation() || verticalOverscrollBehaviorPreventsPropagation()) && ((horizontalOverscrollBehaviorPreventsPropagation() && verticalOverscrollBehaviorPreventsPropagation()) || (horizontalOverscrollBehaviorPreventsPropagation() && !biasedDelta.height()) || (verticalOverscrollBehaviorPreventsPropagation() && !biasedDelta.width())));
> 
> I'd wrap this line more.
> 
Fixed.
> > Source/WebCore/platform/ScrollableArea.h:378
> > +    virtual bool horizontalOverscrollBehaviorPreventsPropagation() const { return false; }
> > +    virtual bool verticalOverscrollBehaviorPreventsPropagation() const { return false; }
> 
> Can't these just be:
> 
> bool horizontalOverscrollBehaviorPreventsPropagation() const { return
> horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> bool verticalOverscrollBehaviorPreventsPropagation() const { return
> verticalOverscrollBehavior() != OverscrollBehavior::Auto; }
Fixed.
> 
> > Source/WebCore/rendering/RenderLayerScrollableArea.h:241
> > +    bool horizontalOverscrollBehaviorPreventsPropagation() const final { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
> > +    bool verticalOverscrollBehaviorPreventsPropagation() const final { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }
> 
> And you can remove these.
Fixed.
> 
> > LayoutTests/platform/ios/TestExpectations:821
> > +# Overscroll-behavior is not supported on iOS yet: https://bugs.webkit.org/show_bug.cgi?id=233788
> > +fast/scrolling/sync-scroll-overscroll-behavior-element.html [ Skip ]
> > +fast/scrolling/sync-scroll-overscroll-behavior-iframe.html [ Skip ]
> > +fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html [ Skip ]
> > +fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html [ Skip ]
> 
> Not true any more.
Fixed.
Comment 33 Simon Fraser (smfr) 2022-02-02 13:11:55 PST
Comment on attachment 450692 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=450692&action=review

> Source/WebCore/platform/ScrollableArea.h:379
> +    bool overscrollBehaviorAllowRubberBand() const { return horizontalOverscrollBehavior() != OverscrollBehavior::None || verticalOverscrollBehavior() != OverscrollBehavior::None; }

overscrollBehaviorAllowRubberBand -> overscrollBehaviorAllowsRubberBand
Comment 34 Nikos Mouchtaris 2022-02-02 23:35:19 PST
Created attachment 450737 [details]
Patch
Comment 35 EWS 2022-02-03 13:33:56 PST
Committed r289074 (246780@main): <https://commits.webkit.org/246780@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 450737 [details].