Changeset 244370 in webkit
- Timestamp:
- Apr 16, 2019 8:34:10 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r244359 r244370 1 2019-04-16 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss] 4 https://bugs.webkit.org/show_bug.cgi?id=196919 5 <rdar://problem/41630459> 6 7 Reviewed by Tim Horton. 8 9 Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text. 10 The test then activates this custom menu item and checks that the selection rects after triggering this custom 11 action are updated, and the callout bar is still showing. 12 13 * editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added. 14 * editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added. 15 16 This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure 17 that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by 18 tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in 19 automation; when navigating submenus in the callout bar, the next button can't be tapped until the current 20 callout bar transition animation is complete, but there's no delegate method invoked or notification posted when 21 this happens. 22 23 * resources/ui-helper.js: 24 (window.UIHelper.isShowingMenu): 25 (window.UIHelper.isDismissingMenu): 26 (window.UIHelper.rectForMenuAction): 27 (window.UIHelper.async.chooseMenuAction): 28 29 Additionally add a few more UIHelper methods. 30 31 (window.UIHelper): 32 1 33 2019-04-16 John Wilander <wilander@apple.com> 2 34 -
trunk/LayoutTests/resources/ui-helper.js
r244220 r244370 828 828 } 829 829 830 static isShowingMenu() 831 { 832 return new Promise(resolve => { 833 testRunner.runUIScript(`uiController.isShowingMenu`, result => resolve(result === "true")); 834 }); 835 } 836 837 static isDismissingMenu() 838 { 839 return new Promise(resolve => { 840 testRunner.runUIScript(`uiController.isDismissingMenu`, result => resolve(result === "true")); 841 }); 842 } 843 830 844 static menuRect() 831 845 { … … 839 853 return new Promise(resolve => testRunner.runUIScript(`uiController.setHardwareKeyboardAttached(${attached ? "true" : "false"})`, resolve)); 840 854 } 855 856 static rectForMenuAction(action) 857 { 858 return new Promise(resolve => { 859 testRunner.runUIScript(` 860 const rect = uiController.rectForMenuAction("${action}"); 861 uiController.uiScriptComplete(rect ? JSON.stringify(rect) : ""); 862 `, stringResult => { 863 resolve(stringResult.length ? JSON.parse(stringResult) : null); 864 }); 865 }); 866 } 867 868 static async chooseMenuAction(action) 869 { 870 const menuRect = await this.rectForMenuAction(action); 871 if (menuRect) 872 await this.activateAt(menuRect.left + menuRect.width / 2, menuRect.top + menuRect.height / 2); 873 } 841 874 } -
trunk/Source/WebKit/ChangeLog
r244369 r244370 1 2019-04-16 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss] 4 https://bugs.webkit.org/show_bug.cgi?id=196919 5 <rdar://problem/41630459> 6 7 Reviewed by Tim Horton. 8 9 Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new 10 layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html. 11 12 * Platform/spi/ios/UIKitSPI.h: 13 14 Declare the private -dontDismiss property of UIMenuItem. 15 16 * UIProcess/API/Cocoa/WKWebView.mm: 17 (-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]): 18 19 Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case 20 where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu 21 controller. This scenario is exercised by the new layout test. 22 23 * UIProcess/ios/WKContentViewInteraction.h: 24 * UIProcess/ios/WKContentViewInteraction.mm: 25 (-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]): 26 27 If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes 28 to fade the callout bar until after the next remote layer tree commit. 29 30 (-[WKContentView _updateChangedSelection:]): 31 32 Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss 33 property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons 34 (which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however, 35 if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen 36 would be stale after triggering these actions. This effect is most noticeable when bolding text. 37 38 (-[WKContentView shouldAllowHidingSelectionCommands]): 39 1 40 2019-04-16 Ross Kirsling <ross.kirsling@sony.com> 2 41 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r244085 r244370 49 49 #import <UIKit/UIKeyboard_Private.h> 50 50 #import <UIKit/UILongPressGestureRecognizer_Private.h> 51 #import <UIKit/UIMenuController_Private.h> 51 52 #import <UIKit/UIPeripheralHost.h> 52 53 #import <UIKit/UIPeripheralHost_Private.h> … … 988 989 #endif 989 990 991 @interface UIMenuItem (UIMenuController_SPI) 992 @property (nonatomic) BOOL dontDismiss; 993 @end 994 990 995 @interface UICalloutBar : UIView 991 996 + (UICalloutBar *)activeCalloutBar; -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
r244220 r244370 1554 1554 } 1555 1555 1556 - (void)willFinishIgnoringCalloutBarFadeAfterPerformingAction 1557 { 1558 [_contentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]; 1559 } 1560 1556 1561 static inline CGFloat floorToDevicePixel(CGFloat input, float deviceScaleFactor) 1557 1562 { -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
r244296 r244370 320 320 321 321 BOOL _hasSetUpInteractions; 322 NSUInteger _ignoreSelectionCommandFadeCount; 322 323 CompletionHandler<void(WebCore::DOMPasteAccessResponse)> _domPasteRequestHandler; 323 324 BlockPtr<void(UIWKAutocorrectionContext *)> _pendingAutocorrectionContextHandler; … … 450 451 - (void)_didChangeWebViewEditability; 451 452 453 - (void)willFinishIgnoringCalloutBarFadeAfterPerformingAction; 454 452 455 // UIWebFormAccessoryDelegate protocol 453 456 - (void)accessoryDone; -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r244368 r244370 3881 3881 } 3882 3882 3883 - (void)willFinishIgnoringCalloutBarFadeAfterPerformingAction 3884 { 3885 _ignoreSelectionCommandFadeCount++; 3886 _page->callAfterNextPresentationUpdate([weakSelf = WeakObjCPtr<WKContentView>(self)] (auto) { 3887 if (auto strongSelf = weakSelf.get()) 3888 strongSelf->_ignoreSelectionCommandFadeCount--; 3889 }); 3890 } 3891 3883 3892 - (void)_didChangeWebViewEditability 3884 3893 { … … 5648 5657 if (_textSelectionAssistant) { 5649 5658 _markedText = (_page->editorState().hasComposition) ? _page->editorState().markedText : String(); 5650 if (!_showingTextStyleOptions) 5651 [_textSelectionAssistant selectionChanged]; 5659 [_textSelectionAssistant selectionChanged]; 5652 5660 } 5653 5661 … … 5669 5677 _needsDeferredEndScrollingSelectionUpdate = NO; 5670 5678 } 5679 } 5680 5681 - (BOOL)shouldAllowHidingSelectionCommands 5682 { 5683 ASSERT(_ignoreSelectionCommandFadeCount >= 0); 5684 return !_ignoreSelectionCommandFadeCount; 5671 5685 } 5672 5686 -
trunk/Tools/ChangeLog
r244368 r244370 1 2019-04-16 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss] 4 https://bugs.webkit.org/show_bug.cgi?id=196919 5 <rdar://problem/41630459> 6 7 Reviewed by Tim Horton. 8 9 Add iOS support for several new testing hooks. See below for more detail. 10 11 * DumpRenderTree/ios/UIScriptControllerIOS.mm: 12 (WTR::UIScriptController::isDismissingMenu const): 13 14 Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done 15 dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent 16 by UIKit when dismissing the callout bar (i.e. UIMenuController). 17 18 * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: 19 * TestRunnerShared/UIScriptContext/UIScriptController.cpp: 20 (WTR::UIScriptController::isDismissingMenu const): 21 * TestRunnerShared/UIScriptContext/UIScriptController.h: 22 * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: 23 * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: 24 (WTR::InjectedBundle::didReceiveMessageToPage): 25 * WebKitTestRunner/InjectedBundle/TestRunner.cpp: 26 (WTR::TestRunner::setAllowedMenuActions): 27 28 Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of 29 actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or 30 "Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match 31 against the name of the custom action. 32 33 (WTR::TestRunner::installCustomMenuAction): 34 35 Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This 36 takes the name of the action (which appears in a button in the callout bar), whether the action should cause 37 the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is 38 triggered. 39 40 (WTR::TestRunner::performCustomMenuAction): 41 42 Invoked when the custom menu action is triggered. 43 44 * WebKitTestRunner/InjectedBundle/TestRunner.h: 45 * WebKitTestRunner/TestController.cpp: 46 (WTR::TestController::installCustomMenuAction): 47 (WTR::TestController::setAllowedMenuActions): 48 * WebKitTestRunner/TestController.h: 49 * WebKitTestRunner/TestInvocation.cpp: 50 (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): 51 (WTR::TestInvocation::performCustomMenuAction): 52 53 Add plumbing to call back into the injected bundle when performing the custom action. 54 55 * WebKitTestRunner/TestInvocation.h: 56 * WebKitTestRunner/cocoa/TestControllerCocoa.mm: 57 (WTR::TestController::installCustomMenuAction): 58 (WTR::TestController::setAllowedMenuActions): 59 * WebKitTestRunner/cocoa/TestRunnerWKWebView.h: 60 * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm: 61 (-[TestRunnerWKWebView initWithFrame:configuration:]): 62 (-[TestRunnerWKWebView becomeFirstResponder]): 63 (-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]): 64 65 Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the 66 shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior 67 in the Mail app on iOS. 68 69 (-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]): 70 (-[TestRunnerWKWebView setAllowedMenuActions:]): 71 (-[TestRunnerWKWebView resetCustomMenuAction]): 72 (-[TestRunnerWKWebView performCustomAction:]): 73 (-[TestRunnerWKWebView canPerformAction:withSender:]): 74 (-[TestRunnerWKWebView _willHideMenu]): 75 (-[TestRunnerWKWebView _didHideMenu]): 76 * WebKitTestRunner/ios/TestControllerIOS.mm: 77 (WTR::TestController::platformResetStateToConsistentValues): 78 79 Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions, 80 if specified. 81 82 * WebKitTestRunner/ios/UIScriptControllerIOS.mm: 83 (WTR::UIScriptController::isDismissingMenu const): 84 1 85 2019-04-16 Megan Gardner <megan_gardner@apple.com> 2 86 -
trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm
r244220 r244370 382 382 } 383 383 384 bool UIScriptController::isDismissingMenu() const 385 { 386 return false; 387 } 388 384 389 void UIScriptController::platformSetDidEndScrollingCallback() 385 390 { -
trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
r244220 r244370 228 228 attribute object didShowMenuCallback; 229 229 attribute object didHideMenuCallback; 230 readonly attribute boolean isDismissingMenu; 230 231 readonly attribute boolean isShowingMenu; 231 232 readonly attribute object menuRect; -
trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp
r244220 r244370 599 599 } 600 600 601 bool UIScriptController::isDismissingMenu() const 602 { 603 return false; 604 } 605 601 606 bool UIScriptController::isShowingMenu() const 602 607 { -
trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
r244220 r244370 176 176 JSValueRef willPresentPopoverCallback() const; 177 177 178 bool isDismissingMenu() const; 178 179 bool isShowingMenu() const; 179 180 JSObjectRef rectForMenuAction(JSStringRef action) const; -
trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
r244288 r244370 272 272 273 273 void accummulateLogsForChannel(DOMString channel); 274 275 // Contextual menu actions 276 void setAllowedMenuActions(object actions); 277 void installCustomMenuAction(DOMString name, boolean dismissesAutomatically, object callback); 274 278 275 279 // Gamepad -
trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
r243927 r244370 446 446 return; 447 447 } 448 449 if (WKStringIsEqualToUTF8CString(messageName, "PerformCustomMenuAction")) { 450 m_testRunner->performCustomMenuAction(); 451 return; 452 } 448 453 449 454 WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); -
trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
r244288 r244370 794 794 TextFieldDidBeginEditingCallbackID, 795 795 TextFieldDidEndEditingCallbackID, 796 CustomMenuActionCallbackID, 796 797 FirstUIScriptCallbackID = 100 797 798 }; … … 1341 1342 JSValueRef resultValue = JSValueMakeString(context, result); 1342 1343 callTestRunnerCallback(callbackID, 1, &resultValue); 1344 } 1345 1346 void TestRunner::setAllowedMenuActions(JSValueRef actions) 1347 { 1348 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAllowedMenuActions")); 1349 WKRetainPtr<WKMutableArrayRef> messageBody(AdoptWK, WKMutableArrayCreate()); 1350 1351 auto page = InjectedBundle::singleton().page()->page(); 1352 auto mainFrame = WKBundlePageGetMainFrame(page); 1353 auto context = WKBundleFrameGetJavaScriptContext(mainFrame); 1354 auto lengthPropertyName = adopt(JSStringCreateWithUTF8CString("length")); 1355 auto actionsArray = JSValueToObject(context, actions, nullptr); 1356 auto lengthValue = JSObjectGetProperty(context, actionsArray, lengthPropertyName.get(), nullptr); 1357 if (!JSValueIsNumber(context, lengthValue)) 1358 return; 1359 1360 auto length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0)); 1361 for (size_t i = 0; i < length; ++i) { 1362 auto value = JSObjectGetPropertyAtIndex(context, actionsArray, i, 0); 1363 if (!JSValueIsString(context, value)) 1364 continue; 1365 1366 auto actionName = adopt(JSValueToStringCopy(context, value, 0)); 1367 WKRetainPtr<WKStringRef> action(AdoptWK, WKStringCreateWithJSString(actionName.get())); 1368 WKArrayAppendItem(messageBody.get(), action.get()); 1369 } 1370 1371 WKBundlePagePostMessage(page, messageName.get(), messageBody.get()); 1372 } 1373 1374 void TestRunner::installCustomMenuAction(JSStringRef name, bool dismissesAutomatically, JSValueRef callback) 1375 { 1376 cacheTestRunnerCallback(CustomMenuActionCallbackID, callback); 1377 1378 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("InstallCustomMenuAction")); 1379 WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); 1380 1381 WKRetainPtr<WKStringRef> nameKey(AdoptWK, WKStringCreateWithUTF8CString("name")); 1382 WKRetainPtr<WKStringRef> nameValue(AdoptWK, WKStringCreateWithJSString(name)); 1383 WKDictionarySetItem(messageBody.get(), nameKey.get(), nameValue.get()); 1384 1385 WKRetainPtr<WKStringRef> dismissesAutomaticallyKey(AdoptWK, WKStringCreateWithUTF8CString("dismissesAutomatically")); 1386 WKRetainPtr<WKBooleanRef> dismissesAutomaticallyValue(AdoptWK, WKBooleanCreate(dismissesAutomatically)); 1387 WKDictionarySetItem(messageBody.get(), dismissesAutomaticallyKey.get(), dismissesAutomaticallyValue.get()); 1388 1389 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); 1343 1390 } 1344 1391 … … 2466 2513 } 2467 2514 2515 void TestRunner::performCustomMenuAction() 2516 { 2517 callTestRunnerCallback(CustomMenuActionCallbackID); 2518 } 2519 2468 2520 size_t TestRunner::userScriptInjectedCount() const 2469 2521 { -
trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
r244288 r244370 355 355 void runUIScript(JSStringRef script, JSValueRef callback); 356 356 void runUIScriptCallback(unsigned callbackID, JSStringRef result); 357 358 // Contextual menu actions 359 void setAllowedMenuActions(JSValueRef); 360 void installCustomMenuAction(JSStringRef name, bool dismissesAutomatically, JSValueRef callback); 361 void performCustomMenuAction(); 357 362 358 363 void installDidBeginSwipeCallback(JSValueRef); -
trunk/Tools/WebKitTestRunner/TestController.cpp
r244288 r244370 3512 3512 } 3513 3513 3514 void TestController::installCustomMenuAction(const String&, bool) 3515 { 3516 } 3517 3518 void TestController::setAllowedMenuActions(const Vector<String>&) 3519 { 3520 } 3521 3514 3522 #endif 3515 3523 -
trunk/Tools/WebKitTestRunner/TestController.h
r244288 r244370 297 297 #endif 298 298 299 void setAllowedMenuActions(const Vector<String>&); 300 void installCustomMenuAction(const String& name, bool dismissesAutomatically); 301 299 302 bool canDoServerTrustEvaluationInNetworkProcess() const; 300 303 uint64_t serverTrustEvaluationCallbackCallsCount() const { return m_serverTrustEvaluationCallbackCallsCount; } -
trunk/Tools/WebKitTestRunner/TestInvocation.cpp
r244288 r244370 769 769 } 770 770 771 if (WKStringIsEqualToUTF8CString(messageName, "InstallCustomMenuAction")) { 772 auto messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); 773 WKRetainPtr<WKStringRef> nameKey(AdoptWK, WKStringCreateWithUTF8CString("name")); 774 WKRetainPtr<WKStringRef> name = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, nameKey.get())); 775 WKRetainPtr<WKStringRef> dismissesAutomaticallyKey(AdoptWK, WKStringCreateWithUTF8CString("dismissesAutomatically")); 776 auto dismissesAutomatically = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dismissesAutomaticallyKey.get())); 777 TestController::singleton().installCustomMenuAction(toWTFString(name.get()), WKBooleanGetValue(dismissesAutomatically)); 778 return; 779 } 780 781 if (WKStringIsEqualToUTF8CString(messageName, "SetAllowedMenuActions")) { 782 auto messageBodyArray = static_cast<WKArrayRef>(messageBody); 783 auto size = WKArrayGetSize(messageBodyArray); 784 Vector<String> actions; 785 actions.reserveInitialCapacity(size); 786 for (size_t index = 0; index < size; ++index) 787 actions.append(toWTFString(static_cast<WKStringRef>(WKArrayGetItemAtIndex(messageBodyArray, index)))); 788 TestController::singleton().setAllowedMenuActions(actions); 789 return; 790 } 791 771 792 if (WKStringIsEqualToUTF8CString(messageName, "SetOpenPanelFileURLs")) { 772 793 TestController::singleton().setOpenPanelFileURLs(static_cast<WKArrayRef>(messageBody)); … … 1786 1807 } 1787 1808 1809 void TestInvocation::performCustomMenuAction() 1810 { 1811 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("PerformCustomMenuAction")); 1812 WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); 1813 } 1814 1788 1815 } // namespace WTR -
trunk/Tools/WebKitTestRunner/TestInvocation.h
r241451 r244370 89 89 90 90 void dumpAdClickAttribution(); 91 void performCustomMenuAction(); 91 92 92 93 private: -
trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm
r244134 r244370 401 401 } 402 402 403 void TestController::installCustomMenuAction(const String& name, bool dismissesAutomatically) 404 { 405 #if PLATFORM(IOS_FAMILY) 406 auto* invocation = m_currentInvocation.get(); 407 [m_mainWebView->platformView() installCustomMenuAction:name dismissesAutomatically:dismissesAutomatically callback:[invocation] { 408 if (TestController::singleton().isCurrentInvocation(invocation)) 409 invocation->performCustomMenuAction(); 410 }]; 411 #else 412 UNUSED_PARAM(name); 413 UNUSED_PARAM(dismissesAutomatically); 414 #endif 415 } 416 417 void TestController::setAllowedMenuActions(const Vector<String>& actions) 418 { 419 #if PLATFORM(IOS_FAMILY) 420 auto actionNames = adoptNS([[NSMutableArray<NSString *> alloc] initWithCapacity:actions.size()]); 421 for (auto action : actions) 422 [actionNames addObject:action]; 423 [m_mainWebView->platformView() setAllowedMenuActions:actionNames.get()]; 424 #else 425 UNUSED_PARAM(actions); 426 #endif 427 } 428 403 429 bool TestController::isDoingMediaCapture() const 404 430 { -
trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.h
r244096 r244370 50 50 @property (nonatomic, copy) NSString *accessibilitySpeakSelectionContent; 51 51 52 - (void)setAllowedMenuActions:(NSArray<NSString *> *)actions; 53 54 - (void)resetCustomMenuAction; 55 - (void)installCustomMenuAction:(NSString *)name dismissesAutomatically:(BOOL)dismissesAutomatically callback:(dispatch_block_t)callback; 56 52 57 - (void)resetInteractionCallbacks; 53 58 - (void)zoomToScale:(double)scale animated:(BOOL)animated completionHandler:(void (^)(void))completionHandler; … … 59 64 @property (nonatomic, readonly, getter=isShowingKeyboard) BOOL showingKeyboard; 60 65 @property (nonatomic, readonly, getter=isShowingMenu) BOOL showingMenu; 66 @property (nonatomic, readonly, getter=isDismissingMenu) BOOL dismissingMenu; 61 67 @property (nonatomic, readonly, getter=isShowingPopover) BOOL showingPopover; 62 68 @property (nonatomic, assign) BOOL usesSafariLikeRotation; -
trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm
r244096 r244370 30 30 #import <WebKit/WKUIDelegatePrivate.h> 31 31 #import <wtf/Assertions.h> 32 #import <wtf/BlockPtr.h> 33 #import <wtf/Optional.h> 32 34 #import <wtf/RetainPtr.h> 33 35 … … 46 48 #endif 47 49 50 struct CustomMenuActionInfo { 51 RetainPtr<NSString> name; 52 BOOL dismissesAutomatically { NO }; 53 BlockPtr<void()> callback; 54 }; 55 48 56 @interface TestRunnerWKWebView () <WKUIDelegatePrivate> { 49 57 RetainPtr<NSNumber> m_stableStateOverride; 50 58 BOOL _isInteractingWithFormControl; 51 59 BOOL _scrollingUpdatesDisabled; 60 Optional<CustomMenuActionInfo> _customMenuActionInfo; 61 RetainPtr<NSArray<NSString *>> _allowedMenuActions; 52 62 } 53 63 … … 56 66 @property (nonatomic, getter=isShowingKeyboard, setter=setIsShowingKeyboard:) BOOL showingKeyboard; 57 67 @property (nonatomic, getter=isShowingMenu, setter=setIsShowingMenu:) BOOL showingMenu; 68 @property (nonatomic, getter=isDismissingMenu, setter=setIsDismissingMenu:) BOOL dismissingMenu; 58 69 @property (nonatomic, getter=isShowingPopover, setter=setIsShowingPopover:) BOOL showingPopover; 59 70 … … 80 91 [center addObserver:self selector:@selector(_invokeHideKeyboardCallbackIfNecessary) name:UIKeyboardDidHideNotification object:nil]; 81 92 [center addObserver:self selector:@selector(_didShowMenu) name:UIMenuControllerDidShowMenuNotification object:nil]; 93 [center addObserver:self selector:@selector(_willHideMenu) name:UIMenuControllerWillHideMenuNotification object:nil]; 82 94 [center addObserver:self selector:@selector(_didHideMenu) name:UIMenuControllerDidHideMenuNotification object:nil]; 83 95 [center addObserver:self selector:@selector(_willPresentPopover) name:@"UIPopoverControllerWillPresentPopoverNotification" object:nil]; … … 131 143 if (self.didDismissForcePressPreviewCallback) 132 144 self.didDismissForcePressPreviewCallback(); 145 } 146 147 - (BOOL)becomeFirstResponder 148 { 149 BOOL wasFirstResponder = self.isFirstResponder; 150 BOOL becameFirstResponder = [super becomeFirstResponder]; 151 if (!wasFirstResponder && becameFirstResponder) 152 [self _addCustomItemToMenuControllerIfNecessary]; 153 return becameFirstResponder; 154 } 155 156 - (void)_addCustomItemToMenuControllerIfNecessary 157 { 158 if (!_customMenuActionInfo) 159 return; 160 161 auto item = adoptNS([[UIMenuItem alloc] initWithTitle:_customMenuActionInfo->name.get() action:@selector(performCustomAction:)]); 162 [item setDontDismiss:!_customMenuActionInfo->dismissesAutomatically]; 163 UIMenuController *controller = UIMenuController.sharedMenuController; 164 controller.menuItems = @[ item.get() ]; 165 [controller update]; 166 } 167 168 - (void)installCustomMenuAction:(NSString *)name dismissesAutomatically:(BOOL)dismissesAutomatically callback:(dispatch_block_t)callback 169 { 170 _customMenuActionInfo = {{ name, dismissesAutomatically, callback }}; 171 [self _addCustomItemToMenuControllerIfNecessary]; 172 } 173 174 - (void)setAllowedMenuActions:(NSArray<NSString *> *)actions 175 { 176 _allowedMenuActions = actions; 177 } 178 179 - (void)resetCustomMenuAction 180 { 181 _customMenuActionInfo.reset(); 182 UIMenuController.sharedMenuController.menuItems = @[ ]; 183 } 184 185 - (void)performCustomAction:(id)sender 186 { 187 if (!_customMenuActionInfo) 188 return; 189 190 if (!_customMenuActionInfo->callback) { 191 ASSERT_NOT_REACHED(); 192 return; 193 } 194 195 _customMenuActionInfo->callback(); 196 } 197 198 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender 199 { 200 BOOL isCustomAction = action == @selector(performCustomAction:); 201 BOOL canPerformActionByDefault = [super canPerformAction:action withSender:sender]; 202 if (isCustomAction) 203 canPerformActionByDefault = _customMenuActionInfo.hasValue(); 204 205 if (canPerformActionByDefault && _allowedMenuActions && sender == UIMenuController.sharedMenuController) { 206 BOOL isAllowed = NO; 207 if (isCustomAction) { 208 for (NSString *allowedAction in _allowedMenuActions.get()) { 209 if ([[_customMenuActionInfo->name lowercaseString] isEqualToString:allowedAction.lowercaseString]) { 210 isAllowed = YES; 211 break; 212 } 213 } 214 } else { 215 for (NSString *allowedAction in _allowedMenuActions.get()) { 216 NSString *lowercaseSelectorName = [[allowedAction lowercaseString] stringByAppendingString:@":"]; 217 if ([NSStringFromSelector(action).lowercaseString isEqualToString:lowercaseSelectorName]) { 218 isAllowed = YES; 219 break; 220 } 221 } 222 } 223 if (!isAllowed) 224 return NO; 225 } 226 return canPerformActionByDefault; 133 227 } 134 228 … … 196 290 } 197 291 292 - (void)_willHideMenu 293 { 294 self.dismissingMenu = YES; 295 } 296 198 297 - (void)_didHideMenu 199 298 { 299 self.dismissingMenu = NO; 300 200 301 if (!self.showingMenu) 201 302 return; -
trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm
r244220 r244370 164 164 [webView _clearInterfaceOrientationOverride]; 165 165 [webView resetInteractionCallbacks]; 166 [webView resetCustomMenuAction]; 167 [webView setAllowedMenuActions:nil]; 166 168 167 169 UIScrollView *scrollView = webView.scrollView; -
trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm
r244220 r244370 972 972 } 973 973 974 bool UIScriptController::isDismissingMenu() const 975 { 976 return TestController::singleton().mainWebView()->platformView().dismissingMenu; 977 } 978 974 979 bool UIScriptController::isShowingMenu() const 975 980 {
Note: See TracChangeset
for help on using the changeset viewer.