From e3c90b41386986ef53e512994d6e2f7ceadfc177 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 8 Nov 2021 02:07:23 +0100 Subject: Add window function to get key state, allow invalid utf8 --- src/window/window.c | 65 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'src/window/window.c') diff --git a/src/window/window.c b/src/window/window.c index 05cd5f5..642609b 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -57,8 +57,20 @@ typedef struct { an event for all of them. */ x11_events_circular_buffer events; + bool key_pressed[__MGL_NUM_KEYS__]; } x11_context; +static void x11_context_init(x11_context *self) { + self->glx_context = NULL; + self->xim = NULL; + self->xic = NULL; + x11_events_circular_buffer_init(&self->events); + + for(size_t i = 0; i < __MGL_NUM_KEYS__; ++i) { + self->key_pressed[i] = false; + } +} + static bool x11_context_append_event(x11_context *self, const mgl_event *event) { return x11_events_circular_buffer_append(&self->events, event); } @@ -67,6 +79,20 @@ static bool x11_context_pop_event(x11_context *self, mgl_event *event) { return x11_events_circular_buffer_pop(&self->events, event); } +/* Returns true if the state changed */ +static bool x11_context_update_key_state(x11_context *self, mgl_key key, bool key_pressed) { + if(self->key_pressed[key] != key_pressed) { + self->key_pressed[key] = key_pressed; + return true; + } else { + return false; + } +} + +static bool x11_context_is_key_pressed(const x11_context *self, mgl_key key) { + return self->key_pressed[key]; +} + /* TODO: Use gl OML present for other platforms than nvidia? nvidia doesn't support present yet */ /* TODO: check for glx swap control extension string (GLX_EXT_swap_control, etc) */ @@ -118,10 +144,7 @@ static int mgl_window_init(mgl_window *self, const char *title, int width, int h } x11_context *x11_context = self->context; - x11_context->glx_context = NULL, - x11_context->xim = NULL, - x11_context->xic = NULL; - x11_events_circular_buffer_init(&x11_context->events); + x11_context_init(x11_context); mgl_context *context = mgl_get_context(); @@ -281,6 +304,14 @@ static mgl_key x11_keysym_to_mgl_key(KeySym key_sym) { case XK_Tab: return MGL_KEY_TAB; case XK_Return: return MGL_KEY_ENTER; case XK_Escape: return MGL_KEY_ESCAPE; + case XK_Control_L: return MGL_KEY_LCONTROL; + case XK_Shift_L: return MGL_KEY_LSHIFT; + case XK_Alt_L: return MGL_KEY_LALT; + case XK_Super_L: return MGL_KEY_LSYSTEM; + case XK_Control_R: return MGL_KEY_RCONTROL; + case XK_Shift_R: return MGL_KEY_RSHIFT; + case XK_Alt_R: return MGL_KEY_RALT; + case XK_Super_R: return MGL_KEY_RSYSTEM; case XK_Delete: return MGL_KEY_DELETE; case XK_Home: return MGL_KEY_HOME; case XK_Left: return MGL_KEY_LEFT; @@ -320,12 +351,13 @@ static mgl_mouse_button x11_button_to_mgl_button(unsigned int button) { return MGL_BUTTON_UNKNOWN; } -static void mgl_window_handle_key_event(mgl_window *self, XKeyEvent *xkey, mgl_event *event, mgl_context *context) { +static void mgl_window_handle_key_event(mgl_window *self, XKeyEvent *xkey, mgl_event *event, mgl_context *context, bool pressed) { event->key.code = x11_keysym_to_mgl_key(XKeycodeToKeysym(context->connection, xkey->keycode, 0)); event->key.alt = ((xkey->state & Mod1Mask) != 0); event->key.control = ((xkey->state & ControlMask) != 0); event->key.shift = ((xkey->state & ShiftMask) != 0); - event->key.system = ((xkey->state & Mod5Mask) != 0); /* TODO: Fix, doesn't work */ + event->key.system = ((xkey->state & Mod4Mask) != 0); /* TODO: Fix, doesn't work */ + x11_context_update_key_state(self->context, event->key.code, pressed); } static void mgl_window_handle_text_event(mgl_window *self, XEvent *xev) { @@ -344,12 +376,15 @@ static void mgl_window_handle_text_event(mgl_window *self, XEvent *xev) { return; /* TODO: Set XIC location on screen with XSetICValues */ - if(!mgl_utf8_is_valid((const unsigned char*)buf, input_str_len)) - return; for(size_t i = 0; i < input_str_len;) { - uint32_t codepoint = 0; - const size_t clen = mgl_utf8_decode((const unsigned char*)&buf[i], &codepoint); + const unsigned char *cp = (const unsigned char*)&buf[i]; + uint32_t codepoint; + size_t clen; + if(!mgl_utf8_decode(cp, input_str_len - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } mgl_event text_event; text_event.type = MGL_EVENT_TEXT_ENTERED; @@ -370,13 +405,13 @@ static void mgl_window_on_receive_event(mgl_window *self, XEvent *xev, mgl_event switch(xev->type) { case KeyPress: { event->type = MGL_EVENT_KEY_PRESSED; - mgl_window_handle_key_event(self, &xev->xkey, event, context); + mgl_window_handle_key_event(self, &xev->xkey, event, context, true); mgl_window_handle_text_event(self, xev); return; } case KeyRelease: { event->type = MGL_EVENT_KEY_RELEASED; - mgl_window_handle_key_event(self, &xev->xkey, event, context); + mgl_window_handle_key_event(self, &xev->xkey, event, context, false); return; } case ButtonPress: { @@ -480,3 +515,9 @@ void mgl_window_get_view(mgl_window *self, mgl_view *view) { bool mgl_window_is_open(const mgl_window *self) { return self->open; } + +bool mgl_window_is_key_pressed(const mgl_window *self, mgl_key key) { + if(key < 0 || key >= __MGL_NUM_KEYS__) + return false; + return x11_context_is_key_pressed(self->context, key); +} -- cgit v1.2.3