diff options
Diffstat (limited to 'wayland/registry.c')
-rw-r--r-- | wayland/registry.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/wayland/registry.c b/wayland/registry.c index 883c69d3..45735ccd 100644 --- a/wayland/registry.c +++ b/wayland/registry.c @@ -1,6 +1,10 @@ #include <wayland-client.h> +#include <xkbcommon/xkbcommon.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/timerfd.h> #include "wayland-desktop-shell-client-protocol.h" #include "wayland-swaylock-client-protocol.h" #include "client/registry.h" @@ -38,8 +42,73 @@ static const struct wl_output_listener output_listener = { .scale = display_handle_scale }; +const char *XKB_MASK_NAMES[MASK_LAST] = { + XKB_MOD_NAME_SHIFT, + XKB_MOD_NAME_CAPS, + XKB_MOD_NAME_CTRL, + XKB_MOD_NAME_ALT, + "Mod2", + "Mod3", + XKB_MOD_NAME_LOGO, + "Mod5", +}; + +const enum mod_bit XKB_MODS[MASK_LAST] = { + MOD_SHIFT, + MOD_CAPS, + MOD_CTRL, + MOD_ALT, + MOD_MOD2, + MOD_MOD3, + MOD_LOGO, + MOD_MOD5 +}; + static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { + // Keyboard errors are abort-worthy because you wouldn't be able to unlock your screen otherwise. + + struct registry *registry = data; + if (!data) { + close(fd); + return; + } + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + sway_abort("Unknown keymap format %d, aborting", format); + } + + char *map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + sway_abort("Unable to initialized shared keyboard memory, aborting"); + } + + struct xkb_keymap *keymap = xkb_keymap_new_from_string(registry->input->xkb.context, + map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_str, size); + close(fd); + + if (!keymap) { + sway_abort("Failed to compile keymap, aborting"); + } + + struct xkb_state *state = xkb_state_new(keymap); + if (!state) { + xkb_keymap_unref(keymap); + sway_abort("Failed to create xkb state, aborting"); + } + + xkb_keymap_unref(registry->input->xkb.keymap); + xkb_state_unref(registry->input->xkb.state); + registry->input->xkb.keymap = keymap; + registry->input->xkb.state = state; + + int i; + for (i = 0; i < MASK_LAST; ++i) { + registry->input->xkb.masks[i] = 1 << xkb_keymap_mod_get_index(registry->input->xkb.keymap, XKB_MASK_NAMES[i]); + } } static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, @@ -115,6 +184,8 @@ struct registry *registry_poll(void) { struct registry *registry = malloc(sizeof(struct registry)); memset(registry, 0, sizeof(struct registry)); registry->outputs = create_list(); + registry->input = calloc(sizeof(struct input), 1); + registry->input->xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); registry->display = wl_display_connect(NULL); if (!registry->display) { |