2021-09-27 23:22:21 +02:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2021 - 2022 , Andreas Kling < andreas @ ladybird . org >
2021-09-27 23:22:21 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/CharacterTypes.h>
2023-07-08 19:19:26 -04:00
# include <LibUnicode/CharacterTypes.h>
2022-09-25 18:06:11 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/KeyboardEventPrototype.h>
2024-10-21 16:30:10 -04:00
# include <LibWeb/UIEvents/EventNames.h>
2021-09-27 23:22:21 +02:00
# include <LibWeb/UIEvents/KeyboardEvent.h>
namespace Web : : UIEvents {
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( KeyboardEvent ) ;
2021-09-27 23:22:21 +02:00
// 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 ;
2023-12-01 11:08:12 -05:00
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 ;
}
2021-09-27 23:22:21 +02:00
// 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 ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftShift :
case KeyCode : : Key_RightShift :
2021-09-27 23:22:21 +02:00
return 16 ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftControl :
case KeyCode : : Key_RightControl :
2021-09-27 23:22:21 +02:00
return 17 ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftAlt :
case KeyCode : : Key_RightAlt :
2021-09-27 23:22:21 +02:00
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 ;
}
2023-12-01 11:08:12 -05:00
// 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 ;
}
2021-09-27 23:22:21 +02:00
// Return the virtual key code from the operating system.
return platform_key ;
}
2024-10-21 16:30:10 -04:00
// 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 ;
}
2023-07-08 19:19:26 -04:00
// 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
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftAlt :
2023-12-30 06:19:04 +02:00
case KeyCode : : Key_RightAlt :
2024-10-09 08:56:55 -04:00
return " Alt " _string ;
case KeyCode : : Key_AltGr :
return " AltGraph " _string ;
2023-07-08 19:19:26 -04:00
case KeyCode : : Key_CapsLock :
return " CapsLock " _string ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftControl :
case KeyCode : : Key_RightControl :
2023-07-08 19:19:26 -04:00
return " Control " _string ;
2024-10-09 08:56:55 -04:00
// FIXME: Fn
// FIXME: FnLock
case KeyCode : : Key_LeftSuper :
case KeyCode : : Key_RightSuper :
2023-07-08 19:19:26 -04:00
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.
2024-06-21 11:24:00 -04:00
return ! Unicode : : code_point_has_control_general_category ( code_point ) ;
2023-07-08 19:19:26 -04:00
} ;
// 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
2023-05-23 02:33:57 +00:00
static ErrorOr < String > get_event_key ( KeyCode platform_key , u32 code_point )
{
2023-07-08 19:19:26 -04:00
// 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
2024-10-09 15:45:07 -04:00
// 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 ( ) ;
}
2023-05-23 02:33:57 +00:00
}
2023-07-08 19:19:26 -04:00
// 3. Else, if the key event generates a valid key string, then
2024-10-09 15:45:07 -04:00
if ( auto key_string = TRY ( get_event_key_string ( code_point ) ) ; key_string . has_value ( ) ) {
2023-07-08 19:19:26 -04:00
// 1. Set key to that key string value.
2024-10-09 15:45:07 -04:00
return key_string . release_value ( ) ;
2023-05-23 02:33:57 +00:00
}
2023-07-08 19:19:26 -04:00
// 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
// modifer keys removed except for glyph modifier keys.
// 5. Return key as the key attribute value for this key event.
2023-08-07 11:12:38 +02:00
return " Unidentified " _string ;
2023-05-23 02:33:57 +00:00
}
2023-07-08 18:20:02 -04:00
// 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 ;
2024-10-09 18:47:44 -04:00
case KeyCode : : Key_Comma :
return " NumpadComma " _string ;
2023-07-08 18:20:02 -04:00
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 :
2024-10-09 18:47:44 -04:00
return " NumpadMultiply " _string ;
2023-07-08 18:20:02 -04:00
case KeyCode : : Key_Minus :
return " NumpadSubtract " _string ;
2024-10-09 18:47:44 -04:00
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 ;
2023-07-08 18:20:02 -04:00
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
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftAlt :
2023-12-30 06:19:04 +02:00
return " AltLeft " _string ;
case KeyCode : : Key_RightAlt :
return " AltRight " _string ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_AltGr :
return " AltGraph " _string ;
2023-07-08 18:20:02 -04:00
case KeyCode : : Key_Backspace :
return " Backspace " _string ;
case KeyCode : : Key_CapsLock :
return " CapsLock " _string ;
case KeyCode : : Key_Menu :
return " ContextMenu " _string ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftControl :
2023-12-30 06:19:04 +02:00
return " ControlLeft " _string ;
case KeyCode : : Key_RightControl :
return " ControlRight " _string ;
2023-07-08 18:20:02 -04:00
case KeyCode : : Key_Return :
return " Enter " _string ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftSuper :
return " MetaLeft " _string ;
case KeyCode : : Key_RightSuper :
return " MetaRight " _string ;
2023-07-08 18:20:02 -04:00
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 ;
2023-12-30 06:19:04 +02:00
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 ;
2023-07-08 18:20:02 -04:00
// 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 ( ) ;
}
2023-07-08 19:30:36 -04:00
// 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 ) {
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftAlt :
case KeyCode : : Key_LeftControl :
2023-07-08 19:30:36 -04:00
case KeyCode : : Key_LeftShift :
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_LeftSuper :
2023-07-08 19:30:36 -04:00
return DOMKeyLocation : : Left ;
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_RightAlt :
case KeyCode : : Key_RightControl :
2023-07-08 19:30:36 -04:00
case KeyCode : : Key_RightShift :
2024-10-09 08:56:55 -04:00
case KeyCode : : Key_RightSuper :
2023-07-08 19:30:36 -04:00
return DOMKeyLocation : : Right ;
default :
break ;
}
return DOMKeyLocation : : Standard ;
}
2023-08-13 13:05:26 +02:00
JS : : NonnullGCPtr < KeyboardEvent > KeyboardEvent : : create_from_platform_event ( JS : : Realm & realm , FlyString const & event_name , KeyCode platform_key , unsigned modifiers , u32 code_point )
2021-09-27 23:22:21 +02:00
{
2023-08-13 13:05:26 +02:00
auto event_key = MUST ( get_event_key ( platform_key , code_point ) ) ;
auto event_code = MUST ( get_event_code ( platform_key , modifiers ) ) ;
2021-09-27 23:22:21 +02:00
auto key_code = determine_key_code ( platform_key , code_point ) ;
2024-10-21 16:30:10 -04:00
auto char_code = determine_char_code ( event_name , code_point ) ;
2021-10-01 20:25:37 +03:00
KeyboardEventInit event_init { } ;
event_init . key = move ( event_key ) ;
event_init . code = move ( event_code ) ;
2023-07-08 19:30:36 -04:00
event_init . location = to_underlying ( get_event_location ( platform_key , modifiers ) ) ;
2021-10-01 20:25:37 +03:00
event_init . ctrl_key = modifiers & Mod_Ctrl ;
event_init . shift_key = modifiers & Mod_Shift ;
event_init . alt_key = modifiers & Mod_Alt ;
2023-12-15 17:31:21 +01:00
event_init . meta_key = modifiers & Mod_Super ;
2021-10-01 20:25:37 +03:00
event_init . repeat = false ;
event_init . is_composing = false ;
event_init . key_code = key_code ;
2024-10-21 16:30:10 -04:00
event_init . char_code = char_code ;
2021-10-01 20:25:37 +03:00
event_init . bubbles = true ;
event_init . cancelable = true ;
event_init . composed = true ;
2024-10-21 16:30:10 -04:00
2024-01-18 12:54:28 -07:00
auto event = KeyboardEvent : : create ( realm , event_name , event_init ) ;
event - > set_is_trusted ( true ) ;
return event ;
2022-09-25 18:06:11 -06:00
}
2024-01-19 18:52:45 +01:00
bool KeyboardEvent : : get_modifier_state ( String const & key_arg ) const
2021-09-27 23:22:21 +02:00
{
if ( key_arg = = " Control " )
return m_ctrl_key ;
if ( key_arg = = " Shift " )
return m_shift_key ;
2024-01-19 18:52:45 +01:00
if ( key_arg = = " Alt " )
return m_alt_key ;
2021-09-27 23:22:21 +02:00
if ( key_arg = = " Meta " )
return m_meta_key ;
2024-01-19 18:52:45 +01:00
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 ;
2021-09-27 23:22:21 +02:00
return false ;
}
2022-08-08 22:29:40 +02:00
2024-07-17 11:48:27 +01:00
// https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent
void KeyboardEvent : : init_keyboard_event ( String const & type , bool bubbles , bool cancelable , HTML : : Window * 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 ;
}
2023-08-13 13:05:26 +02:00
JS : : NonnullGCPtr < KeyboardEvent > KeyboardEvent : : create ( JS : : Realm & realm , FlyString const & event_name , KeyboardEventInit const & event_init )
2022-08-08 22:29:40 +02:00
{
2023-08-13 13:05:26 +02:00
return realm . heap ( ) . allocate < KeyboardEvent > ( realm , realm , event_name , event_init ) ;
2022-08-08 22:29:40 +02:00
}
2023-03-09 21:35:15 +01:00
WebIDL : : ExceptionOr < JS : : NonnullGCPtr < KeyboardEvent > > KeyboardEvent : : construct_impl ( JS : : Realm & realm , FlyString const & event_name , KeyboardEventInit const & event_init )
2022-08-08 22:29:40 +02:00
{
2022-09-25 18:06:11 -06:00
return create ( realm , event_name , event_init ) ;
2022-08-08 22:29:40 +02:00
}
2023-03-09 21:35:15 +01:00
KeyboardEvent : : KeyboardEvent ( JS : : Realm & realm , FlyString const & event_name , KeyboardEventInit const & event_init )
2023-04-06 16:12:33 +02:00
: UIEvent ( realm , event_name , event_init )
2022-08-08 22:29:40 +02:00
, 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 )
2024-01-19 18:52:45 +01:00
, 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 )
2022-08-08 22:29:40 +02:00
, 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 ;
2023-08-07 08:41:28 +02:00
void KeyboardEvent : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( KeyboardEvent ) ;
2023-01-10 06:28:20 -05:00
}
2021-09-27 23:22:21 +02:00
}