- Revision
- 255907
- Author
- [email protected]
- Date
- 2020-02-05 22:44:38 -0800 (Wed, 05 Feb 2020)
Log Message
[iOS] Provide a way to suppress software keyboards on WKWebView's WKContentView
https://bugs.webkit.org/show_bug.cgi?id=207272
<rdar://problem/59190828>
Reviewed by Tim Horton.
Source/WebKit:
Allow SPI clients to suppress the software keyboard using -_setSuppressSoftwareKeyboard: on WKWebView by
propagating the call to the WKContentView, which is the view that actually becomes first responder when an
element (e.g. a form control) is focused.
Test: KeyboardInputTests.SuppressSoftwareKeyboard
* Platform/spi/ios/UIKitSPI.h:
* UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView _setSuppressSoftwareKeyboard:]):
Tools:
Add an API test to verify (through UIKeyboardImpl) that the software keyboard should be suppressed when setting
-_setSuppressSoftwareKeyboard: on the web view. This involves making `-makeKeyWindow` "work" in the API testing
environment on iOS, by swizzling out both `-[NSBundle bundleIdentifier]` and `-[UIApplication keyWindow]`.
* TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(TestWebKitAPI::overrideBundleIdentifier):
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(setOverriddenApplicationKeyWindow):
(applicationKeyWindowOverride):
(-[TestWKWebViewHostWindow makeKeyWindow]):
* TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:
* TestWebKitAPI/ios/UIKitSPI.h:
Also move the `UIResponder (UIKitSPI)` category from the internal section to the SPI section; this is redundant
when using the internal SDK to build, since these methods are already declared in UIResponder_Private.h.
Modified Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (255906 => 255907)
--- trunk/Source/WebKit/ChangeLog 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Source/WebKit/ChangeLog 2020-02-06 06:44:38 UTC (rev 255907)
@@ -1,3 +1,21 @@
+2020-02-05 Wenson Hsieh <[email protected]>
+
+ [iOS] Provide a way to suppress software keyboards on WKWebView's WKContentView
+ https://bugs.webkit.org/show_bug.cgi?id=207272
+ <rdar://problem/59190828>
+
+ Reviewed by Tim Horton.
+
+ Allow SPI clients to suppress the software keyboard using -_setSuppressSoftwareKeyboard: on WKWebView by
+ propagating the call to the WKContentView, which is the view that actually becomes first responder when an
+ element (e.g. a form control) is focused.
+
+ Test: KeyboardInputTests.SuppressSoftwareKeyboard
+
+ * Platform/spi/ios/UIKitSPI.h:
+ * UIProcess/API/ios/WKWebViewIOS.mm:
+ (-[WKWebView _setSuppressSoftwareKeyboard:]):
+
2020-02-05 Don Olmstead <[email protected]>
[PlayStation] Miscellaneous build fixes February 2020 edition
Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (255906 => 255907)
--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2020-02-06 06:44:38 UTC (rev 255907)
@@ -1237,6 +1237,7 @@
- (UIResponder *)firstResponder;
- (void)pasteAndMatchStyle:(id)sender;
- (void)makeTextWritingDirectionNatural:(id)sender;
+@property (nonatomic, setter=_setSuppressSoftwareKeyboard:) BOOL _suppressSoftwareKeyboard;
@end
@interface _UINavigationInteractiveTransitionBase ()
Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (255906 => 255907)
--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2020-02-06 06:44:38 UTC (rev 255907)
@@ -2851,6 +2851,12 @@
}
}
+- (void)_setSuppressSoftwareKeyboard:(BOOL)suppressSoftwareKeyboard
+{
+ [super _setSuppressSoftwareKeyboard:suppressSoftwareKeyboard];
+ [_contentView _setSuppressSoftwareKeyboard:suppressSoftwareKeyboard];
+}
+
- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler
{
if (_dynamicViewportUpdateMode != WebKit::DynamicViewportUpdateMode::NotResizing) {
Modified: trunk/Tools/ChangeLog (255906 => 255907)
--- trunk/Tools/ChangeLog 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Tools/ChangeLog 2020-02-06 06:44:38 UTC (rev 255907)
@@ -1,3 +1,27 @@
+2020-02-05 Wenson Hsieh <[email protected]>
+
+ [iOS] Provide a way to suppress software keyboards on WKWebView's WKContentView
+ https://bugs.webkit.org/show_bug.cgi?id=207272
+ <rdar://problem/59190828>
+
+ Reviewed by Tim Horton.
+
+ Add an API test to verify (through UIKeyboardImpl) that the software keyboard should be suppressed when setting
+ -_setSuppressSoftwareKeyboard: on the web view. This involves making `-makeKeyWindow` "work" in the API testing
+ environment on iOS, by swizzling out both `-[NSBundle bundleIdentifier]` and `-[UIApplication keyWindow]`.
+
+ * TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
+ (TestWebKitAPI::overrideBundleIdentifier):
+ * TestWebKitAPI/cocoa/TestWKWebView.mm:
+ (setOverriddenApplicationKeyWindow):
+ (applicationKeyWindowOverride):
+ (-[TestWKWebViewHostWindow makeKeyWindow]):
+ * TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:
+ * TestWebKitAPI/ios/UIKitSPI.h:
+
+ Also move the `UIResponder (UIKitSPI)` category from the internal section to the SPI section; this is redundant
+ when using the internal SDK to build, since these methods are already declared in UIResponder_Private.h.
+
2020-02-05 Don Olmstead <[email protected]>
[PlayStation] Build a shared _javascript_Core
Modified: trunk/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm (255906 => 255907)
--- trunk/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm 2020-02-06 06:44:38 UTC (rev 255907)
@@ -28,6 +28,7 @@
#if PLATFORM(IOS_FAMILY)
#import "IPadUserInterfaceSwizzler.h"
+#import "InstanceMethodSwizzler.h"
#import "PlatformUtilities.h"
#import "TestInputDelegate.h"
#import "TestWKWebView.h"
@@ -629,6 +630,32 @@
EXPECT_TRUE(contentView.supportsImagePaste);
}
+static NSString *overrideBundleIdentifier()
+{
+ return @"com.apple.TestWebKitAPI";
+}
+
+TEST(KeyboardInputTests, SuppressSoftwareKeyboard)
+{
+ InstanceMethodSwizzler bundleIdentifierSwizzler(NSBundle.class, @selector(bundleIdentifier), reinterpret_cast<IMP>(overrideBundleIdentifier));
+ UIApplicationInitialize();
+ UIApplicationInstantiateSingleton(UIApplication.class);
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+ [webView _setSuppressSoftwareKeyboard:YES];
+ [[webView window] makeKeyWindow];
+
+ auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);
+ [inputDelegate setFocusStartsInputSessionPolicyHandler:[&](WKWebView *, id <_WKFocusedElementInfo>) {
+ return _WKFocusStartsInputSessionPolicyAllow;
+ }];
+
+ [webView _setInputDelegate:inputDelegate.get()];
+ [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
+ [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];
+ EXPECT_TRUE(UIKeyboardImpl.sharedInstance._shouldSuppressSoftwareKeyboard);
+}
+
} // namespace TestWebKitAPI
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (255906 => 255907)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2020-02-06 06:44:38 UTC (rev 255907)
@@ -27,6 +27,7 @@
#import "TestWKWebView.h"
#import "ClassMethodSwizzler.h"
+#import "InstanceMethodSwizzler.h"
#import "TestNavigationDelegate.h"
#import "Utilities.h"
@@ -306,6 +307,30 @@
return _forceKeyWindow || [super isKeyWindow];
}
+#if PLATFORM(IOS_FAMILY)
+static NeverDestroyed<RetainPtr<UIWindow>> gOverriddenApplicationKeyWindow;
+static NeverDestroyed<std::unique_ptr<InstanceMethodSwizzler>> gApplicationKeyWindowSwizzler;
+static NeverDestroyed<std::unique_ptr<InstanceMethodSwizzler>> gSharedApplicationSwizzler;
+
+static void setOverriddenApplicationKeyWindow(UIWindow *window)
+{
+ if (gOverriddenApplicationKeyWindow.get() == window)
+ return;
+
+ ASSERT(UIApplication.sharedApplication);
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ gApplicationKeyWindowSwizzler.get() = makeUnique<InstanceMethodSwizzler>(UIApplication.class, @selector(keyWindow), reinterpret_cast<IMP>(applicationKeyWindowOverride));
+ });
+ gOverriddenApplicationKeyWindow.get() = window;
+}
+
+static UIWindow *applicationKeyWindowOverride(id, SEL)
+{
+ return gOverriddenApplicationKeyWindow.get().get();
+}
+#endif
+
- (void)makeKeyWindow
{
if (_forceKeyWindow)
@@ -315,6 +340,7 @@
#if PLATFORM(MAC)
[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidBecomeKeyNotification object:self];
#else
+ setOverriddenApplicationKeyWindow(self);
[[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeKeyNotification object:self];
#endif
}
Modified: trunk/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm (255906 => 255907)
--- trunk/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm 2020-02-06 06:44:38 UTC (rev 255907)
@@ -41,9 +41,6 @@
#import <wtf/RetainPtr.h>
#import <wtf/SoftLinking.h>
-SOFT_LINK_FRAMEWORK(UIKit)
-SOFT_LINK(UIKit, UIApplicationInstantiateSingleton, void, (Class singletonClass), (singletonClass))
-
using namespace TestWebKitAPI;
@implementation WKWebView (DragAndDropTesting)
Modified: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (255906 => 255907)
--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h 2020-02-06 06:39:28 UTC (rev 255906)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h 2020-02-06 06:44:38 UTC (rev 255907)
@@ -62,6 +62,7 @@
WTF_EXTERN_C_BEGIN
void UIApplicationInitialize(void);
+void UIApplicationInstantiateSingleton(Class principalClass);
WTF_EXTERN_C_END
@@ -195,6 +196,16 @@
@property (nonatomic, readonly) CGRect _referenceBounds;
@end
+@interface UIResponder (UIKitSPI)
+- (UIResponder *)firstResponder;
+- (void)makeTextWritingDirectionNatural:(id)sender;
+@property (nonatomic, setter=_setSuppressSoftwareKeyboard:) BOOL _suppressSoftwareKeyboard;
+@end
+
+@interface UIKeyboardImpl : UIView
++ (instancetype)sharedInstance;
+@end
+
#endif // USE(APPLE_INTERNAL_SDK)
#define UIWKDocumentRequestMarkedTextRects (1 << 5)
@@ -207,15 +218,14 @@
@property (nonatomic, copy, setter=_setTitle:) NSString *_title;
@end
-@interface UIResponder (UIKitSPI)
-- (UIResponder *)firstResponder;
-- (void)makeTextWritingDirectionNatural:(id)sender;
-@end
-
@interface UIKeyboard ()
+ (BOOL)isInHardwareKeyboardMode;
@end
+@interface UIKeyboardImpl (UIKitIPI)
+- (BOOL)_shouldSuppressSoftwareKeyboard;
+@end
+
#if PLATFORM(IOS)
@protocol UIDropInteractionDelegate_Private <UIDropInteractionDelegate>