diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 47fa53498..82bbcf9a2 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -843,6 +843,28 @@ void GuiMenu::openOtherOptions() }); #endif + // Exit button configuration. + auto exit_button_config = std::make_shared> + (mWindow, getHelpStyle(), "EXIT BUTTON COMBO", false); + std::string selectedExitButtonCombo = Settings::getInstance()->getString("ExitButtonCombo"); + exit_button_config->add("F4", "F4", selectedExitButtonCombo == "F4"); + exit_button_config->add("Alt + F4", "AltF4", selectedExitButtonCombo == "AltF4"); + #if defined(_WIN64) || defined(__unix__) + exit_button_config->add("Alt + Q", "AltQ", selectedExitButtonCombo == "AltQ"); + #endif + #if defined(__APPLE__) + exit_button_config->add("\u2318 + Q", "CmdQ", selectedExitButtonCombo == "CmdQ"); + #endif + s->addWithLabel("EXIT BUTTON COMBO", exit_button_config); + s->addSaveFunc([exit_button_config, s] { + if (exit_button_config->getSelected() != + Settings::getInstance()->getString("ExitButtonCombo")) { + Settings::getInstance()->setString("ExitButtonCombo", + exit_button_config->getSelected()); + s->setNeedsSaving(); + } + }); + // When to save game metadata. auto save_gamelist_mode = std::make_shared>( mWindow, getHelpStyle(), "WHEN TO SAVE METADATA", false); diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index ad6ffb624..6b5d1bccc 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -28,6 +28,10 @@ int SDL_USER_CECBUTTONDOWN = -1; int SDL_USER_CECBUTTONUP = -1; +// Save button states for combo-button exit support and predefine exit option-function map. +static bool altDown = false; +static bool lguiDown = false; + InputManager* InputManager::sInstance = nullptr; InputManager::InputManager() @@ -426,13 +430,31 @@ bool InputManager::parseEvent(const SDL_Event& event, Window* window) return true; } case SDL_KEYDOWN: { + + // Save button states for alt and command. + if (event.key.keysym.sym == SDLK_LALT) + altDown = true; + if (event.key.keysym.sym == SDLK_LGUI) + lguiDown = true; + if (event.key.keysym.sym == SDLK_BACKSPACE && SDL_IsTextInputActive()) window->textInput("\b"); if (event.key.repeat) return false; - if (event.key.keysym.sym == SDLK_F4) { + // Handle application exit. + bool exitState; + std::string exitOption = Settings::getInstance()->getString("ExitButtonCombo"); + if (exitOption == "AltF4") + exitState = event.key.keysym.sym == SDLK_F4 && altDown; + else if (exitOption == "CmdQ") + exitState = event.key.keysym.sym == SDLK_q && lguiDown; + else if (exitOption == "AltQ") + exitState = event.key.keysym.sym == SDLK_q && altDown; + else + exitState = event.key.keysym.sym == SDLK_F4; + if (exitState) { SDL_Event quit; quit.type = SDL_QUIT; SDL_PushEvent(&quit); @@ -444,6 +466,13 @@ bool InputManager::parseEvent(const SDL_Event& event, Window* window) return true; } case SDL_KEYUP: { + + // Release button states. + if (event.key.keysym.sym == SDLK_LALT) + altDown = false; + if (event.key.keysym.sym == SDLK_LGUI) + lguiDown = false; + window->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, event.key.keysym.sym, 0, false)); return true; diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 86c4b663e..5b7b3b8e4 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -247,6 +247,7 @@ void Settings::setDefaults() mBoolMap["DisableComposition"] = { true, true }; #endif mBoolMap["DisplayGPUStatistics"] = { false, false }; + mStringMap["ExitButtonCombo"] = { "F4", "F4" }; // macOS requires root privileges to reboot and power off so it doesn't make much // sense to enable this setting and menu entry for that operating system. #if !defined(__APPLE__)