From a14eb65e82d226fe8b33ca23d29eeba02066357d Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 17 Nov 2021 09:42:11 +0100 Subject: Window: implement function to disable key repeat --- src/mgl.c | 2 ++ src/window/window.c | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mgl.c b/src/mgl.c index 02fe8a5..f93704e 100644 --- a/src/mgl.c +++ b/src/mgl.c @@ -1,5 +1,6 @@ #include "../include/mgl/mgl.h" #include +#include #include #ifndef NDEBUG #include @@ -67,6 +68,7 @@ int mgl_init(void) { prev_xerror = XSetErrorHandler(ignore_xerror); prev_xioerror = XSetIOErrorHandler(ignore_xioerror); + XkbSetDetectableAutoRepeat(context.connection, True, NULL); context.wm_delete_window_atom = XInternAtom(context.connection, "WM_DELETE_WINDOW", False); if(!context.wm_delete_window_atom) { diff --git a/src/window/window.c b/src/window/window.c index 3dbb81f..c6dab51 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -61,6 +61,8 @@ typedef struct { Atom incr_atom; Cursor default_cursor; Cursor invisible_cursor; + unsigned int prev_keycode_pressed; + bool key_was_released; /* Used to stack text event on top of key press/release events and other text events. For example pressing a key should give the user both key press and text events @@ -89,6 +91,9 @@ static int x11_context_init(x11_context *self) { self->default_cursor = None; self->invisible_cursor = None; + self->prev_keycode_pressed = 0; + self->key_was_released = false; + self->default_cursor = XCreateFontCursor(context->connection, XC_arrow); if(!self->default_cursor) { x11_context_deinit(self); @@ -226,6 +231,7 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window self->context = NULL; self->open = false; self->focused = false; + self->key_repeat_enabled = true; self->frame_time_limit = 0.0; mgl_clock_init(&self->frame_timer); self->clipboard_string = NULL; @@ -495,6 +501,7 @@ static void mgl_window_handle_text_event(mgl_window *self, XEvent *xev) { text_event.text.size = clen; memcpy(text_event.text.str, &buf[i], clen); text_event.text.str[clen] = '\0'; + /* Text may contain multiple codepoints so they need to separated into multiple events */ if(!x11_context_append_event(x11_context, &text_event)) break; @@ -502,17 +509,29 @@ static void mgl_window_handle_text_event(mgl_window *self, XEvent *xev) { } } -/* Returns true if processed */ static void mgl_window_on_receive_event(mgl_window *self, XEvent *xev, mgl_event *event, mgl_context *context) { - /* TODO: Handle wm_delete_window event */ switch(xev->type) { case KeyPress: { + x11_context *x11_context = self->context; + + if(!self->key_repeat_enabled && xev->xkey.keycode == x11_context->prev_keycode_pressed && !x11_context->key_was_released) { + event->type = MGL_EVENT_UNKNOWN; + return; + } + + x11_context->prev_keycode_pressed = xev->xkey.keycode; + x11_context->key_was_released = false; + event->type = MGL_EVENT_KEY_PRESSED; mgl_window_handle_key_event(self, &xev->xkey, event, context, true); mgl_window_handle_text_event(self, xev); return; } case KeyRelease: { + x11_context *x11_context = self->context; + if(xev->xkey.keycode == x11_context->prev_keycode_pressed) + x11_context->key_was_released = true; + event->type = MGL_EVENT_KEY_RELEASED; mgl_window_handle_key_event(self, &xev->xkey, event, context, false); return; @@ -891,3 +910,7 @@ bool mgl_window_get_clipboard(mgl_window *self, char **str, size_t *size) { /* Timed out waiting for clipboard */ return false; } + +void mgl_window_set_key_repeat_enabled(mgl_window *self, bool enabled) { + self->key_repeat_enabled = enabled; +} -- cgit v1.2.3