Home | History | Annotate | Download | only in test
      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