Title: [249031] trunk
Revision
249031
Author
[email protected]
Date
2019-08-22 15:22:49 -0700 (Thu, 22 Aug 2019)

Log Message

[iOS] Should show input view when became first responder if keyboard was showing when the view was resigned
https://bugs.webkit.org/show_bug.cgi?id=200902
<rdar://problem/54231756>

Reviewed by Wenson Hsieh.

Source/WebKit:

When resigning first responder save whether the peripheral host has an input view on screen,
including the software keyboard, so that we show the input view(s) again when the WKWebView
is made first responder. In Safari, this avoids the need for a person to explicitly focus an
editable element again to bring up the keyboard when returning to a tab they were previously
typing in. It also makes the behavior of switching tabs in Safari with a software keyboard
match the behavior of doing the same thing when a hardware keyboard attached.

* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::focusedElementDidChangeInputMode):
Pass a diff of the activity state from the web process to the UI process so that we can
differentiate between an inputmode change as a result of page deactivation vs a change
caused by some other means. We need to differentiate these cases because we want to
ignore a page that sets inputmode "none" (i.e. a request to hide the keyboard) from inside
a focus event handler if the handler was called as part of the process of page activation
(i.e. switching to the tab). Google Docs is one example of a web site that sets inputmode
to "none" as a result of the page activation process.

* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanupInteraction]): Clear out state.
(-[WKContentView resignFirstResponderForWebView]): Save whether the peripheral host is on screen
into a local before ending the editing session. We then copy the local into the ivar if we
actually will resign. This ordering is explicitly done because:
        1. Ending the editing session may dismiss the keyboard => we need to query the peripheral
           host first.
        2. If the view is being resigned as a result of a keyboard dismissal (i.e. a person pressed
           the hide keyboard button on iPad) then the user has indicated that they are finished
           with the keyboard and we do not want to show the keyboard on page re-activation => we
           do not want to copy the local to the ivar.
        3. If the view refuses to resign itself then it does not make sense to save the keyboard
           state as responder status hasn't changed.
(-[WKContentView shouldShowAutomaticKeyboardUI]): Ignore inputmode="none", if needed.
(-[WKContentView _didCommitLoadForMainFrame]): Clear out state.
(-[WKContentView isFirstResponderOrBecomingFirstResponder]): Added.
(-[WKContentView shouldShowInputViewOnPageActivation:]): Added.
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
Update ivar if this element is being focused as a result of page activation.
(-[WKContentView _didUpdateInputMode:activityStateChanges:]): Modified to take the activity state
diff. If the input mode was changed as a result of page activation then we want to update our ivar
so that when we call -reloadInputViews and UIKit calls us back in -shouldShowAutomaticKeyboardUI we
will know to ignore inputmode set to "none" when determining whether to show the automatic keyboard UI.
Note that we do not need to check/track whether an earlier -_elementDidFocus actually started an
input session as part of updating the value of our ivar because if an input session was not started,
say the embedding client disallowed it, then we would not have a focused element => we early return from
this function. Also remove duplication and improve code readbility by making use of the convenience function
hasFocusedElement() instead of duplicating what it does.
(-[WKContentView _didUpdateInputMode:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::focusedElementDidChangeInputMode): Modified to take the activity state diff
and pass it through.
(WebKit::WebPageProxy::didReleaseAllTouchPoints): Pass the empty set for the activity state diff to
keep our current behavior.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::focusedElementDidChangeInputMode): Send the activity state diff to the UI process.

LayoutTests:

Add tests to ensure that we show the keyboard when becoming first responder if the view resigned with the
keyboard on screen. Also add a test to ensure that we keep our current behavior and do NOT show the keyboard
for an autofocused text field when the view becomes first responder.

* fast/events/ios/resources/check-keyboard-on-screen.js: Added.
(async.checkKeyboardOnScreen):
(async.checkKeyboardNotOnScreen):
* fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation-expected.txt: Added.
* fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation.html: Added.
* fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none-expected.txt: Added.
* fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none.html: Added.
* fast/events/ios/show-keyboard-when-becoming-first-responder-expected.txt: Added.
* fast/events/ios/show-keyboard-when-becoming-first-responder.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForKeyboardToShow.return.new.Promise): Added.
(window.UIHelper.waitForKeyboardToShow): Added.
(window.UIHelper.becomeFirstResponder): Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (249030 => 249031)


