Title: [230752] trunk
Revision
230752
Author
wenson_hs...@apple.com
Date
2018-04-17 23:03:06 -0700 (Tue, 17 Apr 2018)

Log Message

[Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
https://bugs.webkit.org/show_bug.cgi?id=184635
<rdar://problem/39440642>

Reviewed by Tim Horton.

Source/WebKit:

Currently on iOS, we allow element focus to present UI if the keyboard is already shown. In extra zoom mode,
this would lead to a confusing experience when the focus form control overlay is disabled, since fullscreen
input view controllers are swapped out from underneath the user. Currently, this also puts the UI process into a
bad state where the focused form control overlay is active, but still hidden. This patch makes some tweaks to
input view controller handling in the UI process to address these issues, and also adds WebKitTestRunner support
for simulating interactions with select menus in extra zoom mode. See comments below for more detail.

Test: fast/events/extrazoom/change-focus-during-change-event.html

* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:

Add new SPI delegate hooks to notify the UI delegate when view controllers are presented or dismissed in extra
zoom mode. See -presentViewControllerForCurrentAssistedNode and -dismissAllInputViewControllers.

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput):
(WebKit::WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput):

See the comment below -dismissAllInputViewControllers.

* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):

In extra zoom mode, when changing focus from one assisted node to another, only allow the second node to be
assisted if the focused form control overlay is being shown. Otherwise, (i.e. when a fullscreen input view
controller is being presented), don't allow focus to start an input session.

Additionally, make a minor tweak to allow the previous node to blur, even if we are not showing the keyboard for
the new focused element. Without this adjustment, in the case where the page has programmatically focused
another element while a fullscreen input view controller is presented, we'll show the old view controller for
the new focused element.

(-[WKContentView presentViewControllerForCurrentAssistedNode]):
(-[WKContentView dismissAllInputViewControllers:]):

Currently, when a fullscreen input view controller is presented, the web process gets backgrounded. This
prevents event handlers from executing, which leads to strange behaviors in many cases (for instance: if we
have a multiple select, and the "change" event handler blurs the select, the user may check or uncheck multiple
items, but only the first change will actually take effect).

To fix this, we maintain a background activity token while presenting an input view controller.

(-[WKContentView focusedFormControlViewDidBeginEditing:]):

Start hiding the focused form overlay when re-presenting an input view controller. This allows us to bail from
showing fullscreen input UI for another focused element if focus programmatically changes while the current
fullscreen input view controller is presented, due to the -isHidden check in -_startAssistingNode:.

(-[WKContentView selectFormAccessoryPickerRow:]):

Simulate tapping a given row in select menu UI in extra zoom mode.

Tools:

Add plumbing to support invoking `didHideKeyboardCallback` and `didShowKeyboardCallback` when (respectively)
dismissing or presenting fullscreen input view controllers in extra zoom mode.

* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView dealloc]):
(-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _keyboardDidShow:]):
(-[TestRunnerWKWebView _keyboardDidHide:]):
(-[TestRunnerWKWebView _webView:didPresentFocusedElementViewController:]):
(-[TestRunnerWKWebView _webView:didDismissFocusedElementViewController:]):

LayoutTests:

Add a new layout test to exercise the following sequence of events in extra zoom mode:

1. Focus select element #1.
2. Choose an unselected option.
3. Programmatically focus select element #2 in the "change" event handler.
4. Choose an unselected option.
5. Programmatically blur select element #2 in the "change" event handler.

* fast/events/extrazoom/change-focus-during-change-event-expected.txt: Added.
* fast/events/extrazoom/change-focus-during-change-event.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForKeyboardToHide.return.new.Promise):
(window.UIHelper.waitForKeyboardToHide):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (230751 => 230752)


--- trunk/LayoutTests/ChangeLog	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/LayoutTests/ChangeLog	2018-04-18 06:03:06 UTC (rev 230752)
@@ -1,5 +1,27 @@
 2018-04-17  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        [Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
+        https://bugs.webkit.org/show_bug.cgi?id=184635
+        <rdar://problem/39440642>
+
+        Reviewed by Tim Horton.
+
+        Add a new layout test to exercise the following sequence of events in extra zoom mode:
+
+        1. Focus select element #1.
+        2. Choose an unselected option.
+        3. Programmatically focus select element #2 in the "change" event handler.
+        4. Choose an unselected option.
+        5. Programmatically blur select element #2 in the "change" event handler.
+
+        * fast/events/extrazoom/change-focus-during-change-event-expected.txt: Added.
+        * fast/events/extrazoom/change-focus-during-change-event.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForKeyboardToHide.return.new.Promise):
+        (window.UIHelper.waitForKeyboardToHide):
+
+2018-04-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
         [Extra zoom mode] Double tap to zoom should account for text legibility in extra zoom mode
         https://bugs.webkit.org/show_bug.cgi?id=184631
         <rdar://problem/39303706>

Added: trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event-expected.txt (0 => 230752)


--- trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event-expected.txt	2018-04-18 06:03:06 UTC (rev 230752)
@@ -0,0 +1,9 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+Choosing second option in top select...
+Option two should be selected: true
+Choosing second option in bottom select...
+Option four should be selected: true
+

Added: trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event.html (0 => 230752)


--- trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/extrazoom/change-focus-during-change-event.html	2018-04-18 06:03:06 UTC (rev 230752)
@@ -0,0 +1,60 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<meta name="viewport" content="width=device-width">
+<head>
+    <script src=""
+    <script src=""
+    <style>
+        body, html {
+            margin: 0;
+            width: 100%;
+            height: 100%;
+            position: absolute;
+        }
+        select {
+            width: 100%;
+            height: 80px;
+            display: block;
+        }
+    </style>
+    <script>
+        jsTestIsAsync = true;
+
+        function selectOptionAtIndexAndWaitForKeyboardToHide(index) {
+            return new Promise(resolve => {
+                UIHelper.waitForKeyboardToHide().then(resolve);
+                UIHelper.selectFormAccessoryPickerRow(index);
+            });
+        }
+
+        async function runTest() {
+            // First, tap on the top select and choose the second option. Changing the value of the select causes the
+            // bottom select to be focused.
+            await UIHelper.activateAndWaitForInputSessionAt(50, 40);
+            output.innerHTML += "Choosing second option in top select...<br>";
+            await selectOptionAtIndexAndWaitForKeyboardToHide(1);
+            output.innerHTML += `Option two should be selected: ${two.selected}<br>`;
+
+            // Now tap on the bottom select and choose the second option. Changing the value of this select causes the
+            // select to blur, dismissing the input view.
+            await UIHelper.activateAndWaitForInputSessionAt(50, 120);
+            output.innerHTML += "Choosing second option in bottom select...<br>";
+            await selectOptionAtIndexAndWaitForKeyboardToHide(1);
+            output.innerHTML += `Option four should be selected: ${four.selected}<br>`;
+
+            finishJSTest();
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+<select id="top" _onchange_="document.getElementById('bottom').focus()">
+    <option selected>One</option>
+    <option id="two">Two</option>
+</select>
+<select id="bottom" _onchange_="this.blur()">
+    <option selected>Three</option>
+    <option id="four">Four</option>
+</select>
+<pre id="output"></pre>
+</body>
+</html>

Modified: trunk/LayoutTests/resources/ui-helper.js (230751 => 230752)


--- trunk/LayoutTests/resources/ui-helper.js	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/LayoutTests/resources/ui-helper.js	2018-04-18 06:03:06 UTC (rev 230752)
@@ -100,6 +100,16 @@
         });
     }
 
