/** Handle keypress event. * \param L Lua stack to push the key pressed. * \param e Received XKeyEvent. * \return True if a key was successfully retrieved, false otherwise. */ bool keygrabber_handlekpress(lua_State *L, xcb_key_press_event_t *e) { /* convert keysym to string */ char buf[MAX(MB_LEN_MAX, 32)]; /* snprintf-like return value could be used here, but that should not be * necessary, as we have buffer big enough */ xkb_state_key_get_utf8(globalconf.xkb_state, e->detail, buf, countof(buf) ); if (is_control(buf)) { /* Use text names for control characters, ignoring all modifiers. */ xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, e->detail, 0); xkb_keysym_get_name(keysym, buf, countof(buf)); } luaA_pushmodifiers(L, e->state); lua_pushstring(L, buf); switch(e->response_type) { case XCB_KEY_PRESS: lua_pushliteral(L, "press"); break; case XCB_KEY_RELEASE: lua_pushliteral(L, "release"); break; } return true; }
static bool handle_key_press(Keyboard *keyboard, xkb_keycode_t keycode, char *password, char **password_cursor) { xkb_keysym_t keysym = xkb_state_key_get_one_sym(keyboard->state, keycode); enum xkb_compose_status status = XKB_COMPOSE_NOTHING; if (xkb_compose_state_feed(keyboard->compose_state, keysym) == XKB_COMPOSE_FEED_ACCEPTED) { status = xkb_compose_state_get_status(keyboard->compose_state); if (status == XKB_COMPOSE_COMPOSED) { keysym = xkb_compose_state_get_one_sym(keyboard->compose_state); } else if (status == XKB_COMPOSE_COMPOSING || status == XKB_COMPOSE_CANCELLED) { return false; } } if (keysym == XKB_KEY_Return) { return true; } else if (keysym == XKB_KEY_Escape) { running = false; return false; } else if (keysym == XKB_KEY_BackSpace) { if (*password_cursor != &password[0]) { while ((*(--(*password_cursor)) & 0xc0) == 0x80); **password_cursor = '\0'; } return false; } char buffer[16] = { '\0' }; int len; if (status == XKB_COMPOSE_COMPOSED) { len = xkb_compose_state_get_utf8(keyboard->compose_state, buffer, sizeof(buffer)); } else { len = xkb_state_key_get_utf8(keyboard->state, keycode, buffer, sizeof(buffer)); } if (len < 1) { return false; } memcpy(*password_cursor, buffer, len + 1); *password_cursor += len; return false; }
static void test_get_utf8_utf32(struct xkb_keymap *keymap) { char buf[256]; struct xkb_state *state = xkb_state_new(keymap); assert(state); #define TEST_KEY(key, expected_utf8, expected_utf32) do { \ assert(xkb_state_key_get_utf8(state, key + 8, NULL, 0) == strlen(expected_utf8)); \ assert(xkb_state_key_get_utf8(state, key + 8, buf, sizeof(buf)) == strlen(expected_utf8)); \ assert(memcmp(buf, expected_utf8, sizeof(expected_utf8)) == 0); \ assert(xkb_state_key_get_utf32(state, key + 8) == expected_utf32); \ } while (0) /* Simple ASCII. */ TEST_KEY(KEY_A, "a", 0x61); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); /* Invalid. */ TEST_KEY(XKB_KEYCODE_INVALID - 8, "", 0); TEST_KEY(300, "", 0); /* No string. */ TEST_KEY(KEY_LEFTCTRL, "", 0); TEST_KEY(KEY_NUMLOCK, "", 0); /* Multiple keysyms. */ TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); /* Check truncation. */ memset(buf, 'X', sizeof(buf)); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 0) == strlen("HELLO")); assert(memcmp(buf, "X", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 1) == strlen("HELLO")); assert(memcmp(buf, "", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 2) == strlen("HELLO")); assert(memcmp(buf, "H", 2) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 3) == strlen("HELLO")); assert(memcmp(buf, "HE", 3) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 5) == strlen("HELLO")); assert(memcmp(buf, "HELL", 5) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 6) == strlen("HELLO")); assert(memcmp(buf, "HELLO", 6) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 7) == strlen("HELLO")); assert(memcmp(buf, "HELLO\0X", 7) == 0); /* Switch to ru layout */ 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_key_get_layout(state, KEY_A + 8) == 1); /* Non ASCII. */ TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_A, "ф", 0x0444); TEST_KEY(KEY_Z, "я", 0x044F); /* Switch back to us layout */ 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_key_get_layout(state, KEY_A + 8) == 0); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); TEST_KEY(KEY_A, "A", 0x41); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "!", 0x21); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); xkb_state_unref(state); }