[iOS] REGRESSION: Tapping a <select> element does not show a menu on many websites
authorakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Jul 2021 23:30:41 +0000 (23:30 +0000)
committerakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Jul 2021 23:30:41 +0000 (23:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=228340
rdar://77137768

Reviewed by Wenson Hsieh.

Source/WebKit:

Many sites add a touchend event listener to their select elements, that
is responsible for focusing the element. With the introduction of
asynchronous touch events, the single tap gesture recognizer can be
deferred to the point it occurs after the UIProcess is notified that an
element has been focused. This is problematic, since the UIProcess
creates and displays inputs peripherals in response to element focus,
but the gesture recognizer can dismiss presented peripherals via
`-[WKFormPeripheral endEditing]`. Consequently, many sites immediately
display and dismiss the input peripheral.

To fix, only call `-[WKFormPeripheral endEditing]` if the peripheral
was already being displayed once the tap gesture began. This ensures we
do not immediately display and dismiss peripherals.

Note that with the redesigned form controls, the call to `endEditing` is
unnecessary, as the presented views handle their own dismissal. However,
the logic is still needed for the old select control (using a keyboard
input view), to commit value changes. The old control is displayed on
apps linked against iOS 13 or earlier. This behavior is tested in
fast/forms/ios/select-picker-change-and-focus-another-select.html.

Test: fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapIdentified:]):
(-[WKContentView _singleTapRecognized:]):
* UIProcess/ios/forms/WKFormPeripheral.h:
* UIProcess/ios/forms/WKFormPeripheralBase.h:

LayoutTests:

Added a test to verify that tapping a select element, that focuses itself
inside a touchend listener, displays a menu.

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

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@280359 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/forms/WKFormPeripheral.h
Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.h

index f2c87aa4114da666fccd40157907095fd8c94d70..a03fcb4aade6419198919f5f3b05f1a78e46d50c 100644 (file)
@@ -1,3 +1,17 @@
+2021-07-27  Aditya Keerthi  <akeerthi@apple.com>
+
+        [iOS] REGRESSION: Tapping a <select> element does not show a menu on many websites
+        https://bugs.webkit.org/show_bug.cgi?id=228340
+        rdar://77137768
+
+        Reviewed by Wenson Hsieh.
+
+        Added a test to verify that tapping a select element, that focuses itself
+        inside a touchend listener, displays a menu.
+
+        * fast/forms/ios/form-control-refresh/select/focus-select-in-touchend-expected.txt: Added.
+        * fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html: Added.
+
 2021-07-27  Ayumi Kojima  <ayumi_kojima@apple.com>
 
         [ iOS ] media/track/track-in-band-duplicate-tracks-when-source-changes.html is a flaky timeout.
