Branch: refs/heads/main Home: https://github.com/WebKit/WebKit Commit: 8612f9f7a3cda362a6280a9ef0e0e687f4d360c1 https://github.com/WebKit/WebKit/commit/8612f9f7a3cda362a6280a9ef0e0e687f4d360c1 Author: Wenson Hsieh <wenson_hs...@apple.com> Date: 2024-11-11 (Mon, 11 Nov 2024)
Changed paths: A LayoutTests/fast/events/touch/ios/programmatic-scrolling-on-touchmove-expected.txt A LayoutTests/fast/events/touch/ios/programmatic-scrolling-on-touchmove.html M Source/WebCore/dom/ios/MouseEventIOS.cpp M Source/WebCore/dom/ios/PointerEventIOS.cpp M Source/WebCore/page/PointerCaptureController.cpp M Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm M Source/WebCore/platform/ios/ScrollAnimatorIOS.mm M Source/WebKit/Shared/WebEvent.serialization.in M Source/WebKit/Shared/WebEventConversion.cpp M Source/WebKit/Shared/WebTouchEvent.h M Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm M Source/WebKit/UIProcess/WebPageProxy.cpp M Source/WebKit/UIProcess/ios/WKContentViewInteraction.h M Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm M Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.h M Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.mm M Tools/TestWebKitAPI/Tests/ios/TouchEventTests.mm Log Message: ----------- REGRESSION (265825@main): [iOS] europa.eu: Scroll position jitters when scrolling over interactive map https://bugs.webkit.org/show_bug.cgi?id=282933 rdar://112427506 Reviewed by Abrar Rahman Protyasha. The changes in 265825@main exacerbated an existing bug, regarding how our touch event handling logic propagates the location of the user's touches from the UI process to the web process; this results in scrolling on the immigration portal on europa.eu becoming extremely jittery (bouncing between the minimum and maximum scroll positions in the main document) as the user performs an upwards swipe over the interactive map to scroll down. The interactive map on europa.eu intercepts and prevents all `touchstart` and `touchmove` events that are dispatched over it. When the user attempts to scroll the page by swiping over the element and `touchmove` is dispatched, their script attempts to adjust `pageYOffset` such that the location of the user's touch relative to the document remains the same, before and after handling the `touchmove` delta. In other words, the `touchmove` event listener simulates scrolling by keeping a point in content coordinates fixed underneath the user's finger as they pan. However, this doesn't quite work well in practice, especially after the changes in 265825@main elided an extra CA commit that would otherwise more aggressively sync programmatic scrolling to UI- side scroll content offset. That's because touch locations are computed in `WKContentView` coordinates in the UI process (when receiving gesture recognizer subclass method calls from UIKit), and then dispatched to the web process where they're asynchronously queued and delivered to event listeners for processing. Throughout this process, the root view location of the touch remains unchanged since it was computed in the UI process, which means that it ignores any changes to the scroll position of the page that happened after the gesture was recognized. This is particularly disastrous when combined with europa.eu's touch event handling logic, which constantly shifts the scroll position when receiving `touchmove` events — the result is that the page can be scrolled programmatically, but the root view coordinates of subsequent `touchmove` touch locations don't reflect this scrolling at all, causing the event listener to try and move the `pageYOffset` in the *opposite* direction to compensate. This error then compounds very quickly, causing the scroll position to jump between min and max scroll positions on the page. To fix this, we make some adjustments to propagate the user's touch location relative to the viewport (unobscured content rect), and only map from the viewport back to root view coordinates at the last possible moment before dispatching the event by shifting the touch delta back up, using the main frame's current `contentsScrollPosition()`. See below for more details. * LayoutTests/fast/events/touch/ios/programmatic-scrolling-on-touchmove-expected.txt: Added. * LayoutTests/fast/events/touch/ios/programmatic-scrolling-on-touchmove.html: Added. Add a layout test to exercise the change, by swiping up in a reduced test case that emulates europa.eu's logic for scrolling in response to `touchmove`, and verifying that the scroll position always stays within reasonable limits. Without the fixes in this bug, the `pageYOffset` ends up bouncing between negative values and values of up to 2000-3000. * Source/WebCore/dom/ios/MouseEventIOS.cpp: (WebCore::MouseEvent::create): * Source/WebCore/dom/ios/PointerEventIOS.cpp: (WebCore::PointerEvent::PointerEvent): * Source/WebCore/page/PointerCaptureController.cpp: (WebCore::PointerCaptureController::dispatchEventForTouchAtIndex): * Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm: (WebCore::PlatformTouchPointBuilder::PlatformTouchPointBuilder): (WebCore::PlatformTouchEventBuilder::PlatformTouchEventBuilder): Pass `locationInViewport` through to `PlatformTouchPoint` on construction. This is optional since we currently don't compute this for `UIWebView` (WebKitLegacy). * Source/WebCore/platform/ios/ScrollAnimatorIOS.mm: Adjust call sites, since `touchLocationAtIndex` is now renamed to `touchLocationInRootViewAtIndex`. (WebCore::ScrollAnimatorIOS::handleTouchEvent): * Source/WebKit/Shared/WebEvent.serialization.in: * Source/WebKit/Shared/WebEventConversion.cpp: (WebKit::WebKit2PlatformTouchPoint::WebKit2PlatformTouchPoint): * Source/WebKit/Shared/WebTouchEvent.h: (WebKit::WebPlatformTouchPoint::WebPlatformTouchPoint): (WebKit::WebPlatformTouchPoint::locationInRootView const): (WebKit::WebPlatformTouchPoint::locationInViewport const): (WebKit::WebPlatformTouchPoint::location const): Deleted. Rename `location` to `locationInRootView` (along with other related members), and plumb a new `locationInViewport` point alongside the touch point. * Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm: (WebKit::NativeWebTouchEvent::extractWebTouchPoints): * Source/WebKit/UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::updateTouchEventTracking): * Source/WebKit/UIProcess/ios/WKContentViewInteraction.h: * Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm: Refactor `WKTouchEventsGestureRecognizer` to just directly take a `WKContentView`. Now that the touch events gesture no longer needs to be generic for both WebKitLegacy and modern WebKit, there's no benefit to maintaining a separate, WebKit-internal `WKTouchEventsGestureRecognizerDelegate` that is only implemented by the content view. This allows us to remove some unused code and unnecessary logic (such as the touch target and action selector, as well as `-isAnyTouchOverActiveArea:`), but importantly allows us to call into the web view to compute the unobscured content offset when determining the viewport-relative location for each `WKTouchPoint`. (-[WKContentView setUpInteraction]): (-[WKContentView _touchEventsRecognized]): (-[WKContentView _handleTouchActionsForTouchEvent:]): (-[WKContentView _shouldIgnoreTouchEvent:]): (-[WKContentView _touchEventsRecognized:]): Deleted. (-[WKContentView gestureRecognizer:shouldIgnoreTouchEvent:]): Deleted. (-[WKContentView isAnyTouchOverActiveArea:]): Deleted. * Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.h: * Source/WebKit/UIProcess/ios/WKTouchEventsGestureRecognizer.mm: (-[WKTouchEventsGestureRecognizer initWithContentView:]): (mapRootViewToViewport): Add a helper function to unadjust the given point in root view coordinates by the current unobscured content offset. (-[WKTouchEventsGestureRecognizer _touchEventForTouch:]): (-[WKTouchEventsGestureRecognizer _recordTouches:type:coalescedTouches:predictedTouches:]): Populate the new `locationInViewport` member on each touch point. (-[WKTouchEventsGestureRecognizer performAction]): (-[WKTouchEventsGestureRecognizer touchesBegan:withEvent:]): (-[WKTouchEventsGestureRecognizer initWithTarget:action:touchDelegate:]): Deleted. * Tools/TestWebKitAPI/Tests/ios/TouchEventTests.mm: Canonical link: https://commits.webkit.org/286448@main To unsubscribe from these emails, change your notification settings at https://github.com/WebKit/WebKit/settings/notifications _______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-changes