#include #include #include #include #include #include #include #include #include static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) { struct keyboard_data *kbd = data; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; } char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (map_str == MAP_FAILED) { close(fd); return; } kbd->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); kbd->xkb_keymap = xkb_keymap_new_from_string( kbd->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); kbd->xkb_state = xkb_state_new(kbd->xkb_keymap); munmap(map_str, size); close(fd); } static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { printf("keyboard_enter\n"); } static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { printf("keyboard_leave\n"); } static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { struct keyboard_data *kbd = data; xkb_keysym_t sym = XKB_KEY_NoSymbol; if (kbd->xkb_state != NULL) { // Wayland keycodes are Linux evdev scancodes; // xkbcommon expects keycodes offset by 8. sym = xkb_state_key_get_one_sym(kbd->xkb_state, key + 8); } printf("keyboard_key: scancode=%d state=%d keysym=%u\n", key, state, sym); uint32_t mods = 0; if (kbd->xkb_state != NULL && kbd->xkb_keymap != NULL) { xkb_mod_index_t ci = xkb_keymap_mod_get_index(kbd->xkb_keymap, "Control"); if (ci != XKB_MOD_INVALID && xkb_state_mod_index_is_active(kbd->xkb_state, ci, XKB_STATE_MODS_EFFECTIVE)) mods |= MOD_CTRL; xkb_mod_index_t si = xkb_keymap_mod_get_index(kbd->xkb_keymap, "Shift"); if (si != XKB_MOD_INVALID && xkb_state_mod_index_is_active(kbd->xkb_state, si, XKB_STATE_MODS_EFFECTIVE)) mods |= MOD_SHIFT; xkb_mod_index_t ai = xkb_keymap_mod_get_index(kbd->xkb_keymap, "Mod1"); if (ai != XKB_MOD_INVALID && xkb_state_mod_index_is_active(kbd->xkb_state, ai, XKB_STATE_MODS_EFFECTIVE)) mods |= MOD_ALT; xkb_mod_index_t sui = xkb_keymap_mod_get_index(kbd->xkb_keymap, "Mod4"); if (sui != XKB_MOD_INVALID && xkb_state_mod_index_is_active(kbd->xkb_state, sui, XKB_STATE_MODS_EFFECTIVE)) mods |= MOD_SUPER; } if (kbd->handler != NULL) { kbd->handler(key, state, sym, mods, kbd->user_data); } } static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { struct keyboard_data *kbd = data; if (kbd->xkb_state != NULL) { xkb_state_update_mask(kbd->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); } } static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay) { // not implemented } const struct wl_keyboard_listener keyboard_listener = { .keymap = keyboard_keymap, .enter = keyboard_enter, .leave = keyboard_leave, .key = keyboard_key, .modifiers = keyboard_modifiers, .repeat_info = keyboard_repeat_info}; void keyboard_set_handler(struct keyboard_data *kbd, keyboard_key_handler_t handler, void *user_data) { kbd->handler = handler; kbd->user_data = user_data; }