keyboard_util.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include <string>
  5. #include "base/containers/fixed_flat_map.h"
  6. #include "base/strings/string_number_conversions.h"
  7. #include "base/strings/string_util.h"
  8. #include "shell/common/keyboard_util.h"
  9. #include "third_party/blink/public/common/input/web_input_event.h"
  10. #include "ui/events/event_constants.h"
  11. namespace electron {
  12. namespace {
  13. using CodeAndShiftedChar =
  14. std::pair<ui::KeyboardCode, absl::optional<char16_t>>;
  15. constexpr CodeAndShiftedChar KeyboardCodeFromKeyIdentifier(
  16. base::StringPiece str) {
  17. #if BUILDFLAG(IS_MAC)
  18. constexpr auto CommandOrControl = ui::VKEY_COMMAND;
  19. #else
  20. constexpr auto CommandOrControl = ui::VKEY_CONTROL;
  21. #endif
  22. constexpr auto Lookup =
  23. base::MakeFixedFlatMapSorted<base::StringPiece, CodeAndShiftedChar>({
  24. {"alt", {ui::VKEY_MENU, {}}},
  25. {"altgr", {ui::VKEY_ALTGR, {}}},
  26. {"backspace", {ui::VKEY_BACK, {}}},
  27. {"capslock", {ui::VKEY_CAPITAL, {}}},
  28. {"cmd", {ui::VKEY_COMMAND, {}}},
  29. {"cmdorctrl", {CommandOrControl, {}}},
  30. {"command", {ui::VKEY_COMMAND, {}}},
  31. {"commandorcontrol", {CommandOrControl, {}}},
  32. {"control", {ui::VKEY_CONTROL, {}}},
  33. {"ctrl", {ui::VKEY_CONTROL, {}}},
  34. {"delete", {ui::VKEY_DELETE, {}}},
  35. {"down", {ui::VKEY_DOWN, {}}},
  36. {"end", {ui::VKEY_END, {}}},
  37. {"enter", {ui::VKEY_RETURN, {}}},
  38. {"esc", {ui::VKEY_ESCAPE, {}}},
  39. {"escape", {ui::VKEY_ESCAPE, {}}},
  40. {"f1", {ui::VKEY_F1, {}}},
  41. {"f10", {ui::VKEY_F10, {}}},
  42. {"f11", {ui::VKEY_F11, {}}},
  43. {"f12", {ui::VKEY_F12, {}}},
  44. {"f13", {ui::VKEY_F13, {}}},
  45. {"f14", {ui::VKEY_F14, {}}},
  46. {"f15", {ui::VKEY_F15, {}}},
  47. {"f16", {ui::VKEY_F16, {}}},
  48. {"f17", {ui::VKEY_F17, {}}},
  49. {"f18", {ui::VKEY_F18, {}}},
  50. {"f19", {ui::VKEY_F19, {}}},
  51. {"f2", {ui::VKEY_F2, {}}},
  52. {"f20", {ui::VKEY_F20, {}}},
  53. {"f21", {ui::VKEY_F21, {}}},
  54. {"f22", {ui::VKEY_F22, {}}},
  55. {"f23", {ui::VKEY_F23, {}}},
  56. {"f24", {ui::VKEY_F24, {}}},
  57. {"f3", {ui::VKEY_F3, {}}},
  58. {"f4", {ui::VKEY_F4, {}}},
  59. {"f5", {ui::VKEY_F5, {}}},
  60. {"f6", {ui::VKEY_F6, {}}},
  61. {"f7", {ui::VKEY_F7, {}}},
  62. {"f8", {ui::VKEY_F8, {}}},
  63. {"f9", {ui::VKEY_F9, {}}},
  64. {"home", {ui::VKEY_HOME, {}}},
  65. {"insert", {ui::VKEY_INSERT, {}}},
  66. {"left", {ui::VKEY_LEFT, {}}},
  67. {"medianexttrack", {ui::VKEY_MEDIA_NEXT_TRACK, {}}},
  68. {"mediaplaypause", {ui::VKEY_MEDIA_PLAY_PAUSE, {}}},
  69. {"mediaprevioustrack", {ui::VKEY_MEDIA_PREV_TRACK, {}}},
  70. {"mediastop", {ui::VKEY_MEDIA_STOP, {}}},
  71. {"meta", {ui::VKEY_COMMAND, {}}},
  72. {"num0", {ui::VKEY_NUMPAD0, {}}},
  73. {"num1", {ui::VKEY_NUMPAD1, {}}},
  74. {"num2", {ui::VKEY_NUMPAD2, {}}},
  75. {"num3", {ui::VKEY_NUMPAD3, {}}},
  76. {"num4", {ui::VKEY_NUMPAD4, {}}},
  77. {"num5", {ui::VKEY_NUMPAD5, {}}},
  78. {"num6", {ui::VKEY_NUMPAD6, {}}},
  79. {"num7", {ui::VKEY_NUMPAD7, {}}},
  80. {"num8", {ui::VKEY_NUMPAD8, {}}},
  81. {"num9", {ui::VKEY_NUMPAD9, {}}},
  82. {"numadd", {ui::VKEY_ADD, {}}},
  83. {"numdec", {ui::VKEY_DECIMAL, {}}},
  84. {"numdiv", {ui::VKEY_DIVIDE, {}}},
  85. {"numlock", {ui::VKEY_NUMLOCK, {}}},
  86. {"nummult", {ui::VKEY_MULTIPLY, {}}},
  87. {"numsub", {ui::VKEY_SUBTRACT, {}}},
  88. {"option", {ui::VKEY_MENU, {}}},
  89. {"pagedown", {ui::VKEY_NEXT, {}}},
  90. {"pageup", {ui::VKEY_PRIOR, {}}},
  91. {"plus", {ui::VKEY_OEM_PLUS, '+'}},
  92. {"printscreen", {ui::VKEY_SNAPSHOT, {}}},
  93. {"return", {ui::VKEY_RETURN, {}}},
  94. {"right", {ui::VKEY_RIGHT, {}}},
  95. {"scrolllock", {ui::VKEY_SCROLL, {}}},
  96. {"shift", {ui::VKEY_SHIFT, {}}},
  97. {"space", {ui::VKEY_SPACE, {}}},
  98. {"super", {ui::VKEY_COMMAND, {}}},
  99. {"tab", {ui::VKEY_TAB, {}}},
  100. {"up", {ui::VKEY_UP, {}}},
  101. {"volumedown", {ui::VKEY_VOLUME_DOWN, {}}},
  102. {"volumemute", {ui::VKEY_VOLUME_MUTE, {}}},
  103. {"volumeup", {ui::VKEY_VOLUME_UP, {}}},
  104. });
  105. if (auto* const iter = Lookup.find(str); iter != Lookup.end())
  106. return iter->second;
  107. return {ui::VKEY_UNKNOWN, {}};
  108. }
  109. constexpr CodeAndShiftedChar KeyboardCodeFromCharCode(char16_t c) {
  110. switch (c) {
  111. case ' ':
  112. return {ui::VKEY_SPACE, {}};
  113. case '!':
  114. return {ui::VKEY_1, '!'};
  115. case '"':
  116. return {ui::VKEY_OEM_7, '"'};
  117. case '#':
  118. return {ui::VKEY_3, '#'};
  119. case '$':
  120. return {ui::VKEY_4, '$'};
  121. case '%':
  122. return {ui::VKEY_5, '%'};
  123. case '&':
  124. return {ui::VKEY_7, '&'};
  125. case '(':
  126. return {ui::VKEY_9, '('};
  127. case ')':
  128. return {ui::VKEY_0, ')'};
  129. case '*':
  130. return {ui::VKEY_8, '*'};
  131. case '+':
  132. return {ui::VKEY_OEM_PLUS, '+'};
  133. case ',':
  134. return {ui::VKEY_OEM_COMMA, {}};
  135. case '-':
  136. return {ui::VKEY_OEM_MINUS, {}};
  137. case '.':
  138. return {ui::VKEY_OEM_PERIOD, {}};
  139. case '/':
  140. return {ui::VKEY_OEM_2, {}};
  141. case '0':
  142. return {ui::VKEY_0, {}};
  143. case '1':
  144. return {ui::VKEY_1, {}};
  145. case '2':
  146. return {ui::VKEY_2, {}};
  147. case '3':
  148. return {ui::VKEY_3, {}};
  149. case '4':
  150. return {ui::VKEY_4, {}};
  151. case '5':
  152. return {ui::VKEY_5, {}};
  153. case '6':
  154. return {ui::VKEY_6, {}};
  155. case '7':
  156. return {ui::VKEY_7, {}};
  157. case '8':
  158. return {ui::VKEY_8, {}};
  159. case '9':
  160. return {ui::VKEY_9, {}};
  161. case ':':
  162. return {ui::VKEY_OEM_1, ':'};
  163. case ';':
  164. return {ui::VKEY_OEM_1, {}};
  165. case '<':
  166. return {ui::VKEY_OEM_COMMA, '<'};
  167. case '=':
  168. return {ui::VKEY_OEM_PLUS, {}};
  169. case '>':
  170. return {ui::VKEY_OEM_PERIOD, '>'};
  171. case '?':
  172. return {ui::VKEY_OEM_2, '?'};
  173. case '@':
  174. return {ui::VKEY_2, '@'};
  175. case '[':
  176. return {ui::VKEY_OEM_4, {}};
  177. case '\'':
  178. return {ui::VKEY_OEM_7, {}};
  179. case '\\':
  180. return {ui::VKEY_OEM_5, {}};
  181. case ']':
  182. return {ui::VKEY_OEM_6, {}};
  183. case '^':
  184. return {ui::VKEY_6, '^'};
  185. case '_':
  186. return {ui::VKEY_OEM_MINUS, '_'};
  187. case '`':
  188. return {ui::VKEY_OEM_3, {}};
  189. case 'a':
  190. return {ui::VKEY_A, {}};
  191. case 'b':
  192. return {ui::VKEY_B, {}};
  193. case 'c':
  194. return {ui::VKEY_C, {}};
  195. case 'd':
  196. return {ui::VKEY_D, {}};
  197. case 'e':
  198. return {ui::VKEY_E, {}};
  199. case 'f':
  200. return {ui::VKEY_F, {}};
  201. case 'g':
  202. return {ui::VKEY_G, {}};
  203. case 'h':
  204. return {ui::VKEY_H, {}};
  205. case 'i':
  206. return {ui::VKEY_I, {}};
  207. case 'j':
  208. return {ui::VKEY_J, {}};
  209. case 'k':
  210. return {ui::VKEY_K, {}};
  211. case 'l':
  212. return {ui::VKEY_L, {}};
  213. case 'm':
  214. return {ui::VKEY_M, {}};
  215. case 'n':
  216. return {ui::VKEY_N, {}};
  217. case 'o':
  218. return {ui::VKEY_O, {}};
  219. case 'p':
  220. return {ui::VKEY_P, {}};
  221. case 'q':
  222. return {ui::VKEY_Q, {}};
  223. case 'r':
  224. return {ui::VKEY_R, {}};
  225. case 's':
  226. return {ui::VKEY_S, {}};
  227. case 't':
  228. return {ui::VKEY_T, {}};
  229. case 'u':
  230. return {ui::VKEY_U, {}};
  231. case 'v':
  232. return {ui::VKEY_V, {}};
  233. case 'w':
  234. return {ui::VKEY_W, {}};
  235. case 'x':
  236. return {ui::VKEY_X, {}};
  237. case 'y':
  238. return {ui::VKEY_Y, {}};
  239. case 'z':
  240. return {ui::VKEY_Z, {}};
  241. case '{':
  242. return {ui::VKEY_OEM_4, '{'};
  243. case '|':
  244. return {ui::VKEY_OEM_5, '|'};
  245. case '}':
  246. return {ui::VKEY_OEM_6, '}'};
  247. case '~':
  248. return {ui::VKEY_OEM_3, '~'};
  249. case 0x08:
  250. return {ui::VKEY_BACK, {}};
  251. case 0x09:
  252. return {ui::VKEY_TAB, {}};
  253. case 0x0D:
  254. return {ui::VKEY_RETURN, {}};
  255. case 0x1B:
  256. return {ui::VKEY_ESCAPE, {}};
  257. case 0x7F:
  258. return {ui::VKEY_DELETE, {}};
  259. default:
  260. return {ui::VKEY_UNKNOWN, {}};
  261. }
  262. }
  263. } // namespace
  264. ui::KeyboardCode KeyboardCodeFromStr(base::StringPiece str,
  265. absl::optional<char16_t>* shifted_char) {
  266. auto const [code, shifted] =
  267. str.size() == 1 ? KeyboardCodeFromCharCode(base::ToLowerASCII(str[0]))
  268. : KeyboardCodeFromKeyIdentifier(base::ToLowerASCII(str));
  269. if (code == ui::VKEY_UNKNOWN)
  270. LOG(WARNING) << "Invalid accelerator token: " << str;
  271. *shifted_char = shifted;
  272. return code;
  273. }
  274. } // namespace electron