[iOS] Allow programmatic focus when hardware keyboard is attached
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Sep 2018 23:02:41 +0000 (23:02 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Sep 2018 23:02:41 +0000 (23:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190017
<rdar://problem/42270463>

Reviewed by Wenson Hsieh.

Source/WebCore:

Add support for checking if the embedding client is WebKitTestRunner and export isDumpRenderTree()
so that we can make use of it from WebKit. We will make use of these functions to keep the current
behavior of disallowing programmatic focus when running tests in these apps. This is needed to
keep testing deterministic. Otherwise, test results would be dependent on whether a hardware
keyboard is attached. When running tests in Simulator.app the hardware keyboard may also not be
connected (i.e. Hardware > Keyboard > Connect Hardware Keyboard is disabled).

* platform/RuntimeApplicationChecks.h:
* platform/cocoa/RuntimeApplicationChecksCocoa.mm:
(WebCore::IOSApplication::isWebKitTestRunner): Added.

Source/WebKit:

Make the experience of using iOS with a hardware keyboard more desktop-like by allowing
programmatic focusing of editable elements.

* Platform/spi/ios/UIKitSPI.h: Forward declare SPI.
* Shared/NativeWebKeyboardEvent.h:
* Shared/ios/NativeWebKeyboardEventIOS.mm:
(WebKit::isInHardwareKeyboardMode): Returns whether we are in hardware keyboard mode. In DumpRenderTree
and WebKitTestRunner this function always returns false to keep test results deterministic.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
Allow starting an input session if we are in hardware keyboard mode.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const): Send the full editor state if we are in hardware
keyboard mode regardless of whether layout has been performed so that UIProcess can update UI,
including the position of the caret, immediately.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236619 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/RuntimeApplicationChecks.h
Source/WebCore/platform/cocoa/RuntimeApplicationChecksCocoa.mm
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/UIKitSPI.h
Source/WebKit/Shared/NativeWebKeyboardEvent.h
Source/WebKit/Shared/ios/NativeWebKeyboardEventIOS.mm
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index 38cbd49..2276740 100644 (file)
@@ -1,3 +1,22 @@
+2018-09-28  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Allow programmatic focus when hardware keyboard is attached
+        https://bugs.webkit.org/show_bug.cgi?id=190017
+        <rdar://problem/42270463>
+
+        Reviewed by Wenson Hsieh.
+
+        Add support for checking if the embedding client is WebKitTestRunner and export isDumpRenderTree()
+        so that we can make use of it from WebKit. We will make use of these functions to keep the current
+        behavior of disallowing programmatic focus when running tests in these apps. This is needed to
+        keep testing deterministic. Otherwise, test results would be dependent on whether a hardware
+        keyboard is attached. When running tests in Simulator.app the hardware keyboard may also not be
+        connected (i.e. Hardware > Keyboard > Connect Hardware Keyboard is disabled).
+
+        * platform/RuntimeApplicationChecks.h:
+        * platform/cocoa/RuntimeApplicationChecksCocoa.mm:
+        (WebCore::IOSApplication::isWebKitTestRunner): Added.
+
 2018-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION(r236609): API tests for mso list preservation are failing
index 90d0a7f..ee3b271 100644 (file)
@@ -79,7 +79,8 @@ namespace IOSApplication {
 WEBCORE_EXPORT bool isMobileMail();
 WEBCORE_EXPORT bool isMobileSafari();
 WEBCORE_EXPORT bool isWebBookmarksD();
-bool isDumpRenderTree();
+WEBCORE_EXPORT bool isWebKitTestRunner();
+WEBCORE_EXPORT bool isDumpRenderTree();
 bool isMobileStore();
 bool isSpringBoard();
 WEBCORE_EXPORT bool isWebApp();
index 6530c02..81984e2 100644 (file)
@@ -217,6 +217,14 @@ bool IOSApplication::isDumpRenderTree()
     return isDumpRenderTree;
 }
 
+bool IOSApplication::isWebKitTestRunner()
+{
+    // We use a prefix match instead of strict equality since multiple instances of WebKitTestRunner
+    // may be launched, where the bundle identifier of each instance has a unique suffix.
+    static bool isWebKitTestRunner = applicationBundleIsEqualTo("org.webkit.WebKitTestRunnerApp"_s); // e.g. org.webkit.WebKitTestRunnerApp0
+    return isWebKitTestRunner;
+}
+
 bool IOSApplication::isMobileStore()
 {
     static bool isMobileStore = applicationBundleIsEqualTo("com.apple.MobileStore"_s);
index 3790827..6d1138b 100644 (file)
@@ -1,3 +1,27 @@
+2018-09-28  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Allow programmatic focus when hardware keyboard is attached
+        https://bugs.webkit.org/show_bug.cgi?id=190017
+        <rdar://problem/42270463>
+
+        Reviewed by Wenson Hsieh.
+
+        Make the experience of using iOS with a hardware keyboard more desktop-like by allowing
+        programmatic focusing of editable elements.
+
+        * Platform/spi/ios/UIKitSPI.h: Forward declare SPI.
+        * Shared/NativeWebKeyboardEvent.h:
+        * Shared/ios/NativeWebKeyboardEventIOS.mm:
+        (WebKit::isInHardwareKeyboardMode): Returns whether we are in hardware keyboard mode. In DumpRenderTree
+        and WebKitTestRunner this function always returns false to keep test results deterministic.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+        Allow starting an input session if we are in hardware keyboard mode.
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::platformEditorState const): Send the full editor state if we are in hardware
+        keyboard mode regardless of whether layout has been performed so that UIProcess can update UI,
+        including the position of the caret, immediately.
+
 2018-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         Rename createMarkup to serializePreservingVisualAppearance
index 44698d2..aaeca0e 100644 (file)
@@ -247,6 +247,7 @@ typedef enum {
 - (void)activate;
 - (void)geometryChangeDone:(BOOL)keyboardVisible;
 - (void)prepareForGeometryChange;
++ (BOOL)isInHardwareKeyboardMode;
 @end
 
 @interface UIKeyboardImpl : UIView <UIKeyboardCandidateListDelegate>
index 64a8f31..8dace37 100644 (file)
@@ -105,6 +105,11 @@ private:
 #endif
 };
 
+// FIXME: Find a better place for this.
+#if PLATFORM(IOS)
+bool isInHardwareKeyboardMode();
+#endif
+
 } // namespace WebKit
 
 #endif // NativeWebKeyboardEvent_h
index affb48b..3bce7ad 100644 (file)
 
 #if PLATFORM(IOS)
 
+#import "UIKitSPI.h"
 #import "WebIOSEventFactory.h"
+#import <WebCore/RuntimeApplicationChecks.h>
 
 namespace WebKit {
 
+bool isInHardwareKeyboardMode()
+{
+    return !WebCore::IOSApplication::isDumpRenderTree() && !WebCore::IOSApplication::isWebKitTestRunner() && [UIKeyboard isInHardwareKeyboardMode];
+}
+
 NativeWebKeyboardEvent::NativeWebKeyboardEvent(::WebEvent *event)
     : WebKeyboardEvent(WebIOSEventFactory::createWebKeyboardEvent(event))
     , m_nativeEvent(event)
index aaab409..7e64a5e 100644 (file)
@@ -4191,6 +4191,7 @@ static bool isAssistableInputType(InputType type)
             || (_isChangingFocus && ![_focusedFormControlView isHidden])
 #else
             || _isChangingFocus
+            || isInHardwareKeyboardMode()
 #endif
 #if ENABLE(DRAG_SUPPORT)
             || _dragDropInteractionState.isPerformingDrop()
index b5761b0..4b082cb 100644 (file)
@@ -37,6 +37,7 @@
 #import "GestureTypes.h"
 #import "InteractionInformationAtPosition.h"
 #import "Logging.h"
+#import "NativeWebKeyboardEvent.h"
 #import "PluginView.h"
 #import "PrintInfo.h"
 #import "RemoteLayerTreeDrawingArea.h"
@@ -191,12 +192,12 @@ void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePost
         }
     }
 
-    // We only set the remaining EditorState entries if the layout is done. To compute these
-    // entries, we need the layout to be done and we don't want to trigger a synchronous
-    // layout as this would be bad for performance. If we have a composition, we send everything
-    // right away as the UIProcess needs the caretRects ASAP for marked text.
-    bool frameViewHasFinishedLayout = frame.view() && !frame.view()->needsLayout();
-    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No && !frameViewHasFinishedLayout && !frame.editor().hasComposition()) {
+    // We only set the remaining EditorState entries if layout is done as a performance optimization
+    // to avoid the need to force a synchronous layout here to compute these entries. If we
+    // have a composition or are using a hardware keyboard then we send the full editor state
+    // immediately so that the UIProcess can update UI, including the position of the caret.
+    bool needsLayout = !frame.view() || frame.view()->needsLayout();
+    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No && needsLayout && !isInHardwareKeyboardMode() && !frame.editor().hasComposition()) {
         result.isMissingPostLayoutData = true;
         return;
     }