[iPad] Should open popover when the spacebar is pressed
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 21:45:03 +0000 (21:45 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 21:45:03 +0000 (21:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196360
<rdar://problem/49389129>

Patch by Daniel Bates <dabates@apple.com> on 2019-04-09
Reviewed by Brent Fulgham.

Source/WebKit:

Pressing the spacebar should open the popover for a focused popup button (e.g. <select>) on iOS
just like it does on the Mac.

For now, we keep the iPhone behavior of blurring the element when the Done button is pressed and
hence pressing spacebar does nothing (because there is no focused element).

* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView accessoryOpen]): Added. Extracted the logic from -_elementDidFocus to scroll to
the focused element, update the accessory and then tell the accessory to begin editing.
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
Write in terms of -accessoryOpen.
* UIProcess/ios/forms/WKFormPeripheralBase.mm:
(-[WKFormPeripheralBase handleKeyEvent:]): Interpret the spacebar when the peripheral is closed (!_editing)
and call -accessoryOpen to ultimately call back to this peripheral to tell it to begin editing,
which will cause the popover to appear again.

Tools:

Add testing infrastructure to support waiting for a popover to be presented or dismissed.

* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isShowingPopover const): Added.
(WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
(WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptContext.h:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setWillPresentPopoverCallback): Added.
(WTR::UIScriptController::willPresentPopoverCallback const): Added.
(WTR::UIScriptController::setDidDismissPopoverCallback): Added.
(WTR::UIScriptController::didDismissPopoverCallback const): Added.
(WTR::UIScriptController::isShowingPopover const): Added.
(WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
(WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]): Update some state.
(-[TestRunnerWKWebView resetInteractionCallbacks]): Ditto.
(-[TestRunnerWKWebView _willPresentPopover]): Added.
(-[TestRunnerWKWebView _didDismissPopover]): Added.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isShowingPopover const): Added.
(WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
(WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.

LayoutTests:

Add an iPad-specific test to ensure that pressing the spacebar opens the popover and scrolls
the form control into view.

* fast/forms/ios/ipad/open-picker-using-keyboard-expected.txt: Added.
* fast/forms/ios/ipad/open-picker-using-keyboard.html: Added.
* platform/ios/TestExpectations: Skip tests in fast/forms/ios/ipad. We will unskip for iPad below.
* platform/ipad/TestExpectations: Mark tests in fast/forms/ios/ipad as PASS so we run them.
* resources/ui-helper.js:
(window.UIHelper.waitForPopoverToPresent):
(window.UIHelper.waitForPopoverToDismiss):

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

19 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/ipad/TestExpectations
LayoutTests/resources/ui-helper.js
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.mm
Tools/ChangeLog
Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm
Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
Tools/TestRunnerShared/UIScriptContext/UIScriptContext.h
Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp
Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.h
Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

index 98ef636..b785385 100644 (file)
@@ -1,3 +1,22 @@
+2019-04-09  Daniel Bates  <dabates@apple.com>
+
+        [iPad] Should open popover when the spacebar is pressed
+        https://bugs.webkit.org/show_bug.cgi?id=196360
+        <rdar://problem/49389129>
+
+        Reviewed by Brent Fulgham.
+
+        Add an iPad-specific test to ensure that pressing the spacebar opens the popover and scrolls
+        the form control into view.
+
+        * fast/forms/ios/ipad/open-picker-using-keyboard-expected.txt: Added.
+        * fast/forms/ios/ipad/open-picker-using-keyboard.html: Added.
+        * platform/ios/TestExpectations: Skip tests in fast/forms/ios/ipad. We will unskip for iPad below.
+        * platform/ipad/TestExpectations: Mark tests in fast/forms/ios/ipad as PASS so we run them.
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForPopoverToPresent):
+        (window.UIHelper.waitForPopoverToDismiss):
+
 2019-04-09  Youenn Fablet  <youenn@apple.com>
 
         Refresh WPT service worker expectations
diff --git a/LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard-expected.txt b/LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard-expected.txt
new file mode 100644 (file)
index 0000000..86c30da
--- /dev/null
@@ -0,0 +1,22 @@
+Tests that pressing the spacebar and Escape to open and close the popover work, do not cause a value change, and that we scroll the form control into view when the popover is opened.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+After tab focused:
+PASS document.getElementById("test").value is "First"
+
+After dismissing popover by pressing Escape:
+PASS document.getElementById("test").value is "First"
+
+After opening popover by pressing spacebar:
+PASS document.getElementById("test").value is "First"
+
+After scrolling the page and pressing spacebar:
+PASS window.scrollY is non-zero.
+PASS window.scrollY is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard.html b/LayoutTests/fast/forms/ios/ipad/open-picker-using-keyboard.html
new file mode 100644 (file)
index 0000000..46dcd95
--- /dev/null
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=800">
+<script src="../../../../resources/js-test.js"></script>
+<script src="../../../../resources/ui-helper.js"></script>
+</head>
+<body style="height: 4096px">
+<!-- Place the test container above the console output to avoid the need to compensate for page scroll. -->
+<div id="test-container">
+    <p><select id="test">
+        <option>First</option>
+        <option>Second</option>
+    </select></p>
+</div>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+window.jsTestIsAsync = true;
+
+let expectedValue;
+
+const modifierDisplayNameMap = {
+    "altKey": "Option",
+    "ctrlKey": "Control",
+    "metaKey": "Command",
+    "shiftKey": "Shift",
+    "capsLockKey": "Caps Lock",
+}
+
+class KeyCommand {
+    constructor(key, modifiers = [])
+    {
+        this.key = key;
+        this.modifiers = modifiers;
+    }
+
+    toString()
+    {
+        let readableCommand = this.modifiers.map((modifier) => modifierDisplayNameMap[modifier]);
+        readableCommand.push(this.key);
+        return readableCommand.join(" + ");
+    }
+}
+
+function done()
+{
+    let testContainer = document.getElementById("test-container");
+    document.body.removeChild(testContainer);
+    finishJSTest()
+}
+
+async function runTest()
+{
+    if (!window.testRunner) {
+        testFailed("Must be run in WebKitTestRunner.");
+        done();
+        return;
+    }
+
+    async function testScrollIntoView() {
+        shouldBeNonZero("window.scrollY");
+        async function handleScroll() {
+            if (window.scrollY)
+                return;
+            shouldBeZero("window.scrollY");
+            await UIHelper.waitForPopoverToPresent();
+            UIHelper.keyDown("escape");
+            await UIHelper.waitForPopoverToDismiss();
+            done();
+        }
+        // The scroll initiated by pressing the spacebar is animated. Multiple scroll events are
+        // dispatched. We want to wait until the page scrolls to the top before continuing to ensure
+        // consistent test results.
+        window.addEventListener("scroll", handleScroll);
+        UIHelper.keyDown(" ");
+    }
+
+    async function handleFocus() {
+        debug("<br>After tab focused:");
+        shouldBeEqualToString('document.getElementById("test").value', expectedValue);
+        debug("<br>After dismissing popover by pressing Escape:");
+        UIHelper.keyDown("escape");
+        await UIHelper.waitForPopoverToDismiss();
+        shouldBeEqualToString('document.getElementById("test").value', expectedValue);
+        debug("<br>After opening popover by pressing spacebar:");
+        UIHelper.keyDown(" ");
+        await UIHelper.waitForPopoverToPresent();
+        shouldBeEqualToString('document.getElementById("test").value', expectedValue);
+        UIHelper.keyDown("escape");
+        await UIHelper.waitForPopoverToDismiss();
+        debug("<br>After scrolling the page and pressing spacebar:");
+        window.addEventListener("scroll", testScrollIntoView, { once: true });
+        window.scrollTo(0, document.body.scrollHeight); // Scroll to the bottom of the page.
+    }
+    let elementToTest = document.getElementById("test");
+    expectedValue = elementToTest.value;
+    elementToTest.addEventListener("focus", handleFocus, { once: true });
+    UIHelper.keyDown("\t", ["altKey"]);
+}
+
+description("Tests that pressing the spacebar and Escape to open and close the popover work, do not cause a value change, and that we scroll the form control into view when the popover is opened.");
+
+runTest();
+</script>
+</body>
+</html>
index 7a5173b..6bcd4cd 100644 (file)
@@ -25,6 +25,7 @@ http/tests/gzip-content-encoding [ Pass ]
 
 # iPad-specific tests skipped here and re-enabled in platform/ipad
 fast/events/ios/ipad [ Skip ]
+fast/forms/ios/ipad [ Skip ]
 
 ###
 # Unsupported and disabled features
index 515f628..1467c30 100644 (file)
@@ -1,3 +1,5 @@
+fast/forms/ios/ipad [ Pass ]
+
 # iPads don't zoom when form elements are focused
 fast/forms/ios/accessory-bar-navigation.html [ Skip ]
 fast/forms/ios/choose-select-option.html [ Skip ]
index 8399b79..94f0faa 100644 (file)
@@ -382,6 +382,38 @@ window.UIHelper = class UIHelper {
         });
     }
 
+    static waitForPopoverToPresent()
+    {
+        if (!this.isWebKit2() || !this.isIOS())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`
+                (function() {
+                    if (uiController.isShowingPopover)
+                        uiController.uiScriptComplete();
+                    else
+                        uiController.willPresentPopoverCallback = () => uiController.uiScriptComplete();
+                })()`, resolve);
+        });
+    }
+
+    static waitForPopoverToDismiss()
+    {
+        if (!this.isWebKit2() || !this.isIOS())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`
+                (function() {
+                    if (uiController.isShowingPopover)
+                        uiController.didDismissPopoverCallback = () => uiController.uiScriptComplete();
+                    else
+                        uiController.uiScriptComplete();
+                })()`, resolve);
+        });
+    }
+
     static waitForKeyboardToHide()
     {
         if (!this.isWebKit2() || !this.isIOS())
index 8fcc07e..66fcb68 100644 (file)
@@ -1,3 +1,28 @@
+2019-04-09  Daniel Bates  <dabates@apple.com>
+
+        [iPad] Should open popover when the spacebar is pressed
+        https://bugs.webkit.org/show_bug.cgi?id=196360
+        <rdar://problem/49389129>
+
+        Reviewed by Brent Fulgham.
+
+        Pressing the spacebar should open the popover for a focused popup button (e.g. <select>) on iOS
+        just like it does on the Mac.
+
+        For now, we keep the iPhone behavior of blurring the element when the Done button is pressed and
+        hence pressing spacebar does nothing (because there is no focused element).
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView accessoryOpen]): Added. Extracted the logic from -_elementDidFocus to scroll to
+        the focused element, update the accessory and then tell the accessory to begin editing.
+        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+        Write in terms of -accessoryOpen.
+        * UIProcess/ios/forms/WKFormPeripheralBase.mm:
+        (-[WKFormPeripheralBase handleKeyEvent:]): Interpret the spacebar when the peripheral is closed (!_editing)
+        and call -accessoryOpen to ultimately call back to this peripheral to tell it to begin editing,
+        which will cause the popover to appear again.
+
 2019-04-09  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, fix webkitpy failure after r244085.
index ad2fe6e..7fdd146 100644 (file)
@@ -428,7 +428,6 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
 - (void)_showPlaybackTargetPicker:(BOOL)hasVideo fromRect:(const WebCore::IntRect&)elementRect routeSharingPolicy:(WebCore::RouteSharingPolicy)policy routingContextUID:(NSString *)contextUID;
 - (void)_showRunOpenPanel:(API::OpenPanelParameters*)parameters resultListener:(WebKit::WebOpenPanelResultListenerProxy*)listener;
 - (void)_showShareSheet:(const WebCore::ShareDataWithParsedURL&)shareData completionHandler:(WTF::CompletionHandler<void(bool)>&&)completionHandler;
-- (void)accessoryDone;
 - (void)dismissFilePicker;
 - (void)_didHandleKeyEvent:(::WebEvent *)event eventWasHandled:(BOOL)eventWasHandled;
 - (Vector<WebKit::OptionItem>&) focusedSelectElementOptions;
@@ -449,6 +448,11 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
 - (WKFormInputSession *)_formInputSession;
 - (void)_didChangeWebViewEditability;
 
+// UIWebFormAccessoryDelegate protocol
+- (void)accessoryDone;
+
+- (void)accessoryOpen;
+
 - (void)_requestDOMPasteAccessWithElementRect:(const WebCore::IntRect&)elementRect originIdentifier:(const String&)originIdentifier completionHandler:(CompletionHandler<void(WebCore::DOMPasteAccessResponse)>&&)completionHandler;
 
 @property (nonatomic, readonly) WebKit::InteractionInformationAtPosition currentPositionInformation;
index 09e96ab..354189e 100644 (file)
@@ -3807,6 +3807,15 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
     return _formAccessoryView.get();
 }
 
+- (void)accessoryOpen
+{
+    if (!_inputPeripheral)
+        return;
+    [self _zoomToRevealFocusedElement];
+    [self _updateAccessory];
+    [_inputPeripheral beginEditing];
+}
+
 - (void)_updateAccessory
 {
     auto* accessoryView = self.formAccessoryView; // Creates one, if needed.
@@ -4999,9 +5008,7 @@ static RetainPtr<NSObject <WKFormPeripheral>> createInputPeripheralWithView(WebK
         if (_inputPeripheral) {
             if (!self.isFirstResponder)
                 [self becomeFirstResponder];
-            [self _zoomToRevealFocusedElement];
-            [self _updateAccessory];
-            [_inputPeripheral beginEditing];
+            [self accessoryOpen];
         }
         return;
     }
index 5f28969..841527b 100644 (file)
         [_view accessoryDone];
         return YES;
     }
+    if (!_editing && keyEvent._keyCode == kHIDUsage_KeyboardSpacebar) {
+        [_view accessoryOpen];
+        return YES;
+    }
     return NO;
 }
 
index b26f63c..1f10447 100644 (file)
@@ -1,3 +1,39 @@
+2019-04-09  Daniel Bates  <dabates@apple.com>
+
+        [iPad] Should open popover when the spacebar is pressed
+        https://bugs.webkit.org/show_bug.cgi?id=196360
+        <rdar://problem/49389129>
+
+        Reviewed by Brent Fulgham.
+
+        Add testing infrastructure to support waiting for a popover to be presented or dismissed.
+
+        * DumpRenderTree/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptController::isShowingPopover const): Added.
+        (WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
+        (WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptContext.h:
+        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+        (WTR::UIScriptController::setWillPresentPopoverCallback): Added.
+        (WTR::UIScriptController::willPresentPopoverCallback const): Added.
+        (WTR::UIScriptController::setDidDismissPopoverCallback): Added.
+        (WTR::UIScriptController::didDismissPopoverCallback const): Added.
+        (WTR::UIScriptController::isShowingPopover const): Added.
+        (WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
+        (WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        * WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
+        * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+        (-[TestRunnerWKWebView initWithFrame:configuration:]): Update some state.
+        (-[TestRunnerWKWebView resetInteractionCallbacks]): Ditto.
+        (-[TestRunnerWKWebView _willPresentPopover]): Added.
+        (-[TestRunnerWKWebView _didDismissPopover]): Added.
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptController::isShowingPopover const): Added.
+        (WTR::UIScriptController::platformSetWillPresentPopoverCallback): Added.
+        (WTR::UIScriptController::platformSetDidDismissPopoverCallback): Added.
+
 2019-04-09  Alex Christensen  <achristensen@webkit.org>
 
         Clicking "Go Back" from a safe browsing warning from an iframe should navigate the WKWebView back to the previous page
index 22d55ab..2ee91b0 100644 (file)
@@ -353,6 +353,19 @@ void UIScriptController::platformSetDidHideMenuCallback()
 {
 }
 
+bool UIScriptController::isShowingPopover() const
+{
+    return false;
+}
+
+void UIScriptController::platformSetWillPresentPopoverCallback()
+{
+}
+
+void UIScriptController::platformSetDidDismissPopoverCallback()
+{
+}
+
 JSObjectRef UIScriptController::rectForMenuAction(JSStringRef) const
 {
     return nullptr;
index eecb206..23fe326 100644 (file)
@@ -231,6 +231,10 @@ interface UIScriptController {
     readonly attribute object menuRect;
     object rectForMenuAction(DOMString action);
 
+    readonly attribute boolean isShowingPopover;
+    attribute object willPresentPopoverCallback;
+    attribute object didDismissPopoverCallback;
+
     attribute object willBeginZoomingCallback;
     attribute object didEndZoomingCallback;
 
index 8040647..47ffe8f 100644 (file)
@@ -56,6 +56,8 @@ typedef enum  {
     CallbackTypeDidHideKeyboard,
     CallbackTypeDidShowMenu,
     CallbackTypeDidHideMenu,
+    CallbackTypeWillPresentPopover,
+    CallbackTypeDidDismissPopover,
     CallbackTypeDidEndScrolling,
     CallbackTypeDidStartFormControlInteraction,
     CallbackTypeDidEndFormControlInteraction,
index 23e42d1..6faab08 100644 (file)
@@ -227,6 +227,28 @@ JSValueRef UIScriptController::didHideMenuCallback() const
     return m_context->callbackWithID(CallbackTypeDidHideMenu);
 }
 
+void UIScriptController::setWillPresentPopoverCallback(JSValueRef callback)
+{
+    m_context->registerCallback(callback, CallbackTypeWillPresentPopover);
+    platformSetWillPresentPopoverCallback();
+}
+
+JSValueRef UIScriptController::willPresentPopoverCallback() const
+{
+    return m_context->callbackWithID(CallbackTypeWillPresentPopover);
+}
+
+void UIScriptController::setDidDismissPopoverCallback(JSValueRef callback)
+{
+    m_context->registerCallback(callback, CallbackTypeDidDismissPopover);
+    platformSetDidDismissPopoverCallback();
+}
+
+JSValueRef UIScriptController::didDismissPopoverCallback() const
+{
+    return m_context->callbackWithID(CallbackTypeDidDismissPopover);
+}
+
 #if !PLATFORM(COCOA)
 
 void UIScriptController::zoomToScale(double, JSValueRef)
@@ -553,6 +575,19 @@ void UIScriptController::platformSetDidHideMenuCallback()
 {
 }
 
+bool UIScriptController::isShowingPopover() const
+{
+    return false;
+}
+
+void UIScriptController::platformSetWillPresentPopoverCallback()
+{
+}
+
+void UIScriptController::platformSetDidDismissPopoverCallback()
+{
+}
+
 JSObjectRef UIScriptController::menuRect() const
 {
     return nullptr;
index e41f8a3..f24cc7e 100644 (file)
@@ -166,10 +166,15 @@ public:
 
     void setDidHideMenuCallback(JSValueRef);
     JSValueRef didHideMenuCallback() const;
-
     void setDidShowMenuCallback(JSValueRef);
     JSValueRef didShowMenuCallback() const;
 
+    bool isShowingPopover() const;
+    void setDidDismissPopoverCallback(JSValueRef);
+    JSValueRef didDismissPopoverCallback() const;
+    void setWillPresentPopoverCallback(JSValueRef);
+    JSValueRef willPresentPopoverCallback() const;
+
     bool isShowingMenu() const;
     JSObjectRef rectForMenuAction(JSStringRef action) const;
     JSObjectRef menuRect() const;
@@ -250,6 +255,8 @@ private:
     void platformSetDidHideKeyboardCallback();
     void platformSetDidShowMenuCallback();
     void platformSetDidHideMenuCallback();
+    void platformSetWillPresentPopoverCallback();
+    void platformSetDidDismissPopoverCallback();
     void platformSetDidEndScrollingCallback();
     void platformClearAllCallbacks();
     void platformPlayBackEventStream(JSStringRef, JSValueRef);
index bcd62df..96e5152 100644 (file)
@@ -43,6 +43,8 @@
 @property (nonatomic, copy) void (^didHideKeyboardCallback)(void);
 @property (nonatomic, copy) void (^didShowMenuCallback)(void);
 @property (nonatomic, copy) void (^didHideMenuCallback)(void);
+@property (nonatomic, copy) void (^willPresentPopoverCallback)(void);
+@property (nonatomic, copy) void (^didDismissPopoverCallback)(void);
 @property (nonatomic, copy) void (^didEndScrollingCallback)(void);
 @property (nonatomic, copy) void (^rotationDidEndCallback)(void);
 @property (nonatomic, copy) NSString *accessibilitySpeakSelectionContent;
@@ -56,6 +58,7 @@
 
 @property (nonatomic, readonly, getter=isShowingKeyboard) BOOL showingKeyboard;
 @property (nonatomic, readonly, getter=isShowingMenu) BOOL showingMenu;
+@property (nonatomic, readonly, getter=isShowingPopover) BOOL showingPopover;
 @property (nonatomic, assign) BOOL usesSafariLikeRotation;
 @property (nonatomic, readonly, getter=isInteractingWithFormControl) BOOL interactingWithFormControl;
 
index 14d5d59..258080e 100644 (file)
@@ -55,6 +55,7 @@
 @property (nonatomic, copy) void (^retrieveSpeakSelectionContentCompletionHandler)(void);
 @property (nonatomic, getter=isShowingKeyboard, setter=setIsShowingKeyboard:) BOOL showingKeyboard;
 @property (nonatomic, getter=isShowingMenu, setter=setIsShowingMenu:) BOOL showingMenu;
+@property (nonatomic, getter=isShowingPopover, setter=setIsShowingPopover:) BOOL showingPopover;
 
 @end
 
@@ -79,6 +80,8 @@ IGNORE_WARNINGS_END
         [center addObserver:self selector:@selector(_invokeHideKeyboardCallbackIfNecessary) name:UIKeyboardDidHideNotification object:nil];
         [center addObserver:self selector:@selector(_didShowMenu) name:UIMenuControllerDidShowMenuNotification object:nil];
         [center addObserver:self selector:@selector(_didHideMenu) name:UIMenuControllerDidHideMenuNotification object:nil];
+        [center addObserver:self selector:@selector(_willPresentPopover) name:@"UIPopoverControllerWillPresentPopoverNotification" object:nil];
+        [center addObserver:self selector:@selector(_didDismissPopover) name:@"UIPopoverControllerDidDismissPopoverNotification" object:nil];
         self.UIDelegate = self;
     }
     return self;
@@ -141,6 +144,8 @@ IGNORE_WARNINGS_END
     self.didHideKeyboardCallback = nil;
     self.didShowMenuCallback = nil;
     self.didHideMenuCallback = nil;
+    self.willPresentPopoverCallback = nil;
+    self.didDismissPopoverCallback = nil;
     self.didEndScrollingCallback = nil;
     self.rotationDidEndCallback = nil;
 }
@@ -200,6 +205,26 @@ IGNORE_WARNINGS_END
         self.didHideMenuCallback();
 }
 
+- (void)_willPresentPopover
+{
+    if (self.showingPopover)
+        return;
+
+    self.showingPopover = YES;
+    if (self.willPresentPopoverCallback)
+        self.willPresentPopoverCallback();
+}
+
+- (void)_didDismissPopover
+{
+    if (!self.showingPopover)
+        return;
+
+    self.showingPopover = NO;
+    if (self.didDismissPopoverCallback)
+        self.didDismissPopoverCallback();
+}
+
 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
 {
     [super scrollViewWillBeginZooming:scrollView withView:view];
index aa9d848..d249678 100644 (file)
@@ -907,6 +907,29 @@ void UIScriptController::platformSetDidHideMenuCallback()
     };
 }
 
+bool UIScriptController::isShowingPopover() const
+{
+    return TestController::singleton().mainWebView()->platformView().showingPopover;
+}
+
+void UIScriptController::platformSetWillPresentPopoverCallback()
+{
+    TestController::singleton().mainWebView()->platformView().willPresentPopoverCallback = ^{
+        if (!m_context)
+            return;
+        m_context->fireCallback(CallbackTypeWillPresentPopover);
+    };
+}
+
+void UIScriptController::platformSetDidDismissPopoverCallback()
+{
+    TestController::singleton().mainWebView()->platformView().didDismissPopoverCallback = ^{
+        if (!m_context)
+            return;
+        m_context->fireCallback(CallbackTypeDidDismissPopover);
+    };
+}
+
 JSObjectRef UIScriptController::rectForMenuAction(JSStringRef jsAction) const
 {
     auto action = adoptCF(JSStringCopyCFString(kCFAllocatorDefault, jsAction));
@@ -974,6 +997,8 @@ void UIScriptController::platformClearAllCallbacks()
     webView.willBeginZoomingCallback = nil;
     webView.didHideKeyboardCallback = nil;
     webView.didShowKeyboardCallback = nil;
+    webView.willPresentPopoverCallback = nil;
+    webView.didDismissPopoverCallback = nil;
     webView.didEndScrollingCallback = nil;
     webView.rotationDidEndCallback = nil;
 }