[webkit-changes] [WebKit/WebKit] d259d7: [iPadOS] Outlook native app: channels tab does not...
Wenson Hsieh
noreply at github.com
Tue Dec 3 11:10:34 PST 2024
Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: d259d7a2d4e9bd22d8012ab3c9947dd54a366aca
https://github.com/WebKit/WebKit/commit/d259d7a2d4e9bd22d8012ab3c9947dd54a366aca
Author: Wenson Hsieh <wenson_hsieh at apple.com>
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
More information about the webkit-changes
mailing list