--- trunk/LayoutTests/ChangeLog	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/LayoutTests/ChangeLog	2019-08-22 22:22:49 UTC (rev 249031)
@@ -1,3 +1,29 @@
+2019-08-22  Daniel Bates  <[email protected]>
+
+        [iOS] Should show input view when became first responder if keyboard was showing when the view was resigned
+        https://bugs.webkit.org/show_bug.cgi?id=200902
+        <rdar://problem/54231756>
+
+        Reviewed by Wenson Hsieh.
+
+        Add tests to ensure that we show the keyboard when becoming first responder if the view resigned with the
+        keyboard on screen. Also add a test to ensure that we keep our current behavior and do NOT show the keyboard
+        for an autofocused text field when the view becomes first responder.
+
+        * fast/events/ios/resources/check-keyboard-on-screen.js: Added.
+        (async.checkKeyboardOnScreen):
+        (async.checkKeyboardNotOnScreen):
+        * fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation-expected.txt: Added.
+        * fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation.html: Added.
+        * fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none-expected.txt: Added.
+        * fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none.html: Added.
+        * fast/events/ios/show-keyboard-when-becoming-first-responder-expected.txt: Added.
+        * fast/events/ios/show-keyboard-when-becoming-first-responder.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForKeyboardToShow.return.new.Promise): Added.
+        (window.UIHelper.waitForKeyboardToShow): Added.
+        (window.UIHelper.becomeFirstResponder): Added.
+
 2019-08-22  Tim Horton  <[email protected]>
 
         REGRESSION (r248974): fast/events/ios/select-all-with-existing-selection.html fails

