libxkbcommon/test/keyseq.c

471 lines
24 KiB
C
Raw Normal View History

/*
* Copyright © 2012 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <linux/input.h>
#include "test.h"
enum {
DOWN,
REPEAT,
UP,
BOTH,
NEXT,
FINISH,
};
#define EVDEV_OFFSET 8
/*
* Test a sequence of keysyms, resulting from a sequence of key presses,
* against the keysyms they're supposed to generate.
*
* - Each test runs with a clean state.
* - Each line in the test is made up of:
* + A keycode, given as a KEY_* from linux/input.h.
* + A direction - DOWN for press, UP for release, BOTH for
* immediate press + release, REPEAT to just get the syms.
* + A sequence of keysyms that should result from this keypress.
*
* The vararg format is:
* <KEY_*> <DOWN | UP | BOTH> <XKB_KEY_* (zero or more)> <NEXT | FINISH>
*
* See below for examples.
*/
static int
test_key_seq(struct xkb_keymap *keymap, ...)
{
struct xkb_state *state;
va_list ap;
xkb_keycode_t kc;
int op;
xkb_keysym_t keysym;
const xkb_keysym_t *syms;
unsigned int nsyms, i;
char ksbuf[64];
fprintf(stderr, "----\n");
state = xkb_state_new(keymap);
assert(state);
va_start(ap, keymap);
for (;;) {
kc = va_arg(ap, int) + EVDEV_OFFSET;
op = va_arg(ap, int);
nsyms = xkb_state_key_get_syms(state, kc, &syms);
fprintf(stderr, "got %d syms for key 0x%x: [", nsyms, kc);
if (op == DOWN || op == BOTH)
xkb_state_update_key(state, kc, XKB_KEY_DOWN);
if (op == UP || op == BOTH)
xkb_state_update_key(state, kc, XKB_KEY_UP);
for (i = 0; i < nsyms; i++) {
keysym = va_arg(ap, int);
xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
fprintf(stderr, "%s%s", (i != 0) ? ", " : "", ksbuf);
if (keysym == FINISH || keysym == NEXT) {
xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
fprintf(stderr, "Did not expect keysym: %s.\n", ksbuf);
goto fail;
}
if (keysym != syms[i]) {
xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
fprintf(stderr, "Expected keysym: %s. ", ksbuf);;
xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
fprintf(stderr, "Got keysym: %s.\n", ksbuf);;
goto fail;
}
}
fprintf(stderr, "]\n");
keysym = va_arg(ap, int);
if (keysym == NEXT)
continue;
if (keysym == FINISH)
break;
xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
fprintf(stderr, "Expected keysym: %s. Didn't get it.\n", ksbuf);
goto fail;
}
va_end(ap);
xkb_state_unref(state);
return 1;
fail:
va_end(ap);
xkb_state_unref(state);
return 0;
}
int
main(void)
{
struct xkb_context *ctx = test_get_context();
struct xkb_keymap *keymap;
assert(ctx);
symbols: fix real/alias key merge ordering bug Background: The CopySymbolsDef has a comment on a couple of lines which supposedly fixed a bug: /* * kt_index[i] may have been set by a previous run (if we have two * layouts specified). Let's not overwrite it with the ONE_LEVEL * default group if we dont even have keys for this group anyway. * * FIXME: There should be a better fix for this. */ if (!darray_empty(groupi->levels)) key->kt_index[i] = types[i]; But neither the comment nor the fix make any sense, because the kt_index is indexed per group, i.e. each group gets its own type. The original xkbcomp commit which added this (36fecff58) points to this bug: https://bugzilla.redhat.com/show_bug.cgi?id=436626 which complains about -layout "ru,us" -variant "phonetic," not working properly. And indeed when we try: sudo ./test/interactive -l ru,us -v the first group doesn't get any syms for the main keys. The problem (Clearly the fix above is useless): The ru(phonetic) map is specified using aliases, e.g. LatQ, LatW instead of AD01, AD02, etc. When combined with another layout which uses the real names (AD01, AD02), the symbols code should recognize they are the same key and merge them into one KeyInfo. The current code does that, but it doesn't catch the case where the alias was processes *before* the real one; so we get two KeyInfo's and the later one wins. So e.g. the ru(phonetic) symbols are ignored. The fix: Before adding a new KeyInfo to the keys array, always replace its name by the real name, which avoids the entire issue. Luckily this is done pretty late so most error messages should still show the alias name. Signed-off-by: Ran Benita <ran234@gmail.com>
2012-09-12 14:51:19 -06:00
keymap = test_compile_rules(ctx, "evdev", "evdev",
"us,il,ru,de", ",,phonetic,neo",
"grp:alt_shift_toggle,grp:menu_toggle");
assert(keymap);
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_E, BOTH, XKB_KEY_e, NEXT,
KEY_L, BOTH, XKB_KEY_l, NEXT,
KEY_L, BOTH, XKB_KEY_l, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
/* Simple shifted level. */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_L, BOTH, XKB_KEY_l, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
/* Key repeat shifted and unshifted in the middle. */
assert(test_key_seq(keymap,
KEY_H, DOWN, XKB_KEY_h, NEXT,
KEY_H, REPEAT, XKB_KEY_h, NEXT,
KEY_H, REPEAT, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_H, REPEAT, XKB_KEY_H, NEXT,
KEY_H, REPEAT, XKB_KEY_H, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_H, REPEAT, XKB_KEY_h, NEXT,
KEY_H, REPEAT, XKB_KEY_h, NEXT,
KEY_H, UP, XKB_KEY_h, NEXT,
KEY_H, BOTH, XKB_KEY_h, FINISH));
/* Base modifier cleared on key release... */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_O, BOTH, XKB_KEY_O, FINISH));
/* ... But only by the keycode that set it. */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_O, BOTH, XKB_KEY_O, FINISH));
/*
* A base modifier should only be cleared when no other key affecting
* the modifier is down.
*/
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
/* Group switching / locking. */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_E, BOTH, XKB_KEY_e, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_K, BOTH, XKB_KEY_hebrew_lamed, NEXT,
KEY_F, BOTH, XKB_KEY_hebrew_kaph, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
symbols: fix real/alias key merge ordering bug Background: The CopySymbolsDef has a comment on a couple of lines which supposedly fixed a bug: /* * kt_index[i] may have been set by a previous run (if we have two * layouts specified). Let's not overwrite it with the ONE_LEVEL * default group if we dont even have keys for this group anyway. * * FIXME: There should be a better fix for this. */ if (!darray_empty(groupi->levels)) key->kt_index[i] = types[i]; But neither the comment nor the fix make any sense, because the kt_index is indexed per group, i.e. each group gets its own type. The original xkbcomp commit which added this (36fecff58) points to this bug: https://bugzilla.redhat.com/show_bug.cgi?id=436626 which complains about -layout "ru,us" -variant "phonetic," not working properly. And indeed when we try: sudo ./test/interactive -l ru,us -v the first group doesn't get any syms for the main keys. The problem (Clearly the fix above is useless): The ru(phonetic) map is specified using aliases, e.g. LatQ, LatW instead of AD01, AD02, etc. When combined with another layout which uses the real names (AD01, AD02), the symbols code should recognize they are the same key and merge them into one KeyInfo. The current code does that, but it doesn't catch the case where the alias was processes *before* the real one; so we get two KeyInfo's and the later one wins. So e.g. the ru(phonetic) symbols are ignored. The fix: Before adding a new KeyInfo to the keys array, always replace its name by the real name, which avoids the entire issue. Luckily this is done pretty late so most error messages should still show the alias name. Signed-off-by: Ran Benita <ran234@gmail.com>
2012-09-12 14:51:19 -06:00
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
assert(test_key_seq(keymap,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_LEFTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTALT, UP, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH));
assert(test_key_seq(keymap,
KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH));
/* Locked modifiers. */
assert(test_key_seq(keymap,
KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_H, BOTH, XKB_KEY_H, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_O, BOTH, XKB_KEY_O, FINISH));
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_E, BOTH, XKB_KEY_e, NEXT,
KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT,
KEY_E, BOTH, XKB_KEY_E, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_L, BOTH, XKB_KEY_L, NEXT,
KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT,
KEY_O, BOTH, XKB_KEY_O, FINISH));
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_E, BOTH, XKB_KEY_e, NEXT,
KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT,
KEY_L, BOTH, XKB_KEY_l, NEXT,
KEY_L, BOTH, XKB_KEY_l, NEXT,
KEY_O, BOTH, XKB_KEY_o, FINISH));
/*
* A key release affecting a locked modifier should clear it
* regardless of the key press.
*/
/* assert(test_key_seq(keymap, */
/* KEY_H, BOTH, XKB_KEY_h, NEXT, */
/* KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, */
/* KEY_E, BOTH, XKB_KEY_E, NEXT, */
/* KEY_L, BOTH, XKB_KEY_L, NEXT, */
/* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */
/* KEY_L, BOTH, XKB_KEY_L, NEXT, */
/* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */
/* KEY_O, BOTH, XKB_KEY_o, FINISH)); */
/* Simple Num Lock sanity check. */
assert(test_key_seq(keymap,
KEY_KP1, BOTH, XKB_KEY_KP_End, NEXT,
KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT,
KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT,
KEY_KP2, BOTH, XKB_KEY_KP_2, NEXT,
KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT,
KEY_KP2, BOTH, XKB_KEY_KP_Down, FINISH));
symbols: fix real/alias key merge ordering bug Background: The CopySymbolsDef has a comment on a couple of lines which supposedly fixed a bug: /* * kt_index[i] may have been set by a previous run (if we have two * layouts specified). Let's not overwrite it with the ONE_LEVEL * default group if we dont even have keys for this group anyway. * * FIXME: There should be a better fix for this. */ if (!darray_empty(groupi->levels)) key->kt_index[i] = types[i]; But neither the comment nor the fix make any sense, because the kt_index is indexed per group, i.e. each group gets its own type. The original xkbcomp commit which added this (36fecff58) points to this bug: https://bugzilla.redhat.com/show_bug.cgi?id=436626 which complains about -layout "ru,us" -variant "phonetic," not working properly. And indeed when we try: sudo ./test/interactive -l ru,us -v the first group doesn't get any syms for the main keys. The problem (Clearly the fix above is useless): The ru(phonetic) map is specified using aliases, e.g. LatQ, LatW instead of AD01, AD02, etc. When combined with another layout which uses the real names (AD01, AD02), the symbols code should recognize they are the same key and merge them into one KeyInfo. The current code does that, but it doesn't catch the case where the alias was processes *before* the real one; so we get two KeyInfo's and the later one wins. So e.g. the ru(phonetic) symbols are ignored. The fix: Before adding a new KeyInfo to the keys array, always replace its name by the real name, which avoids the entire issue. Luckily this is done pretty late so most error messages should still show the alias name. Signed-off-by: Ran Benita <ran234@gmail.com>
2012-09-12 14:51:19 -06:00
/* Test that the aliases in the ru(phonetic) symbols map work. */
assert(test_key_seq(keymap,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_1, BOTH, XKB_KEY_1, NEXT,
KEY_Q, BOTH, XKB_KEY_Cyrillic_ya, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_1, BOTH, XKB_KEY_exclam, NEXT,
KEY_Q, BOTH, XKB_KEY_Cyrillic_YA, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT,
KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_1, BOTH, XKB_KEY_1, NEXT,
KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, NEXT,
KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT,
KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT,
KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT,
KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, FINISH));
#define KS(name) xkb_keysym_from_name(name, 0)
/* Test that levels (1-5) in de(neo) symbols map work. */
assert(test_key_seq(keymap,
/* Switch to the group. */
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
/* Level 1. */
KEY_1, BOTH, XKB_KEY_1, NEXT,
KEY_Q, BOTH, XKB_KEY_x, NEXT,
KEY_KP7, BOTH, XKB_KEY_KP_7, NEXT,
KEY_ESC, BOTH, XKB_KEY_Escape, NEXT,
/* Level 2 with Shift. */
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_1, BOTH, XKB_KEY_degree, NEXT,
KEY_Q, BOTH, XKB_KEY_X, NEXT,
KEY_KP7, BOTH, KS("U2714"), NEXT,
KEY_ESC, BOTH, XKB_KEY_Escape, NEXT,
/*
* XXX: de(neo) uses shift(both_capslock) which causes
* the interesting result in the next line. Since it's
* a key release, it doesn't actually lock the modifier,
* and applications by-and-large ignore the keysym on
* release(?). Is this a problem?
*/
KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT,
/* Level 2 with the Lock modifier. */
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT,
KEY_6, BOTH, XKB_KEY_6, NEXT,
KEY_H, BOTH, XKB_KEY_S, NEXT,
KEY_KP3, BOTH, XKB_KEY_KP_3, NEXT,
KEY_ESC, BOTH, XKB_KEY_Escape, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT,
/* Level 3. */
KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT,
KEY_6, BOTH, XKB_KEY_cent, NEXT,
KEY_Q, BOTH, XKB_KEY_ellipsis, NEXT,
KEY_KP7, BOTH, KS("U2195"), NEXT,
KEY_ESC, BOTH, XKB_KEY_Escape, NEXT,
KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT,
/* Level 4. */
KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_5, BOTH, XKB_KEY_malesymbol, NEXT,
KEY_E, BOTH, XKB_KEY_Greek_lambda, NEXT,
KEY_SPACE, BOTH, XKB_KEY_nobreakspace, NEXT,
KEY_KP8, BOTH, XKB_KEY_intersection, NEXT,
KEY_ESC, BOTH, XKB_KEY_Escape, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT,
KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT,
/* Level 5. */
KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
/*
* XXX: This doesn't work, but gives level1 keysyms.
* This does work when when de(neo) is the first layout
* (before us,il etc.). It's like that in the X server
* as well. Investigate.
*/
KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT,
KEY_V, BOTH, XKB_KEY_p, FINISH));
xkb_keymap_unref(keymap);
assert(ctx);
keymap = test_compile_rules(ctx, "evdev", "", "us,il,ru", "",
"grp:alt_shift_toggle_bidir,grp:menu_toggle");
assert(keymap);
assert(test_key_seq(keymap,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_LEFTALT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTALT, UP, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH));
assert(test_key_seq(keymap,
KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH));
/* Check backwards (negative) group switching and wrapping. */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT,
KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT,
KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT,
KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_H, BOTH, XKB_KEY_h, FINISH));
xkb_keymap_unref(keymap);
assert(ctx);
keymap = test_compile_rules(ctx, "evdev", "", "us,il,ru", "",
"grp:switch,grp:lswitch,grp:menu_toggle");
assert(keymap);
/* Test depressed group works (Mode_switch). */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT,
KEY_H, BOTH, XKB_KEY_h, FINISH));
/* Test locked+depressed group works, with wrapping and accumulation. */
assert(test_key_seq(keymap,
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT,
KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
/* Should wrap back to first group. */
KEY_H, BOTH, XKB_KEY_h, NEXT,
KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT,
KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT,
KEY_H, BOTH, XKB_KEY_h, NEXT,
/* Two SetGroup(+1)'s should add up. */
KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT,
KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT,
KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT,
KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT,
KEY_H, BOTH, XKB_KEY_h, FINISH));
xkb_keymap_unref(keymap);
xkb_context_unref(ctx);
return 0;
}