+    static waitForKeyboardToHide()
+    {
+        return new Promise(resolve => {
+            testRunner.runUIScript(`
+                (function() {
+                    uiController.didHideKeyboardCallback = () => uiController.uiScriptComplete();
+                })()`, resolve);
+        });
+    }
+
     static getUICaretRect()
     {
         if (!this.isWebKit2() || !this.isIOS())

Modified: trunk/Source/WebKit/ChangeLog (230751 => 230752)


--- trunk/Source/WebKit/ChangeLog	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Source/WebKit/ChangeLog	2018-04-18 06:03:06 UTC (rev 230752)
@@ -1,3 +1,64 @@
+2018-04-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
+        https://bugs.webkit.org/show_bug.cgi?id=184635
+        <rdar://problem/39440642>
+
+        Reviewed by Tim Horton.
+
+        Currently on iOS, we allow element focus to present UI if the keyboard is already shown. In extra zoom mode,
+        this would lead to a confusing experience when the focus form control overlay is disabled, since fullscreen
+        input view controllers are swapped out from underneath the user. Currently, this also puts the UI process into a
+        bad state where the focused form control overlay is active, but still hidden. This patch makes some tweaks to
+        input view controller handling in the UI process to address these issues, and also adds WebKitTestRunner support
+        for simulating interactions with select menus in extra zoom mode. See comments below for more detail.
+
+        Test: fast/events/extrazoom/change-focus-during-change-event.html
+
+        * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+
+        Add new SPI delegate hooks to notify the UI delegate when view controllers are presented or dismissed in extra
+        zoom mode. See -presentViewControllerForCurrentAssistedNode and -dismissAllInputViewControllers.
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput):
+        (WebKit::WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput):
+
+        See the comment below -dismissAllInputViewControllers.
+
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+
+        In extra zoom mode, when changing focus from one assisted node to another, only allow the second node to be
+        assisted if the focused form control overlay is being shown. Otherwise, (i.e. when a fullscreen input view
+        controller is being presented), don't allow focus to start an input session.
+
+        Additionally, make a minor tweak to allow the previous node to blur, even if we are not showing the keyboard for
+        the new focused element. Without this adjustment, in the case where the page has programmatically focused
+        another element while a fullscreen input view controller is presented, we'll show the old view controller for
+        the new focused element.
+
+        (-[WKContentView presentViewControllerForCurrentAssistedNode]):
+        (-[WKContentView dismissAllInputViewControllers:]):
+
+        Currently, when a fullscreen input view controller is presented, the web process gets backgrounded. This
+        prevents event handlers from executing, which leads to strange behaviors in many cases (for instance: if we
+        have a multiple select, and the "change" event handler blurs the select, the user may check or uncheck multiple
+        items, but only the first change will actually take effect).
+
+        To fix this, we maintain a background activity token while presenting an input view controller.
+
+        (-[WKContentView focusedFormControlViewDidBeginEditing:]):
+
+        Start hiding the focused form overlay when re-presenting an input view controller. This allows us to bail from
+        showing fullscreen input UI for another focused element if focus programmatically changes while the current
+        fullscreen input view controller is presented, due to the -isHidden check in -_startAssistingNode:.
+
+        (-[WKContentView selectFormAccessoryPickerRow:]):
+
+        Simulate tapping a given row in select menu UI in extra zoom mode.
+
 2018-04-17  Conrad Shultz  <conrad_shu...@apple.com>
 
         WebKit::DisplayLink maintains a strong reference to WebPageProxy, creating a reference cycle

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (230751 => 230752)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2018-04-18 06:03:06 UTC (rev 230752)
@@ -153,6 +153,8 @@
 - (NSInteger)_webView:(WKWebView *)webView dataOwnerForDragSession:(id <UIDragSession>)session WK_API_AVAILABLE(ios(11.0));
 #endif
 - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInsets:(BOOL)safeAreaShouldAffectObscuredInsets WK_API_AVAILABLE(ios(11.0));
+- (void)_webView:(WKWebView *)webView didPresentFocusedElementViewController:(UIViewController *)controller WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (void)_webView:(WKWebView *)webView didDismissFocusedElementViewController:(UIViewController *)controller WK_API_AVAILABLE(ios(WK_IOS_TBA));
 #else // TARGET_OS_IPHONE
 - (void)_prepareForImmediateActionAnimationForWebView:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.13.4));
 - (void)_cancelImmediateActionAnimationForWebView:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.13.4));

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (230751 => 230752)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2018-04-18 06:03:06 UTC (rev 230752)
@@ -1407,4 +1407,26 @@
     callback(isLocallyReachable ? MessagePortChannelProvider::HasActivity::Yes : MessagePortChannelProvider::HasActivity::No);
 }
 
