[iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2018 21:22:19 +0000 (21:22 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2018 21:22:19 +0000 (21:22 +0000)
commita47f2b43426b61d12faa2af3675819cb21cda3c5
tree9aae1e5abeec966978b2cfc7900ed70c8e0f48bb
parent716f09a561026cab179619c314bc66b7eccb27b8
[iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
https://bugs.webkit.org/show_bug.cgi?id=187554
<rdar://problem/42075638>

Reviewed by Tim Horton.

Source/WebKit:

Add support for automatically switching the base writing direction to the default writing direction with respect
to the current keyboard in an editable WKWebView by implementing `-setBaseWritingDirection:forRange:`. On iOS 12
and earlier, UIKit invokes this protocol method whenever the keyboard is changed to one with a different writing
direction, although in some other versions of iOS, this only happens when first focusing an editable area.

Test: editing/input/ios/rtl-keyboard-input-on-focus.html

* Platform/spi/ios/UIKitSPI.h:

Declare UIKeyboardImpl IPI methods mostly for use in WebKitTestRunner (with the exception of
`-setInitialDirection`, which we may invoke when we receive the first post-layout EditorState update after
focusing an editable element).

* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::increaseListLevel):
(WebKit::WebPageProxy::decreaseListLevel):
(WebKit::WebPageProxy::changeListType):
(WebKit::WebPageProxy::setBaseWritingDirection):

Drive-by style fixes: make these bail and return early if `!isValid()`.

(WebKit::WebPageProxy::resetStateAfterProcessExited):

Reset assisted node state in the UI process upon web process termination.

* UIProcess/WebPageProxy.h:

Add plumbing for `setBaseWritingDirection`, from `WebPageProxy` to `WebPage` to `Editor`.

* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didReceiveEditorStateUpdateAfterFocus):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView baseWritingDirectionForPosition:inDirection:]):
(coreWritingDirection):
(-[WKContentView setBaseWritingDirection:forRange:]):

Support `-setBaseWritingDirectionForPosition:forRange:`, but only in the case where the given range is the
selected range. This is all that's currently needed to fulfill the requirements in <rdar://problem/42075638>,
though we could potentially add full support for this in the future by mapping the given text range to a DOM
range and moving the selection prior to setting the base writing direction.

(-[WKContentView _didReceiveEditorStateUpdateAfterFocus]):

Add a hook to notify WKContentView when the first post-layout EditorState has been received in the UI process.
When this is invoked, if the web view is editable and the selection is not a range, we call into `UIKeyboardImpl`
to change the initial writing direction if necessary.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::stopAssistingNode):
(WebKit::WebPageProxy::editorStateChanged):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setBaseWritingDirection):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

Add support for simulating the keyboard input mode in layout tests using UIScriptController, as well as a new
`TestOption` to make the web view editable.

* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/PlatformWebView.h:
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestController.h:
(WTR::TestController::overriddenKeyboardInputMode const):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::platformCreateWebView):
* WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
(WTR::swizzleCurrentInputMode):
(WTR::TestController::setKeyboardInputModeIdentifier):

Swizzle out several `UIKeyboardInputModeController` methods in order to convince UIKit that the user has
selected a `UIKeyboardInputMode` corresponding to the given identifier. The call to
`-prepareKeyboardInputModeFromPreferences:` is also necessary on iOS 12 in order to update cached writing
direction state in UIKit.

* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* WebKitTestRunner/mac/PlatformWebViewMac.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/win/PlatformWebViewWin.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:
(WTR::PlatformWebView::setEditable):

LayoutTests:

Add a new layout test to verify that when focusing an editable WKWebView using a right-to-left keyboard input
mode, we will set the base writing direction to be right-to-left, and vice versa.

* TestExpectations:
* editing/input/ios/rtl-keyboard-input-on-focus-expected.txt: Added.
* editing/input/ios/rtl-keyboard-input-on-focus.html: Added.
* platform/ios-wk2/TestExpectations:
* resources/ui-helper.js:

Add a UIHelper method to set the keyboard input mode to the given identifier. Example identifiers are "en_US"
(the default U.S. English keyboard) and "he_IL" (the Hebrew keyboard, which is right-to-left).

(window.UIHelper.setKeyboardInputModeIdentifier):
(window.UIHelper):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238939 268f45cc-cd09-0410-ab3c-d52691b4dbfc
36 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus-expected.txt [new file with mode: 0644]
LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus.html [new file with mode: 0644]
LayoutTests/platform/ios-wk2/TestExpectations
LayoutTests/resources/ui-helper.js
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/UIKitSPI.h
Source/WebKit/UIProcess/PageClient.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/PageClientImplIOS.h
Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm
Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp
Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
Tools/WebKitTestRunner/PlatformWebView.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestOptions.h
Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm
Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp
Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm
Tools/WebKitTestRunner/ios/TestControllerIOS.mm
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm
Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm
Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp
Tools/WebKitTestRunner/wpe/PlatformWebViewWPE.cpp