Title: [264187] trunk
Revision
264187
Author
[email protected]
Date
2020-07-09 12:46:09 -0700 (Thu, 09 Jul 2020)

Log Message

REGRESSION (r259840): Pressing Esc or ⌘+"." does not dismiss time picker on iOS
https://bugs.webkit.org/show_bug.cgi?id=214122
<rdar://problem/64940487>

Reviewed by Tim Horton.

Source/WebKit:

Prior to r259840, when presenting context menus for certain input types (i.e. "time" and "datetime-local") on
iOS, UIKit would tell the presented view controller's view (a `UIDatePicker` in this case) to become first
responder. As a result, `WKContentView` would resign first responder, which (by default) blurs the focused
element and dismisses the context menu. The result is thats time pickers would immediately dismiss upon
presentation.

To mitigate this, r259840 adopted the existing active focus retaining mechanism to temporarily decouple
WKContentView's first responder status from the currently focused form element. However, this also causes
`-endEditingAndUpdateFocusAppearanceWithReason:` to bail, due to `self.webView._retainingActiveFocusedState`
returning `YES`. This means that codepaths meant to immediately dismiss UI for the focused element (for example,
when pressing Escape on a hardware keyboard on iOS) will not be able to dismiss UI.

To fix this, push the flag that keeps track of whether we're relinquishing first responder to the focused
element down into `WKContentView`, and have `WKContentView` automatically stop relinquishing first responder to
the focused element in `-[WKContentView accessoryDone]`.

Fixes an existing test: fast/forms/ios/dismiss-picker-using-keyboard.html

* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView accessoryDone]):

Stop relinquishing focus to the focused element, so that form elements that require first responder can be
dismissed when triggering `-accessoryDone` (e.g. when pressing the Esc key on a hardware keyboard).

(-[WKContentView startRelinquishingFirstResponderToFocusedElement]):
(-[WKContentView stopRelinquishingFirstResponderToFocusedElement]):

Renamed from `-preserveFocus` and `-releaseFocus`, respectively. Also, made these methods idempotent using a new
`BOOL` flag, `_isRelinquishingFirstResponderToFocusedElement`.

(-[WKContentView preserveFocus]): Deleted.
(-[WKContentView releaseFocus]): Deleted.
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker controlBeginEditing]):
(-[WKDateTimePicker controlEndEditing]):

Use the renamed WKContentView methods, and also remove the `_preservingFocus` flag.

* UIProcess/ios/forms/WKFormPopover.mm:
(-[WKRotatingPopover presentPopoverAnimated:]):
(-[WKRotatingPopover dismissPopoverAnimated:]):

Use the renamed WKContentView methods.

LayoutTests:

* fast/forms/ios/dismiss-picker-using-keyboard.html:
* fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html:
* fast/forms/ios/time-picker-value-change-expected.txt:
* fast/forms/ios/time-picker-value-change.html:

Adjust a few layout tests to be compatible with date and time inputs.

* resources/ui-helper.js:
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (264186 => 264187)


--- trunk/LayoutTests/ChangeLog	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/ChangeLog	2020-07-09 19:46:09 UTC (rev 264187)
@@ -1,3 +1,22 @@
+2020-07-09  Wenson Hsieh  <[email protected]>
+
+        REGRESSION (r259840): Pressing Esc or ⌘+"." does not dismiss time picker on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=214122
+        <rdar://problem/64940487>
+
+        Reviewed by Tim Horton.
+
+        * fast/forms/ios/dismiss-picker-using-keyboard.html:
+        * fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html:
+        * fast/forms/ios/time-picker-value-change-expected.txt:
+        * fast/forms/ios/time-picker-value-change.html:
+
+        Adjust a few layout tests to be compatible with date and time inputs.
+
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
+        (window.UIHelper.waitForInputSessionToDismiss):
+
 2020-07-09  Truitt Savell  <[email protected]>
 
         REGRESSION (r264117): [ Mac iOS ] imported/w3c/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html

Modified: trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html (264186 => 264187)


--- trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html	2020-07-09 19:46:09 UTC (rev 264187)
@@ -1,5 +1,6 @@
-<!DOCTYPE html>
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
 <html>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
 <head>
 <script src=""
 <script src=""
@@ -69,7 +70,7 @@
             debug(`<br>For ${elementToTest.dataset.testName}:`);
             let expectedValue = elementToTest.value;
             await UIHelper.activateElementAndWaitForInputSession(elementToTest);
-            UIHelper.keyDown(keyCommand.key, keyCommand.modifiers);
+            await UIHelper.keyDown(keyCommand.key, keyCommand.modifiers);
             await UIHelper.waitForInputSessionToDismiss();
             shouldBeEqualToString("elementToTest.value", expectedValue);
         }

Modified: trunk/LayoutTests/fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html (264186 => 264187)


--- trunk/LayoutTests/fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html	2020-07-09 19:46:09 UTC (rev 264187)
@@ -1,5 +1,6 @@
-<!DOCTYPE html>
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
 <html>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
 <head>
     <script src=""
     <meta name=viewport content="width=device-width">
@@ -46,11 +47,12 @@
                 const [calendar, locale] = calendarAndLocale;
                 await UIHelper.setDefaultCalendarType(calendar, locale);
                 for (const element of [target0, target1]) {
-                    await UIHelper.activateFormControl(element);
+                    await UIHelper.activateElementAndWaitForInputSession(element);
                     const isCreditCardField = element.getAttribute("autocomplete") === "cc-exp";
                     appendOutput(`Date input control${isCreditCardField ? "" : " not"} marked as 'cc-exp' (default calendar set to ${calendar}):`);
                     appendOutput(`{ calendarType = ${await UIHelper.calendarType()} }`);
-                    await UIHelper.deactivateFormControl(element);
+                    element.blur();
+                    await UIHelper.waitForInputSessionToDismiss(element);
                 }
             }
 

Modified: trunk/LayoutTests/fast/forms/ios/time-picker-value-change-expected.txt (264186 => 264187)


--- trunk/LayoutTests/fast/forms/ios/time-picker-value-change-expected.txt	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/fast/forms/ios/time-picker-value-change-expected.txt	2020-07-09 19:46:09 UTC (rev 264187)
@@ -7,6 +7,7 @@
 PASS Handled blur event
 PASS pickerValues.hour is 9
 PASS pickerValues.minute is 41
+PASS Handled blur event
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/forms/ios/time-picker-value-change.html (264186 => 264187)


--- trunk/LayoutTests/fast/forms/ios/time-picker-value-change.html	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/fast/forms/ios/time-picker-value-change.html	2020-07-09 19:46:09 UTC (rev 264187)
@@ -20,12 +20,14 @@
     await UIHelper.activateElementAndWaitForInputSession(time);
     await UIHelper.setTimePickerValue(9, 41);
     await UIHelper.dismissFormAccessoryView();
-    await UIHelper.waitForKeyboardToHide();
+    await UIHelper.waitForInputSessionToDismiss();
     await UIHelper.activateElementAndWaitForInputSession(time);
     pickerValues = await UIHelper.timerPickerValues();
 
     shouldBe("pickerValues.hour", "9");
     shouldBe("pickerValues.minute", "41");
+    await UIHelper.dismissFormAccessoryView();
+    await UIHelper.waitForInputSessionToDismiss();
     finishJSTest();
 }
 </script>

Modified: trunk/LayoutTests/resources/ui-helper.js (264186 => 264187)


--- trunk/LayoutTests/resources/ui-helper.js	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/LayoutTests/resources/ui-helper.js	2020-07-09 19:46:09 UTC (rev 264187)
@@ -466,6 +466,11 @@
         return new Promise(resolve => {
             testRunner.runUIScript(`
                 (function() {
+                    if (!uiController.isShowingKeyboard && !uiController.isShowingContextMenu && !uiController.isShowingPopover) {
+                        uiController.uiScriptComplete();
+                        return;
+                    }
+
                     function clearCallbacksAndScriptComplete() {
                         uiController.didHideKeyboardCallback = null;
                         uiController.didDismissPopoverCallback = null;
@@ -472,6 +477,7 @@
                         uiController.didHideContextMenuCallback = null;
                         uiController.uiScriptComplete();
                     }
+
                     uiController.didHideKeyboardCallback = clearCallbacksAndScriptComplete;
                     uiController.didDismissPopoverCallback = clearCallbacksAndScriptComplete;
                     uiController.didHideContextMenuCallback = clearCallbacksAndScriptComplete;

Modified: trunk/Source/WebKit/ChangeLog (264186 => 264187)


--- trunk/Source/WebKit/ChangeLog	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/Source/WebKit/ChangeLog	2020-07-09 19:46:09 UTC (rev 264187)
@@ -1,3 +1,56 @@
+2020-07-09  Wenson Hsieh  <[email protected]>
+
+        REGRESSION (r259840): Pressing Esc or ⌘+"." does not dismiss time picker on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=214122
+        <rdar://problem/64940487>
+
+        Reviewed by Tim Horton.
+
+        Prior to r259840, when presenting context menus for certain input types (i.e. "time" and "datetime-local") on
+        iOS, UIKit would tell the presented view controller's view (a `UIDatePicker` in this case) to become first
+        responder. As a result, `WKContentView` would resign first responder, which (by default) blurs the focused
+        element and dismisses the context menu. The result is thats time pickers would immediately dismiss upon
+        presentation.
+
+        To mitigate this, r259840 adopted the existing active focus retaining mechanism to temporarily decouple
+        WKContentView's first responder status from the currently focused form element. However, this also causes
+        `-endEditingAndUpdateFocusAppearanceWithReason:` to bail, due to `self.webView._retainingActiveFocusedState`
+        returning `YES`. This means that codepaths meant to immediately dismiss UI for the focused element (for example,
+        when pressing Escape on a hardware keyboard on iOS) will not be able to dismiss UI.
+
+        To fix this, push the flag that keeps track of whether we're relinquishing first responder to the focused
+        element down into `WKContentView`, and have `WKContentView` automatically stop relinquishing first responder to
+        the focused element in `-[WKContentView accessoryDone]`.
+
+        Fixes an existing test: fast/forms/ios/dismiss-picker-using-keyboard.html
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView accessoryDone]):
+
+        Stop relinquishing focus to the focused element, so that form elements that require first responder can be
+        dismissed when triggering `-accessoryDone` (e.g. when pressing the Esc key on a hardware keyboard).
+
+        (-[WKContentView startRelinquishingFirstResponderToFocusedElement]):
+        (-[WKContentView stopRelinquishingFirstResponderToFocusedElement]):
+
+        Renamed from `-preserveFocus` and `-releaseFocus`, respectively. Also, made these methods idempotent using a new
+        `BOOL` flag, `_isRelinquishingFirstResponderToFocusedElement`.
+
+        (-[WKContentView preserveFocus]): Deleted.
+        (-[WKContentView releaseFocus]): Deleted.
+        * UIProcess/ios/forms/WKDateTimeInputControl.mm:
+        (-[WKDateTimePicker controlBeginEditing]):
+        (-[WKDateTimePicker controlEndEditing]):
+
+        Use the renamed WKContentView methods, and also remove the `_preservingFocus` flag.
+
+        * UIProcess/ios/forms/WKFormPopover.mm:
+        (-[WKRotatingPopover presentPopoverAnimated:]):
+        (-[WKRotatingPopover dismissPopoverAnimated:]):
+
+        Use the renamed WKContentView methods.
+
 2020-07-09  Brent Fulgham  <[email protected]>
 
         [iOS] Stop telemetry collection for the 'hw.cpu64bit_capable' sysctl

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (264186 => 264187)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2020-07-09 19:46:09 UTC (rev 264187)
@@ -377,6 +377,7 @@
     BOOL _isChangingFocus;
     BOOL _isFocusingElementWithKeyboard;
     BOOL _isBlurringFocusedElement;
+    BOOL _isRelinquishingFirstResponderToFocusedElement;
 
     BOOL _focusRequiresStrongPasswordAssistance;
     BOOL _waitingForEditDragSnapshot;
@@ -548,8 +549,8 @@
 
 - (NSString *)inputLabelText;
 
-- (void)preserveFocus;
-- (void)releaseFocus;
+- (void)startRelinquishingFirstResponderToFocusedElement;
+- (void)stopRelinquishingFirstResponderToFocusedElement;
 
 // UIWebFormAccessoryDelegate protocol
 - (void)accessoryDone;

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (264186 => 264187)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-07-09 19:46:09 UTC (rev 264187)
@@ -4368,6 +4368,7 @@
 
 - (void)accessoryDone
 {
+    [self stopRelinquishingFirstResponderToFocusedElement];
     [self endEditingAndUpdateFocusAppearanceWithReason:EndEditingReasonAccessoryDone];
     _page->setIsShowingInputViewForFocusedElement(false);
 }
@@ -6851,13 +6852,21 @@
     return NO;
 }
 
-- (void)preserveFocus
+- (void)startRelinquishingFirstResponderToFocusedElement
 {
+    if (_isRelinquishingFirstResponderToFocusedElement)
+        return;
+
+    _isRelinquishingFirstResponderToFocusedElement = YES;
     [_webView _incrementFocusPreservationCount];
 }
 
-- (void)releaseFocus
+- (void)stopRelinquishingFirstResponderToFocusedElement
 {
+    if (!_isRelinquishingFirstResponderToFocusedElement)
+        return;
+
+    _isRelinquishingFirstResponderToFocusedElement = NO;
     [_webView _decrementFocusPreservationCount];
 }
 

Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKDateTimeInputControl.mm (264186 => 264187)


--- trunk/Source/WebKit/UIProcess/ios/forms/WKDateTimeInputControl.mm	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKDateTimeInputControl.mm	2020-07-09 19:46:09 UTC (rev 264187)
@@ -370,16 +370,15 @@
 
 - (void)controlBeginEditing
 {
-    
     if (_presenting)
         return;
+
     _presenting = YES;
 
-    if (!_preservingFocus && (_view.focusedElementInformation.elementType == InputType::Time || _view.focusedElementInformation.elementType == InputType::DateTimeLocal)) {
-        [_view preserveFocus];
-        _preservingFocus = YES;
-    }
-    
+    auto elementType = _view.focusedElementInformation.elementType;
+    if (elementType == InputType::Time || elementType == InputType::DateTimeLocal)
+        [_view startRelinquishingFirstResponderToFocusedElement];
+
     // Set the time zone in case it changed.
     _datePicker.get().timeZone = [NSTimeZone localTimeZone];
 
@@ -413,10 +412,9 @@
 - (void)controlEndEditing
 {
     _presenting = NO;
-    if (_preservingFocus) {
-        [_view releaseFocus];
-        _preservingFocus = NO;
-    }
+
+    [_view stopRelinquishingFirstResponderToFocusedElement];
+
 #if USE(UICONTEXTMENU)
     [self removeContextMenuInteraction];
 #endif

Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormPopover.mm (264186 => 264187)


--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormPopover.mm	2020-07-09 19:44:59 UTC (rev 264186)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormPopover.mm	2020-07-09 19:46:09 UTC (rev 264187)
@@ -134,10 +134,7 @@
 - (void)presentPopoverAnimated:(BOOL)animated
 {
 #if PLATFORM(MACCATALYST)
-    if (!_isPreservingFocus) {
-        _isPreservingFocus = YES;
-        [_view preserveFocus];
-    }
+    [_view startRelinquishingFirstResponderToFocusedElement];
 #endif
 
     UIPopoverArrowDirection directions = [self popoverArrowDirections];
@@ -161,10 +158,7 @@
 - (void)dismissPopoverAnimated:(BOOL)animated
 {
 #if PLATFORM(MACCATALYST)
-    if (_isPreservingFocus) {
-        _isPreservingFocus = NO;
-        [_view releaseFocus];
-    }
+    [_view stopRelinquishingFirstResponderToFocusedElement];
 #endif
 
     [_popoverController dismissPopoverAnimated:animated];
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to