[iOS] Do not handle key events that are key commands
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Dec 2018 20:45:41 +0000 (20:45 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Dec 2018 20:45:41 +0000 (20:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191608
<rdar://problem/46046013>

Reviewed by Ryosuke Niwa.

Source/WebKit:

A key down event may be associated with a key command. If it is then we want to execute the
key command instead of inserting or deleting text. We need to ask UIKit to handle the current
event as a key command to find out.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _interpretKeyEvent:isCharEvent:]): Ask UIKit to handle the current event
as a key command. If it handles it then we're done. Otherwise, do what we do now.

Source/WebKitLegacy/ios:

Add default implementation of -handleKeyCommandForCurrentEvent that returns NO - the current
event was not handled as a key command.

* DefaultDelegates/WebDefaultUIKitDelegate.m:
(-[WebDefaultUIKitDelegate handleKeyCommandForCurrentEvent]):
* WebView/WebUIKitDelegate.h:

Source/WebKitLegacy/mac:

A key down event may be associated with a key command. If it is then we want to execute the
key command instead of inserting or deleting text. We need to ask UIKit to handle the current
event as a key command to find out.

* WebView/WebHTMLView.mm:
(-[WebHTMLView _handleEditingKeyEvent:]):

LayoutTests:

Add tests to ensure that we process key commands correctly.

* fast/events/ios/key-command-italic-dispatches-keydown-expected.txt: Added.
* fast/events/ios/key-command-italic-dispatches-keydown.html: Added.
* fast/events/ios/key-command-italic-expected.txt: Added.
* fast/events/ios/key-command-italic.html: Added.
* fast/events/ios/type-digits-holding-control-key-expected.txt: Added.
* fast/events/ios/type-digits-holding-control-key.html: Added.
* platform/ios-wk1/TestExpectations:

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

15 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown.html [new file with mode: 0644]
LayoutTests/fast/events/ios/key-command-italic-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/ios/key-command-italic.html [new file with mode: 0644]
LayoutTests/fast/events/ios/type-digits-holding-control-key-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/ios/type-digits-holding-control-key.html [new file with mode: 0644]
LayoutTests/platform/ios-wk1/TestExpectations
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKitLegacy/ios/ChangeLog
Source/WebKitLegacy/ios/DefaultDelegates/WebDefaultUIKitDelegate.m
Source/WebKitLegacy/ios/WebView/WebUIKitDelegate.h
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebHTMLView.mm

index 41d2523..bbc008d 100644 (file)
@@ -1,3 +1,21 @@
+2018-12-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Do not handle key events that are key commands
+        https://bugs.webkit.org/show_bug.cgi?id=191608
+        <rdar://problem/46046013>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add tests to ensure that we process key commands correctly.
+
+        * fast/events/ios/key-command-italic-dispatches-keydown-expected.txt: Added.
+        * fast/events/ios/key-command-italic-dispatches-keydown.html: Added.
+        * fast/events/ios/key-command-italic-expected.txt: Added.
+        * fast/events/ios/key-command-italic.html: Added.
+        * fast/events/ios/type-digits-holding-control-key-expected.txt: Added.
+        * fast/events/ios/type-digits-holding-control-key.html: Added.
+        * platform/ios-wk1/TestExpectations:
+
 2018-12-03  Ryosuke Niwa  <rniwa@webkit.org>
 
         title attribute on style & link elements should be ignored inside a shadow tree
diff --git a/LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown-expected.txt b/LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown-expected.txt
new file mode 100644 (file)
index 0000000..ca301c8
--- /dev/null
@@ -0,0 +1,11 @@
+Tests that pressing Command + I in a rich editing field dispatches a key down event. To run this test by hand, select all the text below and press Command + I.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.event.key is "i"
+PASS window.event.metaKey is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown.html b/LayoutTests/fast/events/ios/key-command-italic-dispatches-keydown.html
new file mode 100644 (file)
index 0000000..76bc63a
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<script src="../../../resources/js-test.js"></script>
+<script src="../../../resources/ui-helper.js"></script>
+<style>
+#test {
+    border: 1px solid black;
+    height: 500px;
+    width: 500px;
+}
+
+.hidden {
+    display: none;
+}
+</style>
+</head>
+<body>
+<p id="description"></p>
+<div id="test" contenteditable="true">This text should be italicized.</div>
+<div id="console"></div>
+<script>
+window.jsTestIsAsync = true;
+
+let testElement;
+let event;
+let ignoredFirstKeyDownEvent = false;
+
+function shouldIgnoreKeyDownEvent(event)
+{
+    // When performing the test manually a person is not fast enough to press Command + I simultaneously.
+    // We receive a key down for Command followed by a key down for Command + I. So, we ignore the first
+    // event to normalize the test result.
+    if (window.testRunner || ignoredFirstKeyDownEvent)
+        return false;
+    ignoredFirstKeyDownEvent = true;
+    console.assert(event.key == "Meta");
+    return true;
+}
+
+function handleKeyDownEvent(event)
+{
+    if (shouldIgnoreKeyDownEvent(event))
+        return;
+
+    testElement.removeEventListener("keydown", handleKeyDownEvent, true);
+
+    shouldBeEqualToString("window.event.key", "i");
+    shouldBeTrue("window.event.metaKey");
+
+    // Remove the test element to make the output pretty.
+    document.body.removeChild(document.getElementById("test"));
+
+    finishJSTest();
+}
+
+function runTest()
+{
+    if (!window.testRunner)
+        return;
+    function handleFocus() {
+        window.getSelection().selectAllChildren(testElement);
+        UIHelper.keyDown("i", ["metaKey"]);
+    }
+    testElement.addEventListener("focus", handleFocus, { once: true });
+    UIHelper.activateElement(testElement);
+}
+
+description("Tests that pressing Command + I in a rich editing field dispatches a key down event. To run this test by hand, select all the text below and press Command + I.");
+
+testElement = document.getElementById("test");
+testElement.addEventListener("keydown", handleKeyDownEvent, true);
+
+runTest();
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/ios/key-command-italic-expected.txt b/LayoutTests/fast/events/ios/key-command-italic-expected.txt
new file mode 100644 (file)
index 0000000..805ce51
--- /dev/null
@@ -0,0 +1,3 @@
+Tests that pressing Command + I in a rich editing field italizes the selection.
+| <i>
+|   "<#selection-anchor>This text should be italicized.<#selection-focus>"
diff --git a/LayoutTests/fast/events/ios/key-command-italic.html b/LayoutTests/fast/events/ios/key-command-italic.html
new file mode 100644 (file)
index 0000000..6d6a0a5
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/dump-as-markup.js"></script>
+<style>
+#test {
+    border: 1px solid black;
+    height: 500px;
+    width: 500px;
+}
+
+.hidden {
+    display: none;
+}
+</style>
+</head>
+<body>
+<p id="description">Tests that pressing Command + I in a rich editing field italizes the selection.</p>
+<p id="manual-instructions" class="hide">To run this test by hand, select all the text below and press Command + I. This test PASSED if the text becomes italic. Otherwise, it FAILED.</p>
+<div id="test" contenteditable="true">This text should be italicized.</div>
+<script>
+let testElement = document.getElementById("test");
+let mutationObserver = null;
+
+function handleChildListModified()
+{
+    mutationObserver.disconnect();
+    Markup.dump(testElement);
+    Markup.notifyDone();
+}
+
+function runTest()
+{
+    if (!window.testRunner) {
+        document.getElementById("manual-instructions").classList.remove("hidden");
+        return;
+    }
+
+    Markup.description(document.getElementById("description").textContent);
+
+    mutationObserver = new MutationObserver(handleChildListModified);
+    mutationObserver.observe(testElement, { childList: true });
+
+    function handleFocus() {
+        window.getSelection().selectAllChildren(testElement);
+        UIHelper.keyDown("i", ["metaKey"]);
+    }
+    testElement.addEventListener("focus", handleFocus, { once: true });
+    UIHelper.activateElement(testElement);
+}
+
+Markup.waitUntilDone();
+runTest();
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/ios/type-digits-holding-control-key-expected.txt b/LayoutTests/fast/events/ios/type-digits-holding-control-key-expected.txt
new file mode 100644 (file)
index 0000000..56f7e4b
--- /dev/null
@@ -0,0 +1,3 @@
+Tests that decimal numbers typed while holding down the Control key are inserted.
+
+PASS
diff --git a/LayoutTests/fast/events/ios/type-digits-holding-control-key.html b/LayoutTests/fast/events/ios/type-digits-holding-control-key.html
new file mode 100644 (file)
index 0000000..667d51a
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../../resources/ui-helper.js"></script>
+<script type="text/plain" id="ui-script">
+const charactersToType = "1234567890".split("");
+for (const c of charactersToType)
+    uiController.keyDown(c, ["ctrlKey"]);
+</script>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+const expectedCharacters = "1234567890";
+
+function checkDone()
+{
+    let input = document.getElementById("input");
+    if (input.value === expectedCharacters) {
+        document.getElementById("result").textContent = "PASS";
+        document.body.removeChild(input);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+}
+
+function runTest()
+{
+    if (!window.testRunner)
+        return;
+
+    function handleFocus() {
+        testRunner.runUIScript(document.getElementById("ui-script").text, () => { /* Do nothing */ });
+    }
+    let input = document.getElementById("input");
+    input.addEventListener("focus", handleFocus, { once: true });
+    UIHelper.activateFormControl(input);
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests that decimal numbers typed while holding down the <key>Control</key> key are inserted.</p>
+<!--
+Note that when running this test by hande this test assumes that iOS maps Control + k to k for some non-numpad numeral. This
+is a non-issue when running the test in WebKitTestRunner because uiController.keyDown() generates "after key mapping" events.
+-->
+<input type="text" id="input" size="100" oninput="checkDone()">
+<div id="result">FAIL</div>
+</body>
+</html>
index 6cf9f28..8c6bc5d 100644 (file)
@@ -33,6 +33,9 @@ imported/w3c/web-platform-tests/html/semantics/forms/the-datalist-element [ Wont
 
 # No support for testing key commands with modifiers in WK1
 fast/events/ios/focus-tab-previous-field.html [ Skip ]
+fast/events/ios/key-command-italic-dispatches-keydown.html [ Skip ]
+fast/events/ios/key-command-italic.html [ Skip ]
+fast/events/ios/type-digits-holding-control-key.html [ Skip ]
 
 # <input type=color> is not supported in WebKit1 on iOS.
 fast/forms/color/input-color-onchange-event.html [ Failure ]
index 927f642..c7f480a 100644 (file)
@@ -1,3 +1,19 @@
+2018-12-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Do not handle key events that are key commands
+        https://bugs.webkit.org/show_bug.cgi?id=191608
+        <rdar://problem/46046013>
+
+        Reviewed by Ryosuke Niwa.
+
+        A key down event may be associated with a key command. If it is then we want to execute the
+        key command instead of inserting or deleting text. We need to ask UIKit to handle the current
+        event as a key command to find out.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _interpretKeyEvent:isCharEvent:]): Ask UIKit to handle the current event
+        as a key command. If it handles it then we're done. Otherwise, do what we do now.
+
 2018-12-03  Zalan Bujtas  <zalan@apple.com>
 
         [iOS] Add logging channel for hover related content observation
index e6114c7..9a843e0 100644 (file)
 
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+
+@interface UIKeyboardImpl (Staging)
+- (BOOL)handleKeyCommandForCurrentEvent;
+@end
+
+#endif
+
 using namespace WebCore;
 using namespace WebKit;
 
@@ -3963,8 +3971,13 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
         return YES;
 
     UIKeyboardImpl *keyboard = [UIKeyboardImpl sharedInstance];
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
+    if (event.type == WebEventKeyDown && [keyboard respondsToSelector:@selector(handleKeyCommandForCurrentEvent)] && [keyboard handleKeyCommandForCurrentEvent])
+        return YES;
+#endif
+
     NSString *characters = event.characters;
-    
     if (!characters.length)
         return NO;
 
index 45226fd..b5e32fe 100644 (file)
@@ -1,3 +1,18 @@
+2018-12-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Do not handle key events that are key commands
+        https://bugs.webkit.org/show_bug.cgi?id=191608
+        <rdar://problem/46046013>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add default implementation of -handleKeyCommandForCurrentEvent that returns NO - the current
+        event was not handled as a key command.
+
+        * DefaultDelegates/WebDefaultUIKitDelegate.m:
+        (-[WebDefaultUIKitDelegate handleKeyCommandForCurrentEvent]):
+        * WebView/WebUIKitDelegate.h:
+
 2018-11-29  Zalan Bujtas  <zalan@apple.com>
 
         Rename *ObservedContentModifier(s) to *ObservedDOMTimer(s)
index dd3c835..aaee826 100644 (file)
@@ -162,6 +162,11 @@ static WebDefaultUIKitDelegate *sharedDelegate = nil;
 {
 }
 
+- (BOOL)handleKeyCommandForCurrentEvent
+{
+    return NO;
+}
+
 - (void)addInputString:(NSString *)str withFlags:(NSUInteger)flags
 {
 }
index 3a4462e..b85547b 100644 (file)
@@ -90,6 +90,7 @@ typedef NS_ENUM(NSInteger, WebMediaCaptureType) {
 - (void)webView:(WebView *)webView didHideFullScreenForPlugInView:(id)plugInView;
 - (void)webView:(WebView *)aWebView didReceiveMessage:(NSDictionary *)aMessage;
 - (void)addInputString:(NSString *)str withFlags:(NSUInteger)flags;
+- (BOOL)handleKeyCommandForCurrentEvent;
 // FIXME: remove deleteFromInput when UIKit implements deleteFromInputWithFlags.
 - (void)deleteFromInput;
 - (void)deleteFromInputWithFlags:(NSUInteger)flags;
index 1efaf52..56f4628 100644 (file)
@@ -1,3 +1,18 @@
+2018-12-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Do not handle key events that are key commands
+        https://bugs.webkit.org/show_bug.cgi?id=191608
+        <rdar://problem/46046013>
+
+        Reviewed by Ryosuke Niwa.
+
+        A key down event may be associated with a key command. If it is then we want to execute the
+        key command instead of inserting or deleting text. We need to ask UIKit to handle the current
+        event as a key command to find out.
+
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView _handleEditingKeyEvent:]):
+
 2018-12-02  Zalan Bujtas  <zalan@apple.com>
 
         Add a runtime feature flag for LayoutFormattingContext.
index 88a9e4b..7bc3a29 100644 (file)
@@ -6082,13 +6082,19 @@ static BOOL writingDirectionKeyBindingsEnabled()
         WebEvent *event = platformEvent->event();
         if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged)
             return NO;
-        if (![[self _webView] isEditable] && event.isTabKey) 
+
+        WebView *webView = [self _webView];
+        if (!webView.isEditable && event.isTabKey)
             return NO;
-        
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
+        if (event.type == WebEventKeyDown && [webView._UIKitDelegateForwarder handleKeyCommandForCurrentEvent])
+            return YES;
+#endif
+
         NSString *s = [event characters];
         if (!s.length)
             return NO;
-        WebView* webView = [self _webView];
         switch ([s characterAtIndex:0]) {
         case kWebBackspaceKey:
         case kWebDeleteKey: