aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2019-08-24 23:34:39 +0100
committerHarry Jeffery <harry@exec64.co.uk>2019-08-24 23:36:51 +0100
commit1eb634953f018e45aeafde619141c635cd14502c (patch)
treebf803f3ad772b703ac136e3622f4506c547419de /src
parent9d2684a260ffd1a0b2a084ffdd7adbfcc4ceaafa (diff)
downloadimv-1eb634953f018e45aeafde619141c635cd14502c.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/imv.c52
-rw-r--r--src/window.h9
-rw-r--r--src/wl_window.c57
-rw-r--r--src/x11_window.c77
4 files changed, 102 insertions, 93 deletions
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);
@@ -1095,16 +1065,6 @@ static bool setup_window(struct imv *imv)
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);
imv->canvas = imv_canvas_create(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,14 +27,11 @@ 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;
struct {
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 <assert.h>
@@ -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 <xcb/xcb.h>
#include <xkbcommon/xkbcommon-x11.h>
+#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;