Skip to content

Commit 13e748d

Browse files
committed
REGRESSION(308209@main): Top and bottom fixed position elements flicker when rubber band scrolling
https://bugs.webkit.org/show_bug.cgi?id=315320 rdar://176226179 Reviewed by Tim Horton. When we throttle visible content rect updates to the WebContent process, we will still update layer positions and scrolling tree state in the UI process. However, we were missing one change that the full unthrottled path does which is to update the WKContentView's fixed clipping view bounds. Stale data here leads to fixed positioned elements flickering when doing a rubber band scroll while changing obscured insets interactively in iOS Safari. Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/ios/WKScrollViewTests.mm * Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm: (-[WKWebView _updateViewportRelativeLayersOutOfBand]): * Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h: * Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm: (-[WKWebView _fixedClippingViewBoundsForTesting]): * Source/WebKit/UIProcess/ios/WKContentView.h: * Source/WebKit/UIProcess/ios/WKContentView.mm: (-[WKContentView _fixedClippingViewBoundsForTesting]): * Tools/TestWebKitAPI/Tests/WebKit/WKWebView/ios/WKScrollViewTests.mm: (TestWebKitAPI::(WKScrollViewTests, FixedClippingViewTracksRubberBandDuringInteractiveObscuredInsetsChange)): Canonical link: https://commits.webkit.org/313759@main
1 parent 8480ae3 commit 13e748d

6 files changed

Lines changed: 54 additions & 0 deletions

File tree

Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3173,6 +3173,7 @@ - (void)_updateViewportRelativeLayersOutOfBand
31733173
_page->updateVisibleContentRectsLocally(*info);
31743174
auto layoutViewport = _page->unconstrainedLayoutViewportRect();
31753175
_page->adjustLayersForLayoutViewport(_page->unobscuredContentRect().location(), layoutViewport, _page->displayedContentScale());
3176+
[_contentView updateFixedClippingView:layoutViewport];
31763177
}
31773178
}
31783179

Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
- (UIView *)_colorExtensionViewForTesting:(UIRectEdge)edge;
105105

106106
@property (nonatomic, readonly) BOOL _hasPendingVisibleContentRectUpdateTimerForTesting;
107+
@property (nonatomic, readonly) CGRect _fixedClippingViewBoundsForTesting;
107108

108109
@end
109110

Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@ - (BOOL)_hasPendingVisibleContentRectUpdateTimerForTesting
553553
return _pendingInteractiveObscuredInsetsChangeTimer && _pendingInteractiveObscuredInsetsChangeTimer->isActive();
554554
}
555555

556+
- (CGRect)_fixedClippingViewBoundsForTesting
557+
{
558+
return [_contentView _fixedClippingViewBoundsForTesting];
559+
}
560+
556561
@end
557562

558563
#endif // PLATFORM(IOS_FAMILY)

Source/WebKit/UIProcess/ios/WKContentView.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ using LayerHostingContextID = uint32_t;
7878

7979
- (void)didUpdateVisibleRect:(const WebKit::VisibleContentRectUpdateInfo &)visibleContentRectUpdateInfo sendEvenIfUnchanged:(BOOL)sendEvenIfUnchanged;
8080

81+
- (void)updateFixedClippingView:(WebCore::FloatRect)fixedPositionRectForUI;
82+
- (CGRect)_fixedClippingViewBoundsForTesting;
83+
8184
- (void)didFinishScrolling;
8285
- (void)didZoomToScale:(CGFloat)scale;
8386
- (void)willStartZoomOrScroll;

Source/WebKit/UIProcess/ios/WKContentView.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,11 @@ - (void)updateFixedClippingView:(WebCore::FloatRect)fixedPositionRectForUI
611611
[_rootContentView setBounds:clippingBounds];
612612
}
613613

614+
- (CGRect)_fixedClippingViewBoundsForTesting
615+
{
616+
return [_fixedClippingView bounds];
617+
}
618+
614619
- (void)_didExitStableState
615620
{
616621
_needsDeferredEndScrollingSelectionUpdate = self.shouldHideSelectionInFixedPositionWhenScrolling;

Tools/TestWebKitAPI/Tests/WebKit/WKWebView/ios/WKScrollViewTests.mm

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,45 @@ HTTPServer server({
13071307
EXPECT_LE(maxDeviation, 2);
13081308
}
13091309

1310+
TEST(WKScrollViewTests, FixedClippingViewTracksRubberBandDuringInteractiveObscuredInsetsChange)
1311+
{
1312+
RetainPtr webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 800)]);
1313+
1314+
auto insets = UIEdgeInsetsMake(50, 0, 0, 0);
1315+
[webView _setObscuredInsets:insets];
1316+
RetainPtr scrollView = [webView scrollView];
1317+
[scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
1318+
[scrollView setContentInset:insets];
1319+
1320+
[webView synchronouslyLoadTestPageNamed:@"simple-tall"];
1321+
[webView waitForNextPresentationUpdate];
1322+
1323+
// Park past home so the upcoming scroll is itself a rubber-band frame, not a mode transition.
1324+
[scrollView setContentOffset:CGPointMake(0, -100)];
1325+
[webView waitForNextVisibleContentRectUpdate];
1326+
1327+
[webView _beginInteractiveObscuredInsetsChange];
1328+
1329+
// Drive a deeper rubber-band scroll.
1330+
[scrollView setContentOffset:CGPointMake(0, -150)];
1331+
[webView waitForNextPresentationUpdate];
1332+
1333+
// The clip view's bounds origin should track the current unobscured content rect's Y
1334+
// (= scrollOffset.y + topInset = -100), even while updates to WebContent are throttled.
1335+
CGRect clipBounds = [webView _fixedClippingViewBoundsForTesting];
1336+
EXPECT_NEAR(clipBounds.origin.y, -100.0, 1.0);
1337+
1338+
// Drive another rubber-band step within the visible content rect throttle window to confirm we keep
1339+
// updating the clip rect frame-to-frame, not only on the first throttled frame.
1340+
[scrollView setContentOffset:CGPointMake(0, -200)];
1341+
[webView waitForNextPresentationUpdate];
1342+
1343+
clipBounds = [webView _fixedClippingViewBoundsForTesting];
1344+
EXPECT_NEAR(clipBounds.origin.y, -150.0, 1.0);
1345+
1346+
[webView _endInteractiveObscuredInsetsChange];
1347+
}
1348+
13101349
} // namespace TestWebKitAPI
13111350

13121351
#endif // PLATFORM(IOS_FAMILY)

0 commit comments

Comments
 (0)