Title: [278559] trunk
Revision
278559
Author
[email protected]
Date
2021-06-07 06:26:39 -0700 (Mon, 07 Jun 2021)

Log Message

[iOS] Unexpected scrolling when switching focus from a text input to a select element
https://bugs.webkit.org/show_bug.cgi?id=226657
<rdar://problem/78290515>

Reviewed by Tim Horton.

Source/WebKit:

When switching focus from a text input to a select element, UIKit makes
deferred calls to `-[WKWebView inputView]` after the keyboard dismissal.
This method calls `-[WKContentView inputViewForWebView]`, which calls
`-[WKContentView _zoomToRevealFocusedElement]`. Consequently, these
methods can get invoked while the context menu (dropdown) is displayed
for a focused select element.

In this instance, the call should be idempotent, since the focused element
is fully visible in the viewport. However, since the context menu is visible
and overlaps the element, our logic incorrectly determines that the element
is obscured, leading to unexpected zooming/scrolling. To fix, we need to
correct the logic that determines the visible portion of the view.

Test: fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html

* UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]):

Always use the window to determine the portion of the webview that is
visible, rather than relying on the root view controller's top-most
full-screen view controller's view.

The old logic worked fine in most cases, since the root view controller
and the top-most full-screen view controller are almost always the same.
Furthermore, the root view controller's view usually takes up the entire
window.

However, when the context menu is on screen, the top-most full-screen
view controller is an internal UIKit view controller
(_UIContextMenuActionsOnlyViewController), and the associated view
is the context menu view. This exposed a flaw in the existing logic, as
visibility detection could be performed by intersecting with an
incorrect view. In general, the top-most full-screen view is not a
reliable way to determine the visible portion of the webview.

LayoutTests:

Add a layout test to exercise the bug.

* fast/forms/ios/form-control-refresh/select/focus-select-after-textfield-expected.txt: Added.
* fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (278558 => 278559)


--- trunk/LayoutTests/ChangeLog	2021-06-07 11:45:59 UTC (rev 278558)
+++ trunk/LayoutTests/ChangeLog	2021-06-07 13:26:39 UTC (rev 278559)
@@ -1,3 +1,16 @@
+2021-06-07  Aditya Keerthi  <[email protected]>
+
+        [iOS] Unexpected scrolling when switching focus from a text input to a select element
+        https://bugs.webkit.org/show_bug.cgi?id=226657
+        <rdar://problem/78290515>
+
+        Reviewed by Tim Horton.
+
+        Add a layout test to exercise the bug.
+
+        * fast/forms/ios/form-control-refresh/select/focus-select-after-textfield-expected.txt: Added.
+        * fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html: Added.
+
 2021-06-06  Darin Adler  <[email protected]>
 
         Handle custom identifiers and strings separately, so we can quote strings correctly consistently

Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield-expected.txt (0 => 278559)


--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield-expected.txt	2021-06-07 13:26:39 UTC (rev 278559)
@@ -0,0 +1,11 @@
+This test verifies that tapping on a text input and then tapping on a select element does not unexpectedly change the scrolling position.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.scrollingElement.scrollTop is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+

Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html (0 => 278559)


--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html	2021-06-07 13:26:39 UTC (rev 278559)
@@ -0,0 +1,36 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true IOSFormControlRefreshEnabled=true ] -->
+<html>
+    <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+        <script src=""
+        <script src=""
+    </head>
+<body>
+<input id="text">
+<br>
+<select id="select">
+    <option>A</option>
+    <option>B</option>
+    <option>C</option>
+</select>
+<div style="margin-top: 2000px;" id="bottom">Bottom</div>
+</body>
+<script>
+jsTestIsAsync = true;
+
+addEventListener("load", async () => {
+    description("This test verifies that tapping on a text input and then tapping on a select element does not unexpectedly change the scrolling position.");
+
+    await UIHelper.activateElement(text);
+    await UIHelper.activateElement(select);
+    await UIHelper.waitForContextMenuToShow();
+    await UIHelper.selectFormAccessoryPickerRow(0);
+    await UIHelper.waitForContextMenuToHide();
+
+    shouldBeEqualToNumber("document.scrollingElement.scrollTop", 0);
+
+    bottom.remove();
+    finishJSTest();
+});
+</script>
+</html>

Modified: trunk/Source/WebKit/ChangeLog (278558 => 278559)


