From 94adf6cb9e14b91cd98db0174f6a1fbe375b1184 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 25 Jun 2010 16:50:05 -0400 Subject: [PATCH] Use libxkbcommon for mapping keycodes to keysyms --- clients/terminal.c | 46 +++++++++++++--- clients/window.c | 153 +++++++++++++++-------------------------------------- clients/window.h | 4 +- configure.ac | 2 +- 4 files changed, 85 insertions(+), 120 deletions(-) diff --git a/clients/terminal.c b/clients/terminal.c index 162dfe8..e7e054b 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -32,9 +32,10 @@ #include #include #include -#include #include +#include + #include "wayland-util.h" #include "wayland-client.h" #include "wayland-glib.h" @@ -387,25 +388,56 @@ terminal_data(struct terminal *terminal, const char *data, size_t length) } static void -key_handler(struct window *window, uint32_t key, uint32_t unicode, +key_handler(struct window *window, uint32_t key, uint32_t sym, uint32_t state, uint32_t modifiers, void *data) { struct terminal *terminal = data; - char ch = unicode; + char ch[2]; + int len = 0; - switch (key) { - case KEY_F11: + switch (sym) { + case XK_F11: if (!state) break; terminal->fullscreen ^= 1; window_set_fullscreen(window, terminal->fullscreen); window_schedule_redraw(terminal->window); break; + + case XK_Delete: + sym = 0x04; + case XK_BackSpace: + case XK_Tab: + case XK_Linefeed: + case XK_Clear: + case XK_Return: + case XK_Pause: + case XK_Scroll_Lock: + case XK_Sys_Req: + case XK_Escape: + ch[len++] = sym & 0x7f; + break; + + case XK_Shift_L: + case XK_Shift_R: + case XK_Control_L: + case XK_Control_R: + case XK_Alt_L: + case XK_Alt_R: + break; + default: - if (state && unicode) - write(terminal->master, &ch, 1); + if (modifiers & WINDOW_MODIFIER_CONTROL) + sym = sym & 0x1f; + else if (modifiers & WINDOW_MODIFIER_ALT) + ch[len++] = 0x1b; + if (sym < 256) + ch[len++] = sym; break; } + + if (state && len > 0) + write(terminal->master, ch, len); } static void diff --git a/clients/window.c b/clients/window.c index cac1eb8..2d88512 100644 --- a/clients/window.c +++ b/clients/window.c @@ -39,6 +39,8 @@ #include #include +#include + #include #include "wayland-util.h" #include "wayland-client.h" @@ -62,6 +64,7 @@ struct display { struct wl_list window_list; char *device_name; cairo_surface_t *active_frame, *inactive_frame, *shadow; + XkbcDescPtr xkb; }; struct window { @@ -413,128 +416,33 @@ static void window_handle_button(void *data, struct wl_input_device *input_devic } } - -struct key { - uint32_t code[4]; -} evdev_keymap[] = { - { { 0, 0 } }, /* 0 */ - { { 0x1b, 0x1b } }, - { { '1', '!' } }, - { { '2', '@' } }, - { { '3', '#' } }, - { { '4', '$' } }, - { { '5', '%' } }, - { { '6', '^' } }, - { { '7', '&' } }, - { { '8', '*' } }, - { { '9', '(' } }, - { { '0', ')' } }, - { { '-', '_' } }, - { { '=', '+' } }, - { { '\b', '\b' } }, - { { '\t', '\t' } }, - - { { 'q', 'Q', 0x11 } }, /* 16 */ - { { 'w', 'W', 0x17 } }, - { { 'e', 'E', 0x05 } }, - { { 'r', 'R', 0x12 } }, - { { 't', 'T', 0x14 } }, - { { 'y', 'Y', 0x19 } }, - { { 'u', 'U', 0x15 } }, - { { 'i', 'I', 0x09 } }, - { { 'o', 'O', 0x0f } }, - { { 'p', 'P', 0x10 } }, - { { '[', '{', 0x1b } }, - { { ']', '}', 0x1d } }, - { { '\n', '\n' } }, - { { 0, 0 } }, - { { 'a', 'A', 0x01} }, - { { 's', 'S', 0x13 } }, - - { { 'd', 'D', 0x04 } }, /* 32 */ - { { 'f', 'F', 0x06 } }, - { { 'g', 'G', 0x07 } }, - { { 'h', 'H', 0x08 } }, - { { 'j', 'J', 0x0a } }, - { { 'k', 'K', 0x0b } }, - { { 'l', 'L', 0x0c } }, - { { ';', ':' } }, - { { '\'', '"' } }, - { { '`', '~' } }, - { { 0, 0 } }, - { { '\\', '|', 0x1c } }, - { { 'z', 'Z', 0x1a } }, - { { 'x', 'X', 0x18 } }, - { { 'c', 'C', 0x03 } }, - { { 'v', 'V', 0x16 } }, - - { { 'b', 'B', 0x02 } }, /* 48 */ - { { 'n', 'N', 0x0e } }, - { { 'm', 'M', 0x0d } }, - { { ',', '<' } }, - { { '.', '>' } }, - { { '/', '?' } }, - { { 0, 0 } }, - { { '*', '*' } }, - { { 0, 0 } }, - { { ' ', ' ' } }, - { { 0, 0 } } - - /* 59 */ -}; - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -static void -window_update_modifiers(struct window *window, uint32_t key, uint32_t state) -{ - uint32_t mod = 0; - - switch (key) { - case KEY_LEFTSHIFT: - case KEY_RIGHTSHIFT: - mod = WINDOW_MODIFIER_SHIFT; - break; - case KEY_LEFTCTRL: - case KEY_RIGHTCTRL: - mod = WINDOW_MODIFIER_CONTROL; - break; - case KEY_LEFTALT: - case KEY_RIGHTALT: - mod = WINDOW_MODIFIER_ALT; - break; - } - - if (state) - window->modifiers |= mod; - else - window->modifiers &= ~mod; -} - static void window_handle_key(void *data, struct wl_input_device *input_device, uint32_t key, uint32_t state) { struct window *window = data; - uint32_t unicode = 0; + struct display *d = window->display; + uint32_t code, sym, level; + code = key + d->xkb->min_key_code; if (window->keyboard_device != input_device) return; - window_update_modifiers(window, key, state); + level = 0; + if (window->modifiers & WINDOW_MODIFIER_SHIFT && + XkbKeyGroupWidth(d->xkb, code, 0) > 1) + level = 1; - if (key < ARRAY_LENGTH(evdev_keymap)) { - if (window->modifiers & WINDOW_MODIFIER_CONTROL) - unicode = evdev_keymap[key].code[2]; - else if (window->modifiers & WINDOW_MODIFIER_SHIFT) - unicode = evdev_keymap[key].code[1]; - else - unicode = evdev_keymap[key].code[0]; - } + sym = XkbKeySymEntry(d->xkb, code, level, 0); + + if (state) + window->modifiers |= d->xkb->map->modmap[code]; + else + window->modifiers &= ~d->xkb->map->modmap[code]; if (window->key_handler) - (*window->key_handler)(window, key, unicode, - state, window->modifiers, window->user_data); + (*window->key_handler)(window, key, sym, state, + window->modifiers, window->user_data); } static void @@ -551,6 +459,7 @@ window_handle_keyboard_focus(void *data, struct wl_array *keys) { struct window *window = data; + struct display *d = window->display; uint32_t *k, *end; if (window->keyboard_device == input_device && surface != window->surface) @@ -563,7 +472,7 @@ window_handle_keyboard_focus(void *data, if (window->keyboard_device) { end = keys->data + keys->size; for (k = keys->data; k < end; k++) - window_update_modifiers(window, *k, 1); + window->modifiers |= d->xkb->map->modmap[*k]; } else { window->modifiers = 0; } @@ -894,6 +803,26 @@ display_render_frame(struct display *d) cairo_destroy(cr); } +static void +init_xkb(struct display *d) +{ + XkbRMLVOSet rmlvo; + char rules[] = "evdev", model[] = "pc105", layout[] = "us"; + + rmlvo.rules = rules; + rmlvo.model = model; + rmlvo.layout = layout; + rmlvo.variant = ""; + rmlvo.options = ""; + + XkbcInitAtoms(NULL, NULL); + d->xkb = XkbcCompileKeymapFromRules(&rmlvo); + if (!d->xkb) { + fprintf(stderr, "Failed to compile keymap\n"); + exit(1); + } +} + struct display * display_create(int *argc, char **argv[], const GOptionEntry *option_entries) { @@ -993,6 +922,8 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) wl_list_init(&d->window_list); + init_xkb(d); + return d; } diff --git a/clients/window.h b/clients/window.h index 7f8df80..f020ace 100644 --- a/clients/window.h +++ b/clients/window.h @@ -54,8 +54,10 @@ display_run(struct display *d); enum { WINDOW_MODIFIER_SHIFT = 0x01, - WINDOW_MODIFIER_ALT = 0x02, + WINDOW_MODIFIER_LOCK = 0x02, WINDOW_MODIFIER_CONTROL = 0x04, + WINDOW_MODIFIER_ALT = 0x08, + WINDOW_MODIFIER_MOD2 = 0x10, }; typedef void (*window_resize_handler_t)(struct window *window, void *data); diff --git a/configure.ac b/configure.ac index 8097035..fd64439 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(COMPOSITOR, [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes) -PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0]) +PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon]) PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0]) if test $CC = gcc; then -- 2.7.4