diff --git a/CMakeLists.txt b/CMakeLists.txt index 788e8e24b..b35574801 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,15 @@ cmake_minimum_required(VERSION 3.22) project(citron) +# Define the build type, defaulting to "Nightly" for development and CI builds. +set(CITRON_BUILD_TYPE "Stable" CACHE STRING "The build type for the emulator (e.g., Stable, Nightly)") + +# For cmake-gui, this creates a dropdown to select the build type. +set_property(CACHE CITRON_BUILD_TYPE PROPERTY STRINGS Stable Nightly) + +# Pass the build type to the C++ source code as a preprocessor definition. +add_definitions("-DCITRON_BUILD_TYPE=\"${CITRON_BUILD_TYPE}\"") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") @@ -558,7 +567,7 @@ endif() function(set_citron_qt_components) # Best practice is to ask for all components at once, so they are from the same version -set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent) +set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent GuiPrivate) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") list(APPEND CITRON_QT_COMPONENTS2 DBus) endif() diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake index a568e4ea3..e6e226580 100644 --- a/CMakeModules/GenerateSCMRev.cmake +++ b/CMakeModules/GenerateSCMRev.cmake @@ -20,44 +20,60 @@ if (NOT GIT_BRANCH) endif() get_timestamp(BUILD_DATE) -# Generate cpp with Git revision from template -# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well -set(REPO_NAME "") -set(BUILD_VERSION "0") -set(BUILD_ID ${DISPLAY_VERSION}) -if (BUILD_REPOSITORY) - # regex capture the string nightly or canary into CMAKE_MATCH_1 - string(REGEX MATCH "citron-emu/citron-?(.*)" OUTVAR ${BUILD_REPOSITORY}) - if ("${CMAKE_MATCH_COUNT}" GREATER 0) - # capitalize the first letter of each word in the repo name. - string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1}) - foreach(WORD ${REPO_NAME_LIST}) - string(SUBSTRING ${WORD} 0 1 FIRST_LETTER) - string(SUBSTRING ${WORD} 1 -1 REMAINDER) - string(TOUPPER ${FIRST_LETTER} FIRST_LETTER) - set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}") - endforeach() - if (BUILD_TAG) - string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG}) - if (${CMAKE_MATCH_COUNT} GREATER 0) - set(BUILD_VERSION ${CMAKE_MATCH_1}) - endif() - if (BUILD_VERSION) - # This leaves a trailing space on the last word, but we actually want that - # because of how it's styled in the title bar. - set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") - else() - set(BUILD_FULLNAME "") +# +# Generate build information based on the CITRON_BUILD_TYPE variable. +# +if(CITRON_BUILD_TYPE STREQUAL "Stable") + # For Stable builds, use a clean version string and an empty build name for the title bar. + set(BUILD_FULLNAME "") + # These variables are set in the root CMakeLists.txt, but we provide a fallback. + if(DEFINED CITRON_VERSION_MAJOR) + set(BUILD_VERSION "${CITRON_VERSION_MAJOR}.${CITRON_VERSION_MINOR}.${CITRON_VERSION_PATCH}") + else() + set(BUILD_VERSION "0.11.0") # Fallback stable version + endif() + set(BUILD_ID ${DISPLAY_VERSION}) + +else() + # For Nightly or local developer builds, use the existing logic to generate a name and use the git hash. + set(REPO_NAME "") + set(BUILD_VERSION "0") + set(BUILD_ID ${DISPLAY_VERSION}) + if (BUILD_REPOSITORY) + # regex capture the string nightly or canary into CMAKE_MATCH_1 + string(REGEX MATCH "citron-emu/citron-?(.*)" OUTVAR ${BUILD_REPOSITORY}) + if ("${CMAKE_MATCH_COUNT}" GREATER 0) + # capitalize the first letter of each word in the repo name. + string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1}) + foreach(WORD ${REPO_NAME_LIST}) + string(SUBSTRING ${WORD} 0 1 FIRST_LETTER) + string(SUBSTRING ${WORD} 1 -1 REMAINDER) + string(TOUPPER ${FIRST_LETTER} FIRST_LETTER) + set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}") + endforeach() + if (BUILD_TAG) + string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG}) + if (${CMAKE_MATCH_COUNT} GREATER 0) + set(BUILD_VERSION ${CMAKE_MATCH_1}) + endif() + if (BUILD_VERSION) + # This leaves a trailing space on the last word, but we actually want that + # because of how it's styled in the title bar. + set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") + else() + set(BUILD_FULLNAME "") + endif() + endif() endif() endif() - endif() -endif() -# Add a fallback for local builds -# If BUILD_VERSION is still "0", it means the CI-specific logic was not executed. -# In that case, we should use the git description which contains the commit hash. -if (BUILD_VERSION STREQUAL "0") - set(BUILD_VERSION ${GIT_DESC}) + # Add a fallback for local builds + # If BUILD_VERSION is still "0", it means the CI-specific logic was not executed. + # In that case, we should use the git description which contains the commit hash. + if (BUILD_VERSION STREQUAL "0") + set(BUILD_FULLNAME "Nightly ") # Ensure local builds are also identified as Nightly + set(BUILD_VERSION ${GIT_DESC}) + endif() endif() configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY) diff --git a/src/citron/main.cpp b/src/citron/main.cpp index abbd9e0d1..870df1f51 100644 --- a/src/citron/main.cpp +++ b/src/citron/main.cpp @@ -1454,6 +1454,20 @@ void GMainWindow::InitializeHotkeys() { LinkActionShortcut(ui->action_Show_Room, QStringLiteral("Multiplayer Show Current Room")); LinkActionShortcut(ui->action_Leave_Room, QStringLiteral("Multiplayer Leave Room")); + // Create and connect a dedicated, robust QAction for exiting fullscreen. + action_exit_fullscreen = new QAction(this); + connect(action_exit_fullscreen, &QAction::triggered, this, [this] { + if (emulation_running && ui->action_Fullscreen->isChecked()) { + // Un-check the toggle to keep the UI in sync and then exit fullscreen. + ui->action_Fullscreen->setChecked(false); + ToggleFullscreen(); + } + }); + // Now bind the "Exit Fullscreen" hotkey (Esc by default) to this new QAction. + LinkActionShortcut(action_exit_fullscreen, QStringLiteral("Exit Fullscreen")); + + render_window->addAction(action_exit_fullscreen); + static const QString main_window = QStringLiteral("Main Window"); const auto connect_shortcut = [&](const QString& action_name, const Fn& function) { const auto* hotkey = @@ -1466,12 +1480,6 @@ void GMainWindow::InitializeHotkeys() { Qt::QueuedConnection); }; - connect_shortcut(QStringLiteral("Exit Fullscreen"), [&] { - if (emulation_running && ui->action_Fullscreen->isChecked()) { - ui->action_Fullscreen->setChecked(false); - ToggleFullscreen(); - } - }); connect_shortcut(QStringLiteral("Change Adapting Filter"), &GMainWindow::OnToggleAdaptingFilter); connect_shortcut(QStringLiteral("Change Docked Mode"), &GMainWindow::OnToggleDockedMode); @@ -5334,19 +5342,25 @@ void GMainWindow::MigrateConfigFiles() { void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, std::string_view gpu_vendor) { - std::string window_title = "citron | 0.11.0"; -#ifdef CITRON_ENABLE_PGO_USE - window_title += " | PGO"; -#endif + // Build the base title from the CMake-generated variables. + std::string base_title = "citron "; + base_title += Common::g_build_fullname; // This is "Nightly " or "" for Stable + base_title += "| "; + base_title += Common::g_build_version; // This is the git hash or Stable version tag. + + // Add the PGO tag if enabled. + #ifdef CITRON_ENABLE_PGO_USE + base_title += " | PGO"; + #endif if (title_name.empty()) { - setWindowTitle(QString::fromStdString(window_title)); + setWindowTitle(QString::fromStdString(base_title)); } else { - const auto run_title = [window_title, title_name, title_version, gpu_vendor]() { + const auto run_title = [&]() { if (title_version.empty()) { - return fmt::format("{} | {} | {}", window_title, title_name, gpu_vendor); + return fmt::format("{} | {} | {}", base_title, title_name, gpu_vendor); } - return fmt::format("{} | {} | {} | {}", window_title, title_name, title_version, + return fmt::format("{} | {} | {} | {}", base_title, title_name, title_version, gpu_vendor); }(); setWindowTitle(QString::fromStdString(run_title));