static void print_keycode(struct keyboard *kbd, xkb_keycode_t keycode) { unsigned int i; struct xkb_keymap *keymap; struct xkb_state *state; const xkb_keysym_t *syms; unsigned int nsyms; char s[16]; uint32_t unicode; xkb_layout_index_t layout; xkb_mod_index_t mod; xkb_led_index_t led; state = kbd->state; keymap = xkb_state_get_keymap(state); nsyms = xkb_state_key_get_syms(state, keycode, &syms); if (nsyms <= 0) return; printf("keysyms [ "); for (i = 0; i < nsyms; i++) { xkb_keysym_get_name(syms[i], s, sizeof(s)); printf("%-*s ", (int)sizeof(s), s); } printf("] "); /* * Only do this if wchar_t is UCS-4, so we can be lazy and print * with %lc. */ #ifdef __STDC_ISO_10646__ printf("unicode [ "); for (i = 0; i < nsyms; i++) { unicode = xkb_keysym_to_utf32(syms[i]); printf("%lc ", (int)(unicode ? unicode : L' ')); } printf("] "); #endif layout = xkb_state_key_get_layout(state, keycode); printf("layout [ %s (%d) ] ", xkb_keymap_layout_get_name(keymap, layout), layout); printf("level [ %d ] ", xkb_state_key_get_level(state, keycode, layout)); printf("mods [ "); for (mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { if (xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE) <= 0) continue; if (xkb_state_mod_index_is_consumed(state, keycode, mod)) printf("-%s ", xkb_keymap_mod_get_name(keymap, mod)); else printf("%s ", xkb_keymap_mod_get_name(keymap, mod)); } printf("] "); printf("leds [ "); for (led = 0; led < xkb_keymap_num_leds(keymap); led++) { if (xkb_state_led_index_is_active(state, led) <= 0) continue; printf("%s ", xkb_keymap_led_get_name(keymap, led)); } printf("] "); printf("\n"); }
static void input_method_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w) { struct simple_im *keyboard = data; uint32_t code; uint32_t num_syms; const xkb_keysym_t *syms; xkb_keysym_t sym; enum wl_keyboard_key_state state = state_w; if (!keyboard->state) return; code = key + 8; num_syms = xkb_state_key_get_syms(keyboard->state, code, &syms); sym = XKB_KEY_NoSymbol; if (num_syms == 1) sym = syms[0]; if (keyboard->key_handler) (*keyboard->key_handler)(keyboard, serial, time, key, sym, state); }
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) { uint32_t code, numSyms; long cp; const xkb_keysym_t *syms; xkb_keysym_t sym; code = key + 8; numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms); if (numSyms == 1) { #ifdef HAVE_XKBCOMMON_COMPOSE_H sym = composeSymbol(syms[0]); #else sym = syms[0]; #endif cp = _glfwKeySym2Unicode(sym); if (cp != -1) { const int mods = _glfw.wl.xkb.modifiers; const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); _glfwInputChar(window, cp, mods, plain); } } return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]); }
static void uxkb_dev_repeat(struct uterm_input_dev *dev, unsigned int state) { struct xkb_keymap *keymap = xkb_state_get_keymap(dev->state); unsigned int i; int num_keysyms, ret; const uint32_t *keysyms; struct itimerspec spec; if (dev->repeating && dev->repeat_event.keycode == dev->event.keycode) { if (state == KEY_RELEASED) { dev->repeating = false; ev_timer_update(dev->repeat_timer, NULL); } return; } if (state == KEY_PRESSED && xkb_keymap_key_repeats(keymap, dev->event.keycode)) { dev->repeat_event.keycode = dev->event.keycode; dev->repeat_event.ascii = dev->event.ascii; dev->repeat_event.mods = dev->event.mods; dev->repeat_event.num_syms = dev->event.num_syms; for (i = 0; i < dev->event.num_syms; ++i) { dev->repeat_event.keysyms[i] = dev->event.keysyms[i]; dev->repeat_event.codepoints[i] = dev->event.codepoints[i]; } } else if (dev->repeating && !xkb_keymap_key_repeats(keymap, dev->event.keycode)) { num_keysyms = xkb_state_key_get_syms(dev->state, dev->repeat_event.keycode, &keysyms); if (num_keysyms <= 0) return; ret = uxkb_dev_fill_event(dev, &dev->repeat_event, dev->repeat_event.keycode, num_keysyms, keysyms); if (ret) return; return; } else { return; } dev->repeating = true; spec.it_interval.tv_sec = 0; spec.it_interval.tv_nsec = dev->input->repeat_rate * 1000000; spec.it_value.tv_sec = 0; spec.it_value.tv_nsec = dev->input->repeat_delay * 1000000; ev_timer_update(dev->repeat_timer, &spec); }
static void fghKeyboardKey( void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state ) { SFG_PlatformDisplay* pDisplay = data; SFG_Window* win = fgStructure.CurrentWindow; const xkb_keysym_t* syms; xkb_state_key_get_syms( pDisplay->xkb_state, key + 8, &syms ); fghKeyboardInterpretKeysym( win, key, syms[0], state ); }
/* FIXME: Don't handle composed and dead-keys properly. * Waiting for support in libxkbcommon ... */ int handle_xkb(int code, int value) { unsigned i; const xkb_keysym_t *syms = NULL; unsigned num_syms = 0; uint16_t mod = 0; /* Convert Linux evdev to X11 (xkbcommon docs say so at least ...) */ int xk_code = code + 8; if (!xkb_state) return -1; if (value == 2) /* Repeat, release first explicitly. */ xkb_state_update_key(xkb_state, xk_code, XKB_KEY_UP); if (value) num_syms = xkb_state_key_get_syms(xkb_state, xk_code, &syms); if (value > 0) xkb_state_update_key(xkb_state, xk_code, XKB_KEY_DOWN); else xkb_state_update_key(xkb_state, xk_code, XKB_KEY_UP); if (!syms) return -1; /* Build mod state. */ for (i = 0; i < MOD_MAP_SIZE; i++) { xkb_mod_index_t *map_idx = (xkb_mod_index_t*)&mod_map_idx[i]; uint16_t *map_bit = (uint16_t *)&mod_map_bit[i]; if (*map_idx != XKB_MOD_INVALID) mod |= xkb_state_mod_index_is_active( xkb_state, *map_idx, (enum xkb_state_component) ((XKB_STATE_MODS_EFFECTIVE) > 0)) ? *map_bit : 0; } input_keyboard_event(value, input_keymaps_translate_keysym_to_rk(code), num_syms ? xkb_keysym_to_utf32(syms[0]) : 0, mod, RETRO_DEVICE_KEYBOARD); for (i = 1; i < num_syms; i++) input_keyboard_event(value, RETROK_UNKNOWN, xkb_keysym_to_utf32(syms[i]), mod, RETRO_DEVICE_KEYBOARD); return 0; }
int uxkb_dev_process(struct uterm_input_dev *dev, uint16_t key_state, uint16_t code) { struct xkb_state *state; xkb_keycode_t keycode; const xkb_keysym_t *keysyms; int num_keysyms, ret; enum xkb_state_component changed; if (key_state == KEY_REPEATED) return -ENOKEY; state = dev->state; keycode = code + EVDEV_KEYCODE_OFFSET; num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms); changed = 0; if (key_state == KEY_PRESSED) changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN); else if (key_state == KEY_RELEASED) changed = xkb_state_update_key(state, keycode, XKB_KEY_UP); if (changed & XKB_STATE_LEDS) uxkb_dev_update_keyboard_leds(dev); if (num_keysyms <= 0) return -ENOKEY; ret = uxkb_dev_fill_event(dev, &dev->event, keycode, num_keysyms, keysyms); if (ret) return -ENOKEY; uxkb_dev_repeat(dev, key_state); if (key_state == KEY_RELEASED) return -ENOKEY; dev->event.handled = false; shl_hook_call(dev->input->hook, dev->input, &dev->event); return 0; }
static void inputChar(_GLFWwindow* window, uint32_t key) { uint32_t code, numSyms; long cp; const xkb_keysym_t *syms; code = key + 8; numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms); if (numSyms == 1) { cp = _glfwKeySym2Unicode(syms[0]); if (cp != -1) { const int mods = _glfw.wl.xkb.modifiers; const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); _glfwInputChar(window, cp, mods, plain); } } }
static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) { struct input_event *ev = &data->evdev.event; enum xkb_state_component compch; enum xkb_compose_status cstatus; const xkb_keysym_t *keysyms; idev_device *d = &k->device; int num, r; if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN) return 0; /* TODO: We should audit xkb-actions, whether they need @resync as * flag. Most actions should just be executed, however, there might * be actions that depend on modifier-orders. Those should be * suppressed. */ num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms); compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value); if (compch & XKB_STATE_LEDS) { /* TODO: update LEDs */ } if (num < 0) { r = num; goto error; } if (k->xkb_compose && ev->value == KBDKEY_DOWN) { if (num == 1 && !data->resync) { xkb_compose_state_feed(k->xkb_compose, keysyms[0]); cstatus = xkb_compose_state_get_status(k->xkb_compose); } else { cstatus = XKB_COMPOSE_CANCELLED; } switch (cstatus) { case XKB_COMPOSE_NOTHING: /* keep produced keysyms and forward unchanged */ break; case XKB_COMPOSE_COMPOSING: /* consumed by compose-state, drop keysym */ keysyms = NULL; num = 0; break; case XKB_COMPOSE_COMPOSED: /* compose-state produced sth, replace keysym */ num = keyboard_read_compose(k, &keysyms); xkb_compose_state_reset(k->xkb_compose); break; case XKB_COMPOSE_CANCELLED: /* canceled compose, reset, forward cancellation sym */ xkb_compose_state_reset(k->xkb_compose); break; } } else if (k->xkb_compose && num == 1 && keysyms[0] == XKB_KEY_Multi_key && !data->resync && ev->value == KBDKEY_UP) { /* Reset compose state on Multi-Key UP events. This effectively * requires you to hold the key during the whole sequence. I * think it's pretty handy to avoid accidental * Compose-sequences, but this may break Compose for disabled * people. We really need to make this opional! (TODO) */ xkb_compose_state_reset(k->xkb_compose); } if (ev->value == KBDKEY_UP) { /* never produce keysyms for UP */ keysyms = NULL; num = 0; } r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms); if (r < 0) goto error; keyboard_repeat(k); return keyboard_raise_data(k, &k->evdata); error: log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m", d->session->name, d->name); k->repeating = false; keyboard_arm(k, 0); return 0; }
static void keyboard_repeat(idev_keyboard *k) { idev_data *evdata = &k->evdata; idev_data *repdata = &k->repdata; idev_data_keyboard *evkbd = &evdata->keyboard; idev_data_keyboard *repkbd = &repdata->keyboard; const xkb_keysym_t *keysyms; idev_device *d = &k->device; bool repeats; int r, num; if (evdata->resync) { /* * We received a re-sync event. During re-sync, any number of * key-events may have been lost and sync-events may be * re-ordered. Always disable key-repeat for those events. Any * following event will trigger it again. */ k->repeating = false; keyboard_arm(k, 0); return; } repeats = xkb_keymap_key_repeats(k->kbdmap->xkb_keymap, evkbd->keycode + KBDXKB_SHIFT); if (k->repeating && repkbd->keycode == evkbd->keycode) { /* * We received an event for the key we currently repeat. If it * was released, stop key-repeat. Otherwise, ignore the event. */ if (evkbd->value == KBDKEY_UP) { k->repeating = false; keyboard_arm(k, 0); } } else if (evkbd->value == KBDKEY_DOWN && repeats) { /* * We received a key-down event for a key that repeats. The * previous condition caught keys we already repeat, so we know * this is a different key or no key-repeat is running. Start * new key-repeat. */ errno = 0; num = xkb_state_key_get_syms(k->xkb_state, evkbd->keycode + KBDXKB_SHIFT, &keysyms); if (num < 0) r = errno > 0 ? errno : -EFAULT; else r = keyboard_fill(k, repdata, false, evkbd->keycode, KBDKEY_REPEAT, num, keysyms); if (r < 0) { log_debug_errno(r, "idev-keyboard: %s/%s: cannot set key-repeat: %m", d->session->name, d->name); k->repeating = false; keyboard_arm(k, 0); } else { k->repeating = true; keyboard_arm(k, k->repeat_delay); } } else if (k->repeating && !repeats) { /* * We received an event for a key that does not repeat, but we * currently repeat a previously received key. The new key is * usually a modifier, but might be any kind of key. In this * case, we continue repeating the old key, but update the * symbols according to the new state. */ errno = 0; num = xkb_state_key_get_syms(k->xkb_state, repkbd->keycode + KBDXKB_SHIFT, &keysyms); if (num < 0) r = errno > 0 ? errno : -EFAULT; else r = keyboard_fill(k, repdata, false, repkbd->keycode, KBDKEY_REPEAT, num, keysyms); if (r < 0) { log_debug_errno(r, "idev-keyboard: %s/%s: cannot update key-repeat: %m", d->session->name, d->name); k->repeating = false; keyboard_arm(k, 0); } } }
/* * 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. */ int test_key_seq_va(struct xkb_keymap *keymap, va_list ap) { struct xkb_state *state; xkb_keycode_t kc; int op; xkb_keysym_t keysym; const xkb_keysym_t *syms; xkb_keysym_t sym; unsigned int nsyms, i; char ksbuf[64]; fprintf(stderr, "----\n"); state = xkb_state_new(keymap); assert(state); for (;;) { kc = va_arg(ap, int) + EVDEV_OFFSET; op = va_arg(ap, int); nsyms = xkb_state_key_get_syms(state, kc, &syms); if (nsyms == 1) { sym = xkb_state_key_get_one_sym(state, kc); syms = &sym; } fprintf(stderr, "got %u syms for keycode %u: [", 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; } } if (nsyms == 0) { keysym = va_arg(ap, int); if (keysym != XKB_KEY_NoSymbol) { xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf)); fprintf(stderr, "Expected %s, but got no keysyms.\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; }
static void test_caps_keysym_transformation(struct xkb_keymap *keymap) { struct xkb_state *state = xkb_state_new(keymap); xkb_mod_index_t caps, shift; int nsyms; xkb_keysym_t sym; const xkb_keysym_t *syms; assert(state); /* See xkb_state_key_get_one_sym() for what's this all about. */ caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); assert(caps != XKB_MOD_INVALID && shift != XKB_MOD_INVALID); assert(xkb_state_key_get_layout(state, KEY_A + 8) == 0); assert(xkb_state_key_get_layout(state, KEY_SEMICOLON + 8) == 0); /* Without caps, no transformation. */ assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_A + 8); assert(sym == XKB_KEY_a); assert(xkb_state_key_get_level(state, KEY_SEMICOLON + 8, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); assert(sym == XKB_KEY_eacute); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_eacute); /* With shift, no transformation (only different level). */ xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) > 0); assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 1); sym = xkb_state_key_get_one_sym(state, KEY_A + 8); assert(sym == XKB_KEY_A); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); assert(sym == XKB_KEY_odiaeresis); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_odiaeresis); xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); /* With caps, transform in same level, only with _get_one_sym(). */ xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_key_get_level(state, KEY_A + 8, 0) == 1); sym = xkb_state_key_get_one_sym(state, KEY_A + 8); assert(sym == XKB_KEY_A); assert(xkb_state_key_get_level(state, KEY_SEMICOLON + 8, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + 8); assert(sym == XKB_KEY_Eacute); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + 8, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_eacute); xkb_state_update_key(state, KEY_LEFTSHIFT + 8, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + 8, XKB_KEY_UP); xkb_state_unref(state); }
static void test_update_key(struct xkb_keymap *keymap) { struct xkb_state *state = xkb_state_new(keymap); const xkb_keysym_t *syms; xkb_keysym_t one_sym; int num_syms; assert(state); /* LCtrl down */ xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); fprintf(stderr, "dumping state for LCtrl down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED) > 0); /* LCtrl + RAlt down */ xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_DOWN); fprintf(stderr, "dumping state for LCtrl + RAlt down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED) > 0); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, NULL) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL), xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT), XKB_MOD_INVALID) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_ALT, NULL) == 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, XKB_MOD_NAME_ALT, NULL) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE), XKB_MOD_NAME_ALT, NULL) > 0); /* RAlt down */ xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for RAlt down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ANY, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, NULL) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_LATCHED, XKB_STATE_MATCH_ANY, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, NULL) == 0); /* none down */ xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) == 0); /* Caps locked */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_DEPRESSED) > 0); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for Caps Lock:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_DEPRESSED) == 0); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED) > 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) > 0); num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_Q); /* Num Lock locked */ xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for Caps Lock + Num Lock:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED) > 0); assert(xkb_state_mod_name_is_active(state, "Mod2", XKB_STATE_MODS_LOCKED) > 0); num_syms = xkb_state_key_get_syms(state, KEY_KP1 + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_KP_1); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0); /* Num Lock unlocked */ xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); /* Switch to group 2 */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_led_name_is_active(state, "Group 2") > 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) == 0); /* Switch back to group 1. */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); /* Caps unlocked */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) == 0); num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_q); /* Multiple symbols */ num_syms = xkb_state_key_get_syms(state, KEY_6 + EVDEV_OFFSET, &syms); assert(num_syms == 5 && syms[0] == XKB_KEY_H && syms[1] == XKB_KEY_E && syms[2] == XKB_KEY_L && syms[3] == XKB_KEY_L && syms[4] == XKB_KEY_O); one_sym = xkb_state_key_get_one_sym(state, KEY_6 + EVDEV_OFFSET); assert(one_sym == XKB_KEY_NoSymbol); xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_UP); one_sym = xkb_state_key_get_one_sym(state, KEY_5 + EVDEV_OFFSET); assert(one_sym == XKB_KEY_5); xkb_state_unref(state); }