From 293770707e12aa6b725e5ebaa30dc1aa80fdebc3 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 7 Jan 2023 13:33:28 +0100 Subject: Window: add functions to set fullscreen state, vsync state --- include/mgl/window/window.h | 7 +++- src/window/window.c | 88 +++++++++++++++++++++++++++++++++++++-------- tests/main.c | 4 +++ 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; -- cgit v1.2.3