aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-10-31 12:50:05 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-02 02:23:54 +0100
commit111f0ba3f4a4f14d39c8e3f7c00f13e852f47a51 (patch)
treefc7317e332c7a56df7738a62110ad76d4fc8511c
parent8a316a12481282cb2ab966c4cbc770656c258383 (diff)
Start on syntax highlighting, output correct key button event
-rw-r--r--TODO13
-rw-r--r--include/mgl/graphics/text.h23
-rw-r--r--include/mgl/mgl.h3
-rw-r--r--include/mgl/window/event.h54
-rw-r--r--include/mgl/window/key.h109
-rw-r--r--include/mgl/window/window.h3
-rw-r--r--src/graphics/font.c9
-rw-r--r--src/graphics/text.c67
-rw-r--r--src/mgl.c25
-rw-r--r--src/window/window.c120
10 files changed, 390 insertions, 36 deletions
diff --git a/TODO b/TODO
index 611b9c1..a4715d0 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,8 @@
Handle window close (window destroyed event, disconnected from server and socket becomes invalid (check select return?)).\
-Bind texture and cache the bound texture to reduce calls to opengl.
-Use gl triangle instead of quad.
-Fix crash on exit.
-Support using multiple textures in shaders by using glActiveTexture for each one and set the uniform sampler2D value for each as as the index.
-Make sure clock is monotonic (there has been some issues with CLOCK\_MONOTONIC not being monotonic on linux).
-Verify if using a separate glx context for every window is the correct approach. \ No newline at end of file
+Bind texture and cache the bound texture to reduce calls to opengl.\
+Use gl triangle instead of quad.\
+Fix crash on exit.\
+Support using multiple textures in shaders by using glActiveTexture for each one and set the uniform sampler2D value for each as as the index.\
+Make sure clock is monotonic (there has been some issues with CLOCK\_MONOTONIC not being monotonic on linux).\
+Verify if using a separate glx context for every window is the correct approach.\
+Respond to wm ping. \ No newline at end of file
diff --git a/include/mgl/graphics/text.h b/include/mgl/graphics/text.h
index 2c2eeaf..9169ab0 100644
--- a/include/mgl/graphics/text.h
+++ b/include/mgl/graphics/text.h
@@ -1,28 +1,47 @@
#ifndef MGL_TEXT_H
#define MGL_TEXT_H
+/*
+ TODO: Do not render text outside the window and start from the visible part.
+ Support 64-bit text length on 32-bit systems, and use mmap to optimize loading very large files,
+ and munmap the text parts that are not visible on the screen.
+*/
+
#include "../system/vec.h"
#include "color.h"
+#include <stddef.h>
+#include <stdbool.h>
typedef struct mgl_font mgl_font;
typedef struct mgl_context mgl_context;
typedef struct {
+ /* Optional */
+ void (*before_syntax_highlight)(void *userdata);
+ /* Return true if the text format should be changed. Optional */
+ bool (*syntax_highlight)(void *userdata, const char *str, size_t size, mgl_color *color);
+ void *userdata;
+} mgl_text_options;
+
+typedef struct {
mgl_font *font; /* nullable */
const char *text; /* nullable */
+ size_t text_size;
mgl_color color;
mgl_vec2f position;
+ mgl_text_options options;
} mgl_text;
/*
Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used.
|font| and |text| may be NULL.
+ |load_options| can be NULL, in which case the default options are used.
*/
-int mgl_text_init(mgl_text *self, mgl_font *font, const char *text, float x, float y);
+int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size, mgl_text_options *options);
void mgl_text_deinit(mgl_text *self);
/* Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used. |text| may be NULL. */
-void mgl_text_set_string(mgl_text *self, const char *str);
+void mgl_text_set_string(mgl_text *self, const char *str, size_t str_size);
/* |font| may be NULL */
void mgl_text_set_font(mgl_text *self, mgl_font *font);
void mgl_text_set_position(mgl_text *self, mgl_vec2f position);
diff --git a/include/mgl/mgl.h b/include/mgl/mgl.h
index 8e5e2a4..b9d007e 100644
--- a/include/mgl/mgl.h
+++ b/include/mgl/mgl.h
@@ -9,8 +9,9 @@ typedef struct mgl_context mgl_context;
struct mgl_context {
mgl_connection connection;
- _XVisualInfo *visual_info;
mgl_gl gl;
+ _XVisualInfo *visual_info;
+ unsigned long wm_delete_window_atom;
};
/*
diff --git a/include/mgl/window/event.h b/include/mgl/window/event.h
index 2aea478..020d5c9 100644
--- a/include/mgl/window/event.h
+++ b/include/mgl/window/event.h
@@ -1,10 +1,62 @@
#ifndef MGL_EVENT_H
#define MGL_EVENT_H
+#include "key.h"
+#include <stdbool.h>
+
typedef struct mgl_event mgl_event;
+typedef struct {
+ int width;
+ int height;
+} mgl_size_event;
+
+typedef struct {
+ int code; /* mgl_key */
+ bool alt;
+ bool control;
+ bool shift;
+ bool system;
+} mgl_key_event;
+
+typedef struct {
+ int x; /* relative to left of the window */
+ int y; /* relative to the top of the window */
+} mgl_mouse_move_event;
+
+typedef enum {
+ MGL_BUTTON_UNKNOWN,
+ MGL_BUTTON_LEFT,
+ MGL_BUTTON_RIGHT,
+ MGL_BUTTON_MIDDLE,
+ MGL_BUTTON_XBUTTON1,
+ MGL_BUTTON_XBUTTON2
+} mgl_mouse_button;
+
+typedef struct {
+ int button; /* mgl_mouse_button */
+ int x; /* relative to left of the window */
+ int y; /* relative to top of the window */
+} mgl_mouse_button_event;
+
+typedef enum {
+ MGL_EVENT_UNKNOWN,
+ MGL_EVENT_RESIZED,
+ MGL_EVENT_KEY_PRESSED,
+ MGL_EVENT_KEY_RELEASED,
+ MGL_EVENT_MOUSE_BUTTON_PRESSED,
+ MGL_EVENT_MOUSE_BUTTON_RELEASED,
+ MGL_EVENT_MOUSE_MOVED
+} mgl_event_type;
+
struct mgl_event {
- int type;
+ int type; /* mgl_event_type */
+ union {
+ mgl_size_event size;
+ mgl_key_event key;
+ mgl_mouse_button_event mouse_button;
+ mgl_mouse_move_event mouse_move;
+ };
};
#endif /* MGL_EVENT_H */
diff --git a/include/mgl/window/key.h b/include/mgl/window/key.h
new file mode 100644
index 0000000..90a3366
--- /dev/null
+++ b/include/mgl/window/key.h
@@ -0,0 +1,109 @@
+#ifndef _MGL_KEY_H_
+#define _MGL_KEY_H_
+
+typedef enum {
+ MGL_KEY_UNKNOWN,
+ MGL_KEY_A,
+ MGL_KEY_B,
+ MGL_KEY_C,
+ MGL_KEY_D,
+ MGL_KEY_E,
+ MGL_KEY_F,
+ MGL_KEY_G,
+ MGL_KEY_H,
+ MGL_KEY_I,
+ MGL_KEY_J,
+ MGL_KEY_K,
+ MGL_KEY_L,
+ MGL_KEY_M,
+ MGL_KEY_N,
+ MGL_KEY_O,
+ MGL_KEY_P,
+ MGL_KEY_Q,
+ MGL_KEY_R,
+ MGL_KEY_S,
+ MGL_KEY_T,
+ MGL_KEY_U,
+ MGL_KEY_V,
+ MGL_KEY_W,
+ MGL_KEY_X,
+ MGL_KEY_Y,
+ MGL_KEY_Z,
+ MGL_KEY_NUM0,
+ MGL_KEY_NUM1,
+ MGL_KEY_NUM2,
+ MGL_KEY_NUM3,
+ MGL_KEY_NUM4,
+ MGL_KEY_NUM5,
+ MGL_KEY_NUM6,
+ MGL_KEY_NUM7,
+ MGL_KEY_NUM8,
+ MGL_KEY_NUM9,
+ MGL_KEY_ESCAPE,
+ MGL_KEY_LCONTROL,
+ MGL_KEY_LSHIFT,
+ MGL_KEY_LALT,
+ MGL_KEY_LSYSTEM,
+ MGL_KEY_RCONTROL,
+ MGL_KEY_RSHIFT,
+ MGL_KEY_RALT,
+ MGL_KEY_RSYSTEM,
+ MGL_KEY_MENU,
+ MGL_KEY_LBRACKET,
+ MGL_KEY_RBRACKET,
+ MGL_KEY_SEMICOLON,
+ MGL_KEY_COMMA,
+ MGL_KEY_PERIOD,
+ MGL_KEY_QUOTE,
+ MGL_KEY_SLASH,
+ MGL_KEY_BACKSLASH,
+ MGL_KEY_TILDE,
+ MGL_KEY_EQUAL,
+ MGL_KEY_HYPHEN,
+ MGL_KEY_SPACE,
+ MGL_KEY_ENTER,
+ MGL_KEY_BACKSPACE,
+ MGL_KEY_TAB,
+ MGL_KEY_PAGEUP,
+ MGL_KEY_PAGEDOWN,
+ MGL_KEY_END,
+ MGL_KEY_HOME,
+ MGL_KEY_INSERT,
+ MGL_KEY_DELETE,
+ MGL_KEY_ADD,
+ MGL_KEY_SUBTRACT,
+ MGL_KEY_MULTIPLY,
+ MGL_KEY_DIVIDE,
+ MGL_KEY_LEFT,
+ MGL_KEY_RIGHT,
+ MGL_KEY_UP,
+ MGL_KEY_DOWN,
+ MGL_KEY_NUMPAD0,
+ MGL_KEY_NUMPAD1,
+ MGL_KEY_NUMPAD2,
+ MGL_KEY_NUMPAD3,
+ MGL_KEY_NUMPAD4,
+ MGL_KEY_NUMPAD5,
+ MGL_KEY_NUMPAD6,
+ MGL_KEY_NUMPAD7,
+ MGL_KEY_NUMPAD8,
+ MGL_KEY_NUMPAD9,
+ MGL_KEY_F1,
+ MGL_KEY_F2,
+ MGL_KEY_F3,
+ MGL_KEY_F4,
+ MGL_KEY_F5,
+ MGL_KEY_F6,
+ MGL_KEY_F7,
+ MGL_KEY_F8,
+ MGL_KEY_F9,
+ MGL_KEY_F10,
+ MGL_KEY_F11,
+ MGL_KEY_F12,
+ MGL_KEY_F13,
+ MGL_KEY_F14,
+ MGL_KEY_F15,
+ MGL_KEY_PAUSE
+} mgl_key;
+
+#endif /* _MGL_KEY_H_ */
diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h
index b30583b..297ccb9 100644
--- a/include/mgl/window/window.h
+++ b/include/mgl/window/window.h
@@ -5,6 +5,8 @@
#include "../system/vec.h"
#include <stdbool.h>
+/* Vsync is automatically set for windows created, if supported by the system */
+
typedef struct __GLXcontextRec *GLXContext;
typedef struct mgl_event mgl_event;
/* x11 window handle. TODO: Add others when wayland, etc is added */
@@ -16,6 +18,7 @@ struct mgl_window {
mgl_window_handle window;
GLXContext glx_context;
mgl_vec2i size;
+ /* relative to the top left of the window. only updates when the cursor is inside the window */
mgl_vec2i cursor_position;
};
diff --git a/src/graphics/font.c b/src/graphics/font.c
index 8344a04..2ed54d2 100644
--- a/src/graphics/font.c
+++ b/src/graphics/font.c
@@ -47,8 +47,8 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c
/* TODO: Optimize */
/* Find optimal size for atlas, starting from small to large */
for(int i = 0; i < 4; ++i) {
- self->font_atlas.width = (8 + (8 * i)) * self->character_size;
- self->font_atlas.height = (8 + (8 * i)) * self->character_size;
+ self->font_atlas.width = (14 + (8 * i)) * self->character_size;
+ self->font_atlas.height = (14 + (8 * i)) * self->character_size;
unsigned char *new_atlas = realloc(self->font_atlas.atlas, self->font_atlas.width * self->font_atlas.height);
if(!new_atlas) {
fprintf(stderr, "Error: failed to load font %s, error: out of memory\n", filepath);
@@ -67,6 +67,8 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c
return -1;
}
+ stbtt_PackSetOversampling(&pc, 2, 2);
+
if(!stbtt_PackFontRange(&pc, filedata.data, 0, self->character_size, 0, self->num_packed_chars, self->packed_chars)) {
stbtt_PackEnd(&pc);
continue;
@@ -92,7 +94,6 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c
}
/* TODO: Use stbtt_GetCodepointSDF */
- /* TODO: Use stbtt_PackSetOversampling */
mgl_filedata_free(&filedata);
return 0;
@@ -119,7 +120,7 @@ int mgl_font_get_glyph(const mgl_font *self, uint32_t codepoint, mgl_font_glyph
float x = 0.0f;
float y = 0.0f;
stbtt_aligned_quad quad;
- stbtt_GetPackedQuad(packed_chars, self->font_atlas.width, self->font_atlas.height, codepoint, &x, &y, &quad, 1);
+ stbtt_GetPackedQuad(packed_chars, self->font_atlas.width, self->font_atlas.height, codepoint, &x, &y, &quad, 0);
glyph->position = (mgl_vec2f){ quad.x0, quad.y0 };
glyph->size = (mgl_vec2f){ quad.x1 - quad.x0, quad.y1 - quad.y0 };
diff --git a/src/graphics/text.c b/src/graphics/text.c
index 76fd852..9a849a9 100644
--- a/src/graphics/text.c
+++ b/src/graphics/text.c
@@ -2,20 +2,48 @@
#include "../../include/mgl/graphics/font.h"
#include "../../include/mgl/mgl.h"
-int mgl_text_init(mgl_text *self, mgl_font *font, const char *text, float x, float y) {
+/*
+ TODO: Do syntax highlight in constructor/mgl_text_set_string for optimization.
+ Syntax highlighting should the first text that is visible in the text editor and find the start and end,
+ and start syntax highlight from there until the last visible text.
+ In that case there should also be a function to rerun the syntax highlighting, to update it
+ when an asynchronous process finishes that parses code, such as a lsp client parsing C++ code which
+ takes a while.
+*/
+
+static bool default_syntax_highlight(void *userdata, const char *str, size_t size, mgl_color *color) {
+ (void)userdata;
+ (void)str;
+ (void)size;
+ (void)color;
+ return false;
+}
+
+int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size, mgl_text_options *options) {
self->font = font;
- self->text = text;
+ self->text = str;
+ self->text_size = str_size;
self->color = (mgl_color){ 255, 255, 255, 255 };
- self->position = (mgl_vec2f){ x, y };
+ self->position = (mgl_vec2f){ 0.0f, 0.0f };
+
+ if(options)
+ self->options = *options;
+ else
+ self->options.userdata = NULL;
+
+ if(!options || !options->syntax_highlight)
+ self->options.syntax_highlight = default_syntax_highlight;
+
return 0;
}
void mgl_text_deinit(mgl_text *self) {
-
+ (void)self;
}
-void mgl_text_set_string(mgl_text *self, const char *str) {
+void mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) {
self->text = str;
+ self->text_size = str_size;
}
void mgl_text_set_font(mgl_text *self, mgl_font *font) {
@@ -44,25 +72,43 @@ static void mgl_text_draw_glyph(mgl_context *context, mgl_font_glyph *glyph, mgl
context->gl.glVertex3f(position.x + glyph->position.x, position.y + glyph->position.y + glyph->size.y, 0.0f);
}
+static void mgl_text_run_syntax_highlight(mgl_context *context, mgl_text *text, const char *str, size_t size, mgl_color *color, bool *color_changed) {
+ if(text->options.syntax_highlight(text->options.userdata, str, size, color)) {
+ context->gl.glColor4ub(color->r, color->g, color->b, color->a);
+ *color_changed = true;
+ } else {
+ if(*color_changed) {
+ *color = text->color;
+ context->gl.glColor4ub(color->r, color->g, color->b, color->a);
+ *color_changed = false;
+ }
+ }
+}
+
/* TODO: Use opengl buffer object instead */
/* TODO: Cache texture bind to not bind texture if its already bound and do not bind texture 0 */
void mgl_text_draw(mgl_context *context, mgl_text *text) {
- if(!text->text || !text->font)
+ if(!text->text || text->text_size == 0 || !text->font)
return;
- const char *str = text->text;
-
mgl_font_glyph glyph;
mgl_vec2f position = text->position;
position.y += text->font->character_size;
+ mgl_color color = text->color;
+ bool color_changed = false;
+
+ if(text->options.before_syntax_highlight)
+ text->options.before_syntax_highlight(text->options.userdata);
+
context->gl.glColor4ub(text->color.r, text->color.g, text->color.b, text->color.a);
context->gl.glBindTexture(GL_TEXTURE_2D, text->font->texture.id);
context->gl.glBegin(GL_QUADS);
- while(*str) {
- unsigned char c = *(unsigned char*)str;
+ for(size_t i = 0; i < text->text_size; ++i) {
+ unsigned char c = *(unsigned char*)&text->text[i];
if((c >= 32 && c < 128)) {
if(mgl_font_get_glyph(text->font, c, &glyph) == 0) {
+ mgl_text_run_syntax_highlight(context, text, (const char*)&c, 1, &color, &color_changed);
mgl_text_draw_glyph(context, &glyph, position);
position.x += glyph.advance;
}
@@ -78,7 +124,6 @@ void mgl_text_draw(mgl_context *context, mgl_text *text) {
position.x = text->position.x;
position.y += text->font->character_size;
}
- ++str;
}
context->gl.glEnd();
context->gl.glBindTexture(GL_TEXTURE_2D, 0);
diff --git a/src/mgl.c b/src/mgl.c
index 6407d9e..7940def 100644
--- a/src/mgl.c
+++ b/src/mgl.c
@@ -8,6 +8,7 @@
static mgl_context context;
static int init_count = 0;
static XErrorHandler prev_xerror = NULL;
+static XIOErrorHandler prev_xioerror = NULL;
static int ignore_xerror(Display *display, XErrorEvent *ee) {
(void)display;
@@ -15,6 +16,11 @@ static int ignore_xerror(Display *display, XErrorEvent *ee) {
return 0;
}
+static int ignore_xioerror(Display *display) {
+ (void)display;
+ return 0;
+}
+
static int glx_context_init() {
const int attr[] = {
GLX_RGBA,
@@ -60,6 +66,13 @@ int mgl_init(void) {
}
prev_xerror = XSetErrorHandler(ignore_xerror);
+ prev_xioerror = XSetIOErrorHandler(ignore_xioerror);
+
+ context.wm_delete_window_atom = XInternAtom(context.connection, "WM_DELETE_WINDOW", False);
+ if(!context.wm_delete_window_atom) {
+ mgl_deinit();
+ return -1;
+ }
if(mgl_gl_load(&context.gl) != 0) {
mgl_deinit();
@@ -76,10 +89,16 @@ int mgl_init(void) {
void mgl_deinit(void) {
if(init_count == 1) {
- glx_context_deinit();
- mgl_gl_unload(&context.gl);
- XSetErrorHandler(prev_xerror);
if(context.connection) {
+ glx_context_deinit();
+ mgl_gl_unload(&context.gl);
+
+ XSetIOErrorHandler(prev_xioerror);
+ prev_xioerror = NULL;
+
+ XSetErrorHandler(prev_xerror);
+ prev_xerror = NULL;
+
XCloseDisplay(context.connection);
context.connection = NULL;
}
diff --git a/src/window/window.c b/src/window/window.c
index 94756cd..9a650ae 100644
--- a/src/window/window.c
+++ b/src/window/window.c
@@ -1,4 +1,5 @@
#include "../../include/mgl/window/window.h"
+#include "../../include/mgl/window/event.h"
#include "../../include/mgl/mgl.h"
#include <X11/Xutil.h>
#include <errno.h>
@@ -140,23 +141,127 @@ void mgl_window_deinit(mgl_window *self) {
}
}
-static void mgl_window_on_receive_event(mgl_window *self, XEvent *xev) {
+static mgl_key x11_keysym_to_mgl_key(KeySym key_sym) {
+ if(key_sym >= XK_A && key_sym <= XK_Z)
+ return MGL_KEY_A + (key_sym - XK_A);
+ /* TODO: Check if this ever happens */
+ if(key_sym >= XK_a && key_sym <= XK_z)
+ return MGL_KEY_A + (key_sym - XK_a);
+ if(key_sym >= XK_0 && key_sym <= XK_9)
+ return MGL_KEY_NUM0 + (key_sym - XK_0);
+ if(key_sym >= XK_KP_0 && key_sym <= XK_KP_9)
+ return MGL_KEY_NUMPAD0 + (key_sym - XK_KP_0);
+
+ /* TODO: Fill in the rest */
+ switch(key_sym) {
+ case XK_space: return MGL_KEY_SPACE;
+ case XK_BackSpace: return MGL_KEY_BACKSPACE;
+ case XK_Tab: return MGL_KEY_TAB;
+ case XK_Return: return MGL_KEY_ENTER;
+ case XK_Delete: return MGL_KEY_DELETE;
+ case XK_Home: return MGL_KEY_HOME;
+ case XK_Left: return MGL_KEY_LEFT;
+ case XK_Up: return MGL_KEY_UP;
+ case XK_Right: return MGL_KEY_RIGHT;
+ case XK_Down: return MGL_KEY_DOWN;
+ case XK_Page_Up: return MGL_KEY_PAGEUP;
+ case XK_Page_Down: return MGL_KEY_PAGEDOWN;
+ case XK_End: return MGL_KEY_END;
+ case XK_F1: return MGL_KEY_F1;
+ case XK_F2: return MGL_KEY_F2;
+ case XK_F3: return MGL_KEY_F3;
+ case XK_F4: return MGL_KEY_F4;
+ case XK_F5: return MGL_KEY_F5;
+ case XK_F6: return MGL_KEY_F6;
+ case XK_F7: return MGL_KEY_F7;
+ case XK_F8: return MGL_KEY_F8;
+ case XK_F9: return MGL_KEY_F9;
+ case XK_F10: return MGL_KEY_F10;
+ case XK_F11: return MGL_KEY_F11;
+ case XK_F12: return MGL_KEY_F12;
+ case XK_F13: return MGL_KEY_F13;
+ case XK_F14: return MGL_KEY_F14;
+ case XK_F15: return MGL_KEY_F15;
+ }
+ return MGL_KEY_UNKNOWN;
+}
+
+static mgl_mouse_button x11_button_to_mgl_button(unsigned int button) {
+ switch(button) {
+ case 1: return MGL_BUTTON_LEFT;
+ case 2: return MGL_BUTTON_MIDDLE;
+ case 3: return MGL_BUTTON_RIGHT;
+ case 8: return MGL_BUTTON_XBUTTON1;
+ case 9: return MGL_BUTTON_XBUTTON2;
+ }
+ return MGL_BUTTON_UNKNOWN;
+}
+
+/* Returns true if processed */
+static bool 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: {
+ /* TODO: Fill with correct data */
+ event->type = MGL_EVENT_KEY_PRESSED;
+ event->key.code = x11_keysym_to_mgl_key(XKeycodeToKeysym(context->connection, xev->xkey.keycode, 0));
+ event->key.alt = ((xev->xkey.state & Mod1Mask) != 0);
+ event->key.control = ((xev->xkey.state & ControlMask) != 0);
+ event->key.shift = ((xev->xkey.state & ShiftMask) != 0);
+ event->key.system = ((xev->xkey.state & Mod5Mask) != 0); /* TODO: Fix, doesn't work */
+ return true;
+ }
+ case KeyRelease: {
+ /* TODO: Fill with correct data */
+ event->type = MGL_EVENT_KEY_RELEASED;
+ event->key.code = x11_keysym_to_mgl_key(XKeycodeToKeysym(context->connection, xev->xkey.keycode, 0));
+ event->key.alt = ((xev->xkey.state & Mod1Mask) != 0);
+ event->key.control = ((xev->xkey.state & ControlMask) != 0);
+ event->key.shift = ((xev->xkey.state & ShiftMask) != 0);
+ event->key.system = ((xev->xkey.state & Mod5Mask) != 0); /* TODO: Fix, doesn't work */
+ return true;
+ }
+ case ButtonPress: {
+ event->type = MGL_EVENT_MOUSE_BUTTON_PRESSED;
+ event->mouse_button.button = x11_button_to_mgl_button(xev->xbutton.button);
+ event->mouse_button.x = xev->xbutton.x;
+ event->mouse_button.y = xev->xbutton.y;
+ return true;
+ }
+ case ButtonRelease: {
+ event->type = MGL_EVENT_MOUSE_BUTTON_RELEASED;
+ event->mouse_button.button = x11_button_to_mgl_button(xev->xbutton.button);
+ event->mouse_button.x = xev->xbutton.x;
+ event->mouse_button.y = xev->xbutton.y;
+ return true;
+ }
case ConfigureNotify: {
while(XCheckTypedWindowEvent(mgl_get_context()->connection, self->window, ConfigureNotify, xev)) {}
if(xev->xconfigure.width != self->size.x || xev->xconfigure.height != self->size.x) {
mgl_window_on_resize(self, xev->xconfigure.width, xev->xconfigure.height);
- /*fprintf(stderr, "resize!\n");*/
+
+ event->type = MGL_EVENT_RESIZED;
+ event->size.width = self->size.x;
+ event->size.height = self->size.y;
+ event->mouse_move.y = self->cursor_position.y;
+ return true;
}
- break;
+ return false;
}
case MotionNotify: {
while(XCheckTypedWindowEvent(mgl_get_context()->connection, self->window, MotionNotify, xev)) {}
self->cursor_position.x = xev->xmotion.x;
self->cursor_position.y = xev->xmotion.y;
- break;
+
+ event->type = MGL_EVENT_MOUSE_MOVED;
+ event->mouse_move.x = self->cursor_position.x;
+ event->mouse_move.y = self->cursor_position.y;
+ return true;
}
}
+ /*fprintf(stderr, "unhandled event type: %d\n", xev->type);*/
+ event->type = MGL_EVENT_UNKNOWN;
+ return false;
}
void mgl_window_clear(mgl_window *self, mgl_color color) {
@@ -166,13 +271,12 @@ void mgl_window_clear(mgl_window *self, mgl_color color) {
}
bool mgl_window_poll_event(mgl_window *self, mgl_event *event) {
- /* TODO: Use |event| */
-
- Display *display = mgl_get_context()->connection;
+ mgl_context *context = mgl_get_context();
+ Display *display = context->connection;
if(XPending(display)) {
XEvent xev; /* TODO: Move to window struct */
XNextEvent(display, &xev);
- mgl_window_on_receive_event(self, &xev);
+ mgl_window_on_receive_event(self, &xev, event, context);
return true;
} else {
return false;