+#if ENABLE(EXTRA_ZOOM_MODE)
+
+void WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput()
+{
+    if (m_backgroundActivityTokenForFullscreenFormControls)
+        return;
+
+    m_backgroundActivityTokenForFullscreenFormControls = m_throttler.backgroundActivityToken();
+    RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because it is presenting fullscreen UI for form controls.");
+}
+
+void WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput()
+{
+    if (!m_backgroundActivityTokenForFullscreenFormControls)
+        return;
+
+    m_backgroundActivityTokenForFullscreenFormControls = nullptr;
+    RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because it has dismissed fullscreen UI for form controls.");
+}
+
+#endif
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (230751 => 230752)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2018-04-18 06:03:06 UTC (rev 230752)
@@ -212,6 +212,11 @@
     void suspendWebPageProxy(WebPageProxy&);
     void suspendedPageWasDestroyed(SuspendedPageProxy&);
 
+#if ENABLE(EXTRA_ZOOM_MODE)
+    void takeBackgroundActivityTokenForFullscreenInput();
+    void releaseBackgroundActivityTokenForFullscreenInput();
+#endif
+
 protected:
     static uint64_t generatePageID();
     WebProcessProxy(WebProcessPool&, WebsiteDataStore&);
@@ -340,6 +345,10 @@
     HashMap<uint64_t, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>> m_localPortActivityCompletionHandlers;
 
     bool m_hasCommittedAnyProvisionalLoads { false };
+
+#if ENABLE(EXTRA_ZOOM_MODE)
+    ProcessThrottler::BackgroundActivityToken m_backgroundActivityTokenForFullscreenFormControls;
+#endif
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (230751 => 230752)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-04-18 06:03:06 UTC (rev 230752)
@@ -4011,18 +4011,26 @@
     if ([inputDelegate respondsToSelector:@selector(_webView:focusShouldStartInputSession:)])
         shouldShowKeyboard = [inputDelegate _webView:_webView focusShouldStartInputSession:focusedElementInfo.get()];
     else {
-        // The default behavior is to allow node assistance if the user is interacting or the keyboard is already active.
-        shouldShowKeyboard = userIsInteracting || _isChangingFocus || changingActivityState;
-#if ENABLE(DATA_INTERACTION)
-        shouldShowKeyboard |= _dragDropInteractionState.isPerformingDrop();
+        // The default behavior is to allow node assistance if the user is interacting.
+        // We also allow node assistance if the keyboard already is showing, unless we're in extra zoom mode.
+        shouldShowKeyboard = userIsInteracting
+#if ENABLE(EXTRA_ZOOM_MODE)
+            || (_isChangingFocus && ![_focusedFormControlView isHidden])
+#else
+            || _isChangingFocus
 #endif
+#if ENABLE(DRAG_SUPPORT)
+            || _dragDropInteractionState.isPerformingDrop()
+#endif
+            || changingActivityState;
     }
-    if (!shouldShowKeyboard)
-        return;
 
     if (blurPreviousNode)
         [self _stopAssistingNode];
 
+    if (!shouldShowKeyboard)
+        return;
+
     if (!isAssistableInputType(information.elementType))
         return;
 
@@ -4216,6 +4224,16 @@
         [_inputNavigationViewControllerForFullScreenInputs pushViewController:_presentedFullScreenInputViewController.get() animated:YES];
     else
         [presentingViewController presentViewController:_presentedFullScreenInputViewController.get() animated:YES completion:nil];
