diff --git a/src/engine.c b/src/engine.c index d6bd1b609..d25a9ae5b 100644 --- a/src/engine.c +++ b/src/engine.c @@ -34,7 +34,7 @@ int engine_init(engine_init_flags *init_flags) { int w = setting->video.screen_w; int h = setting->video.screen_h; - int fs = setting->video.fullscreen; + window_mode window_mode = setting->video.window_mode; int vsync = setting->video.vsync; int aspect = setting->video.aspect; int fb_scale = setting->video.fb_scale; @@ -57,7 +57,7 @@ int engine_init(engine_init_flags *init_flags) { // Initialize everything. video_scan_renderers(); audio_scan_backends(); - if(!video_init(renderer, w, h, fs, vsync, aspect, framerate_limit, fb_scale, scaling_mode)) { + if(!video_init(renderer, w, h, window_mode, vsync, aspect, framerate_limit, fb_scale, scaling_mode)) { goto exit_0; } if(!audio_init(player, frequency, mono, resampler, music_volume, sound_volume)) { @@ -181,7 +181,7 @@ void engine_run(engine_init_flags *init_flags) { int static_wait = 0; while(run && game_state_is_running(gs)) { // Handle events - bool check_fs; + window_mode check_wm; while(SDL_PollEvent(&e)) { // Handle other events switch(e.type) { @@ -264,8 +264,8 @@ void engine_run(engine_init_flags *init_flags) { enable_screen_updates = 1; break; case SDL_WINDOWEVENT_RESTORED: - video_get_state(NULL, NULL, &check_fs, NULL, NULL, NULL); - if(check_fs) { + video_get_state(NULL, NULL, &check_wm, NULL, NULL, NULL); + if(check_wm != WINDOW_MODE_WINDOWED) { video_reinit_renderer(); } log_debug("RESTORED"); diff --git a/src/game/scenes/mainmenu/menu_video.c b/src/game/scenes/mainmenu/menu_video.c index 7d5fda8f4..8d7beffb8 100644 --- a/src/game/scenes/mainmenu/menu_video.c +++ b/src/game/scenes/mainmenu/menu_video.c @@ -165,16 +165,16 @@ void menu_video_done(component *c, void *u) { bool render_plugin_changed = strcmp(v->renderer, local->old_video_settings.renderer) != 0; if(render_plugin_changed) { video_close(); - video_init(v->renderer, v->screen_w, v->screen_h, v->fullscreen, v->vsync, v->aspect, v->framerate_limit, + video_init(v->renderer, v->screen_w, v->screen_h, v->window_mode, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, v->scaling_mode); menu_set_submenu(c->parent, menu_video_confirm_create(s, &local->old_video_settings)); } else if(local->old_video_settings.screen_w != v->screen_w || local->old_video_settings.screen_h != v->screen_h || - local->old_video_settings.fullscreen != v->fullscreen || local->old_video_settings.vsync != v->vsync || + local->old_video_settings.window_mode != v->window_mode || local->old_video_settings.vsync != v->vsync || local->old_video_settings.aspect != v->aspect || local->old_video_settings.framerate_limit != v->framerate_limit || local->old_video_settings.fb_scale != v->fb_scale || local->old_video_settings.scaling_mode != v->scaling_mode) { - video_reinit(v->screen_w, v->screen_h, v->fullscreen, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, + video_reinit(v->screen_w, v->screen_h, v->window_mode, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, v->scaling_mode); menu_set_submenu(c->parent, menu_video_confirm_create(s, &local->old_video_settings)); @@ -303,8 +303,10 @@ component *menu_video_create(scene *s) { &setting->video.vsync, offon_opts, 2)); menu_attach(menu, textselector_create_bind_opts("ASPECT", "Video aspect ratio. Original game is 4:3.", NULL, NULL, &setting->video.aspect, aspect_opts, 2)); - menu_attach(menu, textselector_create_bind_opts("FULLSCREEN", "Run the game in a fullscreen window.", NULL, NULL, - &setting->video.fullscreen, offon_opts, 2)); + const char *window_mode_opts[] = {"OFF", "WINDOWED", "EXCLUSIVE"}; + menu_attach(menu, textselector_create_bind_opts( + "FS", "OFF=windowed, WINDOWED=borderless fullscreen, EXCLUSIVE=true fullscreen.", NULL, NULL, + &setting->video.window_mode, window_mode_opts, 3)); // Done button menu_attach(menu, button_create("DONE", "Return to the main menu.", false, false, menu_video_done, s)); diff --git a/src/game/scenes/mainmenu/menu_video_confirm.c b/src/game/scenes/mainmenu/menu_video_confirm.c index 5bea1e473..88542b09f 100644 --- a/src/game/scenes/mainmenu/menu_video_confirm.c +++ b/src/game/scenes/mainmenu/menu_video_confirm.c @@ -30,10 +30,10 @@ void video_confirm_cancel_clicked(component *c, void *userdata) { *v = *local->old_video_settings; if(render_plugin_changed) { video_close(); - video_init(v->renderer, v->screen_w, v->screen_h, v->fullscreen, v->vsync, v->aspect, v->framerate_limit, + video_init(v->renderer, v->screen_w, v->screen_h, v->window_mode, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, v->scaling_mode); } else { - video_reinit(v->screen_w, v->screen_h, v->fullscreen, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, + video_reinit(v->screen_w, v->screen_h, v->window_mode, v->vsync, v->aspect, v->framerate_limit, v->fb_scale, v->scaling_mode); } diff --git a/src/game/utils/settings.c b/src/game/utils/settings.c index 5dec6db6b..f89822d42 100644 --- a/src/game/utils/settings.c +++ b/src/game/utils/settings.c @@ -73,7 +73,7 @@ const field f_video[] = { F_INT(settings_video, framerate_limit, 0), F_BOOL(settings_video, vsync, 0), F_INT(settings_video, aspect, 0), - F_BOOL(settings_video, fullscreen, 0), + F_INT(settings_video, window_mode, WINDOW_MODE_WINDOWED), F_INT(settings_video, scaling, 0), F_INT(settings_video, scaling_mode, 0), F_BOOL(settings_video, instant_console, 0), diff --git a/src/game/utils/settings.h b/src/game/utils/settings.h index f6e9eb9bb..7f666790c 100644 --- a/src/game/utils/settings.h +++ b/src/game/utils/settings.h @@ -1,6 +1,13 @@ #ifndef SETTINGS_H #define SETTINGS_H +typedef enum +{ + WINDOW_MODE_WINDOWED, + WINDOW_MODE_BORDERLESS, + WINDOW_MODE_FULLSCREEN +} window_mode; + typedef enum { FIGHT_MODE_NORMAL, @@ -46,7 +53,7 @@ typedef struct { int framerate_limit; int vsync; int aspect; - int fullscreen; + int window_mode; int scaling; int scaling_mode; int instant_console; diff --git a/src/video/renderers/null/null_renderer.c b/src/video/renderers/null/null_renderer.c index 458f6d46f..99a517491 100644 --- a/src/video/renderers/null/null_renderer.c +++ b/src/video/renderers/null/null_renderer.c @@ -15,22 +15,22 @@ static const char *get_name(void) { return "NULL"; } -static bool setup_context(void *userdata, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, +static bool setup_context(void *userdata, int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode) { log_info("NULL Renderer initialized!"); return true; } -static void get_context_state(void *userdata, int *window_w, int *window_h, bool *fullscreen, bool *vsync, int *aspect, - int *fb_scale) { +static void get_context_state(void *userdata, int *window_w, int *window_h, window_mode *window_mode, bool *vsync, + int *aspect, int *fb_scale) { if(window_w != NULL) { *window_w = 0; } if(window_h != NULL) { *window_h = 0; } - if(fullscreen != NULL) { - *fullscreen = false; + if(window_mode != NULL) { + *window_mode = 0; } if(vsync != NULL) { *vsync = false; @@ -43,8 +43,8 @@ static void get_context_state(void *userdata, int *window_w, int *window_h, bool } } -static bool reset_context_with(void *userdata, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, - int framerate_limit, int fb_scale, int scaling_mode) { +static bool reset_context_with(void *userdata, int window_w, int window_h, window_mode window_mode, bool vsync, + int aspect, int framerate_limit, int fb_scale, int scaling_mode) { log_info("NULL renderer reset."); return true; } diff --git a/src/video/renderers/opengl3/gl3_renderer.c b/src/video/renderers/opengl3/gl3_renderer.c index a7eba8386..c6df80b5b 100644 --- a/src/video/renderers/opengl3/gl3_renderer.c +++ b/src/video/renderers/opengl3/gl3_renderer.c @@ -36,7 +36,7 @@ typedef struct gl3_context { int screen_w; int screen_h; int fb_scale; - bool fullscreen; + window_mode window_mode; bool vsync; int aspect; int scaling_mode; @@ -104,12 +104,12 @@ static void reload_scaler_program(const gl3_context *ctx) { bind_uniform_2f(ctx->scale_prog_id, "texture_size", (GLfloat)fb_w, (GLfloat)fb_h); } -static bool setup_context(void *userdata, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, +static bool setup_context(void *userdata, int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode) { gl3_context *ctx = userdata; ctx->screen_w = window_w; ctx->screen_h = window_h; - ctx->fullscreen = fullscreen; + ctx->window_mode = window_mode; ctx->framerate_limit = framerate_limit; ctx->fb_scale = fb_scale; ctx->vsync = vsync; @@ -121,7 +121,7 @@ static bool setup_context(void *userdata, int window_w, int window_h, bool fulls ctx->last_tick = SDL_GetPerformanceCounter(); set_framerate_limit(ctx, framerate_limit); - if(!create_window(&ctx->window, window_w, window_h, fullscreen)) { + if(!create_window(&ctx->window, window_w, window_h, window_mode)) { goto error_0; } if(!create_gl_context(&ctx->gl_context, ctx->window)) { @@ -206,8 +206,8 @@ static bool setup_context(void *userdata, int window_w, int window_h, bool fulls return false; } -static void get_context_state(void *userdata, int *window_w, int *window_h, bool *fullscreen, bool *vsync, int *aspect, - int *fb_scale) { +static void get_context_state(void *userdata, int *window_w, int *window_h, window_mode *window_mode, bool *vsync, + int *aspect, int *fb_scale) { gl3_context *ctx = userdata; if(window_w != NULL) { *window_w = ctx->screen_w; @@ -215,8 +215,8 @@ static void get_context_state(void *userdata, int *window_w, int *window_h, bool if(window_h != NULL) { *window_h = ctx->screen_h; } - if(fullscreen != NULL) { - *fullscreen = ctx->fullscreen; + if(window_mode != NULL) { + *window_mode = ctx->window_mode; } if(vsync != NULL) { *vsync = ctx->vsync; @@ -229,17 +229,17 @@ static void get_context_state(void *userdata, int *window_w, int *window_h, bool } } -static bool reset_context_with(void *userdata, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, - int framerate_limit, int fb_scale, int scaling_mode) { +static bool reset_context_with(void *userdata, int window_w, int window_h, window_mode window_mode, bool vsync, + int aspect, int framerate_limit, int fb_scale, int scaling_mode) { gl3_context *ctx = userdata; ctx->screen_w = window_w; ctx->screen_h = window_h; - ctx->fullscreen = fullscreen; + ctx->window_mode = window_mode; ctx->vsync = vsync; ctx->aspect = aspect; set_framerate_limit(ctx, framerate_limit); - bool success = resize_window(ctx->window, window_w, window_h, fullscreen); + bool success = resize_window(ctx->window, window_w, window_h, window_mode); success = set_vsync(ctx->vsync) && success; const bool fb_scale_changed = ctx->fb_scale != fb_scale; diff --git a/src/video/renderers/opengl3/sdl_window.c b/src/video/renderers/opengl3/sdl_window.c index 49afd09bb..2a52ec611 100644 --- a/src/video/renderers/opengl3/sdl_window.c +++ b/src/video/renderers/opengl3/sdl_window.c @@ -1,4 +1,5 @@ #include "video/renderers/opengl3/sdl_window.h" +#include "game/utils/settings.h" #include "game/utils/version.h" #include "utils/log.h" @@ -73,7 +74,7 @@ bool has_gl_available(int version_major, int version_minor) { return ret; } -bool create_window(SDL_Window **window, int width, int height, bool fullscreen) { +bool create_window(SDL_Window **window, int width, int height, window_mode window_mode) { char title[32]; snprintf(title, 32, "OpenOMF v%s", get_version_string()); @@ -95,11 +96,17 @@ bool create_window(SDL_Window **window, int width, int height, bool fullscreen) return false; } - if(fullscreen) { + if(window_mode == WINDOW_MODE_FULLSCREEN) { if(SDL_SetWindowFullscreen(w, SDL_WINDOW_FULLSCREEN) != 0) { log_error("Could not set fullscreen mode: %s", SDL_GetError()); } else { - log_info("Fullscreen mode enabled!"); + log_info("Fullscreen mode enabled (exclusive)!"); + } + } else if(window_mode == WINDOW_MODE_BORDERLESS) { + if(SDL_SetWindowFullscreen(w, SDL_WINDOW_FULLSCREEN_DESKTOP) != 0) { + log_error("Could not set fullscreen mode: %s", SDL_GetError()); + } else { + log_info("Fullscreen mode enabled (borderless)!"); } } else { SDL_SetWindowFullscreen(w, 0); @@ -110,9 +117,15 @@ bool create_window(SDL_Window **window, int width, int height, bool fullscreen) return true; } -bool resize_window(SDL_Window *window, int width, int height, bool fullscreen) { +bool resize_window(SDL_Window *window, int width, int height, window_mode window_mode) { SDL_SetWindowSize(window, width, height); - if(SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0) < 0) { + unsigned int fs_flag = 0; + if(window_mode == WINDOW_MODE_FULLSCREEN) { + fs_flag = SDL_WINDOW_FULLSCREEN; + } else if(window_mode == WINDOW_MODE_BORDERLESS) { + fs_flag = SDL_WINDOW_FULLSCREEN_DESKTOP; + } + if(SDL_SetWindowFullscreen(window, fs_flag) < 0) { log_error("Could not set fullscreen mode: %s", SDL_GetError()); return false; } diff --git a/src/video/renderers/opengl3/sdl_window.h b/src/video/renderers/opengl3/sdl_window.h index f3dd4193d..b1f8e11f1 100644 --- a/src/video/renderers/opengl3/sdl_window.h +++ b/src/video/renderers/opengl3/sdl_window.h @@ -4,10 +4,12 @@ #include #include +#include "game/utils/settings.h" + bool has_gl_available(int major_version, int minor_version); bool create_gl_context(SDL_GLContext **context, SDL_Window *window); -bool create_window(SDL_Window **window, int width, int height, bool fullscreen); -bool resize_window(SDL_Window *window, int width, int height, bool fullscreen); +bool create_window(SDL_Window **window, int width, int height, window_mode window_mode); +bool resize_window(SDL_Window *window, int width, int height, window_mode window_mode); bool set_vsync(bool enable); void ortho2d(float *matrix, float left, float right, float bottom, float top); diff --git a/src/video/renderers/renderer.h b/src/video/renderers/renderer.h index e3b6d4b19..8d06e5427 100644 --- a/src/video/renderers/renderer.h +++ b/src/video/renderers/renderer.h @@ -4,6 +4,7 @@ #include #include +#include "game/utils/settings.h" #include "video/surface.h" typedef struct renderer renderer; @@ -21,12 +22,12 @@ typedef void (*init_renderer_fn)(renderer *renderer); typedef void (*close_renderer_fn)(renderer *renderer); // Renderer initialization and de-initialization, these must be implemented. -typedef bool (*setup_context_fn)(void *ctx, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, +typedef bool (*setup_context_fn)(void *ctx, int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode); -typedef void (*get_context_state_fn)(void *ctx, int *window_w, int *window_h, bool *fullscreen, bool *vsync, +typedef void (*get_context_state_fn)(void *ctx, int *window_w, int *window_h, window_mode *window_mode, bool *vsync, int *aspect, int *fb_scale); -typedef bool (*reset_context_with_fn)(void *ctx, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, - int framerate_limit, int fb_scale, int scaling_mode); +typedef bool (*reset_context_with_fn)(void *ctx, int window_w, int window_h, window_mode window_mode, bool vsync, + int aspect, int framerate_limit, int fb_scale, int scaling_mode); typedef void (*reset_context_fn)(void *ctx); typedef void (*close_context_fn)(void *ctx); diff --git a/src/video/video.c b/src/video/video.c index 8435e68ab..74875918c 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -153,13 +153,13 @@ static bool video_find_renderer(const char *try_name) { return false; } -bool video_init(const char *try_name, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, +bool video_init(const char *try_name, int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode) { if(!video_find_renderer(try_name)) { goto exit_0; } current_renderer.create(¤t_renderer); - if(!current_renderer.setup_context(current_renderer.ctx, window_w, window_h, fullscreen, vsync, aspect, + if(!current_renderer.setup_context(current_renderer.ctx, window_w, window_h, window_mode, vsync, aspect, framerate_limit, fb_scale, scaling_mode)) { goto exit_1; } @@ -179,9 +179,9 @@ void video_reinit_renderer(void) { current_renderer.reset_context(current_renderer.ctx); } -bool video_reinit(int window_w, int window_h, bool fullscreen, bool vsync, int aspect, int framerate_limit, +bool video_reinit(int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode) { - return current_renderer.reset_context_with(current_renderer.ctx, window_w, window_h, fullscreen, vsync, aspect, + return current_renderer.reset_context_with(current_renderer.ctx, window_w, window_h, window_mode, vsync, aspect, framerate_limit, fb_scale, scaling_mode); } @@ -214,8 +214,8 @@ void video_move_target(int x, int y) { current_renderer.move_target(current_renderer.ctx, x, y); } -void video_get_state(int *w, int *h, bool *fs, bool *vsync, int *aspect, int *fb_scale) { - current_renderer.get_context_state(current_renderer.ctx, w, h, fs, vsync, aspect, fb_scale); +void video_get_state(int *w, int *h, window_mode *window_mode, bool *vsync, int *aspect, int *fb_scale) { + current_renderer.get_context_state(current_renderer.ctx, w, h, window_mode, vsync, aspect, fb_scale); } void video_schedule_screenshot(video_screenshot_signal callback) { diff --git a/src/video/video.h b/src/video/video.h index db2a4d3c6..46e6e973f 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -9,6 +9,7 @@ #include #include +#include "game/utils/settings.h" #include "video/surface.h" #define NATIVE_W 320 ///< Native game resolution width @@ -47,7 +48,7 @@ bool video_get_renderer_info(int index, const char **name, const char **descript * @param try_name Preferred renderer name (NULL to use the best available) * @param window_w Window width in pixels * @param window_h Window height in pixels - * @param fullscreen Enable fullscreen mode + * @param window_mode Window mode (WINDOW_MODE_WINDOWED, WINDOW_MODE_FULLSCREEN, WINDOW_MODE_BORDERLESS) * @param vsync Enable vertical sync * @param aspect Aspect ratio mode * @param framerate_limit Maximum framerate (0 for unlimited) @@ -55,14 +56,14 @@ bool video_get_renderer_info(int index, const char **name, const char **descript * @param scaling_mode Scaling algorithm mode * @return true on success, false on failure */ -bool video_init(const char *try_name, int window_w, int window_h, bool fullscreen, bool vsync, int aspect, +bool video_init(const char *try_name, int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode); /** * @brief Reinitialize video with new settings (keeps current renderer) * @param window_w Window width in pixels * @param window_h Window height in pixels - * @param fullscreen Enable fullscreen mode + * @param window_mode Window mode (WINDOW_MODE_WINDOWED, WINDOW_MODE_FULLSCREEN, WINDOW_MODE_BORDERLESS) * @param vsync Enable vertical sync * @param aspect Aspect ratio mode * @param framerate_limit Maximum framerate (0 for unlimited) @@ -70,7 +71,7 @@ bool video_init(const char *try_name, int window_w, int window_h, bool fullscree * @param scaling_mode Scaling algorithm mode * @return true on success, false on failure */ -bool video_reinit(int window_w, int window_h, bool fullscreen, bool vsync, int aspect, int framerate_limit, +bool video_reinit(int window_w, int window_h, window_mode window_mode, bool vsync, int aspect, int framerate_limit, int fb_scale, int scaling_mode); /** @@ -82,12 +83,12 @@ void video_reinit_renderer(void); * @brief Get current video state * @param w Output for window width (can be NULL) * @param h Output for window height (can be NULL) - * @param fs Output for fullscreen state (can be NULL) + * @param window_mode Output for window mode (can be NULL) * @param vsync Output for vsync state (can be NULL) * @param aspect Output for aspect ratio mode (can be NULL) * @param fb_scale Output for framebuffer scale (can be NULL) */ -void video_get_state(int *w, int *h, bool *fs, bool *vsync, int *aspect, int *fb_scale); +void video_get_state(int *w, int *h, window_mode *window_mode, bool *vsync, int *aspect, int *fb_scale); /** * @brief Move the rendering target position