From 1eb634953f018e45aeafde619141c635cd14502c Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Sat, 24 Aug 2019 23:34:39 +0100 Subject: imv: Move keyboard handling into window subsystem This is required as key repeating is going to need to be handled locally on Wayland, which means a slight refactor. --- src/imv.c | 52 +++++--------------------------------- src/window.h | 9 +++---- src/wl_window.c | 57 +++++++++++++++++++++++++++++++---------- src/x11_window.c | 77 +++++++++++++++++++++++++++++++++++--------------------- 4 files changed, 102 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/imv.c b/src/imv.c index 269a70a..8b57926 100644 --- a/src/imv.c +++ b/src/imv.c @@ -17,7 +17,6 @@ #include "image.h" #include "ini.h" #include "ipc.h" -#include "keyboard.h" #include "list.h" #include "log.h" #include "navigator.h" @@ -167,7 +166,6 @@ struct imv { struct imv_console *console; struct imv_ipc *ipc; struct imv_viewport *view; - struct imv_keyboard *keyboard; struct imv_canvas *canvas; struct imv_window *window; @@ -387,53 +385,32 @@ static void command_callback(const char *text, void *data) imv_window_push_event(imv->window, &e); } -static void key_handler(struct imv *imv, int scancode, bool pressed) +static void key_handler(struct imv *imv, const struct imv_event *event) { - imv_keyboard_update_key(imv->keyboard, scancode, pressed); - - if (!pressed) { - return; - } - - char keyname[128] = {0}; - imv_keyboard_keyname(imv->keyboard, scancode, keyname, sizeof keyname); - if (imv_console_is_active(imv->console)) { - if (imv_console_key(imv->console, keyname)) { + if (imv_console_key(imv->console, event->data.keyboard.keyname)) { imv->need_redraw = true; return; } - char text[128]; - size_t len = imv_keyboard_get_text(imv->keyboard, scancode, text, sizeof text); - if (len >= sizeof text) { - imv_log(IMV_WARNING, "Keyboard input too large for input buffer. Discarding.\n"); - } else { - imv_console_input(imv->console, text); - } + imv_console_input(imv->console, event->data.keyboard.text); } else { /* In regular mode see if we should enter command mode, otherwise send input * to the bind system. */ - if (!strcmp("colon", keyname)) { + if (!strcmp("colon", event->data.keyboard.keyname)) { imv_console_activate(imv->console); imv->need_redraw = true; return; } - char *keyname = imv_keyboard_describe_key(imv->keyboard, scancode); - if (!keyname) { - return; - } - - struct list *cmds = imv_bind_handle_event(imv->binds, keyname); + struct list *cmds = imv_bind_handle_event(imv->binds, event->data.keyboard.description); if (cmds) { imv_command_exec_list(imv->commands, cmds, imv); } - free(keyname); } imv->need_redraw = true; @@ -458,13 +435,7 @@ static void event_handler(void *data, const struct imv_event *e) break; } case IMV_EVENT_KEYBOARD: - key_handler(imv, e->data.keyboard.scancode, e->data.keyboard. pressed); - break; - case IMV_EVENT_KEYBOARD_MODS: - imv_keyboard_update_mods(imv->keyboard, - e->data.keyboard_mods.depressed, - e->data.keyboard_mods.latched, - e->data.keyboard_mods.locked); + key_handler(imv, e); break; case IMV_EVENT_MOUSE_MOTION: if (imv_window_get_mouse_button(imv->window, 1)) { @@ -607,7 +578,6 @@ void imv_free(struct imv *imv) imv_console_free(imv->console); imv_ipc_free(imv->ipc); imv_viewport_free(imv->view); - imv_keyboard_free(imv->keyboard); imv_canvas_free(imv->canvas); if (imv->current_image) { imv_image_free(imv->current_image); @@ -1094,16 +1064,6 @@ static bool setup_window(struct imv *imv) /* put us in fullscren mode to begin with if requested */ imv_window_set_fullscreen(imv->window, imv->start_fullscreen); - { - imv->keyboard = imv_keyboard_create(); - assert(imv->keyboard); - - const char *keymap = imv_window_get_keymap(imv->window); - if (keymap) { - imv_keyboard_set_keymap(imv->keyboard, keymap); - } - } - { int ww, wh; imv_window_get_size(imv->window, &ww, &wh); diff --git a/src/window.h b/src/window.h index eff00ab..6c692cc 100644 --- a/src/window.h +++ b/src/window.h @@ -27,13 +27,10 @@ struct imv_event { } resize; struct { int scancode; - bool pressed; + char *keyname; + char *description; + char *text; } keyboard; - struct { - int depressed; - int latched; - int locked; - } keyboard_mods; struct { double x, y, dx, dy; } mouse_motion; diff --git a/src/wl_window.c b/src/wl_window.c index c50fa81..040aefb 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1,5 +1,6 @@ #include "window.h" +#include "keyboard.h" #include "list.h" #include @@ -34,6 +35,7 @@ struct imv_window { EGLSurface egl_surface; struct wl_egl_window *egl_window; + struct imv_keyboard *keyboard; struct list *wl_outputs; int display_fd; @@ -107,6 +109,8 @@ static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, memcpy(window->keymap, src, size); munmap(src, size); close(fd); + + imv_keyboard_set_keymap(window->keyboard, window->keymap); } static void keyboard_enter(void *data, struct wl_keyboard *keyboard, @@ -128,20 +132,48 @@ static void keyboard_leave(void *data, struct wl_keyboard *keyboard, (void)surface; } +static void cleanup_event(struct imv_event *event) +{ + if (event->type == IMV_EVENT_KEYBOARD) { + free(event->data.keyboard.keyname); + free(event->data.keyboard.text); + } +} + static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { (void)serial; (void)keyboard; (void)time; - + (void)state; struct imv_window *window = data; + + imv_keyboard_update_key(window->keyboard, key, state); + + if (!state) { + return; + } + + char keyname[32] = {0}; + imv_keyboard_keyname(window->keyboard, key, keyname, sizeof keyname); + + char text[64] = {0}; + imv_keyboard_get_text(window->keyboard, key, text, sizeof text); + + char *desc = imv_keyboard_describe_key(window->keyboard, key); + if (!desc) { + desc = strdup(""); + } + struct imv_event e = { .type = IMV_EVENT_KEYBOARD, .data = { .keyboard = { .scancode = key, - .pressed = state + .keyname = strdup(keyname), + .description = desc, + .text = strdup(text), } } }; @@ -156,17 +188,11 @@ static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, (void)serial; (void)group; struct imv_window *window = data; - struct imv_event e = { - .type = IMV_EVENT_KEYBOARD_MODS, - .data = { - .keyboard_mods = { - .depressed = mods_depressed, - .latched = mods_latched, - .locked = mods_locked, - } - } - }; - imv_window_push_event(window, &e); + + imv_keyboard_update_mods(window->keyboard, + mods_depressed, + mods_latched, + mods_locked); } static void keyboard_repeat(void *data, struct wl_keyboard *keyboard, @@ -702,6 +728,9 @@ struct imv_window *imv_window_create(int width, int height, const char *title) struct imv_window *window = calloc(1, sizeof *window); window->scale = 1; + + window->keyboard = imv_keyboard_create(); + assert(window->keyboard); window->wl_outputs = list_create(); connect_to_wayland(window); create_window(window, width, height, title); @@ -710,6 +739,7 @@ struct imv_window *imv_window_create(int width, int height, const char *title) void imv_window_free(struct imv_window *window) { + imv_keyboard_free(window->keyboard); free(window->keymap); shutdown_wayland(window); list_deep_free(window->wl_outputs); @@ -833,6 +863,7 @@ void imv_window_pump_events(struct imv_window *window, imv_event_handler handler if (handler) { handler(data, &e); } + cleanup_event(&e); } } diff --git a/src/x11_window.c b/src/x11_window.c index c7d752f..734a1c4 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -16,6 +16,7 @@ #include #include +#include "keyboard.h" #include "log.h" struct imv_window { @@ -36,9 +37,9 @@ struct imv_window { bool mouse1; } pointer; + struct imv_keyboard *keyboard; int pipe_fds[2]; char *keymap; - int last_mod_state; }; static void set_nonblocking(int fd) @@ -143,13 +144,18 @@ struct imv_window *imv_window_create(int w, int h, const char *title) assert(window->x_glc); glXMakeCurrent(window->x_display, window->x_window, window->x_glc); + window->keyboard = imv_keyboard_create(); + assert(window->keyboard); + setup_keymap(window); + imv_keyboard_set_keymap(window->keyboard, window->keymap); return window; } void imv_window_free(struct imv_window *window) { + imv_keyboard_free(window->keyboard); close(window->pipe_fds[0]); close(window->pipe_fds[1]); glXDestroyContext(window->x_display, window->x_glc); @@ -275,6 +281,47 @@ void imv_window_push_event(struct imv_window *window, struct imv_event *e) write(window->pipe_fds[1], e, sizeof *e); } +static void handle_keyboard(struct imv_window *window, imv_event_handler handler, void *data, const XEvent *xev) +{ + imv_keyboard_update_mods(window->keyboard, (int)xev->xkey.state, 0, 0); + + bool pressed = xev->type == KeyPress; + int scancode = xev->xkey.keycode - 8; + imv_keyboard_update_key(window->keyboard, scancode, pressed); + + if (!pressed) { + return; + } + + char keyname[32] = {0}; + imv_keyboard_keyname(window->keyboard, scancode, keyname, sizeof keyname); + + char text[64] = {0}; + imv_keyboard_get_text(window->keyboard, scancode, text, sizeof text); + + char *desc = imv_keyboard_describe_key(window->keyboard, scancode); + if (!desc) { + desc = strdup(""); + } + + struct imv_event e = { + .type = IMV_EVENT_KEYBOARD, + .data = { + .keyboard = { + .scancode = scancode, + .keyname = keyname, + .description = desc, + .text = text, + } + } + }; + + if (handler) { + handler(data, &e); + } + free(desc); +} + void imv_window_pump_events(struct imv_window *window, imv_event_handler handler, void *data) { XEvent xev; @@ -303,33 +350,7 @@ void imv_window_pump_events(struct imv_window *window, imv_event_handler handler handler(data, &e); } } else if (xev.type == KeyPress || xev.type == KeyRelease) { - if (window->last_mod_state != (int)xev.xkey.state) { - window->last_mod_state = (int)xev.xkey.state; - /* modifiers have changed, push an event for that first */ - struct imv_event e = { - .type = IMV_EVENT_KEYBOARD_MODS, - .data = { - .keyboard_mods = { - .depressed = (int)xev.xkey.state, - } - } - }; - if (handler) { - handler(data, &e); - } - } - struct imv_event e = { - .type = IMV_EVENT_KEYBOARD, - .data = { - .keyboard = { - .scancode = xev.xkey.keycode - 8, - .pressed = xev.type == KeyPress - } - } - }; - if (handler) { - handler(data, &e); - } + handle_keyboard(window, handler, data, &xev); } else if (xev.type == ButtonPress || xev.type == ButtonRelease) { if (xev.xbutton.button == Button1) { window->pointer.mouse1 = xev.type == ButtonPress; -- cgit v1.2.3