From b84d59403fa8649817e84c486e701508f191c949 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 23 Sep 2017 18:32:03 -0400 Subject: [PATCH] Initial keyboard support in rootston --- include/rootston/input.h | 7 ++- rootston/input.c | 2 +- rootston/keyboard.c | 92 ++++++++++++++++++++++++++++++++++++++++ rootston/meson.build | 1 + 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 rootston/keyboard.c diff --git a/include/rootston/input.h b/include/rootston/input.h index 4ac11959..ec1cd32d 100644 --- a/include/rootston/input.h +++ b/include/rootston/input.h @@ -25,10 +25,8 @@ struct roots_keyboard { struct roots_pointer { struct roots_input *input; struct wlr_input_device *device; - struct wl_listener motion; - struct wl_listener motion_absolute; - struct wl_listener button; - struct wl_listener axis; + // We don't listen to any pointer events directly - they go through + // wlr_cursor struct wl_list link; }; @@ -104,6 +102,7 @@ struct roots_input *input_create(struct roots_server *server, void input_destroy(struct roots_input *input); void pointer_add(struct wlr_input_device *device, struct roots_input *input); +void keyboard_add(struct wlr_input_device *device, struct roots_input *input); void cursor_initialize(struct roots_input *input); void cursor_load_config(struct roots_config *config, diff --git a/rootston/input.c b/rootston/input.c index 4925226a..ac8e7396 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -31,7 +31,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { device->vendor, device->product, device_type(device->type)); switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD: - //keyboard_add(device, input); + keyboard_add(device, input); break; case WLR_INPUT_DEVICE_POINTER: pointer_add(device, input); diff --git a/rootston/keyboard.c b/rootston/keyboard.c new file mode 100644 index 00000000..54ae3f8f --- /dev/null +++ b/rootston/keyboard.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rootston/input.h" + +static void keyboard_led_update(struct roots_keyboard *keyboard) { + uint32_t leds = 0; + for (uint32_t i = 0; i < WLR_LED_LAST; ++i) { + if (xkb_state_led_index_is_active( + keyboard->xkb_state, keyboard->leds[i])) { + leds |= (1 << i); + } + } + wlr_keyboard_led_update(keyboard->device->keyboard, leds); +} + +static void keyboard_key_notify(struct wl_listener *listener, void *data) { + struct wlr_event_keyboard_key *event = data; + struct roots_keyboard *keyboard = wl_container_of(listener, keyboard, key); + struct roots_input *input = keyboard->input; + struct roots_server *server = input->server; + uint32_t keycode = event->keycode + 8; + enum wlr_key_state key_state = event->state; + const xkb_keysym_t *syms; + int nsyms = xkb_state_key_get_syms(keyboard->xkb_state, keycode, &syms); + xkb_state_update_key(keyboard->xkb_state, keycode, + event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); + keyboard_led_update(keyboard); + for (int i = 0; i < nsyms; ++i) { + xkb_keysym_t sym = syms[i]; + char name[64]; + int l = xkb_keysym_get_name(sym, name, sizeof(name)); + if (l != -1 && l != sizeof(name)) { + wlr_log(L_DEBUG, "Key event: %s %s", name, + key_state == WLR_KEY_PRESSED ? "pressed" : "released"); + } + // TODO: pass key to clients + if (sym == XKB_KEY_Escape) { + // TEMPORARY, probably + wl_display_terminate(server->wl_display); + } else if (key_state == WLR_KEY_PRESSED && + sym >= XKB_KEY_XF86Switch_VT_1 && + sym <= XKB_KEY_XF86Switch_VT_12) { + if (wlr_backend_is_multi(server->backend)) { + struct wlr_session *session = + wlr_multi_get_session(server->backend); + if (session) { + wlr_session_change_vt(session, sym - XKB_KEY_XF86Switch_VT_1 + 1); + } + } + } + } +} + +void keyboard_add(struct wlr_input_device *device, struct roots_input *input) { + struct roots_keyboard *keyboard = calloc(sizeof(struct roots_keyboard), 1); + keyboard->device = device; + keyboard->input = input; + wl_list_init(&keyboard->key.link); + keyboard->key.notify = keyboard_key_notify; + wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_list_insert(&input->keyboards, &keyboard->link); + + struct xkb_rule_names rules; + memset(&rules, 0, sizeof(rules)); + rules.rules = getenv("XKB_DEFAULT_RULES"); + rules.model = getenv("XKB_DEFAULT_MODEL"); + rules.layout = getenv("XKB_DEFAULT_LAYOUT"); + rules.variant = getenv("XKB_DEFAULT_VARIANT"); + rules.options = getenv("XKB_DEFAULT_OPTIONS"); + struct xkb_context *context; + assert(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS)); + assert(keyboard->keymap = xkb_map_new_from_names(context, &rules, + XKB_KEYMAP_COMPILE_NO_FLAGS)); + xkb_context_unref(context); + assert(keyboard->xkb_state = xkb_state_new(keyboard->keymap)); + const char *led_names[3] = { + XKB_LED_NAME_NUM, + XKB_LED_NAME_CAPS, + XKB_LED_NAME_SCROLL + }; + for (uint32_t i = 0; i < 3; ++i) { + keyboard->leds[i] = xkb_map_led_get_index(keyboard->keymap, led_names[i]); + } +} diff --git a/rootston/meson.build b/rootston/meson.build index 7c0a7f8a..30ae1548 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -5,6 +5,7 @@ executable( 'desktop.c', 'ini.c', 'input.c', + 'keyboard.c', 'main.c', 'output.c', 'pointer.c',