diff --git a/terminal.c b/terminal.c index d380bd89..51506324 100644 --- a/terminal.c +++ b/terminal.c @@ -421,97 +421,14 @@ static const struct wl_compositor_listener compositor_listener = { handle_frame, }; -struct key { - int 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 -key_handler(struct window *window, uint32_t key, uint32_t state, void *data) +key_handler(struct window *window, uint32_t key, uint32_t unicode, + uint32_t state, uint32_t modifiers, void *data) { struct terminal *terminal = data; - uint32_t mod = 0; - char c; + char ch = unicode; switch (key) { - case KEY_LEFTSHIFT: - case KEY_RIGHTSHIFT: - mod = MOD_SHIFT; - break; - case KEY_LEFTCTRL: - case KEY_RIGHTCTRL: - mod = MOD_CTRL; - break; - case KEY_LEFTALT: - case KEY_RIGHTALT: - mod = MOD_ALT; - break; case KEY_F11: if (!state) break; @@ -520,23 +437,10 @@ key_handler(struct window *window, uint32_t key, uint32_t state, void *data) terminal_schedule_redraw(terminal); break; default: - if (key < ARRAY_LENGTH(evdev_keymap)) { - if (terminal->modifiers & MOD_CTRL) - c = evdev_keymap[key].code[2]; - else if (terminal->modifiers & MOD_SHIFT) - c = evdev_keymap[key].code[1]; - else - c = evdev_keymap[key].code[0]; - if (state && c) - write(terminal->master, &c, 1); - } + if (state && unicode) + write(terminal->master, &ch, 1); break; } - - if (state) - terminal->modifiers |= mod; - else - terminal->modifiers &= ~mod; } static struct terminal * diff --git a/window.c b/window.c index 8ec858cc..43fa3cf3 100644 --- a/window.c +++ b/window.c @@ -60,6 +60,7 @@ struct window { int fullscreen; struct wl_input_device *grab_device; uint32_t name; + uint32_t modifiers; cairo_surface_t *cairo_surface; @@ -359,15 +360,119 @@ 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_handle_key(void *data, struct wl_input_device *input_device, - uint32_t button, uint32_t state) + uint32_t key, uint32_t state) { struct window *window = data; + uint32_t mod = 0; + uint32_t unicode = 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; + default: + 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]; + } + break; + } + + if (state) + window->modifiers |= mod; + else + window->modifiers &= ~mod; if (window->key_handler) - (*window->key_handler)(window, button, state, - window->user_data); + (*window->key_handler)(window, key, unicode, + state, window->modifiers, window->user_data); } static const struct wl_input_device_listener input_device_listener = { diff --git a/window.h b/window.h index a8f58530..28019b29 100644 --- a/window.h +++ b/window.h @@ -39,11 +39,17 @@ display_create(struct wl_display *display, int fd); struct wl_compositor * display_get_compositor(struct display *display); +enum { + WINDOW_MODIFIER_SHIFT = 0x01, + WINDOW_MODIFIER_ALT = 0x02, + WINDOW_MODIFIER_CONTROL = 0x04, +}; + typedef void (*window_resize_handler_t)(struct window *window, void *data); typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data); typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, void *data); -typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t state, void *data); - +typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode, + uint32_t state, uint32_t modifiers, void *data); struct window * window_create(struct display *display, const char *title,