[Extra zoom mode] Programmatically changing focus when an element already has focus...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 06:03:06 +0000 (06:03 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 06:03:06 +0000 (06:03 +0000)
commit6192a5a142185d3664f125710bd8101921d0f4e2
tree5c192bef73cb51c7f41c3bbe53d0e1c13202dd5e
parentda11470cd77fd52e1ae7d82ad3fc88ffd1ccaa54
[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):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230752 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/events/extrazoom/change-focus-during-change-event-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/extrazoom/change-focus-during-change-event.html [new file with mode: 0644]
LayoutTests/resources/ui-helper.js
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Tools/ChangeLog
Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm