Initialize keyboard in registry poll

This commit is contained in:
Drew DeVault 2015-12-10 18:34:12 -05:00
parent 266393a705
commit a7710c5537
3 changed files with 128 additions and 0 deletions

View file

@ -2,16 +2,70 @@
#define _SWAY_CLIENT_REGISTRY_H
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include "wayland-desktop-shell-client-protocol.h"
#include "wayland-swaylock-client-protocol.h"
#include "list.h"
enum mod_bit {
MOD_SHIFT = 1<<0,
MOD_CAPS = 1<<1,
MOD_CTRL = 1<<2,
MOD_ALT = 1<<3,
MOD_MOD2 = 1<<4,
MOD_MOD3 = 1<<5,
MOD_LOGO = 1<<6,
MOD_MOD5 = 1<<7,
};
enum mask {
MASK_SHIFT,
MASK_CAPS,
MASK_CTRL,
MASK_ALT,
MASK_MOD2,
MASK_MOD3,
MASK_LOGO,
MASK_MOD5,
MASK_LAST
};
struct output_state {
struct wl_output *output;
uint32_t flags;
uint32_t width, height;
};
struct xkb {
struct xkb_state *state;
struct xkb_context *context;
struct xkb_keymap *keymap;
xkb_mod_mask_t masks[MASK_LAST];
};
struct input {
int *repeat_fd;
struct xkb xkb;
xkb_keysym_t sym;
uint32_t code;
uint32_t last_code;
uint32_t modifiers;
xkb_keysym_t repeat_sym;
uint32_t repeat_key;
int32_t repeat_rate_sec;
int32_t repeat_rate_nsec;
int32_t repeat_delay_sec;
int32_t repeat_delay_nsec;
struct {
void (*key)(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code);
} notify;
};
struct registry {
struct wl_compositor *compositor;
struct wl_display *display;
@ -22,6 +76,7 @@ struct registry {
struct wl_shm *shm;
struct desktop_shell *desktop_shell;
struct lock *swaylock;
struct input *input;
list_t *outputs;
};

View file

@ -2,6 +2,7 @@ include_directories(
${PROTOCOLS_INCLUDE_DIRS}
${PANGO_INCLUDE_DIRS}
${GDK_PIXBUF_INCLUDE_DIRS}
${XKBCOMMON_INCLUDE_DIRS}
)
add_library(sway-wayland
@ -17,4 +18,5 @@ target_link_libraries(sway-wayland
sway-protocols
${PANGO_LIBRARIES}
${GDK_PIXBUF_LIBRARIES}
${XKBCOMMON_LIBRARIES}
)

View file

@ -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) {