1 /* 2 * Copyright 2012 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Author: Daniel Stone <daniel (at) fooishbar.org> 24 */ 25 26 #include <assert.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 30 #include "evdev-scancodes.h" 31 #include "test.h" 32 33 /* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB 34 * keycode set (where ESC is 9). */ 35 #define EVDEV_OFFSET 8 36 37 static void 38 print_state(struct xkb_state *state) 39 { 40 struct xkb_keymap *keymap; 41 xkb_layout_index_t group; 42 xkb_mod_index_t mod; 43 xkb_led_index_t led; 44 45 group = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); 46 mod = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); 47 /* led = xkb_state_serialize_leds(state, XKB_STATE_LEDS); */ 48 if (!group && !mod /* && !led */) { 49 fprintf(stderr, "\tno state\n"); 50 return; 51 } 52 53 keymap = xkb_state_get_keymap(state); 54 55 for (group = 0; group < xkb_keymap_num_layouts(keymap); group++) { 56 if (xkb_state_layout_index_is_active(state, group, 57 XKB_STATE_LAYOUT_EFFECTIVE | 58 XKB_STATE_LAYOUT_DEPRESSED | 59 XKB_STATE_LAYOUT_LATCHED | 60 XKB_STATE_LAYOUT_LOCKED) <= 0) 61 continue; 62 fprintf(stderr, "\tgroup %s (%d): %s%s%s%s\n", 63 xkb_keymap_layout_get_name(keymap, group), 64 group, 65 xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_EFFECTIVE) > 0 ? 66 "effective " : "", 67 xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_DEPRESSED) > 0 ? 68 "depressed " : "", 69 xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_LATCHED) > 0 ? 70 "latched " : "", 71 xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_LOCKED) > 0 ? 72 "locked " : ""); 73 } 74 75 for (mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { 76 if (xkb_state_mod_index_is_active(state, mod, 77 XKB_STATE_MODS_EFFECTIVE | 78 XKB_STATE_MODS_DEPRESSED | 79 XKB_STATE_MODS_LATCHED | 80 XKB_STATE_MODS_LOCKED) <= 0) 81 continue; 82 fprintf(stderr, "\tmod %s (%d): %s%s%s%s\n", 83 xkb_keymap_mod_get_name(keymap, mod), 84 mod, 85 xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE) > 0 ? 86 "effective " : "", 87 xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_DEPRESSED) > 0 ? 88 "depressed " : "", 89 xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_LATCHED) > 0 ? 90 "latched " : "", 91 xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_LOCKED) > 0 ? 92 "locked " : ""); 93 } 94 95 for (led = 0; led < xkb_keymap_num_leds(keymap); led++) { 96 if (xkb_state_led_index_is_active(state, led) <= 0) 97 continue; 98 fprintf(stderr, "\tled %s (%d): active\n", 99 xkb_keymap_led_get_name(keymap, led), 100 led); 101 } 102 } 103 104 static void 105 test_update_key(struct xkb_keymap *keymap) 106 { 107 struct xkb_state *state = xkb_state_new(keymap); 108 const xkb_keysym_t *syms; 109 xkb_keysym_t one_sym; 110 int num_syms; 111 112 assert(state); 113 114 /* LCtrl down */ 115 xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); 116 fprintf(stderr, "dumping state for LCtrl down:\n"); 117 print_state(state); 118 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, 119 XKB_STATE_MODS_DEPRESSED) > 0); 120 121 /* LCtrl + RAlt down */ 122 xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_DOWN); 123 fprintf(stderr, "dumping state for LCtrl + RAlt down:\n"); 124 print_state(state); 125 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, 126 XKB_STATE_MODS_DEPRESSED) > 0); 127 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, 128 XKB_STATE_MODS_DEPRESSED) > 0); 129 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, 130 XKB_STATE_MATCH_ALL, 131 XKB_MOD_NAME_CTRL, 132 XKB_MOD_NAME_ALT, 133 NULL) > 0); 134 assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED, 135 XKB_STATE_MATCH_ALL, 136 xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL), 137 xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT), 138 XKB_MOD_INVALID) > 0); 139 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, 140 XKB_STATE_MATCH_ALL, 141 XKB_MOD_NAME_ALT, 142 NULL) == 0); 143 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, 144 XKB_STATE_MATCH_ALL | 145 XKB_STATE_MATCH_NON_EXCLUSIVE, 146 XKB_MOD_NAME_ALT, 147 NULL) > 0); 148 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, 149 (XKB_STATE_MATCH_ANY | 150 XKB_STATE_MATCH_NON_EXCLUSIVE), 151 XKB_MOD_NAME_ALT, 152 NULL) > 0); 153 154 /* RAlt down */ 155 xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); 156 fprintf(stderr, "dumping state for RAlt down:\n"); 157 print_state(state); 158 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, 159 XKB_STATE_MODS_EFFECTIVE) == 0); 160 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, 161 XKB_STATE_MODS_DEPRESSED) > 0); 162 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, 163 XKB_STATE_MATCH_ANY, 164 XKB_MOD_NAME_CTRL, 165 XKB_MOD_NAME_ALT, 166 NULL) > 0); 167 assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_LATCHED, 168 XKB_STATE_MATCH_ANY, 169 XKB_MOD_NAME_CTRL, 170 XKB_MOD_NAME_ALT, 171 NULL) == 0); 172 173 /* none down */ 174 xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_UP); 175 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, 176 XKB_STATE_MODS_EFFECTIVE) == 0); 177 178 /* Caps locked */ 179 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 180 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, 181 XKB_STATE_MODS_DEPRESSED) > 0); 182 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); 183 fprintf(stderr, "dumping state for Caps Lock:\n"); 184 print_state(state); 185 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, 186 XKB_STATE_MODS_DEPRESSED) == 0); 187 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, 188 XKB_STATE_MODS_LOCKED) > 0); 189 assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) > 0); 190 num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); 191 assert(num_syms == 1 && syms[0] == XKB_KEY_Q); 192 193 /* Num Lock locked */ 194 xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 195 xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); 196 fprintf(stderr, "dumping state for Caps Lock + Num Lock:\n"); 197 print_state(state); 198 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, 199 XKB_STATE_MODS_LOCKED) > 0); 200 assert(xkb_state_mod_name_is_active(state, "Mod2", 201 XKB_STATE_MODS_LOCKED) > 0); 202 num_syms = xkb_state_key_get_syms(state, KEY_KP1 + EVDEV_OFFSET, &syms); 203 assert(num_syms == 1 && syms[0] == XKB_KEY_KP_1); 204 assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0); 205 206 /* Num Lock unlocked */ 207 xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 208 xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); 209 210 /* Switch to group 2 */ 211 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); 212 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); 213 assert(xkb_state_led_name_is_active(state, "Group 2") > 0); 214 assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) == 0); 215 216 /* Switch back to group 1. */ 217 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); 218 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); 219 220 /* Caps unlocked */ 221 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 222 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); 223 assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, 224 XKB_STATE_MODS_EFFECTIVE) == 0); 225 assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) == 0); 226 num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); 227 assert(num_syms == 1 && syms[0] == XKB_KEY_q); 228 229 /* Multiple symbols */ 230 num_syms = xkb_state_key_get_syms(state, KEY_6 + EVDEV_OFFSET, &syms); 231 assert(num_syms == 5 && 232 syms[0] == XKB_KEY_H && syms[1] == XKB_KEY_E && 233 syms[2] == XKB_KEY_L && syms[3] == XKB_KEY_L && 234 syms[4] == XKB_KEY_O); 235 one_sym = xkb_state_key_get_one_sym(state, KEY_6 + EVDEV_OFFSET); 236 assert(one_sym == XKB_KEY_NoSymbol); 237 xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_DOWN); 238 xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_UP); 239 240 one_sym = xkb_state_key_get_one_sym(state, KEY_5 + EVDEV_OFFSET); 241 assert(one_sym == XKB_KEY_5); 242 243 xkb_state_unref(state); 244 } 245 246 static void 247 test_serialisation(struct xkb_keymap *keymap) 248 { 249 struct xkb_state *state = xkb_state_new(keymap); 250 xkb_mod_mask_t base_mods; 251 xkb_mod_mask_t latched_mods; 252 xkb_mod_mask_t locked_mods; 253 xkb_mod_mask_t effective_mods; 254 xkb_mod_index_t caps, shift, ctrl; 255 xkb_layout_index_t base_group = 0; 256 xkb_layout_index_t latched_group = 0; 257 xkb_layout_index_t locked_group = 0; 258 259 assert(state); 260 261 caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); 262 assert(caps != XKB_MOD_INVALID); 263 shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); 264 assert(shift != XKB_MOD_INVALID); 265 ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); 266 assert(ctrl != XKB_MOD_INVALID); 267 268 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 269 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); 270 base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); 271 assert(base_mods == 0); 272 latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); 273 assert(latched_mods == 0); 274 locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); 275 assert(locked_mods == (1U << caps)); 276 effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); 277 assert(effective_mods == locked_mods); 278 279 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); 280 base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); 281 assert(base_mods == (1U << shift)); 282 latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); 283 assert(latched_mods == 0); 284 locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); 285 assert(locked_mods == (1U << caps)); 286 effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); 287 assert(effective_mods == (base_mods | locked_mods)); 288 289 base_mods |= (1U << ctrl); 290 xkb_state_update_mask(state, base_mods, latched_mods, locked_mods, 291 base_group, latched_group, locked_group); 292 293 assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_DEPRESSED) > 0); 294 assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); 295 296 xkb_state_unref(state); 297 } 298 299 static void 300 test_update_mask_mods(struct xkb_keymap *keymap) 301 { 302 struct xkb_state *state = xkb_state_new(keymap); 303 xkb_mod_index_t caps, shift, num, alt, mod1, mod2; 304 enum xkb_state_component changed; 305 306 assert(state); 307 308 caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); 309 assert(caps != XKB_MOD_INVALID); 310 shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); 311 assert(shift != XKB_MOD_INVALID); 312 num = xkb_keymap_mod_get_index(keymap, "NumLock"); 313 assert(num != XKB_MOD_INVALID); 314 alt = xkb_keymap_mod_get_index(keymap, "Alt"); 315 assert(alt != XKB_MOD_INVALID); 316 mod1 = xkb_keymap_mod_get_index(keymap, "Mod1"); 317 assert(mod1 != XKB_MOD_INVALID); 318 mod2 = xkb_keymap_mod_get_index(keymap, "Mod2"); 319 assert(mod2 != XKB_MOD_INVALID); 320 321 changed = xkb_state_update_mask(state, 1 << caps, 0, 0, 0, 0, 0); 322 assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE)); 323 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 324 (1u << caps)); 325 326 changed = xkb_state_update_mask(state, (1 << caps), 0, (1 << shift), 0, 0, 0); 327 assert(changed == (XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | 328 XKB_STATE_LEDS)); 329 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 330 ((1u << caps) | (1u << shift))); 331 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == 332 (1u << caps)); 333 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0); 334 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 335 (1u << shift)); 336 337 changed = xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0); 338 assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | 339 XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); 340 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); 341 342 changed = xkb_state_update_mask(state, (1 << alt), 0, 0, 0, 0, 0); 343 assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE)); 344 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 345 ((1u << alt) | (1u << mod1))); 346 347 changed = xkb_state_update_mask(state, 0, 0, (1 << num), 0, 0, 0); 348 assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | 349 XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); 350 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 351 ((1u << num) | (1u << mod2))); 352 353 xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0); 354 355 changed = xkb_state_update_mask(state, (1 << mod2), 0, (1 << num), 0, 0, 0); 356 assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | 357 XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); 358 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 359 ((1u << mod2) | (1u << num))); 360 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == 361 (1u << mod2)); 362 assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 363 ((1u << num) | (1u << mod2))); 364 365 xkb_state_unref(state); 366 } 367 368 static void 369 test_repeat(struct xkb_keymap *keymap) 370 { 371 assert(!xkb_keymap_key_repeats(keymap, KEY_LEFTSHIFT + 8)); 372 assert(xkb_keymap_key_repeats(keymap, KEY_A + 8)); 373 assert(xkb_keymap_key_repeats(keymap, KEY_8 + 8)); 374 assert(xkb_keymap_key_repeats(keymap, KEY_DOWN + 8)); 375 assert(xkb_keymap_key_repeats(keymap, KEY_KBDILLUMDOWN + 8)); 376 } 377 378 static void 379 test_consume(struct xkb_keymap *keymap) 380 { 381 struct xkb_state *state; 382 xkb_mod_index_t alt, shift, caps, ctrl, mod5; 383 xkb_mod_mask_t mask; 384 385 state = xkb_state_new(keymap); 386 assert(state); 387 388 alt = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT); 389 assert(alt != XKB_MOD_INVALID); 390 shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); 391 assert(shift != XKB_MOD_INVALID); 392 caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); 393 assert(caps != XKB_MOD_INVALID); 394 ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); 395 assert(ctrl != XKB_MOD_INVALID); 396 mod5 = xkb_keymap_mod_get_index(keymap, "Mod5"); 397 assert(mod5 != XKB_MOD_INVALID); 398 399 /* Test remove_consumed() */ 400 xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); 401 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); 402 xkb_state_update_key(state, KEY_EQUAL + EVDEV_OFFSET, XKB_KEY_DOWN); 403 404 fprintf(stderr, "dumping state for Alt-Shift-+\n"); 405 print_state(state); 406 407 mask = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); 408 assert(mask == ((1U << alt) | (1U << shift))); 409 mask = xkb_state_mod_mask_remove_consumed(state, KEY_EQUAL + EVDEV_OFFSET, 410 mask); 411 assert(mask == (1U << alt)); 412 413 /* Test get_consumed_mods() */ 414 mask = xkb_state_key_get_consumed_mods(state, KEY_EQUAL + EVDEV_OFFSET); 415 assert(mask == (1U << shift)); 416 417 mask = xkb_state_key_get_consumed_mods(state, KEY_ESC + EVDEV_OFFSET); 418 assert(mask == 0); 419 420 xkb_state_unref(state); 421 422 /* Test is_consumed() - simple ALPHABETIC type. */ 423 state = xkb_state_new(keymap); 424 assert(state); 425 426 mask = xkb_state_key_get_consumed_mods(state, KEY_A + EVDEV_OFFSET); 427 assert(mask == ((1U << shift) | (1U << caps))); 428 429 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, caps) > 0); 430 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shift) > 0); 431 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 432 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); 433 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, caps) > 0); 434 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shift) > 0); 435 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); 436 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, caps) > 0); 437 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shift) > 0); 438 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); 439 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); 440 xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); 441 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, caps) > 0); 442 assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shift) > 0); 443 444 xkb_state_unref(state); 445 446 /* More complicated - CTRL+ALT */ 447 state = xkb_state_new(keymap); 448 449 mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); 450 assert(mask == ((1U << shift) | (1U << alt) | (1U << ctrl) | (1U << mod5))); 451 452 /* Shift is preserved. */ 453 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); 454 mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); 455 assert(mask == ((1U << alt) | (1U << ctrl) | (1U << mod5))); 456 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); 457 458 mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); 459 assert(mask == ((1U << shift) | (1U << alt) | (1U << ctrl) | (1U << mod5))); 460 461 assert(state); 462 463 xkb_state_unref(state); 464 } 465 466 static void 467 key_iter(struct xkb_keymap *keymap, xkb_keycode_t key, void *data) 468 { 469 xkb_keycode_t *counter = data; 470 471 assert(*counter == key); 472 (*counter)++; 473 } 474 475 static void 476 test_range(struct xkb_keymap *keymap) 477 { 478 xkb_keycode_t counter; 479 480 assert(xkb_keymap_min_keycode(keymap) == 9); 481 assert(xkb_keymap_max_keycode(keymap) == 253); 482 483 counter = xkb_keymap_min_keycode(keymap); 484 xkb_keymap_key_for_each(keymap, key_iter, &counter); 485 assert(counter == xkb_keymap_max_keycode(keymap) + 1); 486 } 487 488 static void 489 test_caps_keysym_transformation(struct xkb_keymap *keymap) 490 { 491 struct xkb_state *state = xkb_state_new(keymap); 492 xkb_mod_index_t caps, shift; 493 int nsyms; 494 xkb_keysym_t sym; 495 const xkb_keysym_t *syms; 496 497 assert(state); 498 499 /* See xkb_state_key_get_one_sym() for what's this all about. */ 500 501 caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); 502 shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); 503 assert(caps != XKB_MOD_INVALID && shift != XKB_MOD_INVALID); 504 505 assert(xkb_state_key_get_layout(state, KEY_A + 8) == 0); 506 assert(xkb_state_key_get_layout(state, KEY_SEMICOLON + 8) == 0); 507 508 /* Without caps, no transformation. */ 509 assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); 510 assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); 511 assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 0); 512 sym = xkb_state_key_get_one_sym(state, KEY_A + 8); 513 assert(sym == XKB_KEY_a); 514 assert(xkb_state_key_get_level(state, KEY_SEMICOLON + 8, 0) == 0); 515 sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); 516 assert(sym == XKB_KEY_eacute); 517 nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); 518 assert(nsyms == 1 && syms[0] == XKB_KEY_eacute); 519 520 /* With shift, no transformation (only different level). */ 521 xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_DOWN); 522 assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); 523 assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) > 0); 524 assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 1); 525 sym = xkb_state_key_get_one_sym(state, KEY_A + 8); 526 assert(sym == XKB_KEY_A); 527 sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); 528 assert(sym == XKB_KEY_odiaeresis); 529 nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); 530 assert(nsyms == 1 && syms[0] == XKB_KEY_odiaeresis); 531 xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_UP); 532 assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); 533 534 /* With caps, transform in same level, only with _get_one_sym(). */ 535 xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_DOWN); 536 xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_UP); 537 assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0); 538 assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); 539 assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 1); 540 sym = xkb_state_key_get_one_sym(state, KEY_A + 8); 541 assert(sym == XKB_KEY_A); 542 assert(xkb_state_key_get_level(state, KEY_SEMICOLON + 8, 0) == 0); 543 sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); 544 assert(sym == XKB_KEY_Eacute); 545 nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); 546 assert(nsyms == 1 && syms[0] == XKB_KEY_eacute); 547 xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_UP); 548 assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); 549 xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_DOWN); 550 xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_UP); 551 552 xkb_state_unref(state); 553 } 554 555 static void 556 test_get_utf8_utf32(struct xkb_keymap *keymap) 557 { 558 char buf[256]; 559 struct xkb_state *state = xkb_state_new(keymap); 560 assert(state); 561 562 #define TEST_KEY(key, expected_utf8, expected_utf32) do { \ 563 assert(xkb_state_key_get_utf8(state, key + 8, NULL, 0) == strlen(expected_utf8)); \ 564 assert(xkb_state_key_get_utf8(state, key + 8, buf, sizeof(buf)) == strlen(expected_utf8)); \ 565 assert(memcmp(buf, expected_utf8, sizeof(expected_utf8)) == 0); \ 566 assert(xkb_state_key_get_utf32(state, key + 8) == expected_utf32); \ 567 } while (0) 568 569 /* Simple ASCII. */ 570 TEST_KEY(KEY_A, "a", 0x61); 571 TEST_KEY(KEY_ESC, "\x1B", 0x1B); 572 TEST_KEY(KEY_1, "1", 0x31); 573 574 /* Invalid. */ 575 TEST_KEY(XKB_KEYCODE_INVALID - 8, "", 0); 576 TEST_KEY(300, "", 0); 577 578 /* No string. */ 579 TEST_KEY(KEY_LEFTCTRL, "", 0); 580 TEST_KEY(KEY_NUMLOCK, "", 0); 581 582 /* Multiple keysyms. */ 583 TEST_KEY(KEY_6, "HELLO", 0); 584 TEST_KEY(KEY_7, "YES THIS IS DOG", 0); 585 586 /* Check truncation. */ 587 memset(buf, 'X', sizeof(buf)); 588 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 0) == strlen("HELLO")); 589 assert(memcmp(buf, "X", 1) == 0); 590 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 1) == strlen("HELLO")); 591 assert(memcmp(buf, "", 1) == 0); 592 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 2) == strlen("HELLO")); 593 assert(memcmp(buf, "H", 2) == 0); 594 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 3) == strlen("HELLO")); 595 assert(memcmp(buf, "HE", 3) == 0); 596 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 5) == strlen("HELLO")); 597 assert(memcmp(buf, "HELL", 5) == 0); 598 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 6) == strlen("HELLO")); 599 assert(memcmp(buf, "HELLO", 6) == 0); 600 assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 7) == strlen("HELLO")); 601 assert(memcmp(buf, "HELLO\0X", 7) == 0); 602 603 /* Switch to ru layout */ 604 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); 605 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); 606 assert(xkb_state_key_get_layout(state, KEY_A + 8) == 1); 607 608 /* Non ASCII. */ 609 TEST_KEY(KEY_ESC, "\x1B", 0x1B); 610 TEST_KEY(KEY_A, "", 0x0444); 611 TEST_KEY(KEY_Z, "", 0x044F); 612 613 /* Switch back to us layout */ 614 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); 615 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); 616 assert(xkb_state_key_get_layout(state, KEY_A + 8) == 0); 617 618 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); 619 TEST_KEY(KEY_A, "A", 0x41); 620 TEST_KEY(KEY_ESC, "\x1B", 0x1B); 621 TEST_KEY(KEY_1, "!", 0x21); 622 xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); 623 624 TEST_KEY(KEY_6, "HELLO", 0); 625 TEST_KEY(KEY_7, "YES THIS IS DOG", 0); 626 627 xkb_state_unref(state); 628 } 629 630 static void 631 test_ctrl_string_transformation(struct xkb_keymap *keymap) 632 { 633 char buf[256]; 634 struct xkb_state *state = xkb_state_new(keymap); 635 xkb_mod_index_t ctrl; 636 637 assert(state); 638 639 /* See xkb_state_key_get_utf8() for what's this all about. */ 640 641 ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); 642 assert(ctrl != XKB_MOD_INVALID); 643 644 /* First without. */ 645 TEST_KEY(KEY_A, "a", 0x61); 646 TEST_KEY(KEY_B, "b", 0x62); 647 TEST_KEY(KEY_C, "c", 0x63); 648 TEST_KEY(KEY_ESC, "\x1B", 0x1B); 649 TEST_KEY(KEY_1, "1", 0x31); 650 651 /* And with. */ 652 xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); 653 assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); 654 TEST_KEY(KEY_A, "\x01", 0x01); 655 TEST_KEY(KEY_B, "\x02", 0x02); 656 TEST_KEY(KEY_C, "\x03", 0x03); 657 TEST_KEY(KEY_ESC, "\x1B", 0x1B); 658 TEST_KEY(KEY_1, "1", 0x31); 659 xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); 660 661 /* Switch to ru layout */ 662 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); 663 xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); 664 assert(xkb_state_key_get_layout(state, KEY_A + 8) == 1); 665 666 /* Non ASCII. */ 667 xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); 668 assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); 669 TEST_KEY(KEY_A, "\x01", 0x01); 670 TEST_KEY(KEY_B, "\x02", 0x02); 671 xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); 672 673 xkb_state_unref(state); 674 } 675 676 int 677 main(void) 678 { 679 struct xkb_context *context = test_get_context(0); 680 struct xkb_keymap *keymap; 681 682 assert(context); 683 684 /* Make sure these are allowed. */ 685 xkb_context_unref(NULL); 686 xkb_keymap_unref(NULL); 687 xkb_state_unref(NULL); 688 689 keymap = test_compile_rules(context, "evdev", "pc104", "us,ru", NULL, "grp:menu_toggle"); 690 assert(keymap); 691 692 test_update_key(keymap); 693 test_serialisation(keymap); 694 test_update_mask_mods(keymap); 695 test_repeat(keymap); 696 test_consume(keymap); 697 test_range(keymap); 698 test_get_utf8_utf32(keymap); 699 test_ctrl_string_transformation(keymap); 700 701 xkb_keymap_unref(keymap); 702 keymap = test_compile_rules(context, "evdev", NULL, "ch", "fr", NULL); 703 assert(keymap); 704 705 test_caps_keysym_transformation(keymap); 706 707 xkb_keymap_unref(keymap); 708 xkb_context_unref(context); 709 } 710