diff --git a/config.def.h b/config.def.h index fd350ad07e..760a089aed 100644 --- a/config.def.h +++ b/config.def.h @@ -156,7 +156,8 @@ static const unsigned rewind_buffer_size = 20 << 20; // 20MiB // How many frames to rewind at a time. static const unsigned rewind_granularity = 1; - +// Pause gameplay when gameplay loses focus. +static const bool pause_nonactive = true; //////////////////// diff --git a/driver.h b/driver.h index 35247020a9..07d0da34bc 100644 --- a/driver.h +++ b/driver.h @@ -110,6 +110,7 @@ typedef struct video_driver void (*set_nonblock_state)(void* data, bool toggle); // Should we care about syncing to vblank? Fast forwarding. // Is the window still active? bool (*alive)(void *data); + bool (*focus)(void *data); // Does the window have focus? void (*free)(void* data); const char *ident; } video_driver_t; diff --git a/general.h b/general.h index b763b98e24..fc3d453653 100644 --- a/general.h +++ b/general.h @@ -90,6 +90,8 @@ struct settings bool rewind_enable; unsigned rewind_buffer_size; unsigned rewind_granularity; + + bool pause_nonactive; }; enum ssnes_game_type diff --git a/gfx/gl.c b/gfx/gl.c index bfec6c50cb..6a8a3bf300 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -553,11 +553,18 @@ static bool gl_alive(void *data) return !gl->quitting; } +static bool gl_focus(void *data) +{ + (void)data; + return (SDL_GetAppState() & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) == (SDL_APPINPUTFOCUS | SDL_APPACTIVE); +} + const video_driver_t video_gl = { .init = gl_init, .frame = gl_frame, .alive = gl_alive, .set_nonblock_state = gl_set_nonblock_state, + .focus = gl_focus, .free = gl_free, .ident = "gl" }; diff --git a/input/sdl.c b/input/sdl.c index 66b9561193..52c5feb540 100644 --- a/input/sdl.c +++ b/input/sdl.c @@ -322,7 +322,7 @@ static void sdl_input_poll(void *data) *sdl->should_resize = true; } break; - + default: break; } diff --git a/settings.c b/settings.c index 2edf005d3c..af031c72b5 100644 --- a/settings.c +++ b/settings.c @@ -127,6 +127,7 @@ static void set_defaults(void) g_settings.rewind_enable = rewind_enable; g_settings.rewind_buffer_size = rewind_buffer_size; g_settings.rewind_granularity = rewind_granularity; + g_settings.pause_nonactive = pause_nonactive; assert(sizeof(g_settings.input.binds[0]) >= sizeof(snes_keybinds_1)); assert(sizeof(g_settings.input.binds[1]) >= sizeof(snes_keybinds_2)); @@ -320,6 +321,8 @@ static void parse_config_file(void) CONFIG_GET_INT(rewind_granularity, "rewind_granularity"); + CONFIG_GET_BOOL(pause_nonactive, "pause_nonactive"); + read_keybinds(conf); config_file_free(conf); diff --git a/ssnes.c b/ssnes.c index ed507edb97..f4287d33ca 100644 --- a/ssnes.c +++ b/ssnes.c @@ -943,7 +943,14 @@ static void check_pause(void) { static bool old_state = false; bool new_state = driver.input->key_pressed(driver.input_data, SSNES_PAUSE_TOGGLE); - if (new_state && !old_state) + + static bool old_focus = true; + bool focus = true; + + if (g_settings.pause_nonactive) + focus = driver.video->focus(driver.video_data); + + if (focus && new_state && !old_state) { g_extern.is_paused = !g_extern.is_paused; @@ -960,7 +967,22 @@ static void check_pause(void) driver.audio->start(driver.audio_data); } } + else if (focus && !old_focus) + { + SSNES_LOG("Unpaused!\n"); + g_extern.is_paused = false; + if (driver.audio_data) + driver.audio->start(driver.audio_data); + } + else if (!focus && old_focus) + { + SSNES_LOG("Paused!\n"); + g_extern.is_paused = true; + if (driver.audio_data) + driver.audio->stop(driver.audio_data); + } + old_focus = focus; old_state = new_state; } diff --git a/ssnes.cfg b/ssnes.cfg index 47f4ccabc9..8dbf70698c 100644 --- a/ssnes.cfg +++ b/ssnes.cfg @@ -212,3 +212,5 @@ # Toggle between paused and non-paused state # input_pause_toggle = p +# Pause gameplay when window focus is lost. +# pause_nonactive = true