[webkit-changes] [WebKit/WebKit] e8b8f7: Stop using SPI: -_scrollView:adjustedOffsetForOffs...

Wenson Hsieh noreply at github.com
Mon Nov 27 14:08:26 PST 2023


  Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: e8b8f75b41b3d873fb5aadda2df4da3f1d744f8d
      https://github.com/WebKit/WebKit/commit/e8b8f75b41b3d873fb5aadda2df4da3f1d744f8d
  Author: Wenson Hsieh <wenson_hsieh at apple.com>
  Date:   2023-11-27 (Mon, 27 Nov 2023)

  Changed paths:
    M Source/WebKit/SourcesCocoa.txt
    M Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h
    M Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm
    M Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h
    M Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
    A Source/WebKit/UIProcess/ios/WKAxisLockingScrollView.h
    A Source/WebKit/UIProcess/ios/WKAxisLockingScrollView.mm
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
    M Source/WebKit/UIProcess/ios/WKVelocityTrackingScrollView.h
    M Source/WebKit/WebKit.xcodeproj/project.pbxproj

  Log Message:
  -----------
  Stop using SPI: -_scrollView:adjustedOffsetForOffset:translation:startPoint:horizontalVelocity:verticalVelocity:
https://bugs.webkit.org/show_bug.cgi?id=265215
rdar://118696702

Reviewed by Megan Gardner.

Move off of the private `UIScrollViewDelegate` method `-_scrollView:adjustedOffsetForOffset:…:`,
which allows clients to retarget the would-be target content offset right before a pan gesture (or
pan-gesture-induced momentum scrolling). We currently use this to implement `touch-action: pan-x|y`
by retargeting the content offset such that the `x` or `y` offsets are locked to their initial
values at the start of scrolling, which has the effect of locking pan-gesture-based scrolling to a
single axis.

To achieve the same effect without adopting any scroll view SPI, we can instead create and deploy a
new scroll view subclass, `WKAxisLockingScrollView`, which allows clients, in the form of a
`WKAxisLockingScrollViewDelegate`, to choose which axis to prevent scrolling during a pan gesture by
returning `UIAxisHorizontal` and/or `UIAxisVertical` in a new internal delegate method. For example,
we return `UIAxisVertical` to prevent scrolling in the y-axis, when `pan-x` is specified (and vice-
versa for `pan-y`).

To implement this subclass, we:

1.  Add our own pan gesture recognizer (the "axis locking pan gesture") to the scroll view, right as
    UIKit is about to add the built-in `UIScrollViewPanGestureRecognizer`. The order in which these
    two gestures are added to the scroll view is important, since this guarantees that the gesture
    action for the axis locking pan gesture will always fire right before the scroll view's default
    scrolling pan gesture.

2.  We build on this by calling out to the axis locking delegate to get the set of axes to prevent
    scrolling and use this information to call `-[UIPanGestureRecognizer setTranslation:inView:]` on
    the scroll view's built-in pan gesture recognizer, zeroing out either the `x` or `y` component
    of the translation (depending on what the delegate method returned). This allows us to make
    UIKit behave as if the user was scrolling perfectly along the x or y axis upon converting the
    pan gesture translation amount into scroll deltas, using the built-in pan gesture recognizer.

* Source/WebKit/SourcesCocoa.txt:
* Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h:
* Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView _setupScrollAndContentViews]):
(-[WKWebView scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
(-[WKWebView axesToPreventScrollingForPanGestureInScrollView:]):
(-[WKWebView _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]): Deleted.

Delete this SPI delegate method implementation, and instead move the corresponding logic into the
new `-axesToPreventScrollingForPanGestureInScrollView:` delegate method.

* Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h:

Make `WKChildScrollView` subclass the new `WKAxisLockingScrollView`.

* Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
(-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):

Because the new `-axesToPreventScrollingForPanGestureInScrollView:` delegate method isn't called
after scrolling ends, we need a separate mechanism in order to limit momentum scrolling to the
locked scrolling axis. Achieve this by keeping track of the axes where we prevented scrolling in the
`WKAxisLockingScrollView` during the pan gesutre, and then use public scroll view delegate API to
retarget the default scrolling destination to the current offset value, effectively canceling out
any momentum scrolling in that axis.

(-[WKScrollingNodeScrollViewDelegate axesToPreventScrollingForPanGestureInScrollView:]):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren):
(-[WKScrollingNodeScrollViewDelegate _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]): Deleted.

Same as above; move this logic into `-axesToPreventScrollingForPanGestureInScrollView:` to service
the overflow scrolling case.

* Source/WebKit/UIProcess/ios/WKAxisLockingScrollView.h: Copied from Source/WebKit/UIProcess/ios/WKVelocityTrackingScrollView.h.
* Source/WebKit/UIProcess/ios/WKAxisLockingScrollView.mm: Added.
(-[WKAxisLockingScrollView initWithFrame:]):
(-[WKAxisLockingScrollView addGestureRecognizer:]):
(-[WKAxisLockingScrollView removeGestureRecognizer:]):
(-[WKAxisLockingScrollView _updatePanGestureToPreventScrolling]):
(-[WKAxisLockingScrollView _axesToPreventScrollingFromDelegate]):
(-[WKAxisLockingScrollView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKAxisLockingScrollView gestureRecognizerShouldBegin:]):

Add the new internal scroll view subclass; see above for more details.

* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView setUpInteraction]):

(Drive-by): give these `_touchAction*SwipeGestureRecognizer`s human-readable names, so that they're
easier to identify and debug.

* Source/WebKit/UIProcess/ios/WKVelocityTrackingScrollView.h:

Make the velocity tracking scroll view subclass `WKAxisLockingScrollView` (`WKScrollView`, in turn,
subclasses this).

* Source/WebKit/WebKit.xcodeproj/project.pbxproj:

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




More information about the webkit-changes mailing list