[iOS] Arrow keys do not dispatch DOM events to non-editable elements
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Sep 2018 21:02:50 +0000 (21:02 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Sep 2018 21:02:50 +0000 (21:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189389

Reviewed by Simon Fraser.

Source/WebCore:

On iOS the arrow keys are identified by special multi character key strings: UIKeyInput{Up,
Down, Left, Right}Arrow as opposed to special key codes as on Mac. When converting the iOS-
specific WebEvent we need to take care to recognize when the key string for the event is
one of these special key strings when computing key code, character code, and key identifier
properties for the WebCore platform-specific event. These details will be included in
the corresponding DOM keyboard events that are dispatched when the arrow keys are pressed.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
Mark file PlatformEventFactoryIOS as @no-unify as it is not compatible with the unified sources
build strategy given its use of wtf/cocoa/SoftLinking.h macros.

* platform/ios/PlatformEventFactoryIOS.h:
* platform/ios/PlatformEventFactoryIOS.mm:
(WebCore::convertSpecialKeyToCharCode): Manufacture the appropriate character code for an
event that represents an arrow key. Otherwise, return std::nullopt to indicate that the
event is not for an arrow key.
(WebCore::keyCodeForEvent): Manufacture the appropriate Windows virtual key code for an
event that represents an arrow key. Otherwise, do what we do now and return the key code
associated with the WebEvent.
(WebCore::keyIdentifierForKeyEvent): Modified to test if the event is for an arrow key
and return the appropriate key identifier.
(WebCore::keyForKeyEvent): Modified to test if the event is for an arrow key
and return the appropriate character code.
(WebCore::codeForKeyEvent): Modified to call keyCodeForEvent(), which knows how to account
for events that represent arrow keys.
(WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):

Source/WebKit:

Use WebCore::keyCodeForEvent() to retrieve the key code for a WebEvent instead of querying
the key code from the WebEvent directly. The function WebCore::keyCodeForEvent() knows how
to compute the key code for an event that represents an arrow key.

* Shared/ios/WebIOSEventFactory.mm:
(WebIOSEventFactory::createWebKeyboardEvent):

LayoutTests:

Update expected result now that we compute the correct keyIdentifier, keycode, and which properties
for DOM keyboard events dispatched when the arrow keys are pressed.

* fast/events/ios/keydown-keyup-in-non-editable-content-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/fast/events/ios/keydown-keyup-in-non-editable-content-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/SourcesCocoa.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/ios/PlatformEventFactoryIOS.h
Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm
Source/WebKit/ChangeLog
Source/WebKit/Shared/ios/WebIOSEventFactory.mm

index c5667a2..ab1d6d7 100644 (file)
@@ -1,5 +1,17 @@
 2018-09-10  Daniel Bates  <dabates@apple.com>
 
+        [iOS] Arrow keys do not dispatch DOM events to non-editable elements
+        https://bugs.webkit.org/show_bug.cgi?id=189389
+
+        Reviewed by Simon Fraser.
+
+        Update expected result now that we compute the correct keyIdentifier, keycode, and which properties
+        for DOM keyboard events dispatched when the arrow keys are pressed.
+
+        * fast/events/ios/keydown-keyup-in-non-editable-content-expected.txt:
+
+2018-09-10  Daniel Bates  <dabates@apple.com>
+
         [iOS] Make WKWebView become the first responder to support testing key presses to non-editable elements
         https://bugs.webkit.org/show_bug.cgi?id=189432
 
index 78c7266..2032f20 100644 (file)
@@ -94,10 +94,10 @@ type: keydown, key: /, code: Slash, keyIdentifier: U+002F, keyCode: 191, charCod
 type: keyup, key: Dead, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
 type: keydown, key: Enter, code: Enter, keyIdentifier: Enter, keyCode: 13, charCode: 0, keyCode: 13, which: 13
 type: keyup, key: Dead, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keydown, key: UIKeyInputUpArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keyup, key: UIKeyInputUpArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keyup, key: UIKeyInputDownArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keydown, key: UIKeyInputLeftArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keyup, key: UIKeyInputLeftArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
-type: keyup, key: UIKeyInputRightArrow, code: Unidentified, keyIdentifier: Unidentified, keyCode: 0, charCode: 0, keyCode: 0, which: 0
+type: keydown, key: ArrowUp, code: ArrowUp, keyIdentifier: Up, keyCode: 38, charCode: 0, keyCode: 38, which: 38
+type: keyup, key: ArrowUp, code: ArrowUp, keyIdentifier: Up, keyCode: 38, charCode: 0, keyCode: 38, which: 38
+type: keyup, key: ArrowDown, code: ArrowDown, keyIdentifier: Down, keyCode: 40, charCode: 0, keyCode: 40, which: 40
+type: keydown, key: ArrowLeft, code: ArrowLeft, keyIdentifier: Left, keyCode: 37, charCode: 0, keyCode: 37, which: 37
+type: keyup, key: ArrowLeft, code: ArrowLeft, keyIdentifier: Left, keyCode: 37, charCode: 0, keyCode: 37, which: 37
+type: keyup, key: ArrowRight, code: ArrowRight, keyIdentifier: Right, keyCode: 39, charCode: 0, keyCode: 39, which: 39
 
index 7e9772d..3452739 100644 (file)
@@ -1,3 +1,38 @@
+2018-09-10  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Arrow keys do not dispatch DOM events to non-editable elements
+        https://bugs.webkit.org/show_bug.cgi?id=189389
+
+        Reviewed by Simon Fraser.
+
+        On iOS the arrow keys are identified by special multi character key strings: UIKeyInput{Up,
+        Down, Left, Right}Arrow as opposed to special key codes as on Mac. When converting the iOS-
+        specific WebEvent we need to take care to recognize when the key string for the event is
+        one of these special key strings when computing key code, character code, and key identifier
+        properties for the WebCore platform-specific event. These details will be included in
+        the corresponding DOM keyboard events that are dispatched when the arrow keys are pressed.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Mark file PlatformEventFactoryIOS as @no-unify as it is not compatible with the unified sources
+        build strategy given its use of wtf/cocoa/SoftLinking.h macros.
+
+        * platform/ios/PlatformEventFactoryIOS.h:
+        * platform/ios/PlatformEventFactoryIOS.mm:
+        (WebCore::convertSpecialKeyToCharCode): Manufacture the appropriate character code for an
+        event that represents an arrow key. Otherwise, return std::nullopt to indicate that the
+        event is not for an arrow key.
+        (WebCore::keyCodeForEvent): Manufacture the appropriate Windows virtual key code for an
+        event that represents an arrow key. Otherwise, do what we do now and return the key code
+        associated with the WebEvent.
+        (WebCore::keyIdentifierForKeyEvent): Modified to test if the event is for an arrow key
+        and return the appropriate key identifier.
+        (WebCore::keyForKeyEvent): Modified to test if the event is for an arrow key
+        and return the appropriate character code.
+        (WebCore::codeForKeyEvent): Modified to call keyCodeForEvent(), which knows how to account
+        for events that represent arrow keys.
+        (WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):
+
 2018-09-10  Dan Bernstein  <mitz@apple.com>
 
         [macOS] Editor::readSelectionFromPasteboard’s MailBlockquoteHandling argument is effectively unused
index 5dc3823..354d532 100644 (file)
@@ -385,7 +385,7 @@ platform/ios/LegacyTileLayer.mm
 platform/ios/LegacyTileLayerPool.mm
 platform/ios/LowPowerModeNotifierIOS.mm
 platform/ios/PasteboardIOS.mm
-platform/ios/PlatformEventFactoryIOS.mm
+platform/ios/PlatformEventFactoryIOS.mm @no-unify
 platform/ios/PlatformPasteboardIOS.mm
 platform/ios/PlatformScreenIOS.mm
 platform/ios/PlatformSpeechSynthesizerIOS.mm @no-unify
index 9e5aaba..f40f41e 100644 (file)
                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE7E17831C83A49100AD06AF /* ContentSecurityPolicyHash.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7E17821C83A49100AD06AF /* ContentSecurityPolicyHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26601EBE14B3B9AD0012C0FE /* PlatformEventFactoryIOS.mm */; };
                CEBB8C3320786DCB00039547 /* FetchIdioms.h in Headers */ = {isa = PBXBuildFile; fileRef = CEBB8C3120786DCB00039547 /* FetchIdioms.h */; };
                CECADFC7153778FF00E37068 /* DictationAlternative.h in Headers */ = {isa = PBXBuildFile; fileRef = CECADFC3153778FF00E37068 /* DictationAlternative.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CECADFC9153778FF00E37068 /* DictationCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = CECADFC5153778FF00E37068 /* DictationCommand.h */; };
                                31078CC71880AAB5008099DC /* OESTextureHalfFloatLinear.cpp in Sources */,
                                77A17A7112F28182004E02F6 /* OESVertexArrayObject.cpp in Sources */,
                                DE5F86101FA238D9006DB63A /* PaymentMerchantSessionCocoa.mm in Sources */,
+                               CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */,
                                AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */,
                                CDA29A301CBF74D400901CCF /* PlaybackSessionInterfaceAVKit.mm in Sources */,
                                CDA29A161CBDA56C00901CCF /* PlaybackSessionInterfaceMac.mm in Sources */,
index bc74594..79a8a66 100644 (file)
@@ -53,6 +53,7 @@ public:
 WEBCORE_EXPORT String keyForKeyEvent(WebEvent *);
 WEBCORE_EXPORT String codeForKeyEvent(WebEvent *);
 WEBCORE_EXPORT String keyIdentifierForKeyEvent(WebEvent *);
+WEBCORE_EXPORT int keyCodeForEvent(WebEvent *);
 
 } // namespace WebCore
 
index 9e1fb97..380d66f 100644 (file)
 
 #import "IntPoint.h"
 #import "KeyEventCocoa.h"
+#import "KeyEventCodesIOS.h"
 #import "Logging.h"
 #import "WAKAppKitStubs.h"
 #import "WebEvent.h"
 #import "WindowsKeyboardCodes.h"
+#import <UIKit/UIKit.h>
+#import <wtf/Optional.h>
+#import <wtf/SoftLinking.h>
 #import <wtf/WallTime.h>
 
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK_CONSTANT(UIKit, UIKeyInputUpArrow, NSString *)
+SOFT_LINK_CONSTANT(UIKit, UIKeyInputDownArrow, NSString *)
+SOFT_LINK_CONSTANT(UIKit, UIKeyInputLeftArrow, NSString *)
+SOFT_LINK_CONSTANT(UIKit, UIKeyInputRightArrow, NSString *)
+
+#define UIKeyInputUpArrow getUIKeyInputUpArrow()
+#define UIKeyInputDownArrow getUIKeyInputDownArrow()
+#define UIKeyInputLeftArrow getUIKeyInputLeftArrow()
+#define UIKeyInputRightArrow getUIKeyInputRightArrow()
+
 namespace WebCore {
 
 static OptionSet<PlatformEvent::Modifier> modifiersForEvent(WebEvent *event)
@@ -82,6 +97,32 @@ static PlatformEvent::Type mouseEventType(WebEvent *event)
     }
 }
 
+static std::optional<int> convertSpecialKeyToCharCode(NSString *keyString)
+{
+    if ([keyString isEqualToString:UIKeyInputUpArrow])
+        return NSUpArrowFunctionKey;
+    if ([keyString isEqualToString:UIKeyInputDownArrow])
+        return NSDownArrowFunctionKey;
+    if ([keyString isEqualToString:UIKeyInputLeftArrow])
+        return NSLeftArrowFunctionKey;
+    if ([keyString isEqualToString:UIKeyInputRightArrow])
+        return NSRightArrowFunctionKey;
+    return std::nullopt;
+}
+
+int keyCodeForEvent(WebEvent *event)
+{
+    if ([event.characters isEqualToString:UIKeyInputUpArrow])
+        return VK_UP;
+    if ([event.characters isEqualToString:UIKeyInputDownArrow])
+        return VK_DOWN;
+    if ([event.characters isEqualToString:UIKeyInputLeftArrow])
+        return VK_LEFT;
+    if ([event.characters isEqualToString:UIKeyInputRightArrow])
+        return VK_RIGHT;
+    return event.keyCode;
+}
+
 class PlatformMouseEventBuilder : public PlatformMouseEvent {
 public:
     PlatformMouseEventBuilder(WebEvent *event)
@@ -125,36 +166,36 @@ PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(WebEvent *even
 
 String keyIdentifierForKeyEvent(WebEvent *event)
 {
-    NSString *s = event.charactersIgnoringModifiers;
-    if ([s length] != 1) {
-        LOG(Events, "received an unexpected number of characters in key event: %u", [s length]);
-        return "Unidentified";
+    NSString *characters = event.charactersIgnoringModifiers;
+    if (auto specialKeyCharCode = convertSpecialKeyToCharCode(characters))
+        return keyIdentifierForCharCode(*specialKeyCharCode);
+    if ([characters length] != 1) {
+        LOG(Events, "received an unexpected number of characters in key event: %u", [characters length]);
+        return "Unidentified"_s;
     }
-
-    return keyIdentifierForCharCode(CFStringGetCharacterAtIndex((CFStringRef)s, 0));
+    return keyIdentifierForCharCode([characters characterAtIndex:0]);
 }
 
 String keyForKeyEvent(WebEvent *event)
 {
     NSString *characters = event.characters;
     auto length = [characters length];
-
     // characters return an empty string for dead keys.
     // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
     // "Dead" is defined here https://w3c.github.io/uievents-key/#keys-composition.
     if (!length)
         return "Dead"_s;
-
+    if (auto specialKeyCharCode = convertSpecialKeyToCharCode(characters))
+        return keyForCharCode(*specialKeyCharCode);
     if (length > 1)
         return characters;
-
     return keyForCharCode([characters characterAtIndex:0]);
 }
 
 // https://w3c.github.io/uievents-code/
 String codeForKeyEvent(WebEvent *event)
 {
-    switch (event.keyCode) {
+    switch (keyCodeForEvent(event)) {
     // Keys in the alphanumeric section.
     case VK_OEM_3: return "Backquote"_s;
     case VK_OEM_5: return "Backslash"_s;
@@ -378,7 +419,7 @@ public:
         m_key = keyForKeyEvent(event);
         m_code = codeForKeyEvent(event);
         m_keyIdentifier = keyIdentifierForKeyEvent(event);
-        m_windowsVirtualKeyCode = event.keyCode;
+        m_windowsVirtualKeyCode = keyCodeForEvent(event);
         m_autoRepeat = event.isKeyRepeating;
         m_isKeypad = false; // iOS does not distinguish the numpad. See <rdar://problem/7190835>.
         m_isSystemKey = false;
index 48332bc..90577d9 100644 (file)
@@ -1,3 +1,17 @@
+2018-09-10  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Arrow keys do not dispatch DOM events to non-editable elements
+        https://bugs.webkit.org/show_bug.cgi?id=189389
+
+        Reviewed by Simon Fraser.
+
+        Use WebCore::keyCodeForEvent() to retrieve the key code for a WebEvent instead of querying
+        the key code from the WebEvent directly. The function WebCore::keyCodeForEvent() knows how
+        to compute the key code for an event that represents an arrow key.
+
+        * Shared/ios/WebIOSEventFactory.mm:
+        (WebIOSEventFactory::createWebKeyboardEvent):
+
 2018-09-10  Tim Horton  <timothy_horton@apple.com>
 
         Try to fix the iOSMac build
index 503678b..832fd14 100644 (file)
@@ -58,8 +58,8 @@ WebKit::WebKeyboardEvent WebIOSEventFactory::createWebKeyboardEvent(::WebEvent *
     String key = WebCore::keyForKeyEvent(event);
     String code = WebCore::codeForKeyEvent(event);
     String keyIdentifier = WebCore::keyIdentifierForKeyEvent(event);
-    int windowsVirtualKeyCode = event.keyCode;
-    int nativeVirtualKeyCode = event.keyCode;
+    int windowsVirtualKeyCode = WebCore::keyCodeForEvent(event);
+    int nativeVirtualKeyCode = WebCore::keyCodeForEvent(event);
     int macCharCode = 0;
     bool autoRepeat = event.isKeyRepeating;
     bool isKeypad = false;