diff --git a/command.c b/command.c index 04118a1728..f29f2a76e6 100644 --- a/command.c +++ b/command.c @@ -73,6 +73,7 @@ #include "menu/menu_content.h" #include "menu/menu_display.h" #include "menu/menu_shader.h" +#include "menu/menu_popup.h" #endif #ifdef HAVE_NETPLAY @@ -1775,6 +1776,27 @@ static void command_event_main_state(unsigned cmd) RARCH_LOG("%s\n", msg); } +void handle_quit_event() +{ +#ifdef HAVE_MENU + if (menu_popup_is_active()) + return; +#endif + + command_event(CMD_EVENT_AUTOSAVE_STATE, NULL); + command_event(CMD_EVENT_DISABLE_OVERRIDES, NULL); + command_event(CMD_EVENT_RESTORE_DEFAULT_SHADER_PRESET, NULL); + +#ifdef HAVE_DYNAMIC + command_event(CMD_EVENT_LOAD_CORE_DEINIT, NULL); +#endif + + runloop_ctl(RUNLOOP_CTL_SET_SHUTDOWN, NULL); +#ifdef HAVE_MENU + rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); +#endif +} + /** * command_event: * @cmd : Event command index. @@ -1954,14 +1976,10 @@ bool command_event(enum event_command cmd, void *data) return false; break; case CMD_EVENT_UNLOAD_CORE: - case CMD_EVENT_QUIT: command_event(CMD_EVENT_AUTOSAVE_STATE, NULL); command_event(CMD_EVENT_DISABLE_OVERRIDES, NULL); command_event(CMD_EVENT_RESTORE_DEFAULT_SHADER_PRESET, NULL); - switch (cmd) - { - case CMD_EVENT_UNLOAD_CORE: if (content_is_inited()) if (!task_push_content_load_default( NULL, NULL, @@ -1975,25 +1993,17 @@ bool command_event(enum event_command cmd, void *data) core_unload(); #endif break; - default: + case CMD_EVENT_QUIT_CONFIRM: + handle_quit_event(); break; - } - -#ifdef HAVE_DYNAMIC - command_event(CMD_EVENT_LOAD_CORE_DEINIT, NULL); -#endif - - switch (cmd) - { case CMD_EVENT_QUIT: - runloop_ctl(RUNLOOP_CTL_SET_SHUTDOWN, NULL); #ifdef HAVE_MENU - rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); + if (settings && settings->confirm_on_exit && + !menu_popup_is_active() && !runloop_is_quit_confirm()) + menu_popup_show_message(MENU_POPUP_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT); + break; #endif - break; - default: - break; - } + handle_quit_event(); break; case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE: #ifdef HAVE_CHEEVOS diff --git a/command.h b/command.h index 0771f4fc33..55728fbeb2 100644 --- a/command.h +++ b/command.h @@ -59,6 +59,7 @@ enum event_command CMD_EVENT_TAKE_SCREENSHOT, /* Quits RetroArch. */ CMD_EVENT_QUIT, + CMD_EVENT_QUIT_CONFIRM, /* Reinitialize all drivers. */ CMD_EVENT_REINIT, /* Toggles cheevos hardcore mode. */ diff --git a/config.def.h b/config.def.h index 0ea69afb77..60d7b94f25 100644 --- a/config.def.h +++ b/config.def.h @@ -511,6 +511,8 @@ static unsigned aspect_ratio_idx = ASPECT_RATIO_CORE; /* Save configuration file on exit. */ static bool config_save_on_exit = true; +static bool confirm_on_exit = false; + static bool show_hidden_files = true; static const bool overlay_hide_in_menu = true; diff --git a/configuration.c b/configuration.c index 3cc6ab5faf..da13e689fd 100644 --- a/configuration.c +++ b/configuration.c @@ -796,6 +796,7 @@ static int populate_settings_bool(settings_t *settings, struct config_bool_setti SETTING_BOOL("sort_savefiles_enable", &settings->sort_savefiles_enable, true, default_sort_savefiles_enable, false); SETTING_BOOL("sort_savestates_enable", &settings->sort_savestates_enable, true, default_sort_savestates_enable, false); SETTING_BOOL("config_save_on_exit", &settings->config_save_on_exit, true, config_save_on_exit, false); + SETTING_BOOL("confirm_on_exit", &settings->confirm_on_exit, true, confirm_on_exit, false); SETTING_BOOL("show_hidden_files", &settings->show_hidden_files, true, show_hidden_files, false); SETTING_BOOL("input_autodetect_enable", &settings->input.autodetect_enable, true, input_autodetect_enable, false); SETTING_BOOL("audio_rate_control", &settings->audio.rate_control, true, rate_control, false); diff --git a/configuration.h b/configuration.h index dca3235b5a..cdb2c4f979 100644 --- a/configuration.h +++ b/configuration.h @@ -446,6 +446,7 @@ typedef struct settings #endif bool config_save_on_exit; + bool confirm_on_exit; bool show_hidden_files; #ifdef HAVE_LAKKA diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index 7b83d9b9ba..27be847065 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -991,6 +991,9 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) #endif ); break; + case MENU_ENUM_LABEL_CONFIRM_ON_EXIT: + snprintf(s, len, "Are you sure you want to quit?"); + break; case MENU_ENUM_LABEL_SHOW_HIDDEN_FILES: snprintf(s, len, "Show hidden files\n" "and folders."); @@ -2527,6 +2530,8 @@ static const char *menu_hash_to_str_us_label_enum(enum msg_hash_enums msg) return "auto_overrides_enable"; case MENU_ENUM_LABEL_CONFIG_SAVE_ON_EXIT: return "config_save_on_exit"; + case MENU_ENUM_LABEL_CONFIRM_ON_EXIT: + return "confirm_on_exit"; case MENU_ENUM_LABEL_SHOW_HIDDEN_FILES: return "show_hidden_files"; case MENU_ENUM_LABEL_VIDEO_SMOOTH: @@ -3854,6 +3859,8 @@ const char *msg_hash_to_str_us(enum msg_hash_enums msg) return "Load Override Files Automatically"; case MENU_ENUM_LABEL_VALUE_CONFIG_SAVE_ON_EXIT: return "Save Configuration On Exit"; + case MENU_ENUM_LABEL_VALUE_CONFIRM_ON_EXIT: + return "Ask For Confirmation On Exit"; case MENU_ENUM_LABEL_VALUE_SHOW_HIDDEN_FILES: return "Show Hidden Files and Folders"; case MENU_ENUM_LABEL_VALUE_VIDEO_SMOOTH: diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index ddef65045b..fe6f4f753b 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -1442,7 +1442,7 @@ static int action_ok_shader_pass_load(const char *path, static int generic_action_ok_help(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx, - enum msg_hash_enums id, enum menu_help_type id2) + enum msg_hash_enums id, enum menu_popup_type id2) { const char *lbl = msg_hash_to_str(id); @@ -1457,7 +1457,7 @@ static int action_ok_cheevos(const char *path, return generic_action_ok_help(path, label, new_id, idx, entry_idx, MENU_ENUM_LABEL_CHEEVOS_DESCRIPTION, - MENU_HELP_CHEEVOS_DESCRIPTION); + MENU_POPUP_HELP_CHEEVOS_DESCRIPTION); } static int action_ok_cheat(const char *path, @@ -3146,35 +3146,35 @@ static int action_ok_help_audio_video_troubleshooting(const char *path, { return generic_action_ok_help(path, label, type, idx, entry_idx, MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING, - MENU_HELP_AUDIO_VIDEO_TROUBLESHOOTING); + MENU_POPUP_HELP_AUDIO_VIDEO_TROUBLESHOOTING); } static int action_ok_help(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { return generic_action_ok_help(path, label, type, idx, entry_idx, - MENU_ENUM_LABEL_HELP, MENU_HELP_WELCOME); + MENU_ENUM_LABEL_HELP, MENU_POPUP_WELCOME); } static int action_ok_help_controls(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { return generic_action_ok_help(path, label, type, idx, entry_idx, - MENU_ENUM_LABEL_HELP_CONTROLS, MENU_HELP_CONTROLS); + MENU_ENUM_LABEL_HELP_CONTROLS, MENU_POPUP_HELP_CONTROLS); } static int action_ok_help_what_is_a_core(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { return generic_action_ok_help(path, label, type, idx, entry_idx, - MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE, MENU_HELP_WHAT_IS_A_CORE); + MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE, MENU_POPUP_HELP_WHAT_IS_A_CORE); } static int action_ok_help_scanning_content(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { return generic_action_ok_help(path, label, type, idx, entry_idx, - MENU_ENUM_LABEL_HELP_SCANNING_CONTENT, MENU_HELP_SCANNING_CONTENT); + MENU_ENUM_LABEL_HELP_SCANNING_CONTENT, MENU_POPUP_HELP_SCANNING_CONTENT); } static int action_ok_help_change_virtual_gamepad(const char *path, @@ -3182,14 +3182,14 @@ static int action_ok_help_change_virtual_gamepad(const char *path, { return generic_action_ok_help(path, label, type, idx, entry_idx, MENU_ENUM_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD, - MENU_HELP_CHANGE_VIRTUAL_GAMEPAD); + MENU_POPUP_HELP_CHANGE_VIRTUAL_GAMEPAD); } static int action_ok_help_load_content(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { return generic_action_ok_help(path, label, type, idx, entry_idx, - MENU_ENUM_LABEL_HELP_LOADING_CONTENT, MENU_HELP_LOADING_CONTENT); + MENU_ENUM_LABEL_HELP_LOADING_CONTENT, MENU_POPUP_HELP_LOADING_CONTENT); } static int action_ok_video_resolution(const char *path, diff --git a/menu/drivers/menu_generic.c b/menu/drivers/menu_generic.c index 684e1d3b7a..50004f2909 100644 --- a/menu/drivers/menu_generic.c +++ b/menu/drivers/menu_generic.c @@ -31,6 +31,9 @@ #include "../../performance_counters.h" #include "../../verbosity.h" +#include "../../runloop.h" +#include "../../content.h" +#include "../../retroarch.h" static enum action_iterate_type action_iterate_type(uint32_t hash) { @@ -100,12 +103,35 @@ int generic_menu_iterate(void *data, void *userdata, enum menu_action action) switch (iterate_type) { case ITERATE_TYPE_HELP: - ret = menu_popup_iterate_help( + ret = menu_popup_iterate( menu->menu_state.msg, sizeof(menu->menu_state.msg), label); BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); - if (ret == 1 || action == MENU_ACTION_OK || action == MENU_ACTION_CANCEL) + if (ret == 1 || action == MENU_ACTION_OK) + { BIT64_SET(menu->state, MENU_STATE_POP_STACK); + menu_popup_set_active(false); + + if (menu_popup_get_current_type() == MENU_POPUP_QUIT_CONFIRM) + { + runloop_set_quit_confirm(true); + command_event(CMD_EVENT_QUIT_CONFIRM, NULL); + } + } + + if (action == MENU_ACTION_CANCEL) + { + BIT64_SET(menu->state, MENU_STATE_POP_STACK); + menu_popup_set_active(false); + + if (menu_popup_get_current_type() == MENU_POPUP_QUIT_CONFIRM) + { + runloop_set_quit_confirm(false); + + if (content_is_inited()) + rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); + } + } break; case ITERATE_TYPE_BIND: { @@ -214,6 +240,7 @@ int generic_menu_iterate(void *data, void *userdata, enum menu_action action) BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); if (action == MENU_ACTION_OK || action == MENU_ACTION_CANCEL) BIT64_SET(menu->state, MENU_STATE_POP_STACK); + menu_popup_set_active(false); break; case ITERATE_TYPE_DEFAULT: /* FIXME: Crappy hack, needed for mouse controls diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 3b2362f983..a3572bb19a 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -4338,6 +4338,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CONFIG_SAVE_ON_EXIT, PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_CONFIRM_ON_EXIT, + PARSE_ONLY_BOOL, false); menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_CORE_SPECIFIC_CONFIG, PARSE_ONLY_BOOL, false); diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 08dff17096..13fb9ebc18 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -172,7 +172,7 @@ static bool menu_init(menu_handle_t *menu_data) if (settings->menu_show_start_screen) { - menu_popup_push_pending(true, MENU_HELP_WELCOME); + menu_popup_push_pending(true, MENU_POPUP_WELCOME); settings->menu_show_start_screen = false; command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL); } @@ -188,7 +188,7 @@ static bool menu_init(menu_handle_t *menu_data) #endif ) { - menu_popup_push_pending(true, MENU_HELP_EXTRACT); + menu_popup_push_pending(true, MENU_POPUP_HELP_EXTRACT); #ifdef HAVE_ZLIB task_push_decompress(settings->path.bundle_assets_src, settings->path.bundle_assets_dst, diff --git a/menu/menu_popup.c b/menu/menu_popup.c index 0bb17f68f9..ca43cacbdb 100644 --- a/menu/menu_popup.c +++ b/menu/menu_popup.c @@ -19,6 +19,7 @@ #include "menu_driver.h" #include "menu_popup.h" +#include "../retroarch.h" #include "../configuration.h" #ifdef HAVE_CHEEVOS #include "../cheevos.h" @@ -27,10 +28,12 @@ #include "../input/input_config.h" static bool menu_popup_pending_push = false; +static bool menu_popup_active = false; static unsigned menu_popup_current_id = 0; -static enum menu_help_type menu_popup_current_type = MENU_HELP_NONE; +static enum menu_popup_type menu_popup_current_type = MENU_POPUP_NONE; +static enum msg_hash_enums menu_popup_current_msg = MSG_UNKNOWN; -int menu_popup_iterate_help(char *s, size_t len, const char *label) +int menu_popup_iterate(char *s, size_t len, const char *label) { #ifdef HAVE_CHEEVOS cheevos_ctx_desc_t desc_info; @@ -40,7 +43,7 @@ int menu_popup_iterate_help(char *s, size_t len, const char *label) switch (menu_popup_current_type) { - case MENU_HELP_WELCOME: + case MENU_POPUP_WELCOME: { static int64_t timeout_end; int64_t timeout; @@ -71,7 +74,7 @@ int menu_popup_iterate_help(char *s, size_t len, const char *label) } } break; - case MENU_HELP_CONTROLS: + case MENU_POPUP_HELP_CONTROLS: { unsigned i; char s2[PATH_MAX_LENGTH] = {0}; @@ -169,7 +172,7 @@ int menu_popup_iterate_help(char *s, size_t len, const char *label) break; #ifdef HAVE_CHEEVOS - case MENU_HELP_CHEEVOS_DESCRIPTION: + case MENU_POPUP_HELP_CHEEVOS_DESCRIPTION: desc_info.idx = menu_popup_current_id; desc_info.s = s; desc_info.len = len; @@ -177,29 +180,29 @@ int menu_popup_iterate_help(char *s, size_t len, const char *label) break; #endif - case MENU_HELP_WHAT_IS_A_CORE: + case MENU_POPUP_HELP_WHAT_IS_A_CORE: menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_WHAT_IS_A_CORE_DESC, s, len); break; - case MENU_HELP_LOADING_CONTENT: + case MENU_POPUP_HELP_LOADING_CONTENT: menu_hash_get_help_enum(MENU_ENUM_LABEL_LOAD_CONTENT_LIST, s, len); break; - case MENU_HELP_CHANGE_VIRTUAL_GAMEPAD: + case MENU_POPUP_HELP_CHANGE_VIRTUAL_GAMEPAD: menu_hash_get_help_enum( MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD_DESC, s, len); break; - case MENU_HELP_AUDIO_VIDEO_TROUBLESHOOTING: + case MENU_POPUP_HELP_AUDIO_VIDEO_TROUBLESHOOTING: menu_hash_get_help_enum( MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING_DESC, s, len); break; - case MENU_HELP_SCANNING_CONTENT: + case MENU_POPUP_HELP_SCANNING_CONTENT: menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_HELP_SCANNING_CONTENT_DESC, s, len); break; - case MENU_HELP_EXTRACT: + case MENU_POPUP_HELP_EXTRACT: menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_EXTRACTING_PLEASE_WAIT, s, len); @@ -209,14 +212,22 @@ int menu_popup_iterate_help(char *s, size_t len, const char *label) do_exit = true; } break; - case MENU_HELP_NONE: + case MENU_POPUP_QUIT_CONFIRM: + case MENU_POPUP_INFORMATION: + case MENU_POPUP_QUESTION: + case MENU_POPUP_WARNING: + case MENU_POPUP_ERROR: + menu_hash_get_help_enum(menu_popup_current_msg, + s, len); + break; + case MENU_POPUP_NONE: default: break; } if (do_exit) { - menu_popup_current_type = MENU_HELP_NONE; + menu_popup_current_type = MENU_POPUP_NONE; return 1; } @@ -233,10 +244,11 @@ void menu_popup_unset_pending_push(void) menu_popup_pending_push = false; } -void menu_popup_push_pending(bool push, enum menu_help_type type) +void menu_popup_push_pending(bool push, enum menu_popup_type type) { menu_popup_pending_push = push; menu_popup_current_type = type; + menu_popup_active = true; } void menu_popup_push(void) @@ -259,5 +271,30 @@ void menu_popup_reset(void) { menu_popup_pending_push = false; menu_popup_current_id = 0; - menu_popup_current_type = MENU_HELP_NONE; + menu_popup_current_type = MENU_POPUP_NONE; + menu_popup_current_msg = MSG_UNKNOWN; +} + +void menu_popup_show_message( + enum menu_popup_type type, enum msg_hash_enums msg) +{ + menu_popup_current_msg = msg; + + menu_popup_push_pending(true, type); + menu_popup_push(); +} + +bool menu_popup_is_active(void) +{ + return menu_popup_active; +} + +void menu_popup_set_active(bool on) +{ + menu_popup_active = on; +} + +enum menu_popup_type menu_popup_get_current_type(void) +{ + return menu_popup_current_type; } diff --git a/menu/menu_popup.h b/menu/menu_popup.h index ee1158730e..595eaf791c 100644 --- a/menu/menu_popup.h +++ b/menu/menu_popup.h @@ -24,27 +24,32 @@ #include -enum menu_help_type +enum menu_popup_type { - MENU_HELP_NONE = 0, - MENU_HELP_WELCOME, - MENU_HELP_EXTRACT, - MENU_HELP_CONTROLS, - MENU_HELP_CHEEVOS_DESCRIPTION, - MENU_HELP_LOADING_CONTENT, - MENU_HELP_WHAT_IS_A_CORE, - MENU_HELP_CHANGE_VIRTUAL_GAMEPAD, - MENU_HELP_AUDIO_VIDEO_TROUBLESHOOTING, - MENU_HELP_SCANNING_CONTENT, - MENU_HELP_LAST + MENU_POPUP_NONE = 0, + MENU_POPUP_WELCOME, + MENU_POPUP_HELP_EXTRACT, + MENU_POPUP_HELP_CONTROLS, + MENU_POPUP_HELP_CHEEVOS_DESCRIPTION, + MENU_POPUP_HELP_LOADING_CONTENT, + MENU_POPUP_HELP_WHAT_IS_A_CORE, + MENU_POPUP_HELP_CHANGE_VIRTUAL_GAMEPAD, + MENU_POPUP_HELP_AUDIO_VIDEO_TROUBLESHOOTING, + MENU_POPUP_HELP_SCANNING_CONTENT, + MENU_POPUP_QUIT_CONFIRM, + MENU_POPUP_INFORMATION, + MENU_POPUP_QUESTION, + MENU_POPUP_WARNING, + MENU_POPUP_ERROR, + MENU_POPUP_LAST, }; RETRO_BEGIN_DECLS void menu_popup_push_pending( - bool push, enum menu_help_type type); + bool push, enum menu_popup_type type); -int menu_popup_iterate_help( +int menu_popup_iterate( char *s, size_t len, const char *label); void menu_popup_unset_pending_push(void); @@ -55,6 +60,15 @@ void menu_popup_push(void); void menu_popup_reset(void); +void menu_popup_show_message( + enum menu_popup_type type, enum msg_hash_enums msg); + +bool menu_popup_is_active(void); + +void menu_popup_set_active(bool on); + +enum menu_popup_type menu_popup_get_current_type(void); + RETRO_END_DECLS #endif diff --git a/menu/menu_setting.c b/menu/menu_setting.c index f810be7a67..122f01822a 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -2898,6 +2898,22 @@ static bool setting_append_list( SD_FLAG_NONE); menu_settings_list_current_add_enum_idx(list, list_info, MENU_ENUM_LABEL_CONFIG_SAVE_ON_EXIT); + CONFIG_BOOL( + list, list_info, + &settings->confirm_on_exit, + msg_hash_to_str(MENU_ENUM_LABEL_CONFIRM_ON_EXIT), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONFIRM_ON_EXIT), + confirm_on_exit, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON), + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + menu_settings_list_current_add_enum_idx(list, list_info, MENU_ENUM_LABEL_CONFIRM_ON_EXIT); + CONFIG_BOOL( list, list_info, &settings->show_hidden_files, diff --git a/msg_hash.h b/msg_hash.h index 9d2e114945..2a480e035e 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1149,6 +1149,9 @@ enum msg_hash_enums MENU_ENUM_LABEL_CONFIG_SAVE_ON_EXIT, MENU_ENUM_LABEL_VALUE_CONFIG_SAVE_ON_EXIT, + MENU_ENUM_LABEL_CONFIRM_ON_EXIT, + MENU_ENUM_LABEL_VALUE_CONFIRM_ON_EXIT, + MENU_ENUM_LABEL_SHOW_HIDDEN_FILES, MENU_ENUM_LABEL_VALUE_SHOW_HIDDEN_FILES, diff --git a/retroarch.cfg b/retroarch.cfg index 1dc3230a1f..8b57dc2b9c 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -119,6 +119,9 @@ # Overwrites the config. #include's and comments are not preserved. # config_save_on_exit = true +# Ask for confirmation on exit. +# confirm_on_exit = false + # Load up a specific config file based on the core being used. # core_specific_config = false diff --git a/runloop.c b/runloop.c index 957d7b4dc9..8c4f9f90cf 100644 --- a/runloop.c +++ b/runloop.c @@ -62,6 +62,7 @@ #ifdef HAVE_MENU #include "menu/menu_driver.h" +#include "menu/menu_popup.h" #endif #ifdef HAVE_NETPLAY @@ -118,6 +119,7 @@ static bool runloop_set_frame_limit = false; static bool runloop_paused = false; static bool runloop_idle = false; static bool runloop_exec = false; +static bool runloop_quit_confirm = false; static bool runloop_slowmotion = false; static bool runloop_shutdown_initiated = false; static bool runloop_core_shutdown_initiated = false; @@ -1320,6 +1322,16 @@ static int runloop_iterate_time_to_exit_load_dummy(void) return 1; } +bool runloop_is_quit_confirm(void) +{ + return runloop_quit_confirm; +} + +void runloop_set_quit_confirm(bool on) +{ + runloop_quit_confirm = on; +} + /* Time to exit out of the main loop? * Reasons for exiting: * a) Shutdown environment callback was invoked. @@ -1330,6 +1342,7 @@ static int runloop_iterate_time_to_exit_load_dummy(void) */ static INLINE int runloop_iterate_time_to_exit(bool quit_key_pressed) { + settings_t *settings = config_get_ptr(); bool time_to_exit = runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL); time_to_exit = time_to_exit || quit_key_pressed; time_to_exit = time_to_exit || !video_driver_is_alive(); @@ -1340,6 +1353,21 @@ static INLINE int runloop_iterate_time_to_exit(bool quit_key_pressed) if (!time_to_exit) return 1; +#ifdef HAVE_MENU + if (!runloop_quit_confirm && menu_popup_is_active()) + return 1; + + if (settings && settings->confirm_on_exit && + !runloop_quit_confirm) + { + if (content_is_inited()) + rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); + + menu_popup_show_message(MENU_POPUP_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT); + return 1; + } +#endif + if (runloop_ctl(RUNLOOP_CTL_IS_EXEC, NULL)) runloop_ctl(RUNLOOP_CTL_UNSET_EXEC, NULL); @@ -1509,7 +1537,6 @@ int runloop_iterate(unsigned *sleep_ms) return -1; } - #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { diff --git a/runloop.h b/runloop.h index c2c7625236..0774f55a9f 100644 --- a/runloop.h +++ b/runloop.h @@ -302,6 +302,9 @@ void runloop_msg_queue_push(const char *msg, unsigned prio, char* runloop_msg_queue_pull(void); +bool runloop_is_quit_confirm(void); +void runloop_set_quit_confirm(bool on); + bool runloop_ctl(enum runloop_ctl_state state, void *data); RETRO_END_DECLS