[webkit-changes] [WebKit/WebKit] 4faf2f: Stop using -[UIScrollView _setContentOffsetWithDec...

Wenson Hsieh noreply at github.com
Wed Oct 11 12:41:43 PDT 2023


  Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 4faf2f36c97b176fa72125a0c700e58e33d6bd7a
      https://github.com/WebKit/WebKit/commit/4faf2f36c97b176fa72125a0c700e58e33d6bd7a
  Author: Wenson Hsieh <wenson_hsieh at apple.com>
  Date:   2023-10-11 (Wed, 11 Oct 2023)

  Changed paths:
    M LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom.html
    M LayoutTests/fast/scrolling/ios/key-command-scroll-to-top-expected.html
    M LayoutTests/fast/scrolling/ios/key-command-scroll-to-top.html
    M Source/WebKit/Platform/spi/ios/UIKitSPI.h
    M Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h
    M Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
    M Source/WebKit/UIProcess/ios/WKKeyboardScrollingAnimator.mm
    M Tools/WebKitTestRunner/TestOptions.cpp
    M Tools/WebKitTestRunner/TestOptions.h
    M Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm
    M Tools/WebKitTestRunner/ios/TestControllerIOS.mm

  Log Message:
  -----------
  Stop using -[UIScrollView _setContentOffsetWithDecelerationAnimation:]
https://bugs.webkit.org/show_bug.cgi?id=262997
rdar://112474966

Reviewed by Tim Horton.

Refactor `WKKeyboardScrollingAnimator` to stop using `-_setContentOffsetWithDecelerationAnimation:`.
This is currently used to scroll to the start or end of the webpage using a spring animation that
loosely resembes exponential decay (i.e. the same animation that drives scrolling to the top when
tapping near the top of a `UIScrollView`).

This pulls that same `CASpringAnimation` into WebKit, and scrolls the scroll view using that
animation. Since it's not currently possible to directly drive animated scrolling in a `UIScrollView`
with a custom `CAAnimation`, we instead:

1.  Create a hidden, 0 by 0 `UIView` and add it to the view hierarchy under the scroll view.
2.  Add our spring animation to the `UIView`'s layer, and use it to animate the `position` property.
    The animation starts the `position` off at the scroll view's content offset, and ends with the
    `position` at the target content offset. This allows us to...
3.  Use the existing `CADisplayLink` that drives normal smooth keyboard scrolling to synchronize
    the `position` as it animates, such that the scroll view scrolls using the same animation curve
    as it would when using `-_setContentOffsetWithDecelerationAnimation:`.

* LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom.html:
* LayoutTests/fast/scrolling/ios/key-command-scroll-to-top-expected.html:
* LayoutTests/fast/scrolling/ios/key-command-scroll-to-top.html:

Adjust a couple of layout tests to continue passing after these changes:

•   We need to suppress scroll view indicators for this test, so that they don't show up in the ref
    image. Currently, we flash scrollbars at the beginning of the scroll, such that they fade out by
    the time keyboard scrolling is complete. After this change, we'll start the fade animation only
    after scrolling finishes, which causes the scroll bar to linger around for longer than the hard-
    coded 1000 ms timeout.

•   We also need to actually wait for the keyboard scrolling animation to complete. Currently, this
    Just Works because the hard-coded 1000 ms delay that waits for the scroll indicators to fade out
    also ensures that the scrolling animation completes. Removing this timeout while suppressing
    scrollbars therefore causes the test to still fail, due to subpixel differences since the scroll
    position is rounded to 0, when the scroll view is actually < 0.5 pt away from the top. Fix this
    by teaching `UIHelper.waitForZoomingOrScrollingToEnd()` about keyboard scrolling animations, via
    a new testing-only SPI hook on `WKWebView`, and then adjusting the layout tests to complete only
    after the `waitForZoomingOrScrollingToEnd()` promise resolves.

* Source/WebKit/Platform/spi/ios/UIKitSPI.h:

Remove now-unused SPI declarations. Also clean up a couple of existing SPI declarations, by moving
them to the SPI section (out of the IPI section).

* Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView _isKeyboardScrollingAnimationRunning]):

Add a new test-only SPI property to return whether or not a keyboard scrolling animation is running.

* Source/WebKit/UIProcess/ios/WKContentViewInteraction.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView keyboardScrollViewAnimatorWillScroll:]):
(-[WKContentView keyboardScrollViewAnimatorDidFinishScrolling:]):
(-[WKContentView isKeyboardScrollingAnimationRunning]):
* Source/WebKit/UIProcess/ios/WKKeyboardScrollingAnimator.mm:
(-[WKKeyboardScrollingAnimator invalidate]):
(-[WKKeyboardScrollingAnimator beginWithEvent:]):

Instead of delegating document granularity scrolling to `WKKeyboardScrollViewAnimator`, drive this
(mostly) in `WKKeyboardScrollingAnimator` using the above strategy.

(-[WKKeyboardScrollingAnimator willStartInteractiveScroll]):
(-[WKKeyboardScrollingAnimator resetViewForScrollToExtentAnimation]):
(-[WKKeyboardScrollingAnimator stopScrollingImmediately]):
(-[WKKeyboardScrollingAnimator displayLinkFired:]):

Drive the animation by setting the scroller's content offset based on the animation tracking view's
position. Note that we need a null check for the `presentationLayer` here, since the first
`CADisplayLink` tick after starting the animation sometimes fires when the `presentationLayer` is
still `nil`, which would otherwise cause us to stutter to (0, 0) before animating.

(-[WKKeyboardScrollViewAnimator willBeginScrollingToExtentWithAnimationInTrackingView:]):

Since the `WKKeyboardScrollViewAnimator` no longer drives the "scroll to extent" animation, rename
this method and have it simply install the tracking view in the view hierarchy, under the
`UIScrollView`.

(-[WKKeyboardScrollViewAnimator scrollWithScrollToExtentAnimationTo:]): Deleted.
* Tools/WebKitTestRunner/TestOptions.cpp:
(WTR::TestOptions::defaults):
(WTR::TestOptions::keyTypeMapping):
* Tools/WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::showsScrollIndicators const):

Add a new test option to set whether or not scroll indicators should be shown during the test
(defaults to true, to match behavior of a normal `WKWebView`).

* Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView isZoomingOrScrolling]):

Teach this to take animated keyboard scrolling into account by using the new
`-_isKeyboardScrollingAnimationRunning` test hook.

* Tools/WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):

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




More information about the webkit-changes mailing list