Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: d259d7a2d4e9bd22d8012ab3c9947dd54a366aca
      
https://github.com/WebKit/WebKit/commit/d259d7a2d4e9bd22d8012ab3c9947dd54a366aca
  Author: Wenson Hsieh <[email protected]>
  Date:   2024-12-03 (Tue, 03 Dec 2024)

  Changed paths:
    M Source/WebCore/page/EventHandler.cpp
    M Source/WebCore/page/EventHandler.h
    M Source/WebCore/page/ios/EventHandlerIOS.mm
    M Source/WebCore/page/mac/EventHandlerMac.mm
    M Source/WebCore/platform/ScrollableArea.cpp
    M Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm
    M Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp
    M Source/WebKit/WebProcess/WebPage/WebPage.cpp
    M Source/WebKit/WebProcess/WebPage/WebPage.h
    M Source/WebKit/WebProcess/WebPage/WebPage.messages.in
    M Tools/TestWebKitAPI/Tests/ios/WKScrollViewTests.mm

  Log Message:
  -----------
  [iPadOS] Outlook native app: channels tab does not handle trackpad two-finger 
pans to scroll
https://bugs.webkit.org/show_bug.cgi?id=283931
rdar://139834901

Reviewed by Abrar Rahman Protyasha.

On iPad, when scrolling via 2-finger swipe on a connected trackpad, `wheel` 
events are dispatched to
the page via the `WebPage::dispatchWheelEventWithoutScrolling` IPC message. As 
the name suggests,
this only dispatches `wheel` DOM events to the page, and returns a boolean 
result back to the UI
process indicating whether or not scrolling should be allowed to commence. 
UIKit will then only
drive the default scroll animation on the native scroll view under the pointer 
if the event was not
`handled`.

Whether the event is handled or not depends on the return value of 
`EventHandler::handleWheelEvent`.
In the case of the Outlook native app's Channels tab, which is comprised of a 
large full-viewport
subscrollable overflow container, it returns `true` only because the body and 
root elements have
`overscroll-behavior: none;`, causing us to exit early in 
`handleWheelEventInternal` with `true`:

```
HandleUserInputEventResult EventHandler::handleWheelEventInternal(…)
{
…
    auto adjustedWheelEvent = event;
    auto filteredDelta = adjustedWheelEvent.delta();
    filteredDelta = view->deltaForPropagation(filteredDelta);
    if (view->shouldBlockScrollPropagation(filteredDelta))
        return true;                                            // <---
```

...and subsequently causes us to block scrolling on the subscrollable 
container. In this same
codepath on macOS, we also return `true` here, but the key difference is that 
treating the wheel
event as `handled := true` here doesn't simply block scrolling — that only 
happens if we've blocked
scrolling due to `preventDefault` being called.

To fix this impedance mismatch between the return value of `handleWheelEvent()` 
and how it's
interpreted within `WebPage::dispatchWheelEventWithoutScrolling`, we plumb the 
`EventHandling`
result alongside `HandleUserInputEventResult` up from WebCore to WebKit as a 
`std::pair`, and
consult the event handling result (i.e. whether or not 
`EventHandling::DefaultPrevented` is set) in
addition to checking whether the event was handled.

* Source/WebCore/page/EventHandler.cpp:
(WebCore::EventHandler::handleWheelEvent):

Make this return a `std::pair<HandleUserInputEventResult, 
OptionSet<EventHandling>>`, and plumb it
through to the client layer (see `WebPage` changes below) so that we can check 
if the default was
prevented (not just if the event was handled) in 
`dispatchWheelEventWithoutScrolling`.

(WebCore::EventHandler::passWheelEventToWidget):
* Source/WebCore/page/EventHandler.h:
* Source/WebCore/page/ios/EventHandlerIOS.mm:
(WebCore::EventHandler::wheelEvent):
* Source/WebCore/page/mac/EventHandlerMac.mm:
(WebCore::EventHandler::wheelEvent):
(WebCore::EventHandler::passWheelEventToWidget):
* Source/WebCore/platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::shouldBlockScrollPropagation const):

Drive-by fix: rewrite this method to be more readable:

-   Cache the results of calling 
`(horizontal|vertical)OverscrollBehaviorPreventsPropagation` in
    local variables instead of calling the respective methods multiple times.

-   Split the return value into several early returns that achieve the same 
result, but (more
    clearly) represent the scenarios in which this is true: either both axes 
stop propagation, or
    only one axis stops propagation but the biased delta amount for the 
opposite axis is 0.

* Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView scrollView:handleScrollUpdate:completion:]):
* Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::dispatchWheelEvent):
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::handleWheelEvent):
(WebKit::WebPage::wheelEvent):
(WebKit::WebPage::dispatchWheelEventWithoutScrolling):
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/WebPage.messages.in:

Rename this variable to reflect that this result flag represents whether or not 
scrolling should be
prevented, not just whether the event was handled.

* Tools/TestWebKitAPI/Tests/ios/WKScrollViewTests.mm:
(-[WKWebView synchronouslyHandleScrollEventWithPhase:location:delta:]):
(TEST(WKScrollViewTests, AsynchronousWheelEventHandling)):
(TEST(WKScrollViewTests, OverscrollBehaviorShouldNotPreventScrolling)):

Add a new API test to exercise this change, by verifying that scrolling is not 
prevented when
dispatching wheel events over an overflow scrollable region inside of a root 
and body element with
`overscroll-behavior: contain;`. Also verify that scrolling is (correctly) 
prevented if the page
explicitly calls `preventDefault()` on the wheel event.

Canonical link: https://commits.webkit.org/287293@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to