Added: trunk/LayoutTests/fast/events/ios/resources/check-keyboard-on-screen.js (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/resources/check-keyboard-on-screen.js	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/resources/check-keyboard-on-screen.js	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,15 @@
+async function checkKeyboardOnScreen()
+{
+    if (await UIHelper.isShowingKeyboard())
+        testPassed("Keyboard is on screen.");
+    else
+        testFailed("Keyboard should be on screen, but is not.");
+}
+
+async function checkKeyboardNotOnScreen()
+{
+    if (await UIHelper.isShowingKeyboard())
+        testFailed("Keyboard should not be on screen, but it is.");
+    else
+        testPassed("Keyboard is not on screen.");
+}

Added: trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation-expected.txt (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation-expected.txt	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,11 @@
+This tests that the software keyboard is not shown for an autofocused text field on becoming first responder after navigating from a page with a focused text field.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.activeElement became document.getElementById('input')
+PASS Keyboard is not on screen.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation.html (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/should-not-show-keyboard-for-autofocused-field-when-becoming-first-responder-after-navigation.html	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<input id="input" autofocus> <!-- Only respected on iOS when a hardware keyboard is attached. -->
+<script>
+window.jsTestIsAsync = true;
+
+let inputElement = document.getElementById("input");
+
+async function runTest()
+{
+    if (!window.testRunner) {
+        testFailed("Must be run in WebKitTestRunner.");
+        return;
+    }
+
+    await UIHelper.setHardwareKeyboardAttached(false);
+
+    if (document.location.search == "?checkResult") {
+        async function checkResultAndDone() {
+            await checkKeyboardNotOnScreen();
+            document.body.removeChild(inputElement);
+            finishJSTest();
+        }
+        await UIHelper.becomeFirstResponder();
+        shouldBecomeEqual("document.activeElement", "document.getElementById('input')", checkResultAndDone);
+    } else {
+        await UIHelper.activateElementAndWaitForInputSession(inputElement);
+        await UIHelper.resignFirstResponder();
+        await UIHelper.waitForKeyboardToHide();
+        document.location.href += "?checkResult";
+    }
+}
+
+description("This tests that the software keyboard is not shown for an autofocused text field on becoming first responder after navigating from a page with a focused text field.");
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none-expected.txt (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none-expected.txt	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,18 @@
+This tests that in a focused text field the software keyboard is hidden and shown when the web view resigns and becomes first responder, respectively, eventhough focusing the text field sets inputmode to "none".
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+After tapping <input>:
+PASS Keyboard is on screen.
+
+After resigning first responder:
+PASS Keyboard is not on screen.
+
+After becoming first responder:
+PASS Keyboard is on screen.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none.html (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-despite-inputmode-none.html	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<input id="input">
+<script>
+window.jsTestIsAsync = true;
+
+let inputElement = document.getElementById("input");
+
+async function runTest()
+{
+    if (!window.testRunner) {
+        testFailed("Must be run in WebKitTestRunner.");
+        return;
+    }
+
+    await UIHelper.setHardwareKeyboardAttached(false);
+
+    debug("<br>After tapping &lt;input&gt;:");
+    await UIHelper.activateElementAndWaitForInputSession(inputElement);
+    await checkKeyboardOnScreen();
+
+    debug("<br>After resigning first responder:");
+    await UIHelper.resignFirstResponder();
+    await UIHelper.waitForKeyboardToHide();
+    await checkKeyboardNotOnScreen();
+
+    debug("<br>After becoming first responder:");
+    await UIHelper.becomeFirstResponder();
+    await UIHelper.waitForKeyboardToShow();
+    await checkKeyboardOnScreen();
+
+    document.body.removeChild(inputElement);
+    finishJSTest();
+}
+
+inputElement.addEventListener("focus", () => inputElement.setAttribute("inputmode", "none"), true /* capture phase */);
+
+description("This tests that in a focused text field the software keyboard is hidden and shown when the web view resigns and becomes first responder, respectively, eventhough focusing the text field sets inputmode to &quot;none&quot;.");
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-expected.txt (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder-expected.txt	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,18 @@
+This tests that in a focused text field the software keyboard is hidden and shown when the web view resigns and becomes first responder, respectively.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+After tapping <input>:
+PASS Keyboard is on screen.
+
+After resigning first responder:
+PASS Keyboard is not on screen.
+
+After becoming first responder:
+PASS Keyboard is on screen.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder.html (0 => 249031)


--- trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/ios/show-keyboard-when-becoming-first-responder.html	2019-08-22 22:22:49 UTC (rev 249031)
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<input id="input">
+<script>
+window.jsTestIsAsync = true;
+
+let inputElement = document.getElementById("input");
+
+async function runTest()
+{
+    if (!window.testRunner) {
+        testFailed("Must be run in WebKitTestRunner.");
+        return;
+    }
+
+    await UIHelper.setHardwareKeyboardAttached(false);
+
+    debug("<br>After tapping &lt;input&gt;:");
+    await UIHelper.activateElementAndWaitForInputSession(inputElement);
+    await checkKeyboardOnScreen();
+
+    debug("<br>After resigning first responder:");
+    await UIHelper.resignFirstResponder();
+    await UIHelper.waitForKeyboardToHide();
+    await checkKeyboardNotOnScreen();
+
+    debug("<br>After becoming first responder:");
+    await UIHelper.becomeFirstResponder();
+    await UIHelper.waitForKeyboardToShow();
+    await checkKeyboardOnScreen();
+
+    document.body.removeChild(inputElement);
+    finishJSTest();
+}
+
+description("This tests that in a focused text field the software keyboard is hidden and shown when the web view resigns and becomes first responder, respectively.");
+runTest();
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/resources/ui-helper.js (249030 => 249031)


--- trunk/LayoutTests/resources/ui-helper.js	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/LayoutTests/resources/ui-helper.js	2019-08-22 22:22:49 UTC (rev 249031)
@@ -506,6 +506,22 @@
         });
     }
 
+    static waitForKeyboardToShow()
+    {
+        if (!this.isWebKit2() || !this.isIOSFamily())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`
+                (function() {
+                    if (uiController.isShowingKeyboard)
+                        uiController.uiScriptComplete();
+                    else
+                        uiController.didShowKeyboardCallback = () => uiController.uiScriptComplete();
+                })()`, resolve);
+        });
+    }
+
     static getUICaretRect()
     {
         if (!this.isWebKit2() || !this.isIOSFamily())
@@ -791,6 +807,14 @@
         return new Promise(resolve => testRunner.runUIScript(`uiController.resignFirstResponder()`, resolve));
     }
 
