1
0

keymap.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. /*
  2. * Copyright © 2016 Intel Corporation
  3. * SPDX-License-Identifier: MIT
  4. *
  5. * Author: Mike Blumenkrantz <zmike@osg.samsung.com>
  6. */
  7. #include "config.h"
  8. #include "test-config.h"
  9. #include <assert.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "xkbcommon/xkbcommon.h"
  14. #include "xkbcommon/xkbcommon-keysyms.h"
  15. #include "evdev-scancodes.h"
  16. #include "test.h"
  17. #include "context.h"
  18. #include "keymap.h"
  19. #include "keymap-formats.h"
  20. #include "utils.h"
  21. #define KEY_LVL3 84
  22. #define KEY_LVL5 195
  23. #define GOLDEN_TESTS_OUTPUTS "keymaps/"
  24. static void
  25. test_supported_formats(void)
  26. {
  27. assert(xkb_keymap_parse_format(NULL) == 0);
  28. assert(xkb_keymap_parse_format("") == 0);
  29. assert(xkb_keymap_parse_format("x") == 0);
  30. assert(xkb_keymap_parse_format("v") == 0);
  31. assert(xkb_keymap_parse_format("vx") == 0);
  32. assert(xkb_keymap_parse_format("0b1") == 0); /* only base 10 */
  33. assert(xkb_keymap_parse_format("0o1") == 0); /* only base 10 */
  34. assert(xkb_keymap_parse_format("0x1") == 0); /* only base 10 */
  35. assert(xkb_keymap_parse_format("+1") == 0);
  36. assert(xkb_keymap_parse_format(" 1") == 0);
  37. assert(xkb_keymap_parse_format("1 ") == XKB_KEYMAP_FORMAT_TEXT_V1);
  38. assert(xkb_keymap_parse_format("01") == XKB_KEYMAP_FORMAT_TEXT_V1);
  39. const struct {
  40. int value;
  41. enum xkb_keymap_format expected;
  42. const char* const* labels;
  43. } entries[] = {
  44. { .value = -1 , .labels = NULL, .expected = 0 },
  45. { .value = 0 , .labels = NULL, .expected = 0 },
  46. { .value = 100000000 , .labels = NULL, .expected = 0 },
  47. { .value = XKB_KEYMAP_USE_ORIGINAL_FORMAT, .labels = NULL, .expected = 0 },
  48. {
  49. .value = XKB_KEYMAP_FORMAT_TEXT_V1,
  50. .labels = (const char* const[]) { "xkb_v1", "v1", NULL },
  51. .expected = XKB_KEYMAP_FORMAT_TEXT_V1
  52. },
  53. {
  54. .value = XKB_KEYMAP_FORMAT_TEXT_V2,
  55. .labels = (const char* const[]) { "xkb_v2", "v2", NULL },
  56. .expected = XKB_KEYMAP_FORMAT_TEXT_V2
  57. },
  58. };
  59. char buf[15] = { 0 };
  60. for (size_t k = 0; k < ARRAY_SIZE(entries); k++) {
  61. assert(xkb_keymap_is_supported_format(entries[k].value) ==
  62. !!entries[k].expected);
  63. /* Canonical label */
  64. if (entries[k].labels) {
  65. assert_streq_not_null("Canonical format label", entries[k].labels[0],
  66. xkb_keymap_get_format_label(entries[k].value));
  67. }
  68. /* Parse labels */
  69. for (size_t l = 0; entries[k].labels && entries[k].labels[l]; l++) {
  70. assert_printf(xkb_keymap_parse_format(entries[k].labels[l]) ==
  71. entries[k].expected,
  72. "%s: expected %d, got: %d\n",
  73. entries[k].labels[l], entries[k].value,
  74. xkb_keymap_parse_format(entries[k].labels[l]));
  75. }
  76. /* Parse serialized numeric value */
  77. const int ret = snprintf(buf, sizeof(buf), "%d", entries[k].value);
  78. assert(ret > 0 && ret < (int) sizeof(buf));
  79. assert(xkb_keymap_parse_format(buf) == entries[k].expected);
  80. }
  81. const enum xkb_keymap_format *formats;
  82. const size_t count = xkb_keymap_supported_formats(&formats);
  83. assert(count == 2);
  84. enum xkb_keymap_format previous = 0; /* Lower bound */
  85. for (size_t k = 0; k < count; k++) {
  86. /* Ascending order */
  87. assert(previous < formats[k]);
  88. /* Valid numeric format */
  89. assert(xkb_keymap_is_supported_format(formats[k]));
  90. /* Valid label */
  91. const int ret = snprintf(buf, sizeof(buf), "%d", formats[k]);
  92. assert(ret > 0 && ret < (int) sizeof(buf));
  93. assert(xkb_keymap_parse_format(buf) == formats[k]);
  94. previous = formats[k];
  95. }
  96. }
  97. static void
  98. test_garbage_key(void)
  99. {
  100. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  101. struct xkb_keymap *keymap;
  102. xkb_keycode_t kc;
  103. int nsyms;
  104. const xkb_keysym_t *syms;
  105. const xkb_layout_index_t first_layout = 0;
  106. xkb_level_index_t nlevels;
  107. assert(context);
  108. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, NULL,
  109. NULL, "garbage", NULL, NULL);
  110. assert(keymap);
  111. /* TLDE uses the 'us' sym on the first level and is thus [grave, exclam] */
  112. kc = xkb_keymap_key_by_name(keymap, "TLDE");
  113. assert(kc != XKB_KEYCODE_INVALID);
  114. nlevels = xkb_keymap_num_levels_for_key(keymap, kc, first_layout);
  115. assert(nlevels == 2);
  116. nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &syms);
  117. assert(nsyms == 1);
  118. assert(*syms == XKB_KEY_grave); /* fallback from 'us' */
  119. nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &syms);
  120. assert(nsyms == 1);
  121. assert(*syms == XKB_KEY_exclam);
  122. /* AE13 has no 'us' fallback and ends up as [NoSymbol, asciitilde] */
  123. kc = xkb_keymap_key_by_name(keymap, "AE13");
  124. assert(kc != XKB_KEYCODE_INVALID);
  125. nlevels = xkb_keymap_num_levels_for_key(keymap, kc, first_layout);
  126. assert(nlevels == 2);
  127. nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &syms);
  128. assert(nsyms == 0);
  129. nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &syms);
  130. assert(nsyms == 1);
  131. assert(*syms == XKB_KEY_asciitilde);
  132. xkb_keymap_unref(keymap);
  133. xkb_context_unref(context);
  134. }
  135. static void
  136. test_keymap(void)
  137. {
  138. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  139. struct xkb_keymap *keymap;
  140. xkb_keycode_t kc;
  141. const char *keyname;
  142. xkb_mod_mask_t masks_out[4] = { 0, 0, 0, 0 };
  143. size_t mask_count;
  144. xkb_mod_mask_t shift_mask;
  145. xkb_mod_mask_t lock_mask;
  146. xkb_mod_mask_t mod2_mask;
  147. assert(context);
  148. /* Reject unsupported flags */
  149. static const struct xkb_rule_names names = {NULL, NULL, NULL, NULL, NULL};
  150. assert(!xkb_keymap_new_from_names(context, &names, -1));
  151. assert(!xkb_keymap_new_from_names(context, &names, 0xffff));
  152. assert(!xkb_keymap_new_from_names2(context, &names,
  153. XKB_KEYMAP_FORMAT_TEXT_V1, -1));
  154. assert(!xkb_keymap_new_from_names2(context, &names,
  155. XKB_KEYMAP_FORMAT_TEXT_V1, 0xffff));
  156. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  157. "pc104", "us,ru", NULL, "grp:menu_toggle");
  158. assert(keymap);
  159. kc = xkb_keymap_key_by_name(keymap, "AE09");
  160. assert(kc != XKB_KEYCODE_INVALID);
  161. keyname = xkb_keymap_key_get_name(keymap, kc);
  162. assert(streq(keyname, "AE09"));
  163. kc = xkb_keymap_key_by_name(keymap, "COMP");
  164. assert(kc != XKB_KEYCODE_INVALID);
  165. keyname = xkb_keymap_key_get_name(keymap, kc);
  166. assert(streq(keyname, "COMP"));
  167. kc = xkb_keymap_key_by_name(keymap, "MENU");
  168. assert(kc != XKB_KEYCODE_INVALID);
  169. keyname = xkb_keymap_key_get_name(keymap, kc);
  170. assert(streq(keyname, "COMP"));
  171. kc = xkb_keymap_key_by_name(keymap, "AC01");
  172. assert(kc != XKB_KEYCODE_INVALID);
  173. // AC01 level 0 ('a') requires no modifiers on us-pc104
  174. mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4);
  175. assert(mask_count == 1);
  176. assert(masks_out[0] == 0);
  177. shift_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
  178. lock_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
  179. mod2_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2);
  180. // AC01 level 1 ('A') requires either Shift or Lock modifiers on us-pc104
  181. mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 1, masks_out, 4);
  182. assert(mask_count == 2);
  183. assert(masks_out[0] == shift_mask);
  184. assert(masks_out[1] == lock_mask);
  185. kc = xkb_keymap_key_by_name(keymap, "KP1");
  186. // KP1 level 0 ('End') requires no modifiers or Shift+Mod2 on us-pc104
  187. mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4);
  188. assert(mask_count == 2);
  189. assert(masks_out[0] == 0);
  190. assert(masks_out[1] == (shift_mask | mod2_mask));
  191. // KP1 level 1 ('1') requires either Shift or Mod2 modifiers on us-pc104
  192. mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 1, masks_out, 4);
  193. assert(mask_count == 2);
  194. assert(masks_out[0] == shift_mask);
  195. assert(masks_out[1] == mod2_mask);
  196. // Return key is not affected by modifiers on us-pc104
  197. kc = xkb_keymap_key_by_name(keymap, "RTRN");
  198. mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4);
  199. assert(mask_count == 1);
  200. assert(masks_out[0] == 0);
  201. xkb_keymap_unref(keymap);
  202. xkb_context_unref(context);
  203. }
  204. static void
  205. test_no_extra_groups(void)
  206. {
  207. struct xkb_keymap *keymap;
  208. xkb_keycode_t kc;
  209. const xkb_keysym_t *syms;
  210. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  211. assert(context);
  212. /* RMLVO: Legacy rules may add more layouts than the input RMLVO */
  213. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1,
  214. "multiple-groups", "old", "de", NULL, NULL);
  215. assert(keymap);
  216. kc = xkb_keymap_key_by_name(keymap, "AD01");
  217. assert(kc != XKB_KEYCODE_INVALID);
  218. /* 2 layouts, while only 1 was provided */
  219. assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 2);
  220. assert(xkb_keymap_num_layouts(keymap) == 2);
  221. xkb_keymap_unref(keymap);
  222. /* RMLVO: “one group per key” in symbols sections */
  223. const char *layouts[] = {"us", "us,us", "us,us,us", "us,us,us,us"};
  224. for (xkb_layout_index_t k = 0; k < ARRAY_SIZE(layouts); k++) {
  225. /* `multiple-groups` option defines 4 groups for a key */
  226. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1,
  227. "multiple-groups", NULL, layouts[k], NULL,
  228. "multiple-groups");
  229. assert(keymap);
  230. kc = xkb_keymap_key_by_name(keymap, "RALT");
  231. assert(kc != XKB_KEYCODE_INVALID);
  232. /* Groups after the first one should be dropped */
  233. assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 1);
  234. /* Here we expect RMLVO layouts count = keymap layouts count */
  235. assert(xkb_keymap_num_layouts(keymap) == k + 1);
  236. for (xkb_layout_index_t l = 0; l <= k; l++) {
  237. assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1);
  238. assert(syms[0] == XKB_KEY_a);
  239. syms = NULL;
  240. }
  241. xkb_keymap_unref(keymap);
  242. }
  243. /* RMLVO: Ensure the rule “one group per key” in symbols sections works
  244. * for the 2nd layout */
  245. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, NULL,
  246. NULL, "multiple-groups,multiple-groups", "1,2", NULL);
  247. assert(keymap);
  248. kc = xkb_keymap_key_by_name(keymap, "RALT");
  249. assert(kc != XKB_KEYCODE_INVALID);
  250. assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 2);
  251. assert(xkb_keymap_num_layouts(keymap) == 2);
  252. for (xkb_layout_index_t l = 0; l < 2; l++) {
  253. assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1);
  254. assert(syms[0] == XKB_KEY_a);
  255. syms = NULL;
  256. }
  257. xkb_keymap_unref(keymap);
  258. /* Same configuration as previous, but without using RMLVO resolution:
  259. * We do accept more than one group per key in symbols sections, but only
  260. * when not using a modifier: the second layout (`:2`) will have its extra
  261. * groups dropped. */
  262. const char keymap_str[] =
  263. "xkb_keymap {"
  264. " xkb_keycodes { include \"evdev+aliases(qwerty)\" };"
  265. " xkb_types { include \"complete\" };"
  266. " xkb_compat { include \"complete\" };"
  267. " xkb_symbols { include \"pc+multiple-groups(1)+multiple-groups(2):2"
  268. "+inet(evdev)\" };"
  269. "};";
  270. keymap = test_compile_string(context, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str);
  271. kc = xkb_keymap_key_by_name(keymap, "RALT");
  272. assert(kc != XKB_KEYCODE_INVALID);
  273. assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 4);
  274. assert(xkb_keymap_num_layouts(keymap) == 4);
  275. xkb_keysym_t ref_syms[] = { XKB_KEY_a, XKB_KEY_a, XKB_KEY_c, XKB_KEY_d };
  276. for (xkb_layout_index_t l = 0; l < 4; l++) {
  277. assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1);
  278. assert(syms[0] == ref_syms[l]);
  279. syms = NULL;
  280. }
  281. xkb_keymap_unref(keymap);
  282. xkb_context_unref(context);
  283. }
  284. #define Mod1Mask (UINT32_C(1) << 3)
  285. #define Mod2Mask (UINT32_C(1) << 4)
  286. #define Mod3Mask (UINT32_C(1) << 5)
  287. static void
  288. test_numeric_keysyms(void)
  289. {
  290. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  291. struct xkb_keymap *keymap;
  292. const struct xkb_key *key;
  293. xkb_keycode_t kc;
  294. int keysyms_count;
  295. const xkb_layout_index_t first_layout = 0;
  296. const xkb_keysym_t *keysyms;
  297. assert(context);
  298. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  299. "pc104", "numeric_keysyms", NULL, NULL);
  300. assert(keymap);
  301. kc = xkb_keymap_key_by_name(keymap, "AD01");
  302. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  303. assert(keysyms_count == 1);
  304. assert(keysyms[0] == 0x1ffffffd);
  305. key = XkbKey(keymap, kc);
  306. assert(key);
  307. assert(key->modmap == Mod1Mask);
  308. kc = xkb_keymap_key_by_name(keymap, "AD02");
  309. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  310. assert(keysyms_count == 1);
  311. assert(keysyms[0] == 0x1ffffffe);
  312. key = XkbKey(keymap, kc);
  313. assert(key);
  314. assert(key->modmap == Mod2Mask);
  315. kc = xkb_keymap_key_by_name(keymap, "AD03");
  316. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  317. assert(keysyms_count == 1);
  318. assert(keysyms[0] == 0x1fffffff);
  319. /* Invalid numeric keysym */
  320. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms);
  321. assert(keysyms_count == 0);
  322. key = XkbKey(keymap, kc);
  323. assert(key);
  324. assert(key->modmap == Mod3Mask);
  325. xkb_keymap_unref(keymap);
  326. xkb_context_unref(context);
  327. }
  328. static void
  329. test_multiple_keysyms_per_level(void)
  330. {
  331. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  332. struct xkb_keymap *keymap;
  333. xkb_keycode_t kc;
  334. int keysyms_count;
  335. const xkb_layout_index_t first_layout = 0;
  336. const xkb_keysym_t *keysyms;
  337. assert(context);
  338. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  339. "pc104", "awesome", NULL, NULL);
  340. assert(keymap);
  341. kc = xkb_keymap_key_by_name(keymap, "AD01");
  342. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  343. assert(keysyms_count == 3);
  344. assert(keysyms[0] == 'q');
  345. assert(keysyms[1] == 'a');
  346. assert(keysyms[2] == 'b');
  347. kc = xkb_keymap_key_by_name(keymap, "AD03");
  348. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms);
  349. assert(keysyms_count == 2);
  350. assert(keysyms[0] == 'E');
  351. assert(keysyms[1] == 'F');
  352. // Invalid keysyms
  353. kc = xkb_keymap_key_by_name(keymap, "AD06");
  354. // Only the invalid keysym is dropped, remaining one overrides previous entry
  355. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  356. assert(keysyms_count == 1);
  357. assert(keysyms[0] == XKB_KEY_ydiaeresis);
  358. // All the keysyms are invalid and dropped, previous entry not overriden
  359. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms);
  360. assert(keysyms_count == 1);
  361. assert(keysyms[0] == 'Y');
  362. xkb_keymap_unref(keymap);
  363. xkb_context_unref(context);
  364. }
  365. static void
  366. test_multiple_actions_per_level(void)
  367. {
  368. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  369. struct xkb_keymap *keymap;
  370. struct xkb_state *state;
  371. xkb_keycode_t kc;
  372. int keysyms_count;
  373. const xkb_layout_index_t first_layout = 0;
  374. const xkb_keysym_t *keysyms;
  375. xkb_mod_index_t ctrl, level3;
  376. xkb_layout_index_t layout;
  377. xkb_mod_mask_t base_mods;
  378. assert(context);
  379. /* Test various ways to set multiple actions */
  380. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  381. "pc104", "multiple_actions,cz", NULL, NULL);
  382. assert(keymap);
  383. kc = xkb_keymap_key_by_name(keymap, "LCTL");
  384. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  385. assert(keysyms_count == 2);
  386. assert(keysyms[0] == XKB_KEY_Control_L);
  387. assert(keysyms[1] == XKB_KEY_ISO_Group_Shift);
  388. ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
  389. level3 = xkb_keymap_mod_get_index(keymap, "Mod5");
  390. state = xkb_state_new(keymap);
  391. assert(state);
  392. layout = xkb_state_key_get_layout(state, KEY_LEFTCTRL + EVDEV_OFFSET);
  393. assert(layout == 0);
  394. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
  395. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  396. assert(base_mods == (UINT32_C(1) << ctrl));
  397. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED);
  398. assert(layout == 1);
  399. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED);
  400. assert(layout == 0);
  401. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
  402. assert(layout == 0);
  403. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
  404. assert(layout == 1);
  405. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
  406. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  407. assert(base_mods == 0);
  408. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED);
  409. assert(layout == 0);
  410. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED);
  411. assert(layout == 0);
  412. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
  413. assert(layout == 0);
  414. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
  415. assert(layout == 0);
  416. xkb_state_update_key(state, KEY_LVL3 + EVDEV_OFFSET, XKB_KEY_DOWN);
  417. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  418. assert(base_mods == (UINT32_C(1) << level3));
  419. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED);
  420. assert(layout == 1);
  421. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED);
  422. assert(layout == 0);
  423. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
  424. assert(layout == 0);
  425. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
  426. assert(layout == 1);
  427. xkb_state_update_key(state, KEY_LVL3 + EVDEV_OFFSET, XKB_KEY_UP);
  428. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  429. assert(base_mods == 0);
  430. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED);
  431. assert(layout == 0);
  432. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED);
  433. assert(layout == 0);
  434. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
  435. assert(layout == 0);
  436. layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
  437. assert(layout == 0);
  438. xkb_state_unref(state);
  439. assert(test_key_seq(
  440. keymap,
  441. KEY_2, BOTH, XKB_KEY_2, NEXT,
  442. /* Control switch to the second group */
  443. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT,
  444. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  445. KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT,
  446. KEY_2, BOTH, XKB_KEY_2, NEXT,
  447. KEY_RIGHTCTRL, DOWN, XKB_KEY_Control_R, NEXT,
  448. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  449. KEY_RIGHTCTRL, UP, XKB_KEY_Control_R, NEXT,
  450. KEY_2, BOTH, XKB_KEY_2, NEXT,
  451. /* Fake keys switch to the second group too */
  452. KEY_LVL3, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT,
  453. KEY_2, BOTH, XKB_KEY_at, NEXT,
  454. KEY_LVL3, UP, XKB_KEY_ISO_Level3_Shift,
  455. /* Only one keysym, group=2 + level3(ralt_switch):2 */
  456. NEXT,
  457. KEY_2, BOTH, XKB_KEY_2, NEXT,
  458. KEY_LVL5, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT,
  459. KEY_2, BOTH, XKB_KEY_at, NEXT,
  460. KEY_LVL5, UP, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT,
  461. KEY_2, BOTH, XKB_KEY_2, NEXT,
  462. /* Alt have different keysyms & actions count */
  463. KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT,
  464. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  465. KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT,
  466. KEY_RIGHTALT, DOWN, XKB_KEY_Alt_R, XKB_KEY_ISO_Group_Shift, NEXT,
  467. KEY_2, BOTH, XKB_KEY_2, NEXT,
  468. KEY_RIGHTALT, UP, XKB_KEY_Alt_R, XKB_KEY_ISO_Group_Shift, NEXT,
  469. /* Super have different keysyms & actions count */
  470. KEY_LEFTMETA, DOWN, XKB_KEY_Super_L, XKB_KEY_ISO_Group_Shift, NEXT,
  471. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  472. KEY_LEFTMETA, UP, XKB_KEY_Super_L, XKB_KEY_ISO_Group_Shift, NEXT,
  473. KEY_RIGHTMETA, DOWN, XKB_KEY_Super_R, XKB_KEY_ISO_Group_Shift, NEXT,
  474. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  475. KEY_RIGHTMETA, UP, XKB_KEY_Super_R, XKB_KEY_ISO_Group_Shift, NEXT,
  476. KEY_2, BOTH, XKB_KEY_2, NEXT,
  477. /* Incompatible actions categories */
  478. KEY_RO, DOWN, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT,
  479. KEY_2, BOTH, XKB_KEY_2, NEXT,
  480. KEY_RO, UP, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT,
  481. KEY_YEN, DOWN, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT,
  482. KEY_2, BOTH, XKB_KEY_2, NEXT,
  483. KEY_YEN, UP, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT,
  484. /* Test various overrides */
  485. KEY_Z, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT,
  486. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  487. KEY_Z, UP, XKB_KEY_y, NEXT,
  488. KEY_X, BOTH, XKB_KEY_x, NEXT,
  489. KEY_C, DOWN, XKB_KEY_NoSymbol, NEXT,
  490. KEY_2, BOTH, XKB_KEY_at, NEXT,
  491. KEY_C, UP, XKB_KEY_ampersand, NEXT,
  492. KEY_V, DOWN, XKB_KEY_NoSymbol, NEXT,
  493. KEY_2, BOTH, XKB_KEY_2, NEXT,
  494. KEY_V, UP, XKB_KEY_NoSymbol, NEXT,
  495. KEY_B, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT,
  496. KEY_2, BOTH, XKB_KEY_at, NEXT,
  497. KEY_B, UP, XKB_KEY_braceleft,NEXT,
  498. KEY_N, DOWN, XKB_KEY_Control_L, NEXT,
  499. KEY_2, BOTH, XKB_KEY_2, NEXT,
  500. KEY_N, UP, XKB_KEY_Control_L, NEXT,
  501. KEY_M, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT,
  502. KEY_2, BOTH, XKB_KEY_at, NEXT,
  503. KEY_M, UP, XKB_KEY_asciicircum, NEXT,
  504. /* Modifier_Map */
  505. KEY_Q, DOWN, XKB_KEY_a, XKB_KEY_b, NEXT,
  506. KEY_2, BOTH, XKB_KEY_at, NEXT,
  507. KEY_Q, UP, XKB_KEY_a, XKB_KEY_b, NEXT,
  508. KEY_2, BOTH, XKB_KEY_2, FINISH));
  509. xkb_keymap_unref(keymap);
  510. /* TODO: This example is intended to make keyboard shortcuts use the first
  511. * layout. However, this requires to be able to configure group redirect
  512. * at the *keymap* level, then use ISO_First_Group and SetGroup(group=-4).
  513. * Change the symbols and this test once this is merged. */
  514. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  515. "pc104", "awesome,cz", NULL, "grp:menu_toggle");
  516. assert(keymap);
  517. ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
  518. kc = xkb_keymap_key_by_name(keymap, "LCTL");
  519. keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms);
  520. assert(keysyms_count == 2);
  521. assert(keysyms[0] == XKB_KEY_Control_L);
  522. assert(keysyms[1] == XKB_KEY_ISO_Next_Group);
  523. state = xkb_state_new(keymap);
  524. assert(state);
  525. layout = xkb_state_key_get_layout(state, KEY_LEFTCTRL + EVDEV_OFFSET);
  526. assert(layout == 0);
  527. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
  528. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  529. assert(base_mods == (UINT32_C(1) << ctrl));
  530. layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET);
  531. assert(layout == 1);
  532. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
  533. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  534. assert(base_mods == 0);
  535. layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET);
  536. assert(layout == 0);
  537. xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
  538. xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
  539. layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET);
  540. assert(layout == 1);
  541. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
  542. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  543. assert(base_mods == (UINT32_C(1) << ctrl));
  544. layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET);
  545. assert(layout == 0);
  546. xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
  547. base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  548. assert(base_mods == 0);
  549. layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET);
  550. assert(layout == 1);
  551. xkb_state_unref(state);
  552. assert(test_key_seq(keymap,
  553. KEY_2, BOTH, XKB_KEY_2, NEXT,
  554. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT,
  555. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  556. KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT,
  557. KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  558. KEY_2, BOTH, XKB_KEY_ecaron, NEXT,
  559. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT,
  560. KEY_2, BOTH, XKB_KEY_2, NEXT,
  561. KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT,
  562. KEY_2, BOTH, XKB_KEY_ecaron, FINISH));
  563. xkb_keymap_unref(keymap);
  564. xkb_context_unref(context);
  565. }
  566. static void
  567. count_keys(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
  568. {
  569. if (!xkb_keymap_key_get_name(keymap, key))
  570. return;
  571. darray_size_t * const count = data;
  572. (*count)++;
  573. }
  574. static void
  575. test_keynames_atoms(void)
  576. {
  577. static struct {
  578. const char *rules;
  579. xkb_keycode_t max_keycode;
  580. darray_size_t num_aliases;
  581. darray_size_t num_atoms;
  582. darray_size_t num_key_names;
  583. } tests[] = {
  584. {
  585. .rules = "base",
  586. .max_keycode = 255,
  587. .num_aliases = 63,
  588. .num_atoms = 484,
  589. .num_key_names = 325,
  590. },
  591. {
  592. .rules = "evdev",
  593. .max_keycode = 569,
  594. .num_aliases = 33,
  595. .num_atoms = 501,
  596. .num_key_names = 305,
  597. },
  598. };
  599. for (size_t t = 0; t < ARRAY_SIZE(tests); t++) {
  600. fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, t);
  601. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  602. struct xkb_keymap *keymap = test_compile_rules(
  603. context, XKB_KEYMAP_FORMAT_TEXT_V1, tests[t].rules,
  604. "pc104", "us", NULL, NULL
  605. );
  606. assert(keymap);
  607. darray_size_t expected, got;
  608. expected = (darray_size_t) tests[t].max_keycode;
  609. got = xkb_keymap_max_keycode(keymap);
  610. assert_eq("keynames max keycode", expected, got, "%u");
  611. expected = tests[t].num_aliases;
  612. got = keymap->num_key_aliases;
  613. assert_eq("keynames num aliases", expected, got, "%u");
  614. expected = tests[t].num_atoms;
  615. got = xkb_atom_table_size(context);
  616. assert_eq("atoms", expected, got, "%u");
  617. /*
  618. * Find size of the temporary key name LUT used during compilation.
  619. * It corresponds to: max(key name/alias atom) + 1.
  620. */
  621. darray_size_t num_key_names = 0;
  622. for (xkb_atom_t a = 0; a < xkb_atom_table_size(context); a++) {
  623. const char *name = xkb_atom_text(context, a);
  624. if (name == NULL)
  625. continue;
  626. if (xkb_keymap_key_by_name(keymap, name) != XKB_KEYCODE_INVALID) {
  627. num_key_names = a + 1;
  628. }
  629. }
  630. expected = tests[t].num_key_names;
  631. got = num_key_names;
  632. assert_eq("keynames atoms", expected, got, "%u");
  633. /* Count valid key names */
  634. got = keymap->num_key_aliases;
  635. xkb_keymap_key_for_each(keymap, count_keys, &got);
  636. /*
  637. * Check that we do not waste too much memory with non-key name/alias
  638. * entries in the LUT.
  639. */
  640. const double valid_entries = (double) got / num_key_names;
  641. const double valid_entries_min = 0.92;
  642. const double valid_entries_max = 1.0;
  643. assert_printf(valid_entries >= valid_entries_min &&
  644. valid_entries < valid_entries_max,
  645. "No enough valid entries; expected: %f <= %f < %f\n",
  646. valid_entries_min, valid_entries, valid_entries_max);
  647. xkb_keymap_unref(keymap);
  648. xkb_context_unref(context);
  649. }
  650. }
  651. static void
  652. test_key_iterator(void)
  653. {
  654. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  655. assert(context);
  656. static const xkb_keycode_t test0_all[] = {1, 2, 9};
  657. static const xkb_keycode_t test0_bound[] = {2, 9};
  658. static const xkb_keycode_t test1_all[] = {0x1000, 0x2000, 0x9000};
  659. static const xkb_keycode_t test1_bound[] = {0x2000, 0x9000};
  660. static const xkb_keycode_t test2_all[] = {9, 0x1000, 0x2000};
  661. static const xkb_keycode_t test2_bound[] = {9, 0x2000};
  662. static const struct {
  663. const char *keymap;
  664. const xkb_keycode_t *keys_all;
  665. const xkb_keycode_t *keys_bound;
  666. size_t num_keys_all;
  667. size_t num_keys_bound;
  668. } tests[] = {
  669. {
  670. .keymap =
  671. "xkb_keymap {\n"
  672. " xkb_keycodes {\n"
  673. " <2> = 2;\n"
  674. " <1> = 1;\n"
  675. " <9> = 9;\n"
  676. " };\n"
  677. " xkb_symbols {\n"
  678. " key <2> {[2]};\n"
  679. " key <9> {[9]};\n"
  680. " };\n"
  681. "};",
  682. .keys_all = test0_all,
  683. .num_keys_all = ARRAY_SIZE(test0_all),
  684. .keys_bound = test0_bound,
  685. .num_keys_bound = ARRAY_SIZE(test0_bound),
  686. },
  687. {
  688. .keymap =
  689. "xkb_keymap {\n"
  690. " xkb_keycodes {\n"
  691. " <0x2000> = 0x2000;\n"
  692. " <0x1000> = 0x1000;\n"
  693. " <0x9000> = 0x9000;\n"
  694. " };\n"
  695. " xkb_symbols {\n"
  696. " key <0x2000> {[2]};\n"
  697. " key <0x9000> {[9]};\n"
  698. " };\n"
  699. "};",
  700. .keys_all = test1_all,
  701. .num_keys_all = ARRAY_SIZE(test1_all),
  702. .keys_bound = test1_bound,
  703. .num_keys_bound = ARRAY_SIZE(test1_bound),
  704. },
  705. {
  706. .keymap =
  707. "xkb_keymap {\n"
  708. " xkb_keycodes {\n"
  709. " <0x2000> = 0x2000;\n"
  710. " <0x1000> = 0x1000;\n"
  711. " <9> = 9;\n"
  712. " };\n"
  713. " xkb_symbols {\n"
  714. " key <0x2000> {[2]};\n"
  715. " key <9> {[9]};\n"
  716. " };\n"
  717. "};",
  718. .keys_all = test2_all,
  719. .num_keys_all = ARRAY_SIZE(test2_all),
  720. .keys_bound = test2_bound,
  721. .num_keys_bound = ARRAY_SIZE(test2_bound),
  722. },
  723. };
  724. for (size_t t = 0; t < ARRAY_SIZE(tests); t++) {
  725. struct xkb_keymap * const keymap = test_compile_string(
  726. context, XKB_KEYMAP_FORMAT_TEXT_V1, tests[t].keymap
  727. );
  728. assert(keymap);
  729. /* Reject invalid flags */
  730. assert(!xkb_keymap_key_iterator_new(keymap, -1));
  731. assert(!xkb_keymap_key_iterator_new(keymap, 0xffff));
  732. static const enum xkb_keymap_key_iterator_flags flags[] = {
  733. XKB_KEYMAP_KEY_ITERATOR_NO_FLAGS,
  734. XKB_KEYMAP_KEY_ITERATOR_DESCENDING_ORDER,
  735. XKB_KEYMAP_KEY_ITERATOR_SKIP_UNBOUND,
  736. XKB_KEYMAP_KEY_ITERATOR_DESCENDING_ORDER |
  737. XKB_KEYMAP_KEY_ITERATOR_SKIP_UNBOUND,
  738. };
  739. for (size_t f = 0; f < ARRAY_SIZE(flags); f++) {
  740. fprintf(stderr, "------\n*** %s: #%zu, flags: 0x%x ***\n",
  741. __func__, t, flags[f]);
  742. struct xkb_keymap_key_iterator * const iter =
  743. xkb_keymap_key_iterator_new(keymap, flags[f]);
  744. assert(iter);
  745. const bool ascending =
  746. !(flags[f] & XKB_KEYMAP_KEY_ITERATOR_DESCENDING_ORDER);
  747. const bool skip_unbound =
  748. (flags[f] & XKB_KEYMAP_KEY_ITERATOR_SKIP_UNBOUND);
  749. size_t expected_count = (skip_unbound)
  750. ? tests[t].num_keys_bound
  751. : tests[t].num_keys_all;
  752. const xkb_keycode_t * const keycodes = (skip_unbound)
  753. ? tests[t].keys_bound
  754. : tests[t].keys_all;
  755. size_t count = 0;
  756. size_t index = (skip_unbound)
  757. ? ((ascending) ? 0 : tests[t].num_keys_bound - 1)
  758. : ((ascending) ? 0 : tests[t].num_keys_all - 1);
  759. xkb_keycode_t current = 0;
  760. xkb_keycode_t previous = (ascending)
  761. ? 0
  762. : XKB_KEYCODE_INVALID;
  763. while ((current = xkb_keymap_key_iterator_next(iter)) !=
  764. XKB_KEYCODE_INVALID) {
  765. assert(count < expected_count);
  766. assert(current == keycodes[index]);
  767. assert((ascending && current > previous) ^
  768. (!ascending && current < previous));
  769. count++;
  770. if (ascending)
  771. index++;
  772. else
  773. index--;
  774. previous = current;
  775. }
  776. assert(count == expected_count);
  777. xkb_keymap_key_iterator_destroy(iter);
  778. }
  779. xkb_keymap_unref(keymap);
  780. }
  781. xkb_context_unref(context);
  782. }
  783. /*
  784. * Github issue 934: commit b09aa7c6d8440e1690619239fe57e5f12374af0d introduced
  785. * a segfault while trying to optimize key aliases allocation.
  786. */
  787. static void
  788. test_issue_934(void)
  789. {
  790. struct xkb_keymap *keymap;
  791. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  792. assert(context);
  793. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1,
  794. "base", "pc104", "us", NULL, NULL);
  795. assert(keymap);
  796. xkb_keymap_unref(keymap);
  797. /* Would segfaulted before */
  798. keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1,
  799. "evdev", "pc104", "us", NULL, NULL);
  800. assert(keymap);
  801. xkb_keymap_unref(keymap);
  802. xkb_context_unref(context);
  803. }
  804. static void
  805. test_serialize_layouts_subset(bool update_output_files)
  806. {
  807. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  808. assert(context);
  809. /*
  810. * This keymap is used to test that vmods remains unchanged, independently
  811. * of the subset of layouts.
  812. */
  813. static const char keymap_str[] =
  814. "xkb_keymap {\n"
  815. " xkb_keycodes { <LALT> = 64; <RALT> = 108; };\n"
  816. " xkb_compat {\n"
  817. " virtual_modifiers Alt, LevelThree;\n"
  818. " interpret.repeat= False;\n"
  819. " setMods.clearLocks= True;\n"
  820. " interpret Alt_L+Any {\n"
  821. " virtualModifier= Alt;\n"
  822. " action = SetMods(modifiers=modMapMods);\n"
  823. " };\n"
  824. " interpret ISO_Level3_Shift+Any {\n"
  825. " useModMapMods= level1;\n"
  826. " virtualModifier= LevelThree;\n"
  827. " action= SetMods(modifiers=LevelThree);\n"
  828. " };\n"
  829. " };\n"
  830. " xkb_symbols {\n"
  831. " name[1] = \"1\";\n"
  832. " name[2] = \"2\";\n"
  833. " name[3] = \"3\";\n"
  834. " name[4] = \"4\";\n"
  835. " name[5] = \"5\";\n"
  836. " name[6] = \"6\";\n"
  837. " key <LALT> {\n"
  838. " groupsRedirect = 1,\n"
  839. " symbols[1] = [Alt_L],\n"
  840. " symbols[3] = [ISO_Level3_Shift],\n"
  841. " symbols[4] = [a],\n"
  842. " symbols[5] = [Alt_L],\n"
  843. " symbols[6] = [b]\n"
  844. " };\n"
  845. " key <RALT> {\n"
  846. " groupsRedirect = 2,\n"
  847. " symbols[1] = [ISO_Level3_Shift],\n"
  848. " symbols[3] = [c],\n"
  849. " symbols[4] = [ISO_Level3_Shift],\n"
  850. " symbols[5] = [d],\n"
  851. " symbols[6] = [e]\n"
  852. " };\n"
  853. " modifier_map Mod1 { <LALT> };\n"
  854. " modifier_map Mod5 { ISO_Level3_Shift };\n"
  855. " };\n"
  856. "};";
  857. struct xkb_keymap * const keymap = xkb_keymap_new_from_buffer(
  858. context, keymap_str, sizeof(keymap_str),
  859. XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS
  860. );
  861. assert(keymap);
  862. static const struct {
  863. xkb_layout_mask_t layouts;
  864. const char* expected;
  865. } tests[] = {
  866. {
  867. .layouts = 0x3f,
  868. .expected = GOLDEN_TESTS_OUTPUTS "serialize-layouts-subset-all.xkb"
  869. },
  870. {
  871. .layouts = 0x1e,
  872. .expected = GOLDEN_TESTS_OUTPUTS "serialize-layouts-subset-2,3,4,5.xkb"
  873. },
  874. {
  875. .layouts = 0x1c,
  876. .expected = GOLDEN_TESTS_OUTPUTS "serialize-layouts-subset-3,4,5.xkb"
  877. },
  878. {
  879. .layouts = 0x20,
  880. .expected = GOLDEN_TESTS_OUTPUTS "serialize-layouts-subset-6.xkb"
  881. },
  882. };
  883. for (size_t t = 0; t < ARRAY_SIZE(tests); t++) {
  884. fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, t);
  885. const struct xkb_keymap_serialize_config config = {
  886. .size = sizeof(config),
  887. .format = XKB_KEYMAP_FORMAT_TEXT_V2,
  888. .flags = TEST_KEYMAP_SERIALIZE_FLAGS |
  889. XKB_KEYMAP_SERIALIZE_EXPLICIT_VMODS,
  890. .layouts = tests[t].layouts,
  891. };
  892. struct xkb_keymap_serialize_result result = { .size = sizeof(result) };
  893. const enum xkb_error_code ret =
  894. xkb_keymap_serialize(keymap, &config, &result);
  895. assert(ret ^ !!result.serialized);
  896. assert(ret ^ !!tests[t].expected);
  897. assert(!!result.serialized == !!tests[t].expected);
  898. assert_eq("layout mask", tests[t].layouts, result.layouts, "%"PRIx32);
  899. char* const path = test_get_path(tests[t].expected);
  900. assert(path);
  901. if (tests[t].expected) {
  902. assert(result.length == strlen(result.serialized) + 1);
  903. if (update_output_files) {
  904. fprintf(stderr, "Writing golden test output to: %s\n", path);
  905. FILE *file = fopen(path, "wb");
  906. assert(file);
  907. fwrite(result.serialized, sizeof(*result.serialized),
  908. result.length - 1, file);
  909. fclose(file);
  910. } else {
  911. fprintf(stderr, "Reading golden test output: %s\n", path);
  912. char* const expected = test_read_file(tests[t].expected);
  913. assert(expected);
  914. if (!streq(expected, result.serialized)) {
  915. fprintf(stderr,
  916. "Failure: dumped map differs from expected.\n"
  917. "Path to expected file: %s\n"
  918. "Length: expected %zu, got: %zu\n"
  919. "Dumped map:\n%s\n",
  920. path, strlen(expected),
  921. result.length, result.serialized);
  922. assert(false);
  923. }
  924. free(expected);
  925. }
  926. }
  927. free(path);
  928. free(result.serialized);
  929. }
  930. xkb_keymap_unref(keymap);
  931. xkb_context_unref(context);
  932. }
  933. int
  934. main(int argc, char *argv[])
  935. {
  936. test_init();
  937. bool update_output_files = false;
  938. int arg_index = 0;
  939. while (++arg_index < argc) {
  940. if (streq(argv[arg_index], "update")) {
  941. /* Update files with *obtained* results */
  942. update_output_files = true;
  943. }
  944. }
  945. test_supported_formats();
  946. test_garbage_key();
  947. test_keymap();
  948. test_no_extra_groups();
  949. test_numeric_keysyms();
  950. test_multiple_keysyms_per_level();
  951. test_multiple_actions_per_level();
  952. test_keynames_atoms();
  953. test_key_iterator();
  954. test_issue_934();
  955. test_serialize_layouts_subset(update_output_files);
  956. return EXIT_SUCCESS;
  957. }