--- trunk/Source/WebKit/ChangeLog	2021-06-07 11:45:59 UTC (rev 278558)
+++ trunk/Source/WebKit/ChangeLog	2021-06-07 13:26:39 UTC (rev 278559)
@@ -1,3 +1,46 @@
+2021-06-07  Aditya Keerthi  <[email protected]>
+
+        [iOS] Unexpected scrolling when switching focus from a text input to a select element
+        https://bugs.webkit.org/show_bug.cgi?id=226657
+        <rdar://problem/78290515>
+
+        Reviewed by Tim Horton.
+
+        When switching focus from a text input to a select element, UIKit makes
+        deferred calls to `-[WKWebView inputView]` after the keyboard dismissal.
+        This method calls `-[WKContentView inputViewForWebView]`, which calls
+        `-[WKContentView _zoomToRevealFocusedElement]`. Consequently, these
+        methods can get invoked while the context menu (dropdown) is displayed
+        for a focused select element.
+
+        In this instance, the call should be idempotent, since the focused element
+        is fully visible in the viewport. However, since the context menu is visible
+        and overlaps the element, our logic incorrectly determines that the element
+        is obscured, leading to unexpected zooming/scrolling. To fix, we need to
+        correct the logic that determines the visible portion of the view.
+
+        Test: fast/forms/ios/form-control-refresh/select/focus-select-after-textfield.html
+
+        * UIProcess/API/ios/WKWebViewIOS.mm:
+        (-[WKWebView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]):
+
+        Always use the window to determine the portion of the webview that is
+        visible, rather than relying on the root view controller's top-most
+        full-screen view controller's view.
+
+        The old logic worked fine in most cases, since the root view controller
+        and the top-most full-screen view controller are almost always the same.
+        Furthermore, the root view controller's view usually takes up the entire
+        window.
+
+        However, when the context menu is on screen, the top-most full-screen
+        view controller is an internal UIKit view controller
+        (_UIContextMenuActionsOnlyViewController), and the associated view
+        is the context menu view. This exposed a flaw in the existing logic, as
+        visibility detection could be performed by intersecting with an
+        incorrect view. In general, the top-most full-screen view is not a
+        reliable way to determine the visible portion of the webview.
+
 2021-06-07  Carlos Garcia Campos  <[email protected]>
 
         [GTK][WPE] Signal "window-object-cleared" not emitted unless frame js context is get before

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (278558 => 278559)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-06-07 11:45:59 UTC (rev 278558)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-06-07 13:26:39 UTC (rev 278559)
@@ -106,11 +106,6 @@
 - (BOOL)_isHostedInAnotherProcess;
 @end
 
-@interface UIViewController (UIViewControllerInternal)
-- (UIViewController *)_rootAncestorViewController;
-- (UIViewController *)_viewControllerForSupportedInterfaceOrientations;
-@end
-
 @implementation WKWebView (WKViewInternalIOS)
 
 - (void)setFrame:(CGRect)frame
@@ -1237,14 +1232,8 @@
 
     UIWindow *window = [_scrollView window];
 
-    // Find the portion of the view that is visible on the screen.
-    UIViewController *topViewController = [[[_scrollView _viewControllerForAncestor] _rootAncestorViewController] _viewControllerForSupportedInterfaceOrientations];
-    UIView *fullScreenView = topViewController.view;
-    if (!fullScreenView)
-        fullScreenView = window;
-
     CGRect unobscuredScrollViewRectInWebViewCoordinates = UIEdgeInsetsInsetRect([self bounds], _obscuredInsets);
-    CGRect visibleScrollViewBoundsInWebViewCoordinates = CGRectIntersection(unobscuredScrollViewRectInWebViewCoordinates, [fullScreenView convertRect:[fullScreenView bounds] toView:self]);
+    CGRect visibleScrollViewBoundsInWebViewCoordinates = CGRectIntersection(unobscuredScrollViewRectInWebViewCoordinates, [window convertRect:window.bounds toView:self]);
     CGRect formAssistantFrameInWebViewCoordinates = [window convertRect:_inputViewBoundsInWindow toView:self];
     CGRect intersectionBetweenScrollViewAndFormAssistant = CGRectIntersection(visibleScrollViewBoundsInWebViewCoordinates, formAssistantFrameInWebViewCoordinates);
     CGSize visibleSize = visibleScrollViewBoundsInWebViewCoordinates.size;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to