From b4aa73df70be0146f861ccd318047e51ece599b9 Mon Sep 17 00:00:00 2001 From: siliconsniffer <97843108+siliconsniffer@users.noreply.github.com> Date: Sat, 22 Nov 2025 09:46:37 +0100 Subject: [PATCH] Add exit confirmation dialog on ESC in main menu (#16164) --- builtin/mainmenu/dlg_confirm_exit.lua | 54 +++++++++++++++++++++++++++ builtin/mainmenu/init.lua | 12 +++++- builtin/settingtypes.txt | 3 ++ src/defaultsettings.cpp | 1 + 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 builtin/mainmenu/dlg_confirm_exit.lua diff --git a/builtin/mainmenu/dlg_confirm_exit.lua b/builtin/mainmenu/dlg_confirm_exit.lua new file mode 100644 index 000000000..84dd35df9 --- /dev/null +++ b/builtin/mainmenu/dlg_confirm_exit.lua @@ -0,0 +1,54 @@ +-- Luanti +-- Copyright (C) 2025 siliconsniffer +-- SPDX-License-Identifier: LGPL-2.1-or-later + + +local function exit_dialog_formspec() + local show_dialog = core.settings:get_bool("enable_esc_dialog", true) + local formspec = { + "formspec_version[10]" .. + "size[10,3.6]" .. + "style_type[label;font=bold]" .. + "style[btn_quit_confirm_yes;bgcolor=red]" .. + "label[0.5,0.5;" .. fgettext("Are you sure you want to quit?") .. "]" .. + "checkbox[0.5,1.4;cb_show_dialog;" .. fgettext("Always show this dialog.") .. ";" .. tostring(show_dialog) .. "]" .. + "button[0.5,2.3;3,0.8;btn_quit_confirm_cancel;" .. fgettext("Cancel") .. "]" .. + "button[6.5,2.3;3,0.8;btn_quit_confirm_yes;" .. fgettext("Quit") .. "]" .. + "set_focus[btn_quit_confirm_yes]" + } + return table.concat(formspec, "") +end + + +local function exit_dialog_buttonhandler(this, fields) + if fields.cb_show_dialog ~= nil then + core.settings:set_bool("enable_esc_dialog", core.is_yes(fields.cb_show_dialog)) + return false + elseif fields.btn_quit_confirm_yes then + this:delete() + core.close() + return true + elseif fields.btn_quit_confirm_cancel then + this:delete() + this:show() + return true + end +end + + +local function event_handler(event) + if event == "DialogShow" then + mm_game_theme.set_engine(true) -- hide the menu header + return true + end + return false +end + + +function create_exit_dialog() + local retval = dialog_create("dlg_exit", + exit_dialog_formspec, + exit_dialog_buttonhandler, + event_handler) + return retval +end diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index c1bbc0ae4..01f071a46 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -28,6 +28,7 @@ dofile(menupath .. DIR_DELIM .. "content" .. DIR_DELIM .. "init.lua") dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(basepath .. "common" .. DIR_DELIM .. "settings" .. DIR_DELIM .. "init.lua") +dofile(menupath .. DIR_DELIM .. "dlg_confirm_exit.lua") dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") @@ -49,7 +50,16 @@ local tabs = { -------------------------------------------------------------------------------- local function main_event_handler(tabview, event) if event == "MenuQuit" then - core.close() + local show_dialog = core.settings:get_bool("enable_esc_dialog") + if not ui.childlist["mainmenu_quit_confirm"] and show_dialog then + tabview:hide() + local dlg = create_exit_dialog() + dlg:set_parent(tabview) + dlg:show() + else + core.close() + end + return true end return true end diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 550b31d66..001ef42e0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -162,6 +162,9 @@ autojump (Automatic jumping) bool false # On touchscreens, this only affects digging. safe_dig_and_place (Safe digging and placing) bool false +# Enable a confirmation dialog before closing. +enable_esc_dialog (Confirmation dialog before closing) bool true + [*Keyboard and Mouse] # Invert vertical mouse movement. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 7ec7878e3..5d2cbb0d1 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -370,6 +370,7 @@ void set_default_settings() settings->setDefault("toggle_sneak_key", "false"); settings->setDefault("toggle_aux1_key", "false"); settings->setDefault("autojump", bool_to_cstr(has_touch)); + settings->setDefault("enable_esc_dialog", "true"); settings->setDefault("continuous_forward", "false"); settings->setDefault("enable_joysticks", "false"); settings->setDefault("joystick_id", "0");