You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

qemu-keymap.c 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * QEMU keymap utility
  3. *
  4. * Copyright Red Hat, Inc. 2017
  5. *
  6. * Authors:
  7. * Gerd Hoffmann <kraxel@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qemu/notify.h"
  14. #include "ui/input.h"
  15. #include <xkbcommon/xkbcommon.h>
  16. struct xkb_rule_names names = {
  17. .rules = NULL,
  18. .model = "pc105",
  19. .layout = "us",
  20. .variant = NULL,
  21. .options = NULL,
  22. };
  23. static xkb_mod_mask_t shift;
  24. static xkb_mod_mask_t ctrl;
  25. static xkb_mod_mask_t altgr;
  26. static xkb_mod_mask_t numlock;
  27. static FILE *outfile;
  28. /* ------------------------------------------------------------------------ */
  29. static uint32_t qcode_to_number(uint32_t qcode)
  30. {
  31. KeyValue keyvalue;
  32. uint32_t number;
  33. keyvalue.type = KEY_VALUE_KIND_QCODE;
  34. keyvalue.u.qcode.data = qcode;
  35. number = qemu_input_key_value_to_number(&keyvalue);
  36. assert(number != 0);
  37. return number;
  38. }
  39. static void print_sym(xkb_keysym_t sym, uint32_t qcode, const char *mod)
  40. {
  41. char name[64];
  42. if (sym == XKB_KEY_NoSymbol) {
  43. return;
  44. }
  45. xkb_keysym_get_name(sym, name, sizeof(name));
  46. /* TODO: make ui/keymap.c parser accept QKeyCode names */
  47. fprintf(outfile, "%s 0x%02x%s\n", name, qcode_to_number(qcode), mod);
  48. }
  49. static void walk_map(struct xkb_keymap *map, xkb_keycode_t code, void *data)
  50. {
  51. struct xkb_state *state = data;
  52. xkb_keysym_t kbase, knumlock, kshift, kaltgr, kaltgrshift;
  53. uint32_t evdev, qcode;
  54. char name[64];
  55. fprintf(outfile, "\n");
  56. /*
  57. * map xkb keycode -> QKeyCode
  58. *
  59. * xkb keycode is linux evdev shifted by 8
  60. */
  61. evdev = code - 8;
  62. qcode = qemu_input_linux_to_qcode(evdev);
  63. if (qcode == Q_KEY_CODE_UNMAPPED) {
  64. xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0);
  65. kbase = xkb_state_key_get_one_sym(state, code);
  66. xkb_keysym_get_name(kbase, name, sizeof(name));
  67. fprintf(outfile, "# evdev %d (0x%x): no evdev -> QKeyCode mapping"
  68. " (xkb keysym %s)\n", evdev, evdev, name);
  69. return;
  70. }
  71. fprintf(outfile, "# evdev %d (0x%x), QKeyCode \"%s\", number 0x%x\n",
  72. evdev, evdev,
  73. QKeyCode_str(qcode),
  74. qcode_to_number(qcode));
  75. /*
  76. * check which modifier states generate which keysyms
  77. */
  78. xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0);
  79. kbase = xkb_state_key_get_one_sym(state, code);
  80. print_sym(kbase, qcode, "");
  81. xkb_state_update_mask(state, 0, 0, numlock, 0, 0, 0);
  82. knumlock = xkb_state_key_get_one_sym(state, code);
  83. if (kbase != knumlock) {
  84. print_sym(knumlock, qcode, " numlock");
  85. }
  86. xkb_state_update_mask(state, shift, 0, 0, 0, 0, 0);
  87. kshift = xkb_state_key_get_one_sym(state, code);
  88. if (kbase != kshift && knumlock != kshift) {
  89. print_sym(kshift, qcode, " shift");
  90. }
  91. xkb_state_update_mask(state, altgr, 0, 0, 0, 0, 0);
  92. kaltgr = xkb_state_key_get_one_sym(state, code);
  93. if (kbase != kaltgr) {
  94. print_sym(kaltgr, qcode, " altgr");
  95. }
  96. xkb_state_update_mask(state, altgr | shift, 0, 0, 0, 0, 0);
  97. kaltgrshift = xkb_state_key_get_one_sym(state, code);
  98. if (kshift != kaltgrshift && kaltgr != kaltgrshift) {
  99. print_sym(kaltgrshift, qcode, " shift altgr");
  100. }
  101. return;
  102. }
  103. static void usage(FILE *out)
  104. {
  105. fprintf(out,
  106. "\n"
  107. "This tool generates qemu reverse keymaps from xkb keymaps,\n"
  108. "which can be used with the qemu \"-k\" command line switch.\n"
  109. "\n"
  110. "usage: qemu-keymap <options>\n"
  111. "options:\n"
  112. " -h print this text\n"
  113. " -f <file> set output file (default: stdout)\n"
  114. " -m <model> set kbd model (default: %s)\n"
  115. " -l <layout> set kbd layout (default: %s)\n"
  116. " -v <variant> set kbd variant (default: %s)\n"
  117. " -o <options> set kbd options (default: %s)\n"
  118. "\n",
  119. names.model, names.layout,
  120. names.variant ?: "-",
  121. names.options ?: "-");
  122. }
  123. int main(int argc, char *argv[])
  124. {
  125. struct xkb_context *ctx;
  126. struct xkb_keymap *map;
  127. struct xkb_state *state;
  128. xkb_mod_index_t mod, mods;
  129. int rc;
  130. for (;;) {
  131. rc = getopt(argc, argv, "hm:l:v:o:f:");
  132. if (rc == -1) {
  133. break;
  134. }
  135. switch (rc) {
  136. case 'm':
  137. names.model = optarg;
  138. break;
  139. case 'l':
  140. names.layout = optarg;
  141. break;
  142. case 'v':
  143. names.variant = optarg;
  144. break;
  145. case 'o':
  146. names.options = optarg;
  147. break;
  148. case 'f':
  149. outfile = fopen(optarg, "w");
  150. if (outfile == NULL) {
  151. fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
  152. exit(1);
  153. }
  154. break;
  155. case 'h':
  156. usage(stdout);
  157. exit(0);
  158. default:
  159. usage(stderr);
  160. exit(1);
  161. }
  162. }
  163. if (outfile == NULL) {
  164. outfile = stdout;
  165. }
  166. fprintf(outfile,
  167. "#\n"
  168. "# generated by qemu-keymap\n"
  169. "# model : %s\n"
  170. "# layout : %s\n"
  171. "# variant : %s\n"
  172. "# options : %s\n"
  173. "\n",
  174. names.model, names.layout,
  175. names.variant ?: "-",
  176. names.options ?: "-");
  177. ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
  178. map = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
  179. if (!map) {
  180. /* libxkbcommon prints error */
  181. exit(1);
  182. }
  183. fprintf(outfile, "# name: \"%s\"\n\n",
  184. xkb_keymap_layout_get_name(map, 0));
  185. fprintf(outfile, "# modifiers\n");
  186. mods = xkb_keymap_num_mods(map);
  187. for (mod = 0; mod < mods; mod++) {
  188. fprintf(outfile, "# %2d: %s\n",
  189. mod, xkb_keymap_mod_get_name(map, mod));
  190. }
  191. mod = xkb_keymap_mod_get_index(map, "Shift");
  192. shift = (1 << mod);
  193. mod = xkb_keymap_mod_get_index(map, "Control");
  194. ctrl = (1 << mod);
  195. mod = xkb_keymap_mod_get_index(map, "AltGr");
  196. altgr = (1 << mod);
  197. mod = xkb_keymap_mod_get_index(map, "NumLock");
  198. numlock = (1 << mod);
  199. state = xkb_state_new(map);
  200. xkb_keymap_key_for_each(map, walk_map, state);
  201. /* add quirks */
  202. fprintf(outfile,
  203. "\n"
  204. "#\n"
  205. "# quirks section start\n"
  206. "#\n"
  207. "# Sometimes multiple keysyms map to the same keycodes.\n"
  208. "# The keycode -> keysym lookup finds only one of the\n"
  209. "# keysyms. So append them here.\n"
  210. "#\n"
  211. "\n");
  212. print_sym(XKB_KEY_Print, Q_KEY_CODE_SYSRQ, "");
  213. print_sym(XKB_KEY_Sys_Req, Q_KEY_CODE_SYSRQ, "");
  214. print_sym(XKB_KEY_Execute, Q_KEY_CODE_SYSRQ, "");
  215. print_sym(XKB_KEY_KP_Decimal, Q_KEY_CODE_KP_DECIMAL, " numlock");
  216. print_sym(XKB_KEY_KP_Separator, Q_KEY_CODE_KP_DECIMAL, " numlock");
  217. print_sym(XKB_KEY_Alt_R, Q_KEY_CODE_ALT_R, "");
  218. print_sym(XKB_KEY_ISO_Level3_Shift, Q_KEY_CODE_ALT_R, "");
  219. print_sym(XKB_KEY_Mode_switch, Q_KEY_CODE_ALT_R, "");
  220. fprintf(outfile,
  221. "\n"
  222. "# quirks section end\n");
  223. exit(0);
  224. }