diff --git a/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend-expected.txt b/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend-expected.txt
new file mode 100644 (file)
index 0000000..a6b623b
--- /dev/null
@@ -0,0 +1,11 @@
+This test verifies that a dropdown menu is displayed, and can be interacted with, after tapping on a select element that focuses itself inside a touchend listener.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS select.value is "January"
+PASS select.value is "April"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html b/LayoutTests/fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html
new file mode 100644 (file)
index 0000000..92759cb
--- /dev/null
@@ -0,0 +1,44 @@
+<!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="../../../../../resources/js-test.js"></script>
+        <script src="../../../../../resources/ui-helper.js"></script>
+    </head>
+<body>
+<select id="select">
+    <option>January</option>
+    <option>February</option>
+    <option>March</option>
+    <option>April</option>
+    <option>May</option>
+    <option>June</option>
+    <option>July</option>
+    <option>August</option>
+    <option>September</option>
+    <option>October</option>
+    <option>November</option>
+    <option>December</option>
+</select>
+</body>
+<script>
+jsTestIsAsync = true;
+
+addEventListener("load", async () => {
+    description("This test verifies that a dropdown menu is displayed, and can be interacted with, after tapping on a select element that focuses itself inside a touchend listener.");
+
+    select.addEventListener("touchend", event => {
+        select.focus();
+    });
+
+    shouldBeEqualToString("select.value", "January");
+    await UIHelper.activateElement(select);
+    await UIHelper.waitForContextMenuToShow();
+    await UIHelper.selectFormAccessoryPickerRow(3);
+    await UIHelper.waitForContextMenuToHide();
+    shouldBeEqualToString("select.value", "April");
+
+    finishJSTest();
+});
+</script>
+</html>
index c918fe56e915f77616c914bf1197a21d8352fbdd..41230cab2b64f11b1c9e89caa863b3c00889c7cd 100644 (file)
@@ -1,3 +1,40 @@
+2021-07-27  Aditya Keerthi  <akeerthi@apple.com>
+
+        [iOS] REGRESSION: Tapping a <select> element does not show a menu on many websites
+        https://bugs.webkit.org/show_bug.cgi?id=228340
+        rdar://77137768
+
+        Reviewed by Wenson Hsieh.
+
+        Many sites add a touchend event listener to their select elements, that
+        is responsible for focusing the element. With the introduction of
+        asynchronous touch events, the single tap gesture recognizer can be
+        deferred to the point it occurs after the UIProcess is notified that an
+        element has been focused. This is problematic, since the UIProcess
+        creates and displays inputs peripherals in response to element focus,
+        but the gesture recognizer can dismiss presented peripherals via
+        `-[WKFormPeripheral endEditing]`. Consequently, many sites immediately
+        display and dismiss the input peripheral.
+
+        To fix, only call `-[WKFormPeripheral endEditing]` if the peripheral
+        was already being displayed once the tap gesture began. This ensures we
+        do not immediately display and dismiss peripherals.
+
+        Note that with the redesigned form controls, the call to `endEditing` is
+        unnecessary, as the presented views handle their own dismissal. However,
+        the logic is still needed for the old select control (using a keyboard
+        input view), to commit value changes. The old control is displayed on
+        apps linked against iOS 13 or earlier. This behavior is tested in
+        fast/forms/ios/select-picker-change-and-focus-another-select.html.
+
+        Test: fast/forms/ios/form-control-refresh/select/focus-select-in-touchend.html
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _singleTapIdentified:]):
+        (-[WKContentView _singleTapRecognized:]):
+        * UIProcess/ios/forms/WKFormPeripheral.h:
+        * UIProcess/ios/forms/WKFormPeripheralBase.h:
+
 2021-07-27  Peng Liu  <peng.liu6@apple.com>
 
         Safari hangs when entering PiP from (element) fullscreen
index 01ebf392bb94782529577fd91c8564f3d1fb7dd5..99a2c1955180ed0400294917a01a353d6dc9766c 100644 (file)
@@ -3072,6 +3072,8 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     ASSERT(!_potentialTapInProgress);
     [self _resetIsDoubleTapPending];
 
+    [_inputPeripheral setSingleTapShouldEndEditing:[_inputPeripheral isEditing]];
+
     bool shouldRequestMagnificationInformation = _page->preferences().fasterClicksEnabled();
     if (shouldRequestMagnificationInformation)
         RELEASE_LOG(ViewGestures, "Single tap identified. Request details on potential zoom. (%p)", self);
@@ -3162,7 +3164,8 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
         _hasTapHighlightForPotentialTap = NO;
     }
 
-    [_inputPeripheral endEditing];
+    if ([_inputPeripheral singleTapShouldEndEditing])
+        [_inputPeripheral endEditing];
 
     RELEASE_LOG(ViewGestures, "Single tap recognized - commit potential tap (%p)", self);
 
index b1812be442f22c9f5713091be4f6b7329ca3ea02..43384a9893ddb9bcee7d0288ec48f3fcb767a919 100644 (file)
 @class UIView;
 
 @protocol WKFormPeripheral
+- (BOOL)isEditing;
 - (void)beginEditing;
 - (void)endEditing;
 - (UIView *)assistantView;
 @optional
 - (BOOL)handleKeyEvent:(UIEvent *)event;
+@property (nonatomic) BOOL singleTapShouldEndEditing;
 @end
 
 @protocol WKFormControl
index 46860730d84a830ec25fd08ba1873a5ed95d49ed..d2696b256ee6f5ab9c43f7833a1773117f73f101 100644 (file)
@@ -44,6 +44,7 @@
 @property (nonatomic, readonly) WKContentView *view;
 @property (nonatomic, readonly) NSObject <WKFormControl> *control;
 @property (nonatomic, readonly, getter=isEditing) BOOL editing;
+@property (nonatomic) BOOL singleTapShouldEndEditing;
 
 @end