+
+    // Presenting a fullscreen input view controller fully obscures the web view. Without taking this token, the web content process will get backgrounded.
+    _page->process().takeBackgroundActivityTokenForFullscreenInput();
+
+    [presentingViewController.transitionCoordinator animateAlongsideTransition:nil completion:[weakWebView = WeakObjCPtr<WKWebView>(_webView), controller = _presentedFullScreenInputViewController] (id <UIViewControllerTransitionCoordinatorContext>) {
+        auto strongWebView = weakWebView.get();
+        id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>([strongWebView UIDelegate]);
+        if ([uiDelegate respondsToSelector:@selector(_webView:didPresentFocusedElementViewController:)])
+            [uiDelegate _webView:strongWebView.get() didPresentFocusedElementViewController:controller.get()];
+    }];
 }
 
 - (void)dismissAllInputViewControllers:(BOOL)animated
@@ -4223,16 +4241,28 @@
     auto navigationController = WTFMove(_inputNavigationViewControllerForFullScreenInputs);
     auto presentedController = WTFMove(_presentedFullScreenInputViewController);
 
+    if (!presentedController)
+        return;
+
     if ([navigationController viewControllers].lastObject == presentedController.get())
         [navigationController popViewControllerAnimated:animated];
     else
         [presentedController dismissViewControllerAnimated:animated completion:nil];
 
+    [[presentedController transitionCoordinator] animateAlongsideTransition:nil completion:[weakWebView = WeakObjCPtr<WKWebView>(_webView), controller = presentedController] (id <UIViewControllerTransitionCoordinatorContext>) {
+        auto strongWebView = weakWebView.get();
+        id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>([strongWebView UIDelegate]);
+        if ([uiDelegate respondsToSelector:@selector(_webView:didDismissFocusedElementViewController:)])
+            [uiDelegate _webView:strongWebView.get() didDismissFocusedElementViewController:controller.get()];
+    }];
+
     if (_shouldRestoreFirstResponderStatusAfterLosingFocus) {
         _shouldRestoreFirstResponderStatusAfterLosingFocus = NO;
         if (!self.isFirstResponder)
             [self becomeFirstResponder];
     }
+
+    _page->process().releaseBackgroundActivityTokenForFullscreenInput();
 }
 
 - (void)focusedFormControlViewDidSubmit:(WKFocusedFormControlView *)view
@@ -4249,8 +4279,12 @@
 - (void)focusedFormControlViewDidBeginEditing:(WKFocusedFormControlView *)view
 {
     [self updateCurrentAssistedNodeInformation:[weakSelf = WeakObjCPtr<WKContentView>(self)] (bool didUpdate) {
-        if (didUpdate)
-            [weakSelf presentViewControllerForCurrentAssistedNode];
+        if (!didUpdate)
+            return;
+
+        auto strongSelf = weakSelf.get();
+        [strongSelf presentViewControllerForCurrentAssistedNode];
+        [strongSelf->_focusedFormControlView hide:YES];
     }];
 }
 
@@ -5401,8 +5435,13 @@
 
 - (void)selectFormAccessoryPickerRow:(NSInteger)rowIndex
 {
+#if ENABLE(EXTRA_ZOOM_MODE)
+    if ([_presentedFullScreenInputViewController isKindOfClass:[WKSelectMenuListViewController class]])
+        [(WKSelectMenuListViewController *)_presentedFullScreenInputViewController.get() selectItemAtIndex:rowIndex];
+#else
     if ([_inputPeripheral isKindOfClass:[WKFormSelectControl self]])
         [(WKFormSelectControl *)_inputPeripheral selectRow:rowIndex inComponent:0 extendingSelection:NO];
+#endif
 }
 
 - (NSString *)selectFormPopoverTitle

Modified: trunk/Tools/ChangeLog (230751 => 230752)


