aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2023-01-07 13:33:28 +0100
committerdec05eba <dec05eba@protonmail.com>2023-01-07 13:33:28 +0100
commit293770707e12aa6b725e5ebaa30dc1aa80fdebc3 (patch)
treebb2d730caf83dfbbd853a44011decfcf4c8ab696
parent030b78f7056b35ab53765212ee3ce94c5835a975 (diff)
Window: add functions to set fullscreen state, vsync state
-rw-r--r--include/mgl/window/window.h7
-rw-r--r--src/window/window.c88
-rw-r--r--tests/main.c4
3 files changed, 83 insertions, 16 deletions
diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h
index 350421d..20cfc0d 100644
--- a/include/mgl/window/window.h
+++ b/include/mgl/window/window.h
@@ -38,6 +38,7 @@ struct mgl_window {
bool open;
bool focused;
bool key_repeat_enabled;
+ bool vsync_enabled;
double frame_time_limit;
mgl_clock frame_timer;
char *clipboard_string;
@@ -71,7 +72,7 @@ typedef enum {
*/
typedef bool (*mgl_clipboard_callback)(const unsigned char *data, size_t size, mgl_clipboard_type clipboard_type, void *userdata);
-/* |params| can be NULL */
+/* |params| can be NULL. Note: vsync is enabled by default */
int mgl_window_create(mgl_window *self, const char *title, const mgl_window_create_params *params);
int mgl_window_init_from_existing_window(mgl_window *self, mgl_window_handle existing_window);
void mgl_window_deinit(mgl_window *self);
@@ -111,6 +112,10 @@ void mgl_window_set_title(mgl_window *self, const char *title);
void mgl_window_set_cursor_visible(mgl_window *self, bool visible);
/* 0 = no fps limit, or limit fps to vsync if vsync is enabled */
void mgl_window_set_framerate_limit(mgl_window *self, int fps);
+void mgl_window_set_vsync_enabled(mgl_window *self, bool enabled);
+bool mgl_window_is_vsync_enabled(mgl_window *self);
+void mgl_window_set_fullscreen(mgl_window *self, bool fullscreen);
+bool mgl_window_is_fullscreen(mgl_window *self);
void mgl_window_set_position(mgl_window *self, mgl_vec2i position);
void mgl_window_set_size(mgl_window *self, mgl_vec2i size);
diff --git a/src/window/window.c b/src/window/window.c
index 6927992..7b39153 100644
--- a/src/window/window.c
+++ b/src/window/window.c
@@ -59,11 +59,13 @@ typedef struct {
Atom targets_atom;
Atom text_atom;
Atom utf8_string_atom;
- Atom image_png;
- Atom image_jpg;
- Atom image_jpeg;
- Atom image_gif;
+ Atom image_png_atom;
+ Atom image_jpg_atom;
+ Atom image_jpeg_atom;
+ Atom image_gif_atom;
Atom incr_atom;
+ Atom net_wm_state_atom;
+ Atom wm_state_fullscreen_atom;
Cursor default_cursor;
Cursor invisible_cursor;
unsigned int prev_keycode_pressed;
@@ -134,6 +136,8 @@ static bool glx_context_choose(mgl_context *context, GLXFBConfig **fbconfigs, GL
static int x11_context_init(x11_context *self, bool alpha) {
mgl_context *context = mgl_get_context();
+ /* TODO: Use CLIPBOARD_MANAGER and SAVE_TARGETS to save clipboard in clipboard manager on exit */
+
self->glx_context = NULL;
self->xim = NULL;
self->xic = NULL;
@@ -141,11 +145,13 @@ static int x11_context_init(x11_context *self, bool alpha) {
self->targets_atom = XInternAtom(context->connection, "TARGETS", False);
self->text_atom = XInternAtom(context->connection, "TEXT", False);
self->utf8_string_atom = XInternAtom(context->connection, "UTF8_STRING", False);
- self->image_png = XInternAtom(context->connection, "image/png", False);
- self->image_jpg = XInternAtom(context->connection, "image/jpg", False);
- self->image_jpeg = XInternAtom(context->connection, "image/jpeg", False);
- self->image_gif = XInternAtom(context->connection, "image/gif", False);
+ self->image_png_atom = XInternAtom(context->connection, "image/png", False);
+ self->image_jpg_atom = XInternAtom(context->connection, "image/jpg", False);
+ self->image_jpeg_atom = XInternAtom(context->connection, "image/jpeg", False);
+ self->image_gif_atom = XInternAtom(context->connection, "image/gif", False);
self->incr_atom = XInternAtom(context->connection, "INCR", False);
+ self->net_wm_state_atom = XInternAtom(context->connection, "_NET_WM_STATE", False);
+ self->wm_state_fullscreen_atom = XInternAtom(context->connection, "_NET_WM_STATE_FULLSCREEN", False);
self->default_cursor = None;
self->invisible_cursor = None;
@@ -390,7 +396,10 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window
mgl_window_deinit(self);
return -1;
}
- set_vertical_sync_enabled(self->window, 1);
+
+ self->vsync_enabled = true;
+ set_vertical_sync_enabled(self->window, self->vsync_enabled ? 1 : 0);
+
context->gl.glEnable(GL_TEXTURE_2D);
context->gl.glEnable(GL_BLEND);
context->gl.glEnable(GL_SCISSOR_TEST);
@@ -955,6 +964,55 @@ void mgl_window_set_framerate_limit(mgl_window *self, int fps) {
self->frame_time_limit = 1.0 / fps;
}
+void mgl_window_set_vsync_enabled(mgl_window *self, bool enabled) {
+ self->vsync_enabled = enabled;
+ set_vertical_sync_enabled(self->window, self->vsync_enabled ? 1 : 0);
+}
+
+bool mgl_window_is_vsync_enabled(mgl_window *self) {
+ return self->vsync_enabled;
+}
+
+void mgl_window_set_fullscreen(mgl_window *self, bool fullscreen) {
+ mgl_context *context = mgl_get_context();
+ x11_context *x11_context = self->context;
+
+ XEvent xev;
+ xev.type = ClientMessage;
+ xev.xclient.window = self->window;
+ xev.xclient.message_type = x11_context->net_wm_state_atom;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = fullscreen ? 1 : 0;
+ xev.xclient.data.l[1] = x11_context->wm_state_fullscreen_atom;
+ xev.xclient.data.l[2] = 0;
+ xev.xclient.data.l[3] = 1;
+ xev.xclient.data.l[4] = 0;
+
+ if(!XSendEvent(context->connection, DefaultRootWindow(context->connection), 0, SubstructureRedirectMask | SubstructureNotifyMask, &xev)) {
+ fprintf(stderr, "mgl warning: failed to change window fullscreen state\n");
+ return;
+ }
+
+ XFlush(context->connection);
+}
+
+bool mgl_window_is_fullscreen(mgl_window *self) {
+ mgl_context *context = mgl_get_context();
+ x11_context *x11_context = self->context;
+
+ bool is_fullscreen = false;
+ Atom type = None;
+ int format = 0;
+ unsigned long items = 0;
+ unsigned long remaining_bytes = 0;
+ unsigned char *data = NULL;
+ if(XGetWindowProperty(context->connection, self->window, x11_context->net_wm_state_atom, 0, 1024, False, PropertyNewValue, &type, &format, &items, &remaining_bytes, &data) == Success && data) {
+ is_fullscreen = format == 32 && *(unsigned long*)data == x11_context->wm_state_fullscreen_atom;
+ XFree(data);
+ }
+ return is_fullscreen;
+}
+
void mgl_window_set_position(mgl_window *self, mgl_vec2i position) {
XMoveWindow(mgl_get_context()->connection, self->window, position.x, position.y);
}
@@ -1031,11 +1089,11 @@ static Atom find_matching_atom(const Atom *supported_atoms, size_t num_supported
static mgl_clipboard_type atom_type_to_supported_clipboard_type(x11_context *x11_context, Atom type, int format) {
if((type == x11_context->utf8_string_atom || type == XA_STRING || type == x11_context->text_atom) && format == 8) {
return MGL_CLIPBOARD_TYPE_STRING;
- } else if(type == x11_context->image_png && format == 8){
+ } else if(type == x11_context->image_png_atom && format == 8){
return MGL_CLIPBOARD_TYPE_IMAGE_PNG;
- } else if((type == x11_context->image_jpg || type == x11_context->image_jpeg) && format == 8){
+ } else if((type == x11_context->image_jpg_atom || type == x11_context->image_jpeg_atom) && format == 8){
return MGL_CLIPBOARD_TYPE_IMAGE_JPG;
- } else if(type == x11_context->image_gif && format == 8){
+ } else if(type == x11_context->image_gif_atom && format == 8){
return MGL_CLIPBOARD_TYPE_IMAGE_GIF;
} else {
return -1;
@@ -1070,15 +1128,15 @@ bool mgl_window_get_clipboard(mgl_window *self, mgl_clipboard_callback callback,
int supported_clipboard_type_index = 0;
if(clipboard_types & MGL_CLIPBOARD_TYPE_IMAGE_PNG) {
- supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_png;
+ supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_png_atom;
}
if(clipboard_types & MGL_CLIPBOARD_TYPE_IMAGE_JPG) {
- supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_jpeg;
+ supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_jpeg_atom;
}
if(clipboard_types & MGL_CLIPBOARD_TYPE_IMAGE_GIF) {
- supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_gif;
+ supported_clipboard_types[supported_clipboard_type_index++] = x11_context->image_gif_atom;
}
if(clipboard_types & MGL_CLIPBOARD_TYPE_STRING) {
diff --git a/tests/main.c b/tests/main.c
index ee632a7..2155181 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -297,6 +297,10 @@ int main(int argc, char **argv) {
} else {
fprintf(stderr, "Failed to copy clipboard!\n");
}
+ } else if(event.key.code == MGL_KEY_F) {
+ mgl_window_set_fullscreen(&window, !mgl_window_is_fullscreen(&window));
+ } else if(event.key.code == MGL_KEY_X) {
+ mgl_window_set_vsync_enabled(&window, !mgl_window_is_vsync_enabled(&window));
}
fprintf(stderr, "key press event, code: %u\n", event.key.code);
break;