mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-23 17:33:12 +00:00
Before this change, we were going through the chain of base classes for each IDL interface object and having them set the prototype to their prototype. Instead of doing that, reorder things so that we set the right prototype immediately in Foo::initialize(), and then don't bother in all the base class overrides. This knocks off a ~1% profile item on Speedometer 3.
799 lines
26 KiB
C++
799 lines
26 KiB
C++
/*
|
||
* Copyright (c) 2021-2022, Andreas Kling <andreas@ladybird.org>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <AK/CharacterTypes.h>
|
||
#include <LibUnicode/CharacterTypes.h>
|
||
#include <LibWeb/Bindings/Intrinsics.h>
|
||
#include <LibWeb/Bindings/KeyboardEventPrototype.h>
|
||
#include <LibWeb/UIEvents/EventNames.h>
|
||
#include <LibWeb/UIEvents/KeyboardEvent.h>
|
||
|
||
namespace Web::UIEvents {
|
||
|
||
GC_DEFINE_ALLOCATOR(KeyboardEvent);
|
||
|
||
// https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
|
||
static unsigned long determine_key_code(KeyCode platform_key, u32 code_point)
|
||
{
|
||
// If input key when pressed without modifiers would insert a numerical character (0-9), return the ASCII code of that numerical character.
|
||
if (is_ascii_digit(code_point))
|
||
return code_point;
|
||
|
||
switch (platform_key) {
|
||
case KeyCode::Key_ExclamationPoint:
|
||
return static_cast<unsigned long>('1');
|
||
case KeyCode::Key_AtSign:
|
||
return static_cast<unsigned long>('2');
|
||
case KeyCode::Key_Hashtag:
|
||
return static_cast<unsigned long>('3');
|
||
case KeyCode::Key_Dollar:
|
||
return static_cast<unsigned long>('4');
|
||
case KeyCode::Key_Percent:
|
||
return static_cast<unsigned long>('5');
|
||
case KeyCode::Key_Circumflex:
|
||
return static_cast<unsigned long>('6');
|
||
case KeyCode::Key_Ampersand:
|
||
return static_cast<unsigned long>('7');
|
||
case KeyCode::Key_Asterisk:
|
||
return static_cast<unsigned long>('8');
|
||
case KeyCode::Key_LeftParen:
|
||
return static_cast<unsigned long>('9');
|
||
case KeyCode::Key_RightParen:
|
||
return static_cast<unsigned long>('0');
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// If input key when pressed without modifiers would insert a lower case character in the a-z alphabetical range, return the ASCII code of the upper case equivalent.
|
||
if (is_ascii_lower_alpha(code_point))
|
||
return to_ascii_uppercase(code_point);
|
||
|
||
// If the key’s function, as determined in an implementation-specific way, corresponds to one of the keys in the §8.3.3 Fixed virtual key codes table, return the corresponding key code.
|
||
// https://www.w3.org/TR/uievents/#fixed-virtual-key-codes
|
||
switch (platform_key) {
|
||
case KeyCode::Key_Backspace:
|
||
return 8;
|
||
case KeyCode::Key_Tab:
|
||
return 9;
|
||
case KeyCode::Key_Return:
|
||
return 13;
|
||
case KeyCode::Key_LeftShift:
|
||
case KeyCode::Key_RightShift:
|
||
return 16;
|
||
case KeyCode::Key_LeftControl:
|
||
case KeyCode::Key_RightControl:
|
||
return 17;
|
||
case KeyCode::Key_LeftAlt:
|
||
case KeyCode::Key_RightAlt:
|
||
return 18;
|
||
case KeyCode::Key_CapsLock:
|
||
return 20;
|
||
case KeyCode::Key_Escape:
|
||
return 27;
|
||
case KeyCode::Key_Space:
|
||
return 32;
|
||
case KeyCode::Key_PageUp:
|
||
return 33;
|
||
case KeyCode::Key_PageDown:
|
||
return 34;
|
||
case KeyCode::Key_End:
|
||
return 35;
|
||
case KeyCode::Key_Home:
|
||
return 36;
|
||
case KeyCode::Key_Left:
|
||
return 37;
|
||
case KeyCode::Key_Up:
|
||
return 38;
|
||
case KeyCode::Key_Right:
|
||
return 39;
|
||
case KeyCode::Key_Down:
|
||
return 40;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// https://www.w3.org/TR/uievents/#optionally-fixed-virtual-key-codes
|
||
switch (platform_key) {
|
||
case KeyCode::Key_Semicolon:
|
||
case KeyCode::Key_Colon:
|
||
return 186;
|
||
case KeyCode::Key_Equal:
|
||
case KeyCode::Key_Plus:
|
||
return 187;
|
||
case KeyCode::Key_Comma:
|
||
case KeyCode::Key_LessThan:
|
||
return 188;
|
||
case KeyCode::Key_Minus:
|
||
case KeyCode::Key_Underscore:
|
||
return 189;
|
||
case KeyCode::Key_Period:
|
||
case KeyCode::Key_GreaterThan:
|
||
return 190;
|
||
case KeyCode::Key_Slash:
|
||
case KeyCode::Key_QuestionMark:
|
||
return 191;
|
||
case KeyCode::Key_Backtick:
|
||
case KeyCode::Key_Tilde:
|
||
return 192;
|
||
case KeyCode::Key_LeftBracket:
|
||
case KeyCode::Key_LeftBrace:
|
||
return 219;
|
||
case KeyCode::Key_Backslash:
|
||
case KeyCode::Key_Pipe:
|
||
return 220;
|
||
case KeyCode::Key_RightBracket:
|
||
case KeyCode::Key_RightBrace:
|
||
return 221;
|
||
case KeyCode::Key_Apostrophe:
|
||
case KeyCode::Key_DoubleQuote:
|
||
return 222;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// Return the virtual key code from the operating system.
|
||
return platform_key;
|
||
}
|
||
|
||
// https://www.w3.org/TR/uievents/#dom-keyboardevent-charcode
|
||
static u32 determine_char_code(FlyString const& event_name, u32 code_point)
|
||
{
|
||
// charCode holds a character value, for keypress events which generate character input. The value is the Unicode
|
||
// reference number (code point) of that character (e.g. event.charCode = event.key.charCodeAt(0) for printable
|
||
// characters). For keydown or keyup events, the value of charCode is 0.
|
||
if (event_name == UIEvents::EventNames::keypress) {
|
||
if (Unicode::code_point_is_printable(code_point))
|
||
return code_point;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
// 3. Named key Attribute Values, https://www.w3.org/TR/uievents-key/#named-key-attribute-values
|
||
static ErrorOr<Optional<String>> get_event_named_key(KeyCode platform_key)
|
||
{
|
||
switch (platform_key) {
|
||
// 3.1. Special Keys, https://www.w3.org/TR/uievents-key/#keys-special
|
||
case KeyCode::Key_Invalid:
|
||
return "Unidentified"_string;
|
||
|
||
// 3.2. Modifier Keys, https://www.w3.org/TR/uievents-key/#keys-modifier
|
||
case KeyCode::Key_LeftAlt:
|
||
case KeyCode::Key_RightAlt:
|
||
return "Alt"_string;
|
||
case KeyCode::Key_AltGr:
|
||
return "AltGraph"_string;
|
||
case KeyCode::Key_CapsLock:
|
||
return "CapsLock"_string;
|
||
case KeyCode::Key_LeftControl:
|
||
case KeyCode::Key_RightControl:
|
||
return "Control"_string;
|
||
// FIXME: Fn
|
||
// FIXME: FnLock
|
||
case KeyCode::Key_LeftSuper:
|
||
case KeyCode::Key_RightSuper:
|
||
return "Meta"_string;
|
||
case KeyCode::Key_NumLock:
|
||
return "NumLock"_string;
|
||
case KeyCode::Key_ScrollLock:
|
||
return "ScrollLock"_string;
|
||
case KeyCode::Key_LeftShift:
|
||
case KeyCode::Key_RightShift:
|
||
return "Shift"_string;
|
||
|
||
// 3.3. Whitespace Keys, https://www.w3.org/TR/uievents-key/#keys-whitespace
|
||
case KeyCode::Key_Return:
|
||
return "Enter"_string;
|
||
case KeyCode::Key_Tab:
|
||
return "Tab"_string;
|
||
case KeyCode::Key_Space:
|
||
return " "_string;
|
||
|
||
// 3.4. Navigation Keys, https://www.w3.org/TR/uievents-key/#keys-navigation
|
||
case KeyCode::Key_Down:
|
||
return "ArrowDown"_string;
|
||
case KeyCode::Key_Left:
|
||
return "ArrowLeft"_string;
|
||
case KeyCode::Key_Right:
|
||
return "ArrowRight"_string;
|
||
case KeyCode::Key_Up:
|
||
return "ArrowUp"_string;
|
||
case KeyCode::Key_End:
|
||
return "End"_string;
|
||
case KeyCode::Key_Home:
|
||
return "Home"_string;
|
||
case KeyCode::Key_PageDown:
|
||
return "PageDown"_string;
|
||
case KeyCode::Key_PageUp:
|
||
return "PageUp"_string;
|
||
|
||
// 3.5. Editing Keys, https://www.w3.org/TR/uievents-key/#keys-editing
|
||
case KeyCode::Key_Backspace:
|
||
return "Backspace"_string;
|
||
case KeyCode::Key_Delete:
|
||
return "Delete"_string;
|
||
case KeyCode::Key_Insert:
|
||
return "Insert"_string;
|
||
|
||
// 3.6. UI Keys, https://www.w3.org/TR/uievents-key/#keys-ui
|
||
case KeyCode::Key_Menu:
|
||
return "ContextMenu"_string;
|
||
case KeyCode::Key_Escape:
|
||
return "Escape"_string;
|
||
// FIXME: Help
|
||
// FIXME: Pause
|
||
|
||
// 3.7. Device Keys, https://www.w3.org/TR/uievents-key/#keys-device
|
||
case KeyCode::Key_PrintScreen:
|
||
return "PrintScreen"_string;
|
||
|
||
// 3.9. General-Purpose Function Keys, https://www.w3.org/TR/uievents-key/#keys-function
|
||
case KeyCode::Key_F1:
|
||
return "F1"_string;
|
||
case KeyCode::Key_F2:
|
||
return "F2"_string;
|
||
case KeyCode::Key_F3:
|
||
return "F3"_string;
|
||
case KeyCode::Key_F4:
|
||
return "F4"_string;
|
||
case KeyCode::Key_F5:
|
||
return "F5"_string;
|
||
case KeyCode::Key_F6:
|
||
return "F6"_string;
|
||
case KeyCode::Key_F7:
|
||
return "F7"_string;
|
||
case KeyCode::Key_F8:
|
||
return "F8"_string;
|
||
case KeyCode::Key_F9:
|
||
return "F9"_string;
|
||
case KeyCode::Key_F10:
|
||
return "F10"_string;
|
||
case KeyCode::Key_F11:
|
||
return "F11"_string;
|
||
case KeyCode::Key_F12:
|
||
return "F12"_string;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return OptionalNone {};
|
||
}
|
||
|
||
// 2.1. Unicode Values, https://www.w3.org/TR/uievents-key/#keys-unicode
|
||
static ErrorOr<Optional<String>> get_event_key_string(u32 code_point)
|
||
{
|
||
auto is_non_control_character = [&]() {
|
||
// A non-control character is any valid Unicode character except those that are part of the "Other, Control"
|
||
// ("Cc") General Category.
|
||
return !Unicode::code_point_has_control_general_category(code_point);
|
||
};
|
||
|
||
// A key string is a string containing a 0 or 1 non-control characters ("base" characters) followed by 0 or more
|
||
// combining characters. The string MUST be in Normalized Form C (NFC) as described in [UAX15].
|
||
// FIXME: Our key events are currently set up to provide one code point at a time. We will need to handle multi-
|
||
// code point events and NFC normalize that string.
|
||
if (is_non_control_character())
|
||
return String::from_code_point(code_point);
|
||
|
||
return OptionalNone {};
|
||
}
|
||
|
||
// 2.2. Selecting key Attribute Values, https://www.w3.org/TR/uievents-key/#selecting-key-attribute-values
|
||
static ErrorOr<String> get_event_key(KeyCode platform_key, u32 code_point)
|
||
{
|
||
// 1. Let key be a DOMString initially set to "Unidentified".
|
||
// NOTE: We return "Unidentified" at the end to avoid needlessly allocating it here.
|
||
|
||
// 2. If there exists an appropriate named key attribute value for this key event, then
|
||
// AD-HOC: Key_Invalid would be interpreted as "Unidentified" here. But we also use Key_Invalid for key presses that
|
||
// are not on a standard US keyboard. If such a key would generate a valid key string below, let's allow that
|
||
// to happen; otherwise, we will still return "Unidentified" at the end.
|
||
if (platform_key != KeyCode::Key_Invalid) {
|
||
if (auto named_key = TRY(get_event_named_key(platform_key)); named_key.has_value()) {
|
||
// 1. Set key to that named key attribute value.
|
||
return named_key.release_value();
|
||
}
|
||
}
|
||
|
||
// 3. Else, if the key event generates a valid key string, then
|
||
if (auto key_string = TRY(get_event_key_string(code_point)); key_string.has_value()) {
|
||
// 1. Set key to that key string value.
|
||
return key_string.release_value();
|
||
}
|
||
|
||
// FIXME: 4. Else, if the key event has any modifier keys other than glyph modifier keys, then
|
||
// FIXME: 1. Set key to the key string that would have been generated by this event if it had been typed with all
|
||
// modifier keys removed except for glyph modifier keys.
|
||
|
||
// 5. Return key as the key attribute value for this key event.
|
||
return "Unidentified"_string;
|
||
}
|
||
|
||
// 3. Keyboard Event code Value Tables, https://www.w3.org/TR/uievents-code/#code-value-tables
|
||
static ErrorOr<String> get_event_code(KeyCode platform_key, unsigned modifiers)
|
||
{
|
||
// 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
|
||
if ((modifiers & Mod_Keypad) != 0) {
|
||
switch (platform_key) {
|
||
case KeyCode::Key_0:
|
||
return "Numpad0"_string;
|
||
case KeyCode::Key_1:
|
||
return "Numpad1"_string;
|
||
case KeyCode::Key_2:
|
||
return "Numpad2"_string;
|
||
case KeyCode::Key_3:
|
||
return "Numpad3"_string;
|
||
case KeyCode::Key_4:
|
||
return "Numpad4"_string;
|
||
case KeyCode::Key_5:
|
||
return "Numpad5"_string;
|
||
case KeyCode::Key_6:
|
||
return "Numpad6"_string;
|
||
case KeyCode::Key_7:
|
||
return "Numpad7"_string;
|
||
case KeyCode::Key_8:
|
||
return "Numpad8"_string;
|
||
case KeyCode::Key_9:
|
||
return "Numpad9"_string;
|
||
case KeyCode::Key_Plus:
|
||
return "NumpadAdd"_string;
|
||
case KeyCode::Key_Comma:
|
||
return "NumpadComma"_string;
|
||
case KeyCode::Key_Period:
|
||
case KeyCode::Key_Delete:
|
||
return "NumpadDecimal"_string;
|
||
case KeyCode::Key_Slash:
|
||
return "NumpadDivide"_string;
|
||
case KeyCode::Key_Return:
|
||
return "NumpadEnter"_string;
|
||
case KeyCode::Key_Asterisk:
|
||
return "NumpadMultiply"_string;
|
||
case KeyCode::Key_Minus:
|
||
return "NumpadSubtract"_string;
|
||
case KeyCode::Key_Equal:
|
||
return "NumpadEqual"_string;
|
||
case KeyCode::Key_Hashtag:
|
||
return "NumpadHash"_string;
|
||
case KeyCode::Key_LeftParen:
|
||
return "NumpadParenLeft"_string;
|
||
case KeyCode::Key_RightParen:
|
||
return "NumpadParenRight"_string;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
switch (platform_key) {
|
||
// 3.1.1. Writing System Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-writing-system
|
||
case KeyCode::Key_Backtick:
|
||
case KeyCode::Key_Tilde:
|
||
return "Backquote"_string;
|
||
case KeyCode::Key_Backslash:
|
||
case KeyCode::Key_Pipe:
|
||
return "Backslash"_string;
|
||
case KeyCode::Key_LeftBrace:
|
||
case KeyCode::Key_LeftBracket:
|
||
return "BracketLeft"_string;
|
||
case KeyCode::Key_RightBrace:
|
||
case KeyCode::Key_RightBracket:
|
||
return "BracketRight"_string;
|
||
case KeyCode::Key_Comma:
|
||
case KeyCode::Key_LessThan:
|
||
return "Comma"_string;
|
||
case KeyCode::Key_0:
|
||
case KeyCode::Key_RightParen:
|
||
return "Digit0"_string;
|
||
case KeyCode::Key_1:
|
||
case KeyCode::Key_ExclamationPoint:
|
||
return "Digit1"_string;
|
||
case KeyCode::Key_2:
|
||
case KeyCode::Key_AtSign:
|
||
return "Digit2"_string;
|
||
case KeyCode::Key_3:
|
||
case KeyCode::Key_Hashtag:
|
||
return "Digit3"_string;
|
||
case KeyCode::Key_4:
|
||
case KeyCode::Key_Dollar:
|
||
return "Digit4"_string;
|
||
case KeyCode::Key_5:
|
||
case KeyCode::Key_Percent:
|
||
return "Digit5"_string;
|
||
case KeyCode::Key_6:
|
||
case KeyCode::Key_Circumflex:
|
||
return "Digit6"_string;
|
||
case KeyCode::Key_7:
|
||
case KeyCode::Key_Ampersand:
|
||
return "Digit7"_string;
|
||
case KeyCode::Key_8:
|
||
case KeyCode::Key_Asterisk:
|
||
return "Digit8"_string;
|
||
case KeyCode::Key_9:
|
||
case KeyCode::Key_LeftParen:
|
||
return "Digit9"_string;
|
||
case KeyCode::Key_Equal:
|
||
case KeyCode::Key_Plus:
|
||
return "Equal"_string;
|
||
// FIXME: IntlBackslash
|
||
// FIXME: IntlRo
|
||
// FIXME: IntlYen
|
||
case KeyCode::Key_A:
|
||
return "KeyA"_string;
|
||
case KeyCode::Key_B:
|
||
return "KeyB"_string;
|
||
case KeyCode::Key_C:
|
||
return "KeyC"_string;
|
||
case KeyCode::Key_D:
|
||
return "KeyD"_string;
|
||
case KeyCode::Key_E:
|
||
return "KeyE"_string;
|
||
case KeyCode::Key_F:
|
||
return "KeyF"_string;
|
||
case KeyCode::Key_G:
|
||
return "KeyG"_string;
|
||
case KeyCode::Key_H:
|
||
return "KeyH"_string;
|
||
case KeyCode::Key_I:
|
||
return "KeyI"_string;
|
||
case KeyCode::Key_J:
|
||
return "KeyJ"_string;
|
||
case KeyCode::Key_K:
|
||
return "KeyK"_string;
|
||
case KeyCode::Key_L:
|
||
return "KeyL"_string;
|
||
case KeyCode::Key_M:
|
||
return "KeyM"_string;
|
||
case KeyCode::Key_N:
|
||
return "KeyN"_string;
|
||
case KeyCode::Key_O:
|
||
return "KeyO"_string;
|
||
case KeyCode::Key_P:
|
||
return "KeyP"_string;
|
||
case KeyCode::Key_Q:
|
||
return "KeyQ"_string;
|
||
case KeyCode::Key_R:
|
||
return "KeyR"_string;
|
||
case KeyCode::Key_S:
|
||
return "KeyS"_string;
|
||
case KeyCode::Key_T:
|
||
return "KeyT"_string;
|
||
case KeyCode::Key_U:
|
||
return "KeyU"_string;
|
||
case KeyCode::Key_V:
|
||
return "KeyV"_string;
|
||
case KeyCode::Key_W:
|
||
return "KeyW"_string;
|
||
case KeyCode::Key_X:
|
||
return "KeyX"_string;
|
||
case KeyCode::Key_Y:
|
||
return "KeyY"_string;
|
||
case KeyCode::Key_Z:
|
||
return "KeyZ"_string;
|
||
case KeyCode::Key_Minus:
|
||
case KeyCode::Key_Underscore:
|
||
return "Minus"_string;
|
||
case KeyCode::Key_Period:
|
||
case KeyCode::Key_GreaterThan:
|
||
return "Period"_string;
|
||
case KeyCode::Key_Apostrophe:
|
||
case KeyCode::Key_DoubleQuote:
|
||
return "Quote"_string;
|
||
case KeyCode::Key_Semicolon:
|
||
case KeyCode::Key_Colon:
|
||
return "Semicolon"_string;
|
||
case KeyCode::Key_Slash:
|
||
case KeyCode::Key_QuestionMark:
|
||
return "Slash"_string;
|
||
|
||
// 3.1.2. Functional Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-functional
|
||
case KeyCode::Key_LeftAlt:
|
||
return "AltLeft"_string;
|
||
case KeyCode::Key_RightAlt:
|
||
return "AltRight"_string;
|
||
case KeyCode::Key_AltGr:
|
||
return "AltGraph"_string;
|
||
case KeyCode::Key_Backspace:
|
||
return "Backspace"_string;
|
||
case KeyCode::Key_CapsLock:
|
||
return "CapsLock"_string;
|
||
case KeyCode::Key_Menu:
|
||
return "ContextMenu"_string;
|
||
case KeyCode::Key_LeftControl:
|
||
return "ControlLeft"_string;
|
||
case KeyCode::Key_RightControl:
|
||
return "ControlRight"_string;
|
||
case KeyCode::Key_Return:
|
||
return "Enter"_string;
|
||
case KeyCode::Key_LeftSuper:
|
||
return "MetaLeft"_string;
|
||
case KeyCode::Key_RightSuper:
|
||
return "MetaRight"_string;
|
||
case KeyCode::Key_LeftShift:
|
||
return "ShiftLeft"_string;
|
||
case KeyCode::Key_RightShift:
|
||
return "ShiftRight"_string;
|
||
case KeyCode::Key_Space:
|
||
return "Space"_string;
|
||
case KeyCode::Key_Tab:
|
||
return "Tab"_string;
|
||
|
||
// 3.2. Control Pad Section, https://www.w3.org/TR/uievents-code/#key-controlpad-section
|
||
case KeyCode::Key_Delete:
|
||
return "Delete"_string;
|
||
case KeyCode::Key_End:
|
||
return "End"_string;
|
||
// FIXME: Help
|
||
case KeyCode::Key_Home:
|
||
return "Home"_string;
|
||
case KeyCode::Key_Insert:
|
||
return "Insert"_string;
|
||
case KeyCode::Key_PageDown:
|
||
return "PageDown"_string;
|
||
case KeyCode::Key_PageUp:
|
||
return "PageUp"_string;
|
||
|
||
// 3.3. Arrow Pad Section, https://www.w3.org/TR/uievents-code/#key-arrowpad-section
|
||
case KeyCode::Key_Down:
|
||
return "ArrowDown"_string;
|
||
case KeyCode::Key_Left:
|
||
return "ArrowLeft"_string;
|
||
case KeyCode::Key_Right:
|
||
return "ArrowRight"_string;
|
||
case KeyCode::Key_Up:
|
||
return "ArrowUp"_string;
|
||
|
||
// 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
|
||
case KeyCode::Key_NumLock:
|
||
return "NumLock"_string;
|
||
|
||
// 3.5. Function Section, https://www.w3.org/TR/uievents-code/#key-function-section
|
||
case KeyCode::Key_Escape:
|
||
return "Escape"_string;
|
||
case KeyCode::Key_F1:
|
||
return "F1"_string;
|
||
case KeyCode::Key_F2:
|
||
return "F2"_string;
|
||
case KeyCode::Key_F3:
|
||
return "F3"_string;
|
||
case KeyCode::Key_F4:
|
||
return "F4"_string;
|
||
case KeyCode::Key_F5:
|
||
return "F5"_string;
|
||
case KeyCode::Key_F6:
|
||
return "F6"_string;
|
||
case KeyCode::Key_F7:
|
||
return "F7"_string;
|
||
case KeyCode::Key_F8:
|
||
return "F8"_string;
|
||
case KeyCode::Key_F9:
|
||
return "F9"_string;
|
||
case KeyCode::Key_F10:
|
||
return "F10"_string;
|
||
case KeyCode::Key_F11:
|
||
return "F11"_string;
|
||
case KeyCode::Key_F12:
|
||
return "F12"_string;
|
||
case KeyCode::Key_PrintScreen:
|
||
case KeyCode::Key_SysRq:
|
||
return "PrintScreen"_string;
|
||
case KeyCode::Key_ScrollLock:
|
||
return "ScrollLock"_string;
|
||
case KeyCode::Key_PauseBreak:
|
||
return "Pause"_string;
|
||
|
||
// 3.6. Media Section, https://www.w3.org/TR/uievents-code/#media-keys
|
||
case KeyCode::Key_BrowserSearch:
|
||
return "BrowserSearch"_string;
|
||
case KeyCode::Key_BrowserFavorites:
|
||
return "BrowserFavorites"_string;
|
||
case KeyCode::Key_BrowserHome:
|
||
return "BrowserHome"_string;
|
||
case KeyCode::Key_PreviousTrack:
|
||
return "PreviousTrack"_string;
|
||
case KeyCode::Key_BrowserBack:
|
||
return "BrowserBack"_string;
|
||
case KeyCode::Key_BrowserForward:
|
||
return "BrowserForward"_string;
|
||
case KeyCode::Key_BrowserRefresh:
|
||
return "BrowserRefresh"_string;
|
||
case KeyCode::Key_BrowserStop:
|
||
return "BrowserStop"_string;
|
||
case KeyCode::Key_VolumeDown:
|
||
return "AudioVolumeDown"_string;
|
||
case KeyCode::Key_VolumeUp:
|
||
return "AudioVolumeUp"_string;
|
||
case KeyCode::Key_Wake:
|
||
return "WakeUp"_string;
|
||
case KeyCode::Key_Sleep:
|
||
return "Sleep"_string;
|
||
case KeyCode::Key_NextTrack:
|
||
return "NextTrack"_string;
|
||
case KeyCode::Key_MediaSelect:
|
||
return "MediaSelect"_string;
|
||
case KeyCode::Key_Email:
|
||
return "LaunchMail"_string;
|
||
|
||
case KeyCode::Key_Power:
|
||
return "Power"_string;
|
||
case KeyCode::Key_Stop:
|
||
return "MediaStop"_string;
|
||
case KeyCode::Key_PlayPause:
|
||
return "MediaPlayPause"_string;
|
||
case KeyCode::Key_Mute:
|
||
return "AudioVolumeMute"_string;
|
||
case KeyCode::Key_Calculator:
|
||
return "LaunchApp2"_string;
|
||
case KeyCode::Key_MyComputer:
|
||
return "LaunchApp1"_string;
|
||
|
||
// FIXME: Are these correct?
|
||
case KeyCode::Key_LeftGUI:
|
||
return "LaunchApp2"_string;
|
||
case KeyCode::Key_RightGUI:
|
||
case KeyCode::Key_Apps:
|
||
return "LaunchApp1"_string;
|
||
|
||
// 3.7. Legacy, Non-Standard and Special Keys, https://www.w3.org/TR/uievents-code/#key-legacy
|
||
case KeyCode::Key_Invalid:
|
||
return "Unidentified"_string;
|
||
}
|
||
|
||
VERIFY_NOT_REACHED();
|
||
}
|
||
|
||
// 5.6.2. Keyboard Event Key Location, https://www.w3.org/TR/uievents/#events-keyboard-key-location
|
||
static DOMKeyLocation get_event_location(KeyCode platform_key, unsigned modifiers)
|
||
{
|
||
if ((modifiers & Mod_Keypad) != 0)
|
||
return DOMKeyLocation::Numpad;
|
||
|
||
switch (platform_key) {
|
||
case KeyCode::Key_LeftAlt:
|
||
case KeyCode::Key_LeftControl:
|
||
case KeyCode::Key_LeftShift:
|
||
case KeyCode::Key_LeftSuper:
|
||
return DOMKeyLocation::Left;
|
||
case KeyCode::Key_RightAlt:
|
||
case KeyCode::Key_RightControl:
|
||
case KeyCode::Key_RightShift:
|
||
case KeyCode::Key_RightSuper:
|
||
return DOMKeyLocation::Right;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return DOMKeyLocation::Standard;
|
||
}
|
||
|
||
GC::Ref<KeyboardEvent> KeyboardEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point, bool repeat)
|
||
{
|
||
auto event_key = MUST(get_event_key(platform_key, code_point));
|
||
auto event_code = MUST(get_event_code(platform_key, modifiers));
|
||
auto key_code = determine_key_code(platform_key, code_point);
|
||
auto char_code = determine_char_code(event_name, code_point);
|
||
|
||
KeyboardEventInit event_init {};
|
||
event_init.key = move(event_key);
|
||
event_init.code = move(event_code);
|
||
event_init.location = to_underlying(get_event_location(platform_key, modifiers));
|
||
event_init.ctrl_key = modifiers & Mod_Ctrl;
|
||
event_init.shift_key = modifiers & Mod_Shift;
|
||
event_init.alt_key = modifiers & Mod_Alt;
|
||
event_init.meta_key = modifiers & Mod_Super;
|
||
event_init.repeat = repeat;
|
||
event_init.is_composing = false;
|
||
event_init.key_code = key_code;
|
||
event_init.char_code = char_code;
|
||
event_init.bubbles = true;
|
||
event_init.cancelable = true;
|
||
event_init.composed = true;
|
||
|
||
auto event = KeyboardEvent::create(realm, event_name, event_init);
|
||
event->set_is_trusted(true);
|
||
return event;
|
||
}
|
||
|
||
bool KeyboardEvent::get_modifier_state(String const& key_arg) const
|
||
{
|
||
if (key_arg == "Control")
|
||
return m_ctrl_key;
|
||
if (key_arg == "Shift")
|
||
return m_shift_key;
|
||
if (key_arg == "Alt")
|
||
return m_alt_key;
|
||
if (key_arg == "Meta")
|
||
return m_meta_key;
|
||
if (key_arg == "AltGraph")
|
||
return m_modifier_alt_graph;
|
||
if (key_arg == "CapsLock")
|
||
return m_modifier_caps_lock;
|
||
if (key_arg == "Fn")
|
||
return m_modifier_fn;
|
||
if (key_arg == "FnLock")
|
||
return m_modifier_fn_lock;
|
||
if (key_arg == "Hyper")
|
||
return m_modifier_hyper;
|
||
if (key_arg == "NumLock")
|
||
return m_modifier_num_lock;
|
||
if (key_arg == "ScrollLock")
|
||
return m_modifier_scroll_lock;
|
||
if (key_arg == "Super")
|
||
return m_modifier_super;
|
||
if (key_arg == "Symbol")
|
||
return m_modifier_symbol;
|
||
if (key_arg == "SymbolLock")
|
||
return m_modifier_symbol_lock;
|
||
return false;
|
||
}
|
||
|
||
// https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent
|
||
void KeyboardEvent::init_keyboard_event(String const& type, bool bubbles, bool cancelable, GC::Ptr<HTML::WindowProxy> view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key)
|
||
{
|
||
// Initializes attributes of a KeyboardEvent object. This method has the same behavior as UIEvent.initUIEvent().
|
||
// The value of detail remains undefined.
|
||
|
||
// 1. If this’s dispatch flag is set, then return.
|
||
if (dispatched())
|
||
return;
|
||
|
||
// 2. Initialize this with type, bubbles, and cancelable.
|
||
initialize_event(type, bubbles, cancelable);
|
||
|
||
// Implementation Defined: Initialise other values.
|
||
m_view = view;
|
||
m_key = key;
|
||
m_location = location;
|
||
m_ctrl_key = ctrl_key;
|
||
m_alt_key = alt_key;
|
||
m_shift_key = shift_key;
|
||
m_meta_key = meta_key;
|
||
}
|
||
|
||
GC::Ref<KeyboardEvent> KeyboardEvent::create(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||
{
|
||
return realm.create<KeyboardEvent>(realm, event_name, event_init);
|
||
}
|
||
|
||
WebIDL::ExceptionOr<GC::Ref<KeyboardEvent>> KeyboardEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||
{
|
||
return create(realm, event_name, event_init);
|
||
}
|
||
|
||
KeyboardEvent::KeyboardEvent(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||
: UIEvent(realm, event_name, event_init)
|
||
, m_key(event_init.key)
|
||
, m_code(event_init.code)
|
||
, m_location(event_init.location)
|
||
, m_ctrl_key(event_init.ctrl_key)
|
||
, m_shift_key(event_init.shift_key)
|
||
, m_alt_key(event_init.alt_key)
|
||
, m_meta_key(event_init.meta_key)
|
||
, m_modifier_alt_graph(event_init.modifier_alt_graph)
|
||
, m_modifier_caps_lock(event_init.modifier_caps_lock)
|
||
, m_modifier_fn(event_init.modifier_fn)
|
||
, m_modifier_fn_lock(event_init.modifier_fn_lock)
|
||
, m_modifier_hyper(event_init.modifier_hyper)
|
||
, m_modifier_num_lock(event_init.modifier_num_lock)
|
||
, m_modifier_scroll_lock(event_init.modifier_scroll_lock)
|
||
, m_modifier_super(event_init.modifier_super)
|
||
, m_modifier_symbol(event_init.modifier_symbol)
|
||
, m_modifier_symbol_lock(event_init.modifier_symbol_lock)
|
||
, m_repeat(event_init.repeat)
|
||
, m_is_composing(event_init.is_composing)
|
||
, m_key_code(event_init.key_code)
|
||
, m_char_code(event_init.char_code)
|
||
{
|
||
}
|
||
|
||
KeyboardEvent::~KeyboardEvent() = default;
|
||
|
||
void KeyboardEvent::initialize(JS::Realm& realm)
|
||
{
|
||
WEB_SET_PROTOTYPE_FOR_INTERFACE(KeyboardEvent);
|
||
Base::initialize(realm);
|
||
}
|
||
|
||
}
|