+    static becomeFirstResponder()
+    {
+        if (!this.isWebKit2())
+            return Promise.resolve();
+
+        return new Promise(resolve => testRunner.runUIScript(`uiController.becomeFirstResponder()`, resolve));
+    }
+
     static minimumZoomScale()
     {
         if (!this.isWebKit2())

Modified: trunk/Source/WebKit/ChangeLog (249030 => 249031)


--- trunk/Source/WebKit/ChangeLog	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/ChangeLog	2019-08-22 22:22:49 UTC (rev 249031)
@@ -1,3 +1,69 @@
+2019-08-22  Daniel Bates  <[email protected]>
+
+        [iOS] Should show input view when became first responder if keyboard was showing when the view was resigned
+        https://bugs.webkit.org/show_bug.cgi?id=200902
+        <rdar://problem/54231756>
+
+        Reviewed by Wenson Hsieh.
+
+        When resigning first responder save whether the peripheral host has an input view on screen,
+        including the software keyboard, so that we show the input view(s) again when the WKWebView
+        is made first responder. In Safari, this avoids the need for a person to explicitly focus an
+        editable element again to bring up the keyboard when returning to a tab they were previously
+        typing in. It also makes the behavior of switching tabs in Safari with a software keyboard
+        match the behavior of doing the same thing when a hardware keyboard attached.
+
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::focusedElementDidChangeInputMode):
+        Pass a diff of the activity state from the web process to the UI process so that we can
+        differentiate between an inputmode change as a result of page deactivation vs a change
+        caused by some other means. We need to differentiate these cases because we want to
+        ignore a page that sets inputmode "none" (i.e. a request to hide the keyboard) from inside
+        a focus event handler if the handler was called as part of the process of page activation
+        (i.e. switching to the tab). Google Docs is one example of a web site that sets inputmode
+        to "none" as a result of the page activation process.
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView cleanupInteraction]): Clear out state.
+        (-[WKContentView resignFirstResponderForWebView]): Save whether the peripheral host is on screen
+        into a local before ending the editing session. We then copy the local into the ivar if we
+        actually will resign. This ordering is explicitly done because:
+                1. Ending the editing session may dismiss the keyboard => we need to query the peripheral
+                   host first.
+                2. If the view is being resigned as a result of a keyboard dismissal (i.e. a person pressed
+                   the hide keyboard button on iPad) then the user has indicated that they are finished
+                   with the keyboard and we do not want to show the keyboard on page re-activation => we
+                   do not want to copy the local to the ivar.
+                3. If the view refuses to resign itself then it does not make sense to save the keyboard
+                   state as responder status hasn't changed.
+        (-[WKContentView shouldShowAutomaticKeyboardUI]): Ignore inputmode="none", if needed.
+        (-[WKContentView _didCommitLoadForMainFrame]): Clear out state.
+        (-[WKContentView isFirstResponderOrBecomingFirstResponder]): Added.
+        (-[WKContentView shouldShowInputViewOnPageActivation:]): Added.
+        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
+        Update ivar if this element is being focused as a result of page activation.
+        (-[WKContentView _didUpdateInputMode:activityStateChanges:]): Modified to take the activity state
+        diff. If the input mode was changed as a result of page activation then we want to update our ivar
+        so that when we call -reloadInputViews and UIKit calls us back in -shouldShowAutomaticKeyboardUI we
+        will know to ignore inputmode set to "none" when determining whether to show the automatic keyboard UI.
+        Note that we do not need to check/track whether an earlier -_elementDidFocus actually started an
+        input session as part of updating the value of our ivar because if an input session was not started,
+        say the embedding client disallowed it, then we would not have a focused element => we early return from
+        this function. Also remove duplication and improve code readbility by making use of the convenience function
+        hasFocusedElement() instead of duplicating what it does.
+        (-[WKContentView _didUpdateInputMode:]): Deleted.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::focusedElementDidChangeInputMode): Modified to take the activity state diff
+        and pass it through.
+        (WebKit::WebPageProxy::didReleaseAllTouchPoints): Pass the empty set for the activity state diff to
+        keep our current behavior.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::focusedElementDidChangeInputMode): Send the activity state diff to the UI process.
 2019-08-22  Keith Rollin  <[email protected]>
 
         Remove logging that contains a URL

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2019-08-22 22:22:49 UTC (rev 249031)
@@ -388,7 +388,7 @@
     virtual void elementDidFocus(const FocusedElementInformation&, bool userIsInteracting, bool blurPreviousNode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges, API::Object* userData) = 0;
     virtual void updateInputContextAfterBlurringAndRefocusingElement() = 0;
     virtual void elementDidBlur() = 0;
