KeyboardEvent.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /*
  2. * Copyright (c) 2021-2022, Andreas Kling <andreas@ladybird.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/CharacterTypes.h>
  7. #include <LibUnicode/CharacterTypes.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/Bindings/KeyboardEventPrototype.h>
  10. #include <LibWeb/UIEvents/EventNames.h>
  11. #include <LibWeb/UIEvents/KeyboardEvent.h>
  12. namespace Web::UIEvents {
  13. JS_DEFINE_ALLOCATOR(KeyboardEvent);
  14. // https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
  15. static unsigned long determine_key_code(KeyCode platform_key, u32 code_point)
  16. {
  17. // If input key when pressed without modifiers would insert a numerical character (0-9), return the ASCII code of that numerical character.
  18. if (is_ascii_digit(code_point))
  19. return code_point;
  20. switch (platform_key) {
  21. case KeyCode::Key_ExclamationPoint:
  22. return static_cast<unsigned long>('1');
  23. case KeyCode::Key_AtSign:
  24. return static_cast<unsigned long>('2');
  25. case KeyCode::Key_Hashtag:
  26. return static_cast<unsigned long>('3');
  27. case KeyCode::Key_Dollar:
  28. return static_cast<unsigned long>('4');
  29. case KeyCode::Key_Percent:
  30. return static_cast<unsigned long>('5');
  31. case KeyCode::Key_Circumflex:
  32. return static_cast<unsigned long>('6');
  33. case KeyCode::Key_Ampersand:
  34. return static_cast<unsigned long>('7');
  35. case KeyCode::Key_Asterisk:
  36. return static_cast<unsigned long>('8');
  37. case KeyCode::Key_LeftParen:
  38. return static_cast<unsigned long>('9');
  39. case KeyCode::Key_RightParen:
  40. return static_cast<unsigned long>('0');
  41. default:
  42. break;
  43. }
  44. // 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.
  45. if (is_ascii_lower_alpha(code_point))
  46. return to_ascii_uppercase(code_point);
  47. // 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.
  48. // https://www.w3.org/TR/uievents/#fixed-virtual-key-codes
  49. switch (platform_key) {
  50. case KeyCode::Key_Backspace:
  51. return 8;
  52. case KeyCode::Key_Tab:
  53. return 9;
  54. case KeyCode::Key_Return:
  55. return 13;
  56. case KeyCode::Key_LeftShift:
  57. case KeyCode::Key_RightShift:
  58. return 16;
  59. case KeyCode::Key_LeftControl:
  60. case KeyCode::Key_RightControl:
  61. return 17;
  62. case KeyCode::Key_LeftAlt:
  63. case KeyCode::Key_RightAlt:
  64. return 18;
  65. case KeyCode::Key_CapsLock:
  66. return 20;
  67. case KeyCode::Key_Escape:
  68. return 27;
  69. case KeyCode::Key_Space:
  70. return 32;
  71. case KeyCode::Key_PageUp:
  72. return 33;
  73. case KeyCode::Key_PageDown:
  74. return 34;
  75. case KeyCode::Key_End:
  76. return 35;
  77. case KeyCode::Key_Home:
  78. return 36;
  79. case KeyCode::Key_Left:
  80. return 37;
  81. case KeyCode::Key_Up:
  82. return 38;
  83. case KeyCode::Key_Right:
  84. return 39;
  85. case KeyCode::Key_Down:
  86. return 40;
  87. default:
  88. break;
  89. }
  90. // https://www.w3.org/TR/uievents/#optionally-fixed-virtual-key-codes
  91. switch (platform_key) {
  92. case KeyCode::Key_Semicolon:
  93. case KeyCode::Key_Colon:
  94. return 186;
  95. case KeyCode::Key_Equal:
  96. case KeyCode::Key_Plus:
  97. return 187;
  98. case KeyCode::Key_Comma:
  99. case KeyCode::Key_LessThan:
  100. return 188;
  101. case KeyCode::Key_Minus:
  102. case KeyCode::Key_Underscore:
  103. return 189;
  104. case KeyCode::Key_Period:
  105. case KeyCode::Key_GreaterThan:
  106. return 190;
  107. case KeyCode::Key_Slash:
  108. case KeyCode::Key_QuestionMark:
  109. return 191;
  110. case KeyCode::Key_Backtick:
  111. case KeyCode::Key_Tilde:
  112. return 192;
  113. case KeyCode::Key_LeftBracket:
  114. case KeyCode::Key_LeftBrace:
  115. return 219;
  116. case KeyCode::Key_Backslash:
  117. case KeyCode::Key_Pipe:
  118. return 220;
  119. case KeyCode::Key_RightBracket:
  120. case KeyCode::Key_RightBrace:
  121. return 221;
  122. case KeyCode::Key_Apostrophe:
  123. case KeyCode::Key_DoubleQuote:
  124. return 222;
  125. default:
  126. break;
  127. }
  128. // Return the virtual key code from the operating system.
  129. return platform_key;
  130. }
  131. // https://www.w3.org/TR/uievents/#dom-keyboardevent-charcode
  132. static u32 determine_char_code(FlyString const& event_name, u32 code_point)
  133. {
  134. // charCode holds a character value, for keypress events which generate character input. The value is the Unicode
  135. // reference number (code point) of that character (e.g. event.charCode = event.key.charCodeAt(0) for printable
  136. // characters). For keydown or keyup events, the value of charCode is 0.
  137. if (event_name == UIEvents::EventNames::keypress) {
  138. if (Unicode::code_point_is_printable(code_point))
  139. return code_point;
  140. }
  141. return 0;
  142. }
  143. // 3. Named key Attribute Values, https://www.w3.org/TR/uievents-key/#named-key-attribute-values
  144. static ErrorOr<Optional<String>> get_event_named_key(KeyCode platform_key)
  145. {
  146. switch (platform_key) {
  147. // 3.1. Special Keys, https://www.w3.org/TR/uievents-key/#keys-special
  148. case KeyCode::Key_Invalid:
  149. return "Unidentified"_string;
  150. // 3.2. Modifier Keys, https://www.w3.org/TR/uievents-key/#keys-modifier
  151. case KeyCode::Key_LeftAlt:
  152. case KeyCode::Key_RightAlt:
  153. return "Alt"_string;
  154. case KeyCode::Key_AltGr:
  155. return "AltGraph"_string;
  156. case KeyCode::Key_CapsLock:
  157. return "CapsLock"_string;
  158. case KeyCode::Key_LeftControl:
  159. case KeyCode::Key_RightControl:
  160. return "Control"_string;
  161. // FIXME: Fn
  162. // FIXME: FnLock
  163. case KeyCode::Key_LeftSuper:
  164. case KeyCode::Key_RightSuper:
  165. return "Meta"_string;
  166. case KeyCode::Key_NumLock:
  167. return "NumLock"_string;
  168. case KeyCode::Key_ScrollLock:
  169. return "ScrollLock"_string;
  170. case KeyCode::Key_LeftShift:
  171. case KeyCode::Key_RightShift:
  172. return "Shift"_string;
  173. // 3.3. Whitespace Keys, https://www.w3.org/TR/uievents-key/#keys-whitespace
  174. case KeyCode::Key_Return:
  175. return "Enter"_string;
  176. case KeyCode::Key_Tab:
  177. return "Tab"_string;
  178. case KeyCode::Key_Space:
  179. return " "_string;
  180. // 3.4. Navigation Keys, https://www.w3.org/TR/uievents-key/#keys-navigation
  181. case KeyCode::Key_Down:
  182. return "ArrowDown"_string;
  183. case KeyCode::Key_Left:
  184. return "ArrowLeft"_string;
  185. case KeyCode::Key_Right:
  186. return "ArrowRight"_string;
  187. case KeyCode::Key_Up:
  188. return "ArrowUp"_string;
  189. case KeyCode::Key_End:
  190. return "End"_string;
  191. case KeyCode::Key_Home:
  192. return "Home"_string;
  193. case KeyCode::Key_PageDown:
  194. return "PageDown"_string;
  195. case KeyCode::Key_PageUp:
  196. return "PageUp"_string;
  197. // 3.5. Editing Keys, https://www.w3.org/TR/uievents-key/#keys-editing
  198. case KeyCode::Key_Backspace:
  199. return "Backspace"_string;
  200. case KeyCode::Key_Delete:
  201. return "Delete"_string;
  202. case KeyCode::Key_Insert:
  203. return "Insert"_string;
  204. // 3.6. UI Keys, https://www.w3.org/TR/uievents-key/#keys-ui
  205. case KeyCode::Key_Menu:
  206. return "ContextMenu"_string;
  207. case KeyCode::Key_Escape:
  208. return "Escape"_string;
  209. // FIXME: Help
  210. // FIXME: Pause
  211. // 3.7. Device Keys, https://www.w3.org/TR/uievents-key/#keys-device
  212. case KeyCode::Key_PrintScreen:
  213. return "PrintScreen"_string;
  214. // 3.9. General-Purpose Function Keys, https://www.w3.org/TR/uievents-key/#keys-function
  215. case KeyCode::Key_F1:
  216. return "F1"_string;
  217. case KeyCode::Key_F2:
  218. return "F2"_string;
  219. case KeyCode::Key_F3:
  220. return "F3"_string;
  221. case KeyCode::Key_F4:
  222. return "F4"_string;
  223. case KeyCode::Key_F5:
  224. return "F5"_string;
  225. case KeyCode::Key_F6:
  226. return "F6"_string;
  227. case KeyCode::Key_F7:
  228. return "F7"_string;
  229. case KeyCode::Key_F8:
  230. return "F8"_string;
  231. case KeyCode::Key_F9:
  232. return "F9"_string;
  233. case KeyCode::Key_F10:
  234. return "F10"_string;
  235. case KeyCode::Key_F11:
  236. return "F11"_string;
  237. case KeyCode::Key_F12:
  238. return "F12"_string;
  239. default:
  240. break;
  241. }
  242. return OptionalNone {};
  243. }
  244. // 2.1. Unicode Values, https://www.w3.org/TR/uievents-key/#keys-unicode
  245. static ErrorOr<Optional<String>> get_event_key_string(u32 code_point)
  246. {
  247. auto is_non_control_character = [&]() {
  248. // A non-control character is any valid Unicode character except those that are part of the "Other, Control"
  249. // ("Cc") General Category.
  250. return !Unicode::code_point_has_control_general_category(code_point);
  251. };
  252. // A key string is a string containing a 0 or 1 non-control characters ("base" characters) followed by 0 or more
  253. // combining characters. The string MUST be in Normalized Form C (NFC) as described in [UAX15].
  254. // FIXME: Our key events are currently set up to provide one code point at a time. We will need to handle multi-
  255. // code point events and NFC normalize that string.
  256. if (is_non_control_character())
  257. return String::from_code_point(code_point);
  258. return OptionalNone {};
  259. }
  260. // 2.2. Selecting key Attribute Values, https://www.w3.org/TR/uievents-key/#selecting-key-attribute-values
  261. static ErrorOr<String> get_event_key(KeyCode platform_key, u32 code_point)
  262. {
  263. // 1. Let key be a DOMString initially set to "Unidentified".
  264. // NOTE: We return "Unidentified" at the end to avoid needlessly allocating it here.
  265. // 2. If there exists an appropriate named key attribute value for this key event, then
  266. // AD-HOC: Key_Invalid would be interpreted as "Unidentified" here. But we also use Key_Invalid for key presses that
  267. // are not on a standard US keyboard. If such a key would generate a valid key string below, let's allow that
  268. // to happen; otherwise, we will still return "Unidentified" at the end.
  269. if (platform_key != KeyCode::Key_Invalid) {
  270. if (auto named_key = TRY(get_event_named_key(platform_key)); named_key.has_value()) {
  271. // 1. Set key to that named key attribute value.
  272. return named_key.release_value();
  273. }
  274. }
  275. // 3. Else, if the key event generates a valid key string, then
  276. if (auto key_string = TRY(get_event_key_string(code_point)); key_string.has_value()) {
  277. // 1. Set key to that key string value.
  278. return key_string.release_value();
  279. }
  280. // FIXME: 4. Else, if the key event has any modifier keys other than glyph modifier keys, then
  281. // FIXME: 1. Set key to the key string that would have been generated by this event if it had been typed with all
  282. // modifer keys removed except for glyph modifier keys.
  283. // 5. Return key as the key attribute value for this key event.
  284. return "Unidentified"_string;
  285. }
  286. // 3. Keyboard Event code Value Tables, https://www.w3.org/TR/uievents-code/#code-value-tables
  287. static ErrorOr<String> get_event_code(KeyCode platform_key, unsigned modifiers)
  288. {
  289. // 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
  290. if ((modifiers & Mod_Keypad) != 0) {
  291. switch (platform_key) {
  292. case KeyCode::Key_0:
  293. return "Numpad0"_string;
  294. case KeyCode::Key_1:
  295. return "Numpad1"_string;
  296. case KeyCode::Key_2:
  297. return "Numpad2"_string;
  298. case KeyCode::Key_3:
  299. return "Numpad3"_string;
  300. case KeyCode::Key_4:
  301. return "Numpad4"_string;
  302. case KeyCode::Key_5:
  303. return "Numpad5"_string;
  304. case KeyCode::Key_6:
  305. return "Numpad6"_string;
  306. case KeyCode::Key_7:
  307. return "Numpad7"_string;
  308. case KeyCode::Key_8:
  309. return "Numpad8"_string;
  310. case KeyCode::Key_9:
  311. return "Numpad9"_string;
  312. case KeyCode::Key_Plus:
  313. return "NumpadAdd"_string;
  314. case KeyCode::Key_Comma:
  315. return "NumpadComma"_string;
  316. case KeyCode::Key_Period:
  317. case KeyCode::Key_Delete:
  318. return "NumpadDecimal"_string;
  319. case KeyCode::Key_Slash:
  320. return "NumpadDivide"_string;
  321. case KeyCode::Key_Return:
  322. return "NumpadEnter"_string;
  323. case KeyCode::Key_Asterisk:
  324. return "NumpadMultiply"_string;
  325. case KeyCode::Key_Minus:
  326. return "NumpadSubtract"_string;
  327. case KeyCode::Key_Equal:
  328. return "NumpadEqual"_string;
  329. case KeyCode::Key_Hashtag:
  330. return "NumpadHash"_string;
  331. case KeyCode::Key_LeftParen:
  332. return "NumpadParenLeft"_string;
  333. case KeyCode::Key_RightParen:
  334. return "NumpadParenRight"_string;
  335. default:
  336. break;
  337. }
  338. }
  339. switch (platform_key) {
  340. // 3.1.1. Writing System Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-writing-system
  341. case KeyCode::Key_Backtick:
  342. case KeyCode::Key_Tilde:
  343. return "Backquote"_string;
  344. case KeyCode::Key_Backslash:
  345. case KeyCode::Key_Pipe:
  346. return "Backslash"_string;
  347. case KeyCode::Key_LeftBrace:
  348. case KeyCode::Key_LeftBracket:
  349. return "BracketLeft"_string;
  350. case KeyCode::Key_RightBrace:
  351. case KeyCode::Key_RightBracket:
  352. return "BracketRight"_string;
  353. case KeyCode::Key_Comma:
  354. case KeyCode::Key_LessThan:
  355. return "Comma"_string;
  356. case KeyCode::Key_0:
  357. case KeyCode::Key_RightParen:
  358. return "Digit0"_string;
  359. case KeyCode::Key_1:
  360. case KeyCode::Key_ExclamationPoint:
  361. return "Digit1"_string;
  362. case KeyCode::Key_2:
  363. case KeyCode::Key_AtSign:
  364. return "Digit2"_string;
  365. case KeyCode::Key_3:
  366. case KeyCode::Key_Hashtag:
  367. return "Digit3"_string;
  368. case KeyCode::Key_4:
  369. case KeyCode::Key_Dollar:
  370. return "Digit4"_string;
  371. case KeyCode::Key_5:
  372. case KeyCode::Key_Percent:
  373. return "Digit5"_string;
  374. case KeyCode::Key_6:
  375. case KeyCode::Key_Circumflex:
  376. return "Digit6"_string;
  377. case KeyCode::Key_7:
  378. case KeyCode::Key_Ampersand:
  379. return "Digit7"_string;
  380. case KeyCode::Key_8:
  381. case KeyCode::Key_Asterisk:
  382. return "Digit8"_string;
  383. case KeyCode::Key_9:
  384. case KeyCode::Key_LeftParen:
  385. return "Digit9"_string;
  386. case KeyCode::Key_Equal:
  387. case KeyCode::Key_Plus:
  388. return "Equal"_string;
  389. // FIXME: IntlBackslash
  390. // FIXME: IntlRo
  391. // FIXME: IntlYen
  392. case KeyCode::Key_A:
  393. return "KeyA"_string;
  394. case KeyCode::Key_B:
  395. return "KeyB"_string;
  396. case KeyCode::Key_C:
  397. return "KeyC"_string;
  398. case KeyCode::Key_D:
  399. return "KeyD"_string;
  400. case KeyCode::Key_E:
  401. return "KeyE"_string;
  402. case KeyCode::Key_F:
  403. return "KeyF"_string;
  404. case KeyCode::Key_G:
  405. return "KeyG"_string;
  406. case KeyCode::Key_H:
  407. return "KeyH"_string;
  408. case KeyCode::Key_I:
  409. return "KeyI"_string;
  410. case KeyCode::Key_J:
  411. return "KeyJ"_string;
  412. case KeyCode::Key_K:
  413. return "KeyK"_string;
  414. case KeyCode::Key_L:
  415. return "KeyL"_string;
  416. case KeyCode::Key_M:
  417. return "KeyM"_string;
  418. case KeyCode::Key_N:
  419. return "KeyN"_string;
  420. case KeyCode::Key_O:
  421. return "KeyO"_string;
  422. case KeyCode::Key_P:
  423. return "KeyP"_string;
  424. case KeyCode::Key_Q:
  425. return "KeyQ"_string;
  426. case KeyCode::Key_R:
  427. return "KeyR"_string;
  428. case KeyCode::Key_S:
  429. return "KeyS"_string;
  430. case KeyCode::Key_T:
  431. return "KeyT"_string;
  432. case KeyCode::Key_U:
  433. return "KeyU"_string;
  434. case KeyCode::Key_V:
  435. return "KeyV"_string;
  436. case KeyCode::Key_W:
  437. return "KeyW"_string;
  438. case KeyCode::Key_X:
  439. return "KeyX"_string;
  440. case KeyCode::Key_Y:
  441. return "KeyY"_string;
  442. case KeyCode::Key_Z:
  443. return "KeyZ"_string;
  444. case KeyCode::Key_Minus:
  445. case KeyCode::Key_Underscore:
  446. return "Minus"_string;
  447. case KeyCode::Key_Period:
  448. case KeyCode::Key_GreaterThan:
  449. return "Period"_string;
  450. case KeyCode::Key_Apostrophe:
  451. case KeyCode::Key_DoubleQuote:
  452. return "Quote"_string;
  453. case KeyCode::Key_Semicolon:
  454. case KeyCode::Key_Colon:
  455. return "Semicolon"_string;
  456. case KeyCode::Key_Slash:
  457. case KeyCode::Key_QuestionMark:
  458. return "Slash"_string;
  459. // 3.1.2. Functional Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-functional
  460. case KeyCode::Key_LeftAlt:
  461. return "AltLeft"_string;
  462. case KeyCode::Key_RightAlt:
  463. return "AltRight"_string;
  464. case KeyCode::Key_AltGr:
  465. return "AltGraph"_string;
  466. case KeyCode::Key_Backspace:
  467. return "Backspace"_string;
  468. case KeyCode::Key_CapsLock:
  469. return "CapsLock"_string;
  470. case KeyCode::Key_Menu:
  471. return "ContextMenu"_string;
  472. case KeyCode::Key_LeftControl:
  473. return "ControlLeft"_string;
  474. case KeyCode::Key_RightControl:
  475. return "ControlRight"_string;
  476. case KeyCode::Key_Return:
  477. return "Enter"_string;
  478. case KeyCode::Key_LeftSuper:
  479. return "MetaLeft"_string;
  480. case KeyCode::Key_RightSuper:
  481. return "MetaRight"_string;
  482. case KeyCode::Key_LeftShift:
  483. return "ShiftLeft"_string;
  484. case KeyCode::Key_RightShift:
  485. return "ShiftRight"_string;
  486. case KeyCode::Key_Space:
  487. return "Space"_string;
  488. case KeyCode::Key_Tab:
  489. return "Tab"_string;
  490. // 3.2. Control Pad Section, https://www.w3.org/TR/uievents-code/#key-controlpad-section
  491. case KeyCode::Key_Delete:
  492. return "Delete"_string;
  493. case KeyCode::Key_End:
  494. return "End"_string;
  495. // FIXME: Help
  496. case KeyCode::Key_Home:
  497. return "Home"_string;
  498. case KeyCode::Key_Insert:
  499. return "Insert"_string;
  500. case KeyCode::Key_PageDown:
  501. return "PageDown"_string;
  502. case KeyCode::Key_PageUp:
  503. return "PageUp"_string;
  504. // 3.3. Arrow Pad Section, https://www.w3.org/TR/uievents-code/#key-arrowpad-section
  505. case KeyCode::Key_Down:
  506. return "ArrowDown"_string;
  507. case KeyCode::Key_Left:
  508. return "ArrowLeft"_string;
  509. case KeyCode::Key_Right:
  510. return "ArrowRight"_string;
  511. case KeyCode::Key_Up:
  512. return "ArrowUp"_string;
  513. // 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
  514. case KeyCode::Key_NumLock:
  515. return "NumLock"_string;
  516. // 3.5. Function Section, https://www.w3.org/TR/uievents-code/#key-function-section
  517. case KeyCode::Key_Escape:
  518. return "Escape"_string;
  519. case KeyCode::Key_F1:
  520. return "F1"_string;
  521. case KeyCode::Key_F2:
  522. return "F2"_string;
  523. case KeyCode::Key_F3:
  524. return "F3"_string;
  525. case KeyCode::Key_F4:
  526. return "F4"_string;
  527. case KeyCode::Key_F5:
  528. return "F5"_string;
  529. case KeyCode::Key_F6:
  530. return "F6"_string;
  531. case KeyCode::Key_F7:
  532. return "F7"_string;
  533. case KeyCode::Key_F8:
  534. return "F8"_string;
  535. case KeyCode::Key_F9:
  536. return "F9"_string;
  537. case KeyCode::Key_F10:
  538. return "F10"_string;
  539. case KeyCode::Key_F11:
  540. return "F11"_string;
  541. case KeyCode::Key_F12:
  542. return "F12"_string;
  543. case KeyCode::Key_PrintScreen:
  544. case KeyCode::Key_SysRq:
  545. return "PrintScreen"_string;
  546. case KeyCode::Key_ScrollLock:
  547. return "ScrollLock"_string;
  548. case KeyCode::Key_PauseBreak:
  549. return "Pause"_string;
  550. // 3.6. Media Section, https://www.w3.org/TR/uievents-code/#media-keys
  551. case KeyCode::Key_BrowserSearch:
  552. return "BrowserSearch"_string;
  553. case KeyCode::Key_BrowserFavorites:
  554. return "BrowserFavorites"_string;
  555. case KeyCode::Key_BrowserHome:
  556. return "BrowserHome"_string;
  557. case KeyCode::Key_PreviousTrack:
  558. return "PreviousTrack"_string;
  559. case KeyCode::Key_BrowserBack:
  560. return "BrowserBack"_string;
  561. case KeyCode::Key_BrowserForward:
  562. return "BrowserForward"_string;
  563. case KeyCode::Key_BrowserRefresh:
  564. return "BrowserRefresh"_string;
  565. case KeyCode::Key_BrowserStop:
  566. return "BrowserStop"_string;
  567. case KeyCode::Key_VolumeDown:
  568. return "AudioVolumeDown"_string;
  569. case KeyCode::Key_VolumeUp:
  570. return "AudioVolumeUp"_string;
  571. case KeyCode::Key_Wake:
  572. return "WakeUp"_string;
  573. case KeyCode::Key_Sleep:
  574. return "Sleep"_string;
  575. case KeyCode::Key_NextTrack:
  576. return "NextTrack"_string;
  577. case KeyCode::Key_MediaSelect:
  578. return "MediaSelect"_string;
  579. case KeyCode::Key_Email:
  580. return "LaunchMail"_string;
  581. case KeyCode::Key_Power:
  582. return "Power"_string;
  583. case KeyCode::Key_Stop:
  584. return "MediaStop"_string;
  585. case KeyCode::Key_PlayPause:
  586. return "MediaPlayPause"_string;
  587. case KeyCode::Key_Mute:
  588. return "AudioVolumeMute"_string;
  589. case KeyCode::Key_Calculator:
  590. return "LaunchApp2"_string;
  591. case KeyCode::Key_MyComputer:
  592. return "LaunchApp1"_string;
  593. // FIXME: Are these correct?
  594. case KeyCode::Key_LeftGUI:
  595. return "LaunchApp2"_string;
  596. case KeyCode::Key_RightGUI:
  597. case KeyCode::Key_Apps:
  598. return "LaunchApp1"_string;
  599. // 3.7. Legacy, Non-Standard and Special Keys, https://www.w3.org/TR/uievents-code/#key-legacy
  600. case KeyCode::Key_Invalid:
  601. return "Unidentified"_string;
  602. }
  603. VERIFY_NOT_REACHED();
  604. }
  605. // 5.6.2. Keyboard Event Key Location, https://www.w3.org/TR/uievents/#events-keyboard-key-location
  606. static DOMKeyLocation get_event_location(KeyCode platform_key, unsigned modifiers)
  607. {
  608. if ((modifiers & Mod_Keypad) != 0)
  609. return DOMKeyLocation::Numpad;
  610. switch (platform_key) {
  611. case KeyCode::Key_LeftAlt:
  612. case KeyCode::Key_LeftControl:
  613. case KeyCode::Key_LeftShift:
  614. case KeyCode::Key_LeftSuper:
  615. return DOMKeyLocation::Left;
  616. case KeyCode::Key_RightAlt:
  617. case KeyCode::Key_RightControl:
  618. case KeyCode::Key_RightShift:
  619. case KeyCode::Key_RightSuper:
  620. return DOMKeyLocation::Right;
  621. default:
  622. break;
  623. }
  624. return DOMKeyLocation::Standard;
  625. }
  626. JS::NonnullGCPtr<KeyboardEvent> KeyboardEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point)
  627. {
  628. auto event_key = MUST(get_event_key(platform_key, code_point));
  629. auto event_code = MUST(get_event_code(platform_key, modifiers));
  630. auto key_code = determine_key_code(platform_key, code_point);
  631. auto char_code = determine_char_code(event_name, code_point);
  632. KeyboardEventInit event_init {};
  633. event_init.key = move(event_key);
  634. event_init.code = move(event_code);
  635. event_init.location = to_underlying(get_event_location(platform_key, modifiers));
  636. event_init.ctrl_key = modifiers & Mod_Ctrl;
  637. event_init.shift_key = modifiers & Mod_Shift;
  638. event_init.alt_key = modifiers & Mod_Alt;
  639. event_init.meta_key = modifiers & Mod_Super;
  640. event_init.repeat = false;
  641. event_init.is_composing = false;
  642. event_init.key_code = key_code;
  643. event_init.char_code = char_code;
  644. event_init.bubbles = true;
  645. event_init.cancelable = true;
  646. event_init.composed = true;
  647. auto event = KeyboardEvent::create(realm, event_name, event_init);
  648. event->set_is_trusted(true);
  649. return event;
  650. }
  651. bool KeyboardEvent::get_modifier_state(String const& key_arg) const
  652. {
  653. if (key_arg == "Control")
  654. return m_ctrl_key;
  655. if (key_arg == "Shift")
  656. return m_shift_key;
  657. if (key_arg == "Alt")
  658. return m_alt_key;
  659. if (key_arg == "Meta")
  660. return m_meta_key;
  661. if (key_arg == "AltGraph")
  662. return m_modifier_alt_graph;
  663. if (key_arg == "CapsLock")
  664. return m_modifier_caps_lock;
  665. if (key_arg == "Fn")
  666. return m_modifier_fn;
  667. if (key_arg == "FnLock")
  668. return m_modifier_fn_lock;
  669. if (key_arg == "Hyper")
  670. return m_modifier_hyper;
  671. if (key_arg == "NumLock")
  672. return m_modifier_num_lock;
  673. if (key_arg == "ScrollLock")
  674. return m_modifier_scroll_lock;
  675. if (key_arg == "Super")
  676. return m_modifier_super;
  677. if (key_arg == "Symbol")
  678. return m_modifier_symbol;
  679. if (key_arg == "SymbolLock")
  680. return m_modifier_symbol_lock;
  681. return false;
  682. }
  683. // https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent
  684. 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)
  685. {
  686. // Initializes attributes of a KeyboardEvent object. This method has the same behavior as UIEvent.initUIEvent().
  687. // The value of detail remains undefined.
  688. // 1. If this’s dispatch flag is set, then return.
  689. if (dispatched())
  690. return;
  691. // 2. Initialize this with type, bubbles, and cancelable.
  692. initialize_event(type, bubbles, cancelable);
  693. // Implementation Defined: Initialise other values.
  694. m_view = view;
  695. m_key = key;
  696. m_location = location;
  697. m_ctrl_key = ctrl_key;
  698. m_alt_key = alt_key;
  699. m_shift_key = shift_key;
  700. m_meta_key = meta_key;
  701. }
  702. JS::NonnullGCPtr<KeyboardEvent> KeyboardEvent::create(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
  703. {
  704. return realm.heap().allocate<KeyboardEvent>(realm, realm, event_name, event_init);
  705. }
  706. WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyboardEvent>> KeyboardEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
  707. {
  708. return create(realm, event_name, event_init);
  709. }
  710. KeyboardEvent::KeyboardEvent(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
  711. : UIEvent(realm, event_name, event_init)
  712. , m_key(event_init.key)
  713. , m_code(event_init.code)
  714. , m_location(event_init.location)
  715. , m_ctrl_key(event_init.ctrl_key)
  716. , m_shift_key(event_init.shift_key)
  717. , m_alt_key(event_init.alt_key)
  718. , m_meta_key(event_init.meta_key)
  719. , m_modifier_alt_graph(event_init.modifier_alt_graph)
  720. , m_modifier_caps_lock(event_init.modifier_caps_lock)
  721. , m_modifier_fn(event_init.modifier_fn)
  722. , m_modifier_fn_lock(event_init.modifier_fn_lock)
  723. , m_modifier_hyper(event_init.modifier_hyper)
  724. , m_modifier_num_lock(event_init.modifier_num_lock)
  725. , m_modifier_scroll_lock(event_init.modifier_scroll_lock)
  726. , m_modifier_super(event_init.modifier_super)
  727. , m_modifier_symbol(event_init.modifier_symbol)
  728. , m_modifier_symbol_lock(event_init.modifier_symbol_lock)
  729. , m_repeat(event_init.repeat)
  730. , m_is_composing(event_init.is_composing)
  731. , m_key_code(event_init.key_code)
  732. , m_char_code(event_init.char_code)
  733. {
  734. }
  735. KeyboardEvent::~KeyboardEvent() = default;
  736. void KeyboardEvent::initialize(JS::Realm& realm)
  737. {
  738. Base::initialize(realm);
  739. WEB_SET_PROTOTYPE_FOR_INTERFACE(KeyboardEvent);
  740. }
  741. }