util.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import KeyTable from "./keysym.js";
  2. import keysyms from "./keysymdef.js";
  3. import vkeys from "./vkeys.js";
  4. import fixedkeys from "./fixedkeys.js";
  5. import DOMKeyTable from "./domkeytable.js";
  6. function isMac() {
  7. return navigator && !!(/mac/i).exec(navigator.platform);
  8. }
  9. function isIE() {
  10. return navigator && !!(/trident/i).exec(navigator.userAgent);
  11. }
  12. function isEdge() {
  13. return navigator && !!(/edge/i).exec(navigator.userAgent);
  14. }
  15. // Get 'KeyboardEvent.code', handling legacy browsers
  16. export function getKeycode(evt){
  17. // Are we getting proper key identifiers?
  18. // (unfortunately Firefox and Chrome are crappy here and gives
  19. // us an empty string on some platforms, rather than leaving it
  20. // undefined)
  21. if (evt.code) {
  22. // Mozilla isn't fully in sync with the spec yet
  23. switch (evt.code) {
  24. case 'OSLeft': return 'MetaLeft';
  25. case 'OSRight': return 'MetaRight';
  26. }
  27. return evt.code;
  28. }
  29. // The de-facto standard is to use Windows Virtual-Key codes
  30. // in the 'keyCode' field for non-printable characters. However
  31. // Webkit sets it to the same as charCode in 'keypress' events.
  32. if ((evt.type !== 'keypress') && (evt.keyCode in vkeys)) {
  33. var code = vkeys[evt.keyCode];
  34. // macOS has messed up this code for some reason
  35. if (isMac() && (code === 'ContextMenu')) {
  36. code = 'MetaRight';
  37. }
  38. // The keyCode doesn't distinguish between left and right
  39. // for the standard modifiers
  40. if (evt.location === 2) {
  41. switch (code) {
  42. case 'ShiftLeft': return 'ShiftRight';
  43. case 'ControlLeft': return 'ControlRight';
  44. case 'AltLeft': return 'AltRight';
  45. }
  46. }
  47. // Nor a bunch of the numpad keys
  48. if (evt.location === 3) {
  49. switch (code) {
  50. case 'Delete': return 'NumpadDecimal';
  51. case 'Insert': return 'Numpad0';
  52. case 'End': return 'Numpad1';
  53. case 'ArrowDown': return 'Numpad2';
  54. case 'PageDown': return 'Numpad3';
  55. case 'ArrowLeft': return 'Numpad4';
  56. case 'ArrowRight': return 'Numpad6';
  57. case 'Home': return 'Numpad7';
  58. case 'ArrowUp': return 'Numpad8';
  59. case 'PageUp': return 'Numpad9';
  60. case 'Enter': return 'NumpadEnter';
  61. }
  62. }
  63. return code;
  64. }
  65. return 'Unidentified';
  66. }
  67. // Get 'KeyboardEvent.key', handling legacy browsers
  68. export function getKey(evt) {
  69. // Are we getting a proper key value?
  70. if (evt.key !== undefined) {
  71. // IE and Edge use some ancient version of the spec
  72. // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
  73. switch (evt.key) {
  74. case 'Spacebar': return ' ';
  75. case 'Esc': return 'Escape';
  76. case 'Scroll': return 'ScrollLock';
  77. case 'Win': return 'Meta';
  78. case 'Apps': return 'ContextMenu';
  79. case 'Up': return 'ArrowUp';
  80. case 'Left': return 'ArrowLeft';
  81. case 'Right': return 'ArrowRight';
  82. case 'Down': return 'ArrowDown';
  83. case 'Del': return 'Delete';
  84. case 'Divide': return '/';
  85. case 'Multiply': return '*';
  86. case 'Subtract': return '-';
  87. case 'Add': return '+';
  88. case 'Decimal': return evt.char;
  89. }
  90. // Mozilla isn't fully in sync with the spec yet
  91. switch (evt.key) {
  92. case 'OS': return 'Meta';
  93. }
  94. // IE and Edge have broken handling of AltGraph so we cannot
  95. // trust them for printable characters
  96. if ((evt.key.length !== 1) || (!isIE() && !isEdge())) {
  97. return evt.key;
  98. }
  99. }
  100. // Try to deduce it based on the physical key
  101. var code = getKeycode(evt);
  102. if (code in fixedkeys) {
  103. return fixedkeys[code];
  104. }
  105. // If that failed, then see if we have a printable character
  106. if (evt.charCode) {
  107. return String.fromCharCode(evt.charCode);
  108. }
  109. // At this point we have nothing left to go on
  110. return 'Unidentified';
  111. }
  112. // Get the most reliable keysym value we can get from a key event
  113. export function getKeysym(evt){
  114. var key = getKey(evt);
  115. if (key === 'Unidentified') {
  116. return null;
  117. }
  118. // First look up special keys
  119. if (key in DOMKeyTable) {
  120. var location = evt.location;
  121. // Safari screws up location for the right cmd key
  122. if ((key === 'Meta') && (location === 0)) {
  123. location = 2;
  124. }
  125. if ((location === undefined) || (location > 3)) {
  126. location = 0;
  127. }
  128. return DOMKeyTable[key][location];
  129. }
  130. // Now we need to look at the Unicode symbol instead
  131. var codepoint;
  132. // Special key? (FIXME: Should have been caught earlier)
  133. if (key.length !== 1) {
  134. return null;
  135. }
  136. codepoint = key.charCodeAt();
  137. if (codepoint) {
  138. return keysyms.lookup(codepoint);
  139. }
  140. return null;
  141. }