KeyboardEvent.cpp 24 KB

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