--- trunk/Tools/ChangeLog	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Tools/ChangeLog	2018-04-18 06:03:06 UTC (rev 230752)
@@ -1,3 +1,24 @@
+2018-04-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
+        https://bugs.webkit.org/show_bug.cgi?id=184635
+        <rdar://problem/39440642>
+
+        Reviewed by Tim Horton.
+
+        Add plumbing to support invoking `didHideKeyboardCallback` and `didShowKeyboardCallback` when (respectively)
+        dismissing or presenting fullscreen input view controllers in extra zoom mode.
+
+        * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+        (-[TestRunnerWKWebView initWithFrame:configuration:]):
+        (-[TestRunnerWKWebView dealloc]):
+        (-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
+        (-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
+        (-[TestRunnerWKWebView _keyboardDidShow:]):
+        (-[TestRunnerWKWebView _keyboardDidHide:]):
+        (-[TestRunnerWKWebView _webView:didPresentFocusedElementViewController:]):
+        (-[TestRunnerWKWebView _webView:didDismissFocusedElementViewController:]):
+
 2018-04-17  Michael Catanzaro  <mcatanz...@igalia.com>
 
         [GTK] Webkit should spoof as Safari on a Mac for Outlook.com

Modified: trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm (230751 => 230752)


--- trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm	2018-04-18 05:45:22 UTC (rev 230751)
+++ trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm	2018-04-18 06:03:06 UTC (rev 230752)
@@ -27,6 +27,7 @@
 #import "TestRunnerWKWebView.h"
 
 #import "WebKitTestRunnerDraggingInfo.h"
+#import <WebKit/WKUIDelegatePrivate.h>
 #import <wtf/Assertions.h>
 #import <wtf/RetainPtr.h>
 
@@ -46,12 +47,11 @@
 
 #if WK_API_ENABLED
 
-@interface TestRunnerWKWebView () {
+@interface TestRunnerWKWebView () <WKUIDelegatePrivate> {
     RetainPtr<NSNumber *> m_stableStateOverride;
 }
 
 @property (nonatomic, copy) void (^zoomToScaleCompletionHandler)(void);
-@property (nonatomic, copy) void (^showKeyboardCompletionHandler)(void);
 @property (nonatomic, copy) void (^retrieveSpeakSelectionContentCompletionHandler)(void);
 @property (nonatomic) BOOL isShowingKeyboard;
 
@@ -72,8 +72,10 @@
 {
     if (self = [super initWithFrame:frame configuration:configuration]) {
         NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-        [center addObserver:self selector:@selector(_keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
-        [center addObserver:self selector:@selector(_keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
+        [center addObserver:self selector:@selector(_invokeShowKeyboardCallbackIfNecessary) name:UIKeyboardDidShowNotification object:nil];
+        [center addObserver:self selector:@selector(_invokeHideKeyboardCallbackIfNecessary) name:UIKeyboardDidHideNotification object:nil];
+
+        self.UIDelegate = self;
     }
     return self;
 }
@@ -94,7 +96,6 @@
     self.rotationDidEndCallback = nil;
 
     self.zoomToScaleCompletionHandler = nil;
-    self.showKeyboardCompletionHandler = nil;
     self.retrieveSpeakSelectionContentCompletionHandler = nil;
 
     [super dealloc];
@@ -139,7 +140,7 @@
     [self.scrollView setZoomScale:scale animated:animated];
 }
 
-- (void)_keyboardDidShow:(NSNotification *)notification
+- (void)_invokeShowKeyboardCallbackIfNecessary
 {
     if (self.isShowingKeyboard)
         return;
@@ -149,7 +150,7 @@
         self.didShowKeyboardCallback();
 }
 
-- (void)_keyboardDidHide:(NSNotification *)notification
+- (void)_invokeHideKeyboardCallbackIfNecessary
 {
     if (!self.isShowingKeyboard)
         return;
@@ -231,8 +232,22 @@
     return _overrideSafeAreaInsets;
 }
 
-#endif
+#pragma mark - WKUIDelegatePrivate
 
+// In extra zoom mode, fullscreen form control UI takes on the same role as keyboards and input view controllers
+// in UIKit. As such, we allow keyboard presentation and dismissal callbacks to work in extra zoom mode as well.
+- (void)_webView:(WKWebView *)webView didPresentFocusedElementViewController:(UIViewController *)controller
+{
+    [self _invokeShowKeyboardCallbackIfNecessary];
+}
+
+- (void)_webView:(WKWebView *)webView didDismissFocusedElementViewController:(UIViewController *)controller
+{
+    [self _invokeHideKeyboardCallbackIfNecessary];
+}
+
+#endif // PLATFORM(IOS)
+
 @end
 
 #endif // WK_API_ENABLED
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to