-    virtual void focusedElementDidChangeInputMode(WebCore::InputMode) = 0;
+    virtual void focusedElementDidChangeInputMode(WebCore::InputMode, OptionSet<WebCore::ActivityState::Flag>) = 0;
     virtual void didReceiveEditorStateUpdateAfterFocus() = 0;
     virtual bool isFocusingElement() = 0;
     virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) = 0;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-08-22 22:22:49 UTC (rev 249031)
@@ -1945,7 +1945,7 @@
     void elementDidFocus(const FocusedElementInformation&, bool userIsInteracting, bool blurPreviousNode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges, const UserData&);
     void elementDidBlur();
     void updateInputContextAfterBlurringAndRefocusingElement();
-    void focusedElementDidChangeInputMode(WebCore::InputMode);
+    void focusedElementDidChangeInputMode(WebCore::InputMode, OptionSet<WebCore::ActivityState::Flag>);
     void didReleaseAllTouchPoints();
     void didReceiveEditorStateUpdateAfterFocus();
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-08-22 22:22:49 UTC (rev 249031)
@@ -409,7 +409,7 @@
     ElementDidFocus(struct WebKit::FocusedElementInformation information, bool userIsInteracting, bool blurPreviousNode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges, WebKit::UserData userData)
     ElementDidBlur()
     UpdateInputContextAfterBlurringAndRefocusingElement()
-    FocusedElementDidChangeInputMode(enum:uint8_t WebCore::InputMode mode)
+    FocusedElementDidChangeInputMode(enum:uint8_t WebCore::InputMode mode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges)
     ScrollingNodeScrollWillStartScroll()
     ScrollingNodeScrollDidEndScroll()
     ShowInspectorHighlight(struct WebCore::Highlight highlight)

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2019-08-22 22:22:49 UTC (rev 249031)
@@ -151,7 +151,7 @@
     void elementDidFocus(const FocusedElementInformation&, bool userIsInteracting, bool blurPreviousNode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges, API::Object* userData) override;
     void updateInputContextAfterBlurringAndRefocusingElement() final;
     void elementDidBlur() override;
-    void focusedElementDidChangeInputMode(WebCore::InputMode) override;
+    void focusedElementDidChangeInputMode(WebCore::InputMode, OptionSet<WebCore::ActivityState::Flag>) override;
     void didReceiveEditorStateUpdateAfterFocus() override;
     bool isFocusingElement() override;
     void selectionDidChange() override;

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2019-08-22 22:22:49 UTC (rev 249031)
@@ -573,9 +573,9 @@
     [m_contentView _elementDidBlur];
 }
 
-void PageClientImpl::focusedElementDidChangeInputMode(WebCore::InputMode mode)
+void PageClientImpl::focusedElementDidChangeInputMode(WebCore::InputMode mode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges)
 {
-    [m_contentView _didUpdateInputMode:mode];
+    [m_contentView _didUpdateInputMode:mode activityStateChanges:activityStateChanges];
 }
 
 void PageClientImpl::didReceiveEditorStateUpdateAfterFocus()

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2019-08-22 22:22:49 UTC (rev 249031)
@@ -337,6 +337,8 @@
 #endif
 
     BOOL _keyboardDidRequestDismissal;
+    BOOL _wasResignedWhileShowingInputView;
+    BOOL _shouldShowAutomaticKeyboardUIWhenInputModeNone;
 
 #if USE(UIKIT_KEYBOARD_ADDITIONS)
     BOOL _candidateViewNeedsUpdate;
@@ -462,7 +464,7 @@
 - (void)_updateInputContextAfterBlurringAndRefocusingElement;
 - (void)_elementDidBlur;
 - (void)_hideContextMenuHintContainer;
-- (void)_didUpdateInputMode:(WebCore::InputMode)mode;
+- (void)_didUpdateInputMode:(WebCore::InputMode)mode activityStateChanges:(OptionSet<WebCore::ActivityState::Flag>)activityStateChanges;
 - (void)_didReceiveEditorStateUpdateAfterFocus;
 - (void)_hardwareKeyboardAvailabilityChanged;
 - (void)_selectionChanged;

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-08-22 22:22:49 UTC (rev 249031)
@@ -943,6 +943,7 @@
 
     [self _resetInputViewDeferral];
     _focusedElementInformation = { };
+    _wasResignedWhileShowingInputView = NO;
     
     [_keyboardScrollingAnimator invalidate];
     _keyboardScrollingAnimator = nil;
@@ -1261,7 +1262,8 @@
 
     SetForScope<BOOL> resigningFirstResponderScope { _resigningFirstResponder, YES };
 
-    [self endEditingAndUpdateFocusAppearanceWithReason:EndEditingReasonResigningFirstResponder];
+    BOOL wasKeyboardOnScreen = UIPeripheralHost.activeInstance.isOnScreen;
+    [self endEditingAndUpdateFocusAppearanceWithReason:EndEditingReasonResigningFirstResponder]; // May dismiss the keyboard.
 
     // If the user explicitly dismissed the keyboard then we will lose first responder
     // status only to gain it back again. Just don't resign in that case.
@@ -1273,6 +1275,7 @@
     bool superDidResign = [super resignFirstResponder];
 
     if (superDidResign) {
+        _wasResignedWhileShowingInputView = wasKeyboardOnScreen;
         [self _handleDOMPasteRequestWithResult:WebCore::DOMPasteAccessResponse::DeniedForGesture];
         _page->activityStateDidChange(WebCore::ActivityState::IsFocused);
     }
@@ -1704,7 +1707,7 @@
     // FIXME: We should support inputmode="none" when the hardware keyboard is attached.
     // We currently refrain from doing so because that would prevent UIKit from showing
     // the language picker when pressing the globe key to change the input language.
-    if (_focusedElementInformation.inputMode == WebCore::InputMode::None && !GSEventIsHardwareKeyboardAttached())
+    if (_focusedElementInformation.inputMode == WebCore::InputMode::None && !GSEventIsHardwareKeyboardAttached() && !_shouldShowAutomaticKeyboardUIWhenInputModeNone)
         return NO;
 
     return [self _shouldShowAutomaticKeyboardUIIgnoringInputMode];
@@ -3975,6 +3978,7 @@
 #if USE(UIKIT_KEYBOARD_ADDITIONS)
     _seenHardwareKeyDownInNonEditableElement = NO;
 #endif
+    _wasResignedWhileShowingInputView = NO;
     [self _elementDidBlur];
     [self _cancelLongPressGestureRecognizer];
     [self _hideContextMenuHintContainer];
@@ -5272,6 +5276,16 @@
     }
 }
 
+- (BOOL)isFirstResponderOrBecomingFirstResponder
+{
+    return self.isFirstResponder || _becomingFirstResponder;
+}
+
+- (BOOL)shouldShowInputViewOnPageActivation:(const OptionSet<WebCore::ActivityState::Flag> &)activityStateChanges
+{
+    return [self isFirstResponderOrBecomingFirstResponder] && activityStateChanges.contains(WebCore::ActivityState::IsFocused) && _wasResignedWhileShowingInputView;
+}
+
 - (void)_elementDidFocus:(const WebKit::FocusedElementInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode activityStateChanges:(OptionSet<WebCore::ActivityState::Flag>)activityStateChanges userObject:(NSObject <NSSecureCoding> *)userObject
 {
     SetForScope<BOOL> isChangingFocusForScope { _isChangingFocus, hasFocusedElement(_focusedElementInformation) };
@@ -5296,6 +5310,8 @@
     if ([inputDelegate respondsToSelector:@selector(_webView:decidePolicyForFocusedElement:)])
         startInputSessionPolicy = [inputDelegate _webView:_webView decidePolicyForFocusedElement:focusedElementInfo.get()];
 
+    SetForScope<BOOL> shouldShowAutomaticKeyboardUIWhenInputModeNoneScope { _shouldShowAutomaticKeyboardUIWhenInputModeNone, startInputSessionPolicy == _WKFocusStartsInputSessionPolicyAuto && [self shouldShowInputViewOnPageActivation:activityStateChanges] };
+
     BOOL shouldShowInputView = [&] {
         switch (startInputSessionPolicy) {
         case _WKFocusStartsInputSessionPolicyAuto:
@@ -5304,11 +5320,8 @@
             if (userIsInteracting)
                 return YES;
 
-            if (self.isFirstResponder || _becomingFirstResponder) {
-                // When the software keyboard is being used to enter an url, only the focus activity state is changing.
-                // In this case, auto focus on the page being navigated to should be disabled, unless a hardware
-                // keyboard is attached.
-                if (activityStateChanges && activityStateChanges != WebCore::ActivityState::IsFocused)
+            if ([self isFirstResponderOrBecomingFirstResponder]) {
+                if (_shouldShowAutomaticKeyboardUIWhenInputModeNone)
                     return YES;
 
 #if PLATFORM(WATCHOS)
@@ -5522,12 +5535,13 @@
     [self reloadInputViews];
 }
 
-- (void)_didUpdateInputMode:(WebCore::InputMode)mode
+- (void)_didUpdateInputMode:(WebCore::InputMode)mode activityStateChanges:(OptionSet<WebCore::ActivityState::Flag>)activityStateChanges
 {
-    if (!self.inputDelegate || _focusedElementInformation.elementType == WebKit::InputType::None)
+    if (!self.inputDelegate || !hasFocusedElement(_focusedElementInformation))
         return;
 
 #if !PLATFORM(WATCHOS)
+    SetForScope<BOOL> shouldShowAutomaticKeyboardUIWhenInputModeNoneScope { _shouldShowAutomaticKeyboardUIWhenInputModeNone, [self shouldShowInputViewOnPageActivation:activityStateChanges] };
     _focusedElementInformation.inputMode = mode;
     [self reloadInputViews];
 #endif

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (249030 => 249031)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2019-08-22 22:22:49 UTC (rev 249031)
@@ -932,7 +932,7 @@
     pageClient().elementDidBlur();
 }
 
-void WebPageProxy::focusedElementDidChangeInputMode(WebCore::InputMode mode)
+void WebPageProxy::focusedElementDidChangeInputMode(WebCore::InputMode mode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges)
 {
 #if ENABLE(TOUCH_EVENTS)
     if (m_touchAndPointerEventTracking.isTrackingAnything()) {
@@ -941,7 +941,7 @@
     }
 #endif
 
-    pageClient().focusedElementDidChangeInputMode(mode);
+    pageClient().focusedElementDidChangeInputMode(mode, activityStateChanges);
 }
 
 void WebPageProxy::didReleaseAllTouchPoints()
@@ -949,7 +949,7 @@
     if (!m_pendingInputModeChange)
         return;
 
-    pageClient().focusedElementDidChangeInputMode(*m_pendingInputModeChange);
+    pageClient().focusedElementDidChangeInputMode(*m_pendingInputModeChange, { });
     m_pendingInputModeChange = WTF::nullopt;
 }
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (249030 => 249031)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-08-22 22:06:54 UTC (rev 249030)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-08-22 22:22:49 UTC (rev 249031)
@@ -5535,7 +5535,7 @@
     if (!isTextFormControlOrEditableContent(element))
         return;
 
-    send(Messages::WebPageProxy::FocusedElementDidChangeInputMode(mode));
+    send(Messages::WebPageProxy::FocusedElementDidChangeInputMode(mode, m_lastActivityStateChanges));
 #else
     UNUSED_PARAM(mode);
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to