Title: [252873] trunk
Revision
252873
Author
[email protected]
Date
2019-11-25 21:18:54 -0800 (Mon, 25 Nov 2019)

Log Message

[Win] Update KeyboardEvent as per the latest specification
https://bugs.webkit.org/show_bug.cgi?id=202183

Reviewed by Ross Kirsling.

Source/WebCore:

Add 'key' and 'code' properties of KeyboardEvent for Windows. The
implementation is copied from Chromium for Windows.

For implementing 'key' properties, ToUnicodeEx API is used to
convert a virtual key code to a character information.
Unfortunately, ToUnicodeEx alters the stored previous typed dead
key in the driver, it can't be used for each key event. So,
ToUnicodeEx is used to convert all virtual keys with all modifier
combinations beforehand.

This change turns on ENABLE_KEYBOARD_KEY_ATTRIBUTE and
ENABLE_KEYBOARD_CODE_ATTRIBUTE macros for all ports. A follow-up
patch will remove the macros.

Existing tests covers.

* PlatformWin.cmake:
* platform/win/KeyEventWin.cpp:
(WebCore::windowsKeyNames):
(WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent):
* platform/win/WindowsKeyNames.cpp: Added.
(hasControlAndAlt):
(getModifierFlags):
(nonPrintableVirtualKeyToDomKey):
(WindowsKeyNames::WindowsKeyNames):
(WindowsKeyNames::domKeyFromLParam):
(singleCharacterString):
(WindowsKeyNames::domKeyFromChar):
(WindowsKeyNames::domCodeFromLParam):
(WindowsKeyNames::updateLayout):
* platform/win/WindowsKeyNames.h: Added.

Source/WebKit:

* Shared/WebEvent.h:
* Shared/WebKeyboardEvent.cpp:
(WebKit::WebKeyboardEvent::WebKeyboardEvent):
* Shared/win/WebEventFactory.cpp:
(WebKit::windowsKeyNames):
(WebKit::WebEventFactory::createWebKeyboardEvent):

Source/WTF:

* wtf/FeatureDefines.h:

LayoutTests:

* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:
Unskipped fast/events/arrow-keys-on-body.html, fast/events/keyboardevent-key.html, and fast/events/key-events-in-input-text.html.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (252872 => 252873)


--- trunk/LayoutTests/ChangeLog	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/LayoutTests/ChangeLog	2019-11-26 05:18:54 UTC (rev 252873)
@@ -1,3 +1,14 @@
+2019-11-25  Fujii Hironori  <[email protected]>
+
+        [Win] Update KeyboardEvent as per the latest specification
+        https://bugs.webkit.org/show_bug.cgi?id=202183
+
+        Reviewed by Ross Kirsling.
+
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+        Unskipped fast/events/arrow-keys-on-body.html, fast/events/keyboardevent-key.html, and fast/events/key-events-in-input-text.html.
+
 2019-11-25  Zan Dobersek  <[email protected]>  and  Chris Lord <[email protected]>
 
         Basic OffscreenCanvas functionality

Modified: trunk/LayoutTests/platform/win/TestExpectations (252872 => 252873)


--- trunk/LayoutTests/platform/win/TestExpectations	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/LayoutTests/platform/win/TestExpectations	2019-11-26 05:18:54 UTC (rev 252873)
@@ -3234,7 +3234,6 @@
 fast/dom/HTMLProgressElement/progress-bar-value-pseudo-element.html [ Failure ]
 fast/dom/Window/get-set-properties.html [ Failure ]
 fast/dom/Window/window-lookup-precedence.html [ Failure ]
-fast/events/arrow-keys-on-body.html [ Failure ]
 fast/events/before-input-events-prevent-drag-and-drop.html [ Failure ]
 fast/events/constructors/keyboard-event-constructor.html [ Failure ]
 fast/events/constructors/overconstrained-error-event-constructor.html [ Failure ]
@@ -3245,9 +3244,7 @@
 fast/events/ime-compositionend-on-selection-change.html [ Failure ]
 fast/events/input-events-paste-rich-datatransfer.html [ Failure ]
 fast/events/key-events-in-input-button.html [ Failure ]
-fast/events/key-events-in-input-text.html [ Failure ]
 fast/events/keyboardevent-code.html [ Failure ]
-fast/events/keyboardevent-key.html [ Failure ]
 fast/events/updateLayoutForHitTest.html [ Failure ]
 fast/events/wheelevent-basic.html [ Failure ]
 fast/forms/listbox-respects-padding-bottom.html [ Failure ]

Modified: trunk/LayoutTests/platform/wincairo/TestExpectations (252872 => 252873)


--- trunk/LayoutTests/platform/wincairo/TestExpectations	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/LayoutTests/platform/wincairo/TestExpectations	2019-11-26 05:18:54 UTC (rev 252873)
@@ -1636,7 +1636,6 @@
 fast/css/will-change/will-change-creates-stacking-context.html [ ImageOnlyFailure ]
 fast/dom/adopt-attribute-crash.svg [ Failure ]
 fast/dom/navigator-property-gc-after-frame-detach.html [ Failure ]
-fast/events/arrow-keys-on-body.html [ Failure ]
 fast/events/attempt-scroll-with-no-scrollbars.html [ Failure ]
 fast/events/autoscroll-when-input-is-offscreen.html [ Skip ] # UIScript
 fast/events/autoscroll-with-software-keyboard.html [ Skip ] # UIScript
@@ -1672,9 +1671,7 @@
 fast/events/input-events-paste-data.html [ Pass Failure ]
 fast/events/input-events-paste-rich-datatransfer.html [ Failure ]
 fast/events/key-events-in-input-button.html [ Failure ]
-fast/events/key-events-in-input-text.html [ Failure ]
 fast/events/keyboardevent-code.html [ Failure ]
-fast/events/keyboardevent-key.html [ Failure ]
 fast/events/keydown-numpad-keys.html [ Failure ]
 fast/events/mouse-cursor-image-set.html [ Failure ]
 fast/events/mouseover-button.html [ Failure ]

Modified: trunk/Source/WTF/ChangeLog (252872 => 252873)


--- trunk/Source/WTF/ChangeLog	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WTF/ChangeLog	2019-11-26 05:18:54 UTC (rev 252873)
@@ -1,5 +1,14 @@
 2019-11-25  Fujii Hironori  <[email protected]>
 
+        [Win] Update KeyboardEvent as per the latest specification
+        https://bugs.webkit.org/show_bug.cgi?id=202183
+
+        Reviewed by Ross Kirsling.
+
+        * wtf/FeatureDefines.h:
+
+2019-11-25  Fujii Hironori  <[email protected]>
+
         Add DefaultHash<OptionSet<T>> and HashTrait<OptionSet<T>> specializations
         https://bugs.webkit.org/show_bug.cgi?id=204562
 

Modified: trunk/Source/WTF/wtf/FeatureDefines.h (252872 => 252873)


--- trunk/Source/WTF/wtf/FeatureDefines.h	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WTF/wtf/FeatureDefines.h	2019-11-26 05:18:54 UTC (rev 252873)
@@ -751,11 +751,11 @@
 #endif
 
 #if !defined(ENABLE_KEYBOARD_KEY_ATTRIBUTE)
-#define ENABLE_KEYBOARD_KEY_ATTRIBUTE 0
+#define ENABLE_KEYBOARD_KEY_ATTRIBUTE 1
 #endif
 
 #if !defined(ENABLE_KEYBOARD_CODE_ATTRIBUTE)
-#define ENABLE_KEYBOARD_CODE_ATTRIBUTE 0
+#define ENABLE_KEYBOARD_CODE_ATTRIBUTE 1
 #endif
 
 #if !defined(ENABLE_DATA_INTERACTION)

Modified: trunk/Source/WebCore/ChangeLog (252872 => 252873)


--- trunk/Source/WebCore/ChangeLog	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebCore/ChangeLog	2019-11-26 05:18:54 UTC (rev 252873)
@@ -1,3 +1,42 @@
+2019-11-25  Fujii Hironori  <[email protected]>
+
+        [Win] Update KeyboardEvent as per the latest specification
+        https://bugs.webkit.org/show_bug.cgi?id=202183
+
+        Reviewed by Ross Kirsling.
+
+        Add 'key' and 'code' properties of KeyboardEvent for Windows. The
+        implementation is copied from Chromium for Windows.
+
+        For implementing 'key' properties, ToUnicodeEx API is used to
+        convert a virtual key code to a character information.
+        Unfortunately, ToUnicodeEx alters the stored previous typed dead
+        key in the driver, it can't be used for each key event. So,
+        ToUnicodeEx is used to convert all virtual keys with all modifier
+        combinations beforehand.
+
+        This change turns on ENABLE_KEYBOARD_KEY_ATTRIBUTE and
+        ENABLE_KEYBOARD_CODE_ATTRIBUTE macros for all ports. A follow-up
+        patch will remove the macros.
+
+        Existing tests covers.
+
+        * PlatformWin.cmake:
+        * platform/win/KeyEventWin.cpp:
+        (WebCore::windowsKeyNames):
+        (WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent):
+        * platform/win/WindowsKeyNames.cpp: Added.
+        (hasControlAndAlt):
+        (getModifierFlags):
+        (nonPrintableVirtualKeyToDomKey):
+        (WindowsKeyNames::WindowsKeyNames):
+        (WindowsKeyNames::domKeyFromLParam):
+        (singleCharacterString):
+        (WindowsKeyNames::domKeyFromChar):
+        (WindowsKeyNames::domCodeFromLParam):
+        (WindowsKeyNames::updateLayout):
+        * platform/win/WindowsKeyNames.h: Added.
+
 2019-11-25  Zalan Bujtas  <[email protected]>
 
         [LFC][IFC] Use FontCascade::spaceWidth to measure single or collapsed whitespace content

Modified: trunk/Source/WebCore/PlatformWin.cmake (252872 => 252873)


--- trunk/Source/WebCore/PlatformWin.cmake	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebCore/PlatformWin.cmake	2019-11-26 05:18:54 UTC (rev 252873)
@@ -107,6 +107,7 @@
     platform/win/WheelEventWin.cpp
     platform/win/WidgetWin.cpp
     platform/win/WindowMessageBroadcaster.cpp
+    platform/win/WindowsKeyNames.cpp
 
     rendering/RenderThemeWin.cpp
 )
@@ -142,6 +143,7 @@
     platform/win/WebCoreTextRenderer.h
     platform/win/WindowMessageBroadcaster.h
     platform/win/WindowMessageListener.h
+    platform/win/WindowsKeyNames.h
     platform/win/WindowsTouch.h
 )
 

Modified: trunk/Source/WebCore/platform/win/KeyEventWin.cpp (252872 => 252873)


--- trunk/Source/WebCore/platform/win/KeyEventWin.cpp	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebCore/platform/win/KeyEventWin.cpp	2019-11-26 05:18:54 UTC (rev 252873)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "PlatformKeyboardEvent.h"
 
+#include "WindowsKeyNames.h"
 #include <windows.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/HexNumber.h>
@@ -218,10 +219,18 @@
     return String(&c, 1);
 }
 
+static WindowsKeyNames& windowsKeyNames()
+{
+    static NeverDestroyed<WindowsKeyNames> keyNames;
+    return keyNames;
+}
+
 PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, Type type, bool systemKey)
     : PlatformEvent(type, GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT, GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT, GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT, false, WallTime::fromRawSeconds(::GetTickCount() * 0.001))
     , m_text((type == PlatformEvent::Char) ? singleCharacterString(code) : String())
     , m_unmodifiedText((type == PlatformEvent::Char) ? singleCharacterString(code) : String())
+    , m_key(type == PlatformEvent::Char ? windowsKeyNames().domKeyFromChar(code) : windowsKeyNames().domKeyFromLParam(keyData))
+    , m_code(windowsKeyNames().domCodeFromLParam(keyData))
     , m_keyIdentifier((type == PlatformEvent::Char) ? String() : keyIdentifierForWindowsKeyCode(code))
     , m_windowsVirtualKeyCode((type == RawKeyDown || type == KeyUp) ? windowsKeycodeWithLocation(code, keyData) : 0)
     , m_autoRepeat(HIWORD(keyData) & KF_REPEAT)

Added: trunk/Source/WebCore/platform/win/WindowsKeyNames.cpp (0 => 252873)


--- trunk/Source/WebCore/platform/win/WindowsKeyNames.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/win/WindowsKeyNames.cpp	2019-11-26 05:18:54 UTC (rev 252873)
@@ -0,0 +1,534 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright (C) 2019 Sony Interactive Entertainment Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "config.h"
+#include "WindowsKeyNames.h"
+
+namespace WebCore {
+
+enum class WindowsKeyNames::KeyModifier : uint8_t {
+    Shift = 1 << 0,
+    Control = 1 << 1,
+    Alt = 1 << 2,
+    CapsLock = 1 << 3,
+};
+
+static void setModifierState(BYTE* keyboardState, WindowsKeyNames::KeyModifierSet modifiers)
+{
+    // According to MSDN GetKeyState():
+    // 1. If the high-order bit is 1, the key is down; otherwise, it is up.
+    // 2. If the low-order bit is 1, the key is toggled. A key, such as the
+    //    CAPS LOCK key, is toggled if it is turned on. The key is off and
+    //    untoggled if the low-order bit is 0.
+    // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301.aspx
+    if (modifiers.contains(WindowsKeyNames::KeyModifier::Shift))
+        keyboardState[VK_SHIFT] |= 0x80;
+
+    if (modifiers.contains(WindowsKeyNames::KeyModifier::Control))
+        keyboardState[VK_CONTROL] |= 0x80;
+
+    if (modifiers.contains(WindowsKeyNames::KeyModifier::Alt))
+        keyboardState[VK_MENU] |= 0x80;
+
+    if (modifiers.contains(WindowsKeyNames::KeyModifier::CapsLock))
+        keyboardState[VK_CAPITAL] |= 0x01;
+}
+
+static bool hasControlAndAlt(WindowsKeyNames::KeyModifierSet modifiers)
+{
+    return modifiers.containsAll({ WindowsKeyNames::KeyModifier::Control, WindowsKeyNames::KeyModifier::Alt });
+}
+
+// This table must be sorted by 'virtualKey' for binary search.
+constexpr struct NonPrintableKeyEntry {
+    int virtualKey;
+    ASCIILiteral domKey;
+} cNonPrintableKeyMap[] = {
+    { VK_CANCEL, "Cancel"_s },
+    { VK_BACK, "Backspace"_s },
+    { VK_TAB, "Tab"_s },
+    { VK_CLEAR, "Clear"_s },
+    { VK_RETURN, "Enter"_s },
+    { VK_SHIFT, "Shift"_s },
+    { VK_CONTROL, "Control"_s },
+    { VK_MENU, "Alt"_s },
+    { VK_PAUSE, "Pause"_s },
+    { VK_CAPITAL, "CapsLock"_s },
+    // VK_KANA == VK_HANGUL
+    { VK_JUNJA, "JunjaMode"_s },
+    { VK_FINAL, "FINAL_MODE"_s },
+    // VK_HANJA == VK_KANJI
+    { VK_ESCAPE, "Escape"_s },
+    { VK_CONVERT, "Convert"_s },
+    { VK_NONCONVERT, "NonConvert"_s },
+    { VK_ACCEPT, "Accept"_s },
+    { VK_MODECHANGE, "ModeChange"_s },
+    // VK_SPACE
+    { VK_PRIOR, "PageUp"_s },
+    { VK_NEXT, "PageDown"_s },
+    { VK_END, "End"_s },
+    { VK_HOME, "Home"_s },
+    { VK_LEFT, "ArrowLeft"_s },
+    { VK_UP, "ArrowUp"_s },
+    { VK_RIGHT, "ArrowRight"_s },
+    { VK_DOWN, "ArrowDown"_s },
+    { VK_SELECT, "Select"_s },
+    { VK_PRINT, "Print"_s },
+    { VK_EXECUTE, "Execute"_s },
+    { VK_SNAPSHOT, "PrintScreen"_s },
+    { VK_INSERT, "Insert"_s },
+    { VK_DELETE, "Delete"_s },
+    { VK_HELP, "Help"_s },
+    // VK_0..9
+    // VK_A..Z
+    { VK_LWIN, "Meta"_s },
+    // VK_COMMAND == VK_LWIN
+    { VK_RWIN, "Meta"_s },
+    { VK_APPS, "ContextMenu"_s },
+    { VK_SLEEP, "Standby"_s },
+    // VK_NUMPAD0..9
+    // VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL,
+    // VK_DIVIDE
+    { VK_F1, "F1"_s },
+    { VK_F2, "F2"_s },
+    { VK_F3, "F3"_s },
+    { VK_F4, "F4"_s },
+    { VK_F5, "F5"_s },
+    { VK_F6, "F6"_s },
+    { VK_F7, "F7"_s },
+    { VK_F8, "F8"_s },
+    { VK_F9, "F9"_s },
+    { VK_F10, "F10"_s },
+    { VK_F11, "F11"_s },
+    { VK_F12, "F12"_s },
+    { VK_F13, "F13"_s },
+    { VK_F14, "F14"_s },
+    { VK_F15, "F15"_s },
+    { VK_F16, "F16"_s },
+    { VK_F17, "F17"_s },
+    { VK_F18, "F18"_s },
+    { VK_F19, "F19"_s },
+    { VK_F20, "F20"_s },
+    { VK_F21, "F21"_s },
+    { VK_F22, "F22"_s },
+    { VK_F23, "F23"_s },
+    { VK_F24, "F24"_s },
+    { VK_NUMLOCK, "NumLock"_s },
+    { VK_SCROLL, "ScrollLock"_s },
+    { VK_LSHIFT, "Shift"_s },
+    { VK_RSHIFT, "Shift"_s },
+    { VK_LCONTROL, "Control"_s },
+    { VK_RCONTROL, "Control"_s },
+    { VK_LMENU, "Alt"_s },
+    { VK_RMENU, "Alt"_s },
+    { VK_BROWSER_BACK, "BrowserBack"_s },
+    { VK_BROWSER_FORWARD, "BrowserForward"_s },
+    { VK_BROWSER_REFRESH, "BrowserRefresh"_s },
+    { VK_BROWSER_STOP, "BrowserStop"_s },
+    { VK_BROWSER_SEARCH, "BrowserSearch"_s },
+    { VK_BROWSER_FAVORITES, "BrowserFavorites"_s },
+    { VK_BROWSER_HOME, "BrowserHome"_s },
+    { VK_VOLUME_MUTE, "AudioVolume"_s },
+    { VK_VOLUME_DOWN, "AudioVolumeDown"_s },
+    { VK_VOLUME_UP, "AudioVolumeUp"_s },
+    { VK_MEDIA_NEXT_TRACK, "MediaTrackNext"_s },
+    { VK_MEDIA_PREV_TRACK, "MediaTrackPrevious"_s },
+    { VK_MEDIA_STOP, "MediaStop"_s },
+    { VK_MEDIA_PLAY_PAUSE, "MediaPlayPause"_s },
+    // VK_OEM_1..8, 102, PLUS, COMMA, MINUS, PERIOD
+    { VK_PROCESSKEY, "Process"_s },
+    // VK_PACKET - Used to pass Unicode char, considered as printable key.
+    { VK_ATTN, "Attn"_s },
+    { VK_CRSEL, "CrSel"_s },
+    { VK_EXSEL, "ExSel"_s },
+    { VK_EREOF, "EraseEof"_s },
+    { VK_PLAY, "Play"_s },
+    { VK_ZOOM, "ZoomToggle"_s },
+    { VK_OEM_CLEAR, "Clear"_s },
+};
+
+// Disambiguates the meaning of certain non-printable keys which have different
+// meanings under different languages, but use the same VKEY code.
+static String languageSpecificOemVirtualKeyToDomKey(int virtualKey, HKL layout)
+{
+    WORD language = LOWORD(layout);
+    WORD primaryLanguage = PRIMARYLANGID(language);
+    if (primaryLanguage == LANG_KOREAN) {
+        switch (virtualKey) {
+        case VK_HANGUL:
+            return "HangulMode"_s;
+        case VK_HANJA:
+            return "HanjaMode"_s;
+        default:
+            return String();
+        }
+    } else if (primaryLanguage == LANG_JAPANESE) {
+        switch (virtualKey) {
+        // VK_KANA isn't generated by any modern layouts but is a listed value
+        // that third-party apps might synthesize, so we handle it anyway.
+        case VK_KANA:
+        case VK_ATTN:
+            return "KanaMode"_s;
+        case VK_KANJI:
+            return "KanjiMode"_s;
+        case VK_OEM_ATTN:
+            return "Alphanumeric"_s;
+        case VK_OEM_FINISH:
+            return "Katakana"_s;
+        case VK_OEM_COPY:
+            return "Hiragana"_s;
+        case VK_OEM_BACKTAB:
+            return "Romaji"_s;
+        case VK_OEM_AUTO:
+            return "Hankaku"_s;
+        case VK_OEM_ENLW:
+            return "Zenkaku"_s;
+        default:
+            return String();
+        }
+    }
+    return String();
+}
+
+static String nonPrintableVirtualKeyToDomKey(int virtualKey, HKL layout)
+{
+    // 1. Check if |virtualKey| has a |layout|-specific meaning.
+    const String key = languageSpecificOemVirtualKeyToDomKey(virtualKey, layout);
+    if (!key.isNull())
+        return key;
+
+    // 2. Most |virtualKeys| have the same meaning regardless of |layout|.
+    const NonPrintableKeyEntry* result = std::lower_bound(
+        std::begin(cNonPrintableKeyMap), std::end(cNonPrintableKeyMap), virtualKey,
+        [](const NonPrintableKeyEntry& entry, int needle) {
+            return entry.virtualKey < needle;
+        });
+    if (result != std::end(cNonPrintableKeyMap) && result->virtualKey == virtualKey)
+        return result->domKey;
+
+    return String();
+}
+
+WindowsKeyNames::WindowsKeyNames()
+{
+    updateLayout();
+}
+
+String WindowsKeyNames::domKeyFromLParam(LPARAM lParam)
+{
+    unsigned scanCode = (lParam >> 16) & 0xff;
+    bool extended = lParam & 0x01000000;
+    unsigned virtualKey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
+    KeyModifierSet modifiers;
+    if (GetKeyState(VK_SHIFT) < 0)
+        modifiers.add(KeyModifier::Shift);
+    if (GetKeyState(VK_CONTROL) < 0)
+        modifiers.add(KeyModifier::Control);
+    if (GetKeyState(VK_MENU ) < 0)
+        modifiers.add(KeyModifier::Alt);
+    if (GetKeyState(VK_CAPITAL) & 1)
+        modifiers.add(KeyModifier::CapsLock);
+
+    updateLayout();
+    // Windows expresses right-Alt as VK_MENU with the extended flag set.
+    // This key should generate AltGraph under layouts which use that modifier.
+    if (virtualKey == VK_MENU && extended && m_hasAltGraph)
+        return "AltGraph"_s;
+
+    String key = nonPrintableVirtualKeyToDomKey(virtualKey, m_keyboardLayout);
+    if (!key.isNull())
+        return key;
+
+    const KeyModifierSet modifiersToTry[] = {
+        // Trying to match Firefox's behavior and UIEvents DomKey guidelines.
+        // If the combination doesn't produce a printable character, the key value
+        // should be the key with no modifiers except for Shift and AltGr.
+        // See https://w3c.github.io/uievents/#keys-guidelines
+        modifiers,
+        KeyModifierSet({ KeyModifier::Shift, KeyModifier::CapsLock }) & modifiers,
+    };
+
+    for (auto tryModifiers : modifiersToTry) {
+        const auto& it = m_printableKeyCodeToKey.find(std::make_pair(virtualKey, tryModifiers));
+        if (it != m_printableKeyCodeToKey.end()) {
+            key = it->value;
+            if (!key.isNull())
+                return key;
+        }
+    }
+
+    return "Unidentified"_s;
+}
+
+String WindowsKeyNames::domKeyFromChar(UChar c)
+{
+    switch (c) {
+    case '\x1b':
+        return "Escape"_s;
+    case '\t':
+        return "Tab"_s;
+    case '\r':
+        return "Enter"_s;
+    default:
+        break;
+    }
+    return makeString(c);
+}
+
+// This table must be sorted by 'scanCode' for binary search.
+constexpr struct {
+    unsigned scanCode;
+    ASCIILiteral domCode;
+} cDomCodeMap[] = {
+    { 0x0001, "Escape"_s },
+    { 0x0002, "Digit1"_s },
+    { 0x0003, "Digit2"_s },
+    { 0x0004, "Digit3"_s },
+    { 0x0005, "Digit4"_s },
+    { 0x0006, "Digit5"_s },
+    { 0x0007, "Digit6"_s },
+    { 0x0008, "Digit7"_s },
+    { 0x0009, "Digit8"_s },
+    { 0x000a, "Digit9"_s },
+    { 0x000b, "Digit0"_s },
+    { 0x000c, "Minus"_s },
+    { 0x000d, "Equal"_s },
+    { 0x000e, "Backspace"_s },
+    { 0x000f, "Tab"_s },
+    { 0x0010, "KeyQ"_s },
+    { 0x0011, "KeyW"_s },
+    { 0x0012, "KeyE"_s },
+    { 0x0013, "KeyR"_s },
+    { 0x0014, "KeyT"_s },
+    { 0x0015, "KeyY"_s },
+    { 0x0016, "KeyU"_s },
+    { 0x0017, "KeyI"_s },
+    { 0x0018, "KeyO"_s },
+    { 0x0019, "KeyP"_s },
+    { 0x001a, "BracketLeft"_s },
+    { 0x001b, "BracketRight"_s },
+    { 0x001c, "Enter"_s },
+    { 0x001d, "ControlLeft"_s },
+    { 0x001e, "KeyA"_s },
+    { 0x001f, "KeyS"_s },
+    { 0x0020, "KeyD"_s },
+    { 0x0021, "KeyF"_s },
+    { 0x0022, "KeyG"_s },
+    { 0x0023, "KeyH"_s },
+    { 0x0024, "KeyJ"_s },
+    { 0x0025, "KeyK"_s },
+    { 0x0026, "KeyL"_s },
+    { 0x0027, "Semicolon"_s },
+    { 0x0028, "Quote"_s },
+    { 0x0029, "Backquote"_s },
+    { 0x002a, "ShiftLeft"_s },
+    { 0x002b, "Backslash"_s },
+    { 0x002c, "KeyZ"_s },
+    { 0x002d, "KeyX"_s },
+    { 0x002e, "KeyC"_s },
+    { 0x002f, "KeyV"_s },
+    { 0x0030, "KeyB"_s },
+    { 0x0031, "KeyN"_s },
+    { 0x0032, "KeyM"_s },
+    { 0x0033, "Comma"_s },
+    { 0x0034, "Period"_s },
+    { 0x0035, "Slash"_s },
+    { 0x0036, "ShiftRight"_s },
+    { 0x0037, "NumpadMultiply"_s },
+    { 0x0038, "AltLeft"_s },
+    { 0x0039, "Space"_s },
+    { 0x003a, "CapsLock"_s },
+    { 0x003b, "F1"_s },
+    { 0x003c, "F2"_s },
+    { 0x003d, "F3"_s },
+    { 0x003e, "F4"_s },
+    { 0x003f, "F5"_s },
+    { 0x0040, "F6"_s },
+    { 0x0041, "F7"_s },
+    { 0x0042, "F8"_s },
+    { 0x0043, "F9"_s },
+    { 0x0044, "F10"_s },
+    { 0x0045, "Pause"_s },
+    { 0x0046, "ScrollLock"_s },
+    { 0x0047, "Numpad7"_s },
+    { 0x0048, "Numpad8"_s },
+    { 0x0049, "Numpad9"_s },
+    { 0x004a, "NumpadSubtract"_s },
+    { 0x004b, "Numpad4"_s },
+    { 0x004c, "Numpad5"_s },
+    { 0x004d, "Numpad6"_s },
+    { 0x004e, "NumpadAdd"_s },
+    { 0x004f, "Numpad1"_s },
+    { 0x0050, "Numpad2"_s },
+    { 0x0051, "Numpad3"_s },
+    { 0x0052, "Numpad0"_s },
+    { 0x0053, "NumpadDecimal"_s },
+    { 0x0056, "IntlBackslash"_s },
+    { 0x0057, "F11"_s },
+    { 0x0058, "F12"_s },
+    { 0x0059, "NumpadEqual"_s },
+    { 0x0064, "F13"_s },
+    { 0x0065, "F14"_s },
+    { 0x0066, "F15"_s },
+    { 0x0067, "F16"_s },
+    { 0x0068, "F17"_s },
+    { 0x0069, "F18"_s },
+    { 0x006a, "F19"_s },
+    { 0x006b, "F20"_s },
+    { 0x006c, "F21"_s },
+    { 0x006d, "F22"_s },
+    { 0x006e, "F23"_s },
+    { 0x0070, "KanaMode"_s },
+    { 0x0071, "Lang2"_s },
+    { 0x0072, "Lang1"_s },
+    { 0x0073, "IntlRo"_s },
+    { 0x0076, "F24"_s },
+    { 0x0077, "Lang4"_s },
+    { 0x0078, "Lang3"_s },
+    { 0x0079, "Convert"_s },
+    { 0x007b, "NonConvert"_s },
+    { 0x007d, "IntlYen"_s },
+    { 0x007e, "NumpadComma"_s },
+    { 0x0108, "Undo"_s },
+    { 0x010a, "Paste"_s },
+    { 0x0110, "MediaTrackPrevious"_s },
+    { 0x0117, "Cut"_s },
+    { 0x0118, "Copy"_s },
+    { 0x0119, "MediaTrackNext"_s },
+    { 0x011c, "NumpadEnter"_s },
+    { 0x011d, "ControlRight"_s },
+    { 0x0120, "AudioVolumeMute"_s },
+    { 0x0121, "LaunchApp2"_s },
+    { 0x0122, "MediaPlayPause"_s },
+    { 0x0124, "MediaStop"_s },
+    { 0x012c, "Eject"_s },
+    { 0x012e, "AudioVolumeDown"_s },
+    { 0x0130, "AudioVolumeUp"_s },
+    { 0x0132, "BrowserHome"_s },
+    { 0x0135, "NumpadDivide"_s },
+    { 0x0137, "PrintScreen"_s },
+    { 0x0138, "AltRight"_s },
+    { 0x013b, "Help"_s },
+    { 0x0145, "NumLock"_s },
+    { 0x0147, "Home"_s },
+    { 0x0148, "ArrowUp"_s },
+    { 0x0149, "PageUp"_s },
+    { 0x014b, "ArrowLeft"_s },
+    { 0x014d, "ArrowRight"_s },
+    { 0x014f, "End"_s },
+    { 0x0150, "ArrowDown"_s },
+    { 0x0151, "PageDown"_s },
+    { 0x0152, "Insert"_s },
+    { 0x0153, "Delete"_s },
+    { 0x015b, "MetaLeft"_s },
+    { 0x015c, "MetaRight"_s },
+    { 0x015d, "ContextMenu"_s },
+    { 0x015e, "Power"_s },
+    { 0x015f, "Sleep"_s },
+    { 0x0163, "WakeUp"_s },
+    { 0x0165, "BrowserSearch"_s },
+    { 0x0166, "BrowserFavorites"_s },
+    { 0x0167, "BrowserRefresh"_s },
+    { 0x0168, "BrowserStop"_s },
+    { 0x0169, "BrowserForward"_s },
+    { 0x016a, "BrowserBack"_s },
+    { 0x016b, "LaunchApp1"_s },
+    { 0x016c, "LaunchMail"_s },
+    { 0x016d, "MediaSelect"_s },
+};
+
+String WindowsKeyNames::domCodeFromLParam(LPARAM lParam)
+{
+    unsigned extendedScanCode = (lParam >> 16) & 0x1ff;
+    const auto* result = std::lower_bound(
+        std::begin(cDomCodeMap), std::end(cDomCodeMap), extendedScanCode,
+        [](const auto& entry, int needle) {
+            return entry.scanCode < needle;
+        });
+    if (result != std::end(cDomCodeMap) && result->scanCode == extendedScanCode)
+        return result->domCode;
+
+    return "Unidentified"_s;
+}
+
+void WindowsKeyNames::updateLayout()
+{
+    HKL currentLayout = GetKeyboardLayout(0);
+    if (currentLayout == m_keyboardLayout)
+        return;
+
+    BYTE keyboardStateToRestore[256];
+    if (!GetKeyboardState(keyboardStateToRestore))
+        return;
+
+    m_keyboardLayout = currentLayout;
+    m_printableKeyCodeToKey.clear();
+    m_hasAltGraph = false;
+
+    // Map size for some sample keyboard layouts:
+    // US: 476, French: 602, Persian: 482, Vietnamese: 1436
+    m_printableKeyCodeToKey.reserveInitialCapacity(1500);
+
+    KeyModifierSet allCombination { KeyModifier::Shift, KeyModifier::Control, KeyModifier::Alt, KeyModifier::CapsLock };
+
+    for (int combination = 0; combination <= allCombination.toRaw(); ++combination) {
+        BYTE keyboardState[256] = { };
+
+        // Setting up keyboard state for modifiers.
+        auto modifiers = KeyModifierSet::fromRaw(combination);
+        setModifierState(keyboardState, modifiers);
+
+        for (unsigned virtualKey = 0; virtualKey <= 0xFF; ++virtualKey) {
+            wchar_t translatedChars[5];
+            int rv = ToUnicodeEx(virtualKey, 0, keyboardState, translatedChars,
+                WTF_ARRAY_LENGTH(translatedChars), 0, m_keyboardLayout);
+
+            if (rv == -1) {
+                // Dead key, injecting VK_SPACE to get character representation.
+                BYTE emptyState[256] = { };
+                rv = ToUnicodeEx(VK_SPACE, 0, emptyState, translatedChars,
+                    WTF_ARRAY_LENGTH(translatedChars), 0, m_keyboardLayout);
+                // Expecting a dead key character (not followed by a space).
+                if (rv == 1)
+                    m_printableKeyCodeToKey.set(std::make_pair(virtualKey, modifiers), "Dead"_s);
+            } else if (rv == 1) {
+                if (translatedChars[0] >= 0x20) {
+                    m_printableKeyCodeToKey.set(std::make_pair(virtualKey, modifiers), String(translatedChars, 1));
+
+                    // Detect whether the layout makes use of AltGraph.
+                    if (hasControlAndAlt(modifiers))
+                        m_hasAltGraph = true;
+                }
+            }
+        }
+    }
+    SetKeyboardState(keyboardStateToRestore);
+}
+
+} // namespace WebCore

Added: trunk/Source/WebCore/platform/win/WindowsKeyNames.h (0 => 252873)


--- trunk/Source/WebCore/platform/win/WindowsKeyNames.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/win/WindowsKeyNames.h	2019-11-26 05:18:54 UTC (rev 252873)
@@ -0,0 +1,61 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright (C) 2019 Sony Interactive Entertainment Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <windows.h>
+#include <wtf/HashMap.h>
+#include <wtf/OptionSetHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class WindowsKeyNames {
+public:
+    WindowsKeyNames();
+
+    String domKeyFromLParam(LPARAM);
+    String domKeyFromChar(UChar);
+    String domCodeFromLParam(LPARAM);
+
+    enum class KeyModifier : uint8_t;
+    using KeyModifierSet = OptionSet<KeyModifier>;
+
+private:
+    void updateLayout();
+
+    HKL m_keyboardLayout = 0;
+    bool m_hasAltGraph = false;
+
+    using VirtualKeyModifierSetPair = std::pair<unsigned, KeyModifierSet>;
+    using VirtualKeyToKeyMap = HashMap<VirtualKeyModifierSetPair, String, DefaultHash<VirtualKeyModifierSetPair>::Hash, PairHashTraits<WTF::UnsignedWithZeroKeyHashTraits<unsigned>, HashTraits<KeyModifierSet>>>;
+    VirtualKeyToKeyMap m_printableKeyCodeToKey;
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (252872 => 252873)


--- trunk/Source/WebKit/ChangeLog	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebKit/ChangeLog	2019-11-26 05:18:54 UTC (rev 252873)
@@ -1,3 +1,17 @@
+2019-11-25  Fujii Hironori  <[email protected]>
+
+        [Win] Update KeyboardEvent as per the latest specification
+        https://bugs.webkit.org/show_bug.cgi?id=202183
+
+        Reviewed by Ross Kirsling.
+
+        * Shared/WebEvent.h:
+        * Shared/WebKeyboardEvent.cpp:
+        (WebKit::WebKeyboardEvent::WebKeyboardEvent):
+        * Shared/win/WebEventFactory.cpp:
+        (WebKit::windowsKeyNames):
+        (WebKit::WebEventFactory::createWebKeyboardEvent):
+
 2019-11-25  ChangSeok Oh  <[email protected]>
 
         [GTK] Check EGL image extension by using native gl API in AcceleratedBackingStoreWayland

Modified: trunk/Source/WebKit/Shared/WebEvent.h (252872 => 252873)


--- trunk/Source/WebKit/Shared/WebEvent.h	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebKit/Shared/WebEvent.h	2019-11-26 05:18:54 UTC (rev 252873)
@@ -263,7 +263,7 @@
 #elif USE(LIBWPE)
     WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isKeypad, OptionSet<Modifier>, WallTime timestamp);
 #else
-    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
+    WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier>, WallTime timestamp);
 #endif
 
     const String& text() const { return m_text; }

Modified: trunk/Source/WebKit/Shared/WebKeyboardEvent.cpp (252872 => 252873)


--- trunk/Source/WebKit/Shared/WebKeyboardEvent.cpp	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebKit/Shared/WebKeyboardEvent.cpp	2019-11-26 05:18:54 UTC (rev 252873)
@@ -132,10 +132,12 @@
 
 #else
 
-WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
+WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet<Modifier> modifiers, WallTime timestamp)
     : WebEvent(type, modifiers, timestamp)
     , m_text(text)
     , m_unmodifiedText(unmodifiedText)
+    , m_key(key)
+    , m_code(code)
     , m_keyIdentifier(keyIdentifier)
     , m_windowsVirtualKeyCode(windowsVirtualKeyCode)
     , m_nativeVirtualKeyCode(nativeVirtualKeyCode)

Modified: trunk/Source/WebKit/Shared/win/WebEventFactory.cpp (252872 => 252873)


--- trunk/Source/WebKit/Shared/win/WebEventFactory.cpp	2019-11-26 02:56:33 UTC (rev 252872)
+++ trunk/Source/WebKit/Shared/win/WebEventFactory.cpp	2019-11-26 05:18:54 UTC (rev 252873)
@@ -31,6 +31,7 @@
 #include <WebCore/PlatformKeyboardEvent.h>
 #include <WebCore/PlatformWheelEvent.h>
 #include <WebCore/Scrollbar.h>
+#include <WebCore/WindowsKeyNames.h>
 #include <WebCore/WindowsKeyboardCodes.h>
 #include <windowsx.h>
 #include <wtf/ASCIICType.h>
@@ -446,11 +447,19 @@
     return WebWheelEvent(WebEvent::Wheel, position, globalPosition, FloatSize(deltaX, deltaY), FloatSize(wheelTicksX, wheelTicksY), granularity, modifiers, WallTime::now());
 }
 
+static WindowsKeyNames& windowsKeyNames()
+{
+    static NeverDestroyed<WindowsKeyNames> keyNames;
+    return keyNames;
+}
+
 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
 {
     WebEvent::Type type = keyboardEventTypeForEvent(message);
     String text = textFromEvent(wparam, type);
     String unmodifiedText = unmodifiedTextFromEvent(wparam, type);
+    String key = message == WM_CHAR ? windowsKeyNames().domKeyFromChar(wparam) : windowsKeyNames().domKeyFromLParam(lparam);
+    String code = windowsKeyNames().domCodeFromLParam(lparam);
     String keyIdentifier = keyIdentifierFromEvent(wparam, type);
     int windowsVirtualKeyCode = static_cast<int>(wparam);
     int nativeVirtualKeyCode = static_cast<int>(wparam);
@@ -460,7 +469,7 @@
     bool isSystemKey = isSystemKeyEvent(message);
     auto modifiers = modifiersForCurrentKeyState();
 
-    return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey, modifiers, WallTime::now());
+    return WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey, modifiers, WallTime::now());
 }
 
 #if ENABLE(TOUCH_EVENTS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to