aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-11-17 09:42:11 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-17 09:42:11 +0100
commita14eb65e82d226fe8b33ca23d29eeba02066357d (patch)
treebbdb92dd8105e81a34fea601df851a3c25b03b76
parentff24e4c604479fdcedfacca35af3bb4810683c68 (diff)
Window: implement function to disable key repeat
-rw-r--r--include/mgl/window/window.h2
-rw-r--r--src/mgl.c2
-rw-r--r--src/window/window.c27
3 files changed, 29 insertions, 2 deletions
diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h
index 95e3273..2ce9a4b 100644
--- a/include/mgl/window/window.h
+++ b/include/mgl/window/window.h
@@ -31,6 +31,7 @@ struct mgl_window {
mgl_view view;
bool open;
bool focused;
+ bool key_repeat_enabled;
double frame_time_limit;
mgl_clock frame_timer;
char *clipboard_string;
@@ -81,5 +82,6 @@ void mgl_window_set_size_limits(mgl_window *self, mgl_vec2i minimum, mgl_vec2i m
void mgl_window_set_clipboard(mgl_window *self, const char *str, size_t size);
/* A malloc'ed and null terminated string is returned in |str|, it should be deallocated with free */
bool mgl_window_get_clipboard(mgl_window *self, char **str, size_t *size);
+void mgl_window_set_key_repeat_enabled(mgl_window *self, bool enabled);
#endif /* MGL_WINDOW_H */
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 <X11/Xutil.h>
+#include <X11/XKBlib.h>
#include <stdio.h>
#ifndef NDEBUG
#include <stdlib.h>
@@ -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;
+}