aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
Diffstat (limited to 'src/window')
-rw-r--r--src/window/window.c65
1 files changed, 53 insertions, 12 deletions
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);
+}