keyboard_util.cc 8.4 KB

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