Hide next and previous form control buttons when WKWebView is editable
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Apr 2019 02:25:36 +0000 (02:25 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Apr 2019 02:25:36 +0000 (02:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196672
<rdar://problem/35625321>

Reviewed by Tim Horton.

Source/WebKit:

Adopt new UIKit SPI to hide or show next and previous controls in the form accessory view when changing
editability.

Test: KeyboardInputTests.FormNavigationAssistantBarButtonItems

* Platform/spi/ios/UIKitSPI.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _setEditable:]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _updateAccessory]):
(-[WKContentView _didChangeWebViewEditability]):

Tools:

Add a new API test.

* TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(-[TestWKWebView lastTrailingBarButtonGroup]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/UIKitSPI.h:

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

Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/UIKitSPI.h
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm
Tools/TestWebKitAPI/ios/UIKitSPI.h

index 93e1233..2d08e58 100644 (file)
@@ -1,3 +1,24 @@
+2019-04-06  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Hide next and previous form control buttons when WKWebView is editable
+        https://bugs.webkit.org/show_bug.cgi?id=196672
+        <rdar://problem/35625321>
+
+        Reviewed by Tim Horton.
+
+        Adopt new UIKit SPI to hide or show next and previous controls in the form accessory view when changing
+        editability.
+
+        Test: KeyboardInputTests.FormNavigationAssistantBarButtonItems
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _setEditable:]):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _updateAccessory]):
+        (-[WKContentView _didChangeWebViewEditability]):
+
 2019-04-06  Antti Koivisto  <antti@apple.com>
 
         Combine event and touch action regions into a single class
index f2a843a..9a88773 100644 (file)
@@ -1170,6 +1170,10 @@ static inline bool currentUserInterfaceIdiomIsPad()
 #endif
 }
 
+@interface UIWebFormAccessory (Staging_49666643)
+- (void)setNextPreviousItemsVisible:(BOOL)visible;
+@end
+
 WTF_EXTERN_C_BEGIN
 
 BOOL UIKeyboardEnabledInputModesAllowOneToManyShortcuts(void);
index a7f6a5e..637773c 100644 (file)
@@ -4605,11 +4605,19 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
 
 - (void)_setEditable:(BOOL)editable
 {
+    bool wasEditable = _page->isEditable();
     _page->setEditable(editable);
 #if PLATFORM(MAC)
     if (editable)
         _impl->didBecomeEditable();
 #endif
+
+    if (wasEditable == editable)
+        return;
+
+#if PLATFORM(IOS_FAMILY)
+    [_contentView _didChangeWebViewEditability];
+#endif
 }
 
 - (void)_takeFindStringFromSelection:(id)sender
index fc9bf6c..ad2fe6e 100644 (file)
@@ -447,6 +447,7 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
 - (void)_accessibilityStoreSelection;
 - (void)_accessibilityClearSelection;
 - (WKFormInputSession *)_formInputSession;
+- (void)_didChangeWebViewEditability;
 
 - (void)_requestDOMPasteAccessWithElementRect:(const WebCore::IntRect&)elementRect originIdentifier:(const String&)originIdentifier completionHandler:(CompletionHandler<void(WebCore::DOMPasteAccessResponse)>&&)completionHandler;
 
index 5b3c591..a39638a 100644 (file)
@@ -3811,6 +3811,9 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 {
     auto* accessoryView = self.formAccessoryView; // Creates one, if needed.
 
+    if ([accessoryView respondsToSelector:@selector(setNextPreviousItemsVisible:)])
+        [accessoryView setNextPreviousItemsVisible:!_webView._editable];
+
     [accessoryView setNextEnabled:_focusedElementInformation.hasNextNode];
     [accessoryView setPreviousEnabled:_focusedElementInformation.hasPreviousNode];
 
@@ -3850,6 +3853,12 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
     [self.inputDelegate selectionDidChange:self];
 }
 
+- (void)_didChangeWebViewEditability
+{
+    if ([_formAccessoryView respondsToSelector:@selector(setNextPreviousItemsVisible:)])
+        [_formAccessoryView setNextPreviousItemsVisible:!_webView._editable];
+}
+
 - (void)insertTextSuggestion:(UITextSuggestion *)textSuggestion
 {
     // FIXME: Replace NSClassFromString with actual class as soon as UIKit submitted the new class into the iOS SDK.
index 7c49237..3687d18 100644 (file)
@@ -1,3 +1,18 @@
+2019-04-06  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Hide next and previous form control buttons when WKWebView is editable
+        https://bugs.webkit.org/show_bug.cgi?id=196672
+        <rdar://problem/35625321>
+
+        Reviewed by Tim Horton.
+
+        Add a new API test.
+
+        * TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
+        (-[TestWKWebView lastTrailingBarButtonGroup]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/UIKitSPI.h:
+
 2019-04-05  Yongjun Zhang  <yongjun_zhang@apple.com>
 
         We should pass minimumEffectiveDeviceWidth to web process on new page creation.
index 2708651..777c999 100644 (file)
@@ -27,6 +27,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#import "IPadUserInterfaceSwizzler.h"
 #import "PlatformUtilities.h"
 #import "TestInputDelegate.h"
 #import "TestWKWebView.h"
@@ -140,6 +141,11 @@ static CGRect rounded(CGRect rect)
     }
 }
 
+- (UIBarButtonItemGroup *)lastTrailingBarButtonGroup
+{
+    return self.firstResponder.inputAssistantItem.trailingBarButtonGroups.lastObject;
+}
+
 @end
 
 static RetainPtr<TestWKWebView> webViewWithAutofocusedInput(const RetainPtr<TestInputDelegate>& inputDelegate)
@@ -167,6 +173,34 @@ static RetainPtr<TestWKWebView> webViewWithAutofocusedInput()
 
 namespace TestWebKitAPI {
 
+TEST(KeyboardInputTests, FormNavigationAssistantBarButtonItems)
+{
+    IPadUserInterfaceSwizzler iPadUserInterface;
+
+    auto inputDelegate = adoptNS([TestInputDelegate new]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView _setInputDelegate:inputDelegate.get()];
+    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
+        return _WKFocusStartsInputSessionPolicyAllow;
+    }];
+    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
+    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];
+
+    EXPECT_EQ(2U, [webView lastTrailingBarButtonGroup].barButtonItems.count);
+    EXPECT_FALSE([webView lastTrailingBarButtonGroup].hidden);
+
+    if (![UIWebFormAccessory instancesRespondToSelector:@selector(setNextPreviousItemsVisible:)]) {
+        // The rest of this test requires UIWebFormAccessory to be able to show or hide its next and previous items.
+        return;
+    }
+
+    [webView _setEditable:YES];
+    EXPECT_TRUE([webView lastTrailingBarButtonGroup].hidden);
+
+    [webView _setEditable:NO];
+    EXPECT_FALSE([webView lastTrailingBarButtonGroup].hidden);
+}
+
 TEST(KeyboardInputTests, ModifyInputAssistantItemBarButtonGroups)
 {
     auto inputDelegate = adoptNS([TestInputDelegate new]);
index 8dab4c0..bc86f8d 100644 (file)
@@ -30,6 +30,7 @@
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <UIKit/UIApplication_Private.h>
+#import <UIKit/UIBarButtonItemGroup_Private.h>
 #import <UIKit/UICalloutBar.h>
 #import <UIKit/UIKeyboard_Private.h>
 #import <UIKit/UIResponder_Private.h>
@@ -38,6 +39,7 @@
 #import <UIKit/UITextInput_Private.h>
 #import <UIKit/UIViewController_Private.h>
 #import <UIKit/UIWKTextInteractionAssistant.h>
+#import <UIKit/UIWebFormAccessory.h>
 
 #if PLATFORM(IOS)
 @protocol UIDragSession;
@@ -83,6 +85,13 @@ WTF_EXTERN_C_END
 - (NSDictionary *)_autofillContext;
 @end
 
+@interface UIWebFormAccessory : UIInputView
+@end
+
+@interface UIBarButtonItemGroup ()
+@property (nonatomic, readwrite, assign, getter=_isHidden, setter=_setHidden:) BOOL hidden;
+@end
+
 @protocol UITextInputMultiDocument <NSObject>
 @optional
 - (void)_preserveFocusWithToken:(id <NSCopying, NSSecureCoding>)token destructively:(BOOL)destructively;
@@ -170,4 +179,8 @@ typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
 - (void)pasteWithCompletionHandler:(void (^)(void))completionHandler;
 @end
 
+@interface UIWebFormAccessory (Staging_49666643)
+- (void)setNextPreviousItemsVisible:(BOOL)visible;
+@end
+
 #endif // PLATFORM(IOS_FAMILY)