From a890902d5b83ae10ad1f2287b0cb82b6adeda860 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 16 Jul 2025 16:51:31 +1000 Subject: [PATCH] Qt: Further eliminate redundant window shows And remove a couple of hacks. --- src/duckstation-qt/displaywidget.cpp | 4 ---- src/duckstation-qt/mainwindow.cpp | 33 +++++++++++++--------------- src/duckstation-qt/mainwindow.h | 4 +++- src/duckstation-qt/qthost.cpp | 20 +++++------------ 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/duckstation-qt/displaywidget.cpp b/src/duckstation-qt/displaywidget.cpp index b4d42e90d..035cf6fb6 100644 --- a/src/duckstation-qt/displaywidget.cpp +++ b/src/duckstation-qt/displaywidget.cpp @@ -142,10 +142,6 @@ void DisplayWidget::handleCloseEvent(QCloseEvent* event) QMetaObject::invokeMethod(g_main_window, "requestShutdown", Qt::QueuedConnection, Q_ARG(bool, true), Q_ARG(bool, true), Q_ARG(bool, false), Q_ARG(bool, true)); } - else if (QtHost::IsFullscreenUIStarted()) - { - g_emu_thread->stopFullscreenUI(); - } else { QMetaObject::invokeMethod(g_main_window, "requestExit", Qt::QueuedConnection); diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 45edda922..e8e0c9f18 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -338,6 +338,11 @@ bool MainWindow::wantsDisplayWidget() const return (s_system_starting || s_system_valid || s_fullscreen_ui_started); } +bool MainWindow::hasDisplayWidget() const +{ + return m_display_widget != nullptr; +} + void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos) { // If we're rendering to main and were hidden (e.g. coming back from fullscreen), @@ -434,6 +439,8 @@ void MainWindow::releaseRenderWindow() { // Now we can safely destroy the display window. destroyDisplayWidget(true); + updateWindowTitle(); + updateWindowState(false); } void MainWindow::destroyDisplayWidget(bool show_game_list) @@ -824,11 +831,6 @@ void MainWindow::recreate() notifyRAIntegrationOfWindowChange(); } -void MainWindow::ensureVisible() -{ - updateWindowState(true); -} - void MainWindow::destroySubWindows() { QtUtils::CloseAndDeleteWindow(m_memory_scanner_window); @@ -2051,7 +2053,7 @@ void MainWindow::updateWindowState(bool force_visible) return; const bool hide_window = shouldHideMainWindow(); - const bool disable_resize = Host::GetBoolSettingValue("Main", "DisableWindowResize", false); + const bool disable_resize = (Host::GetBoolSettingValue("Main", "DisableWindowResize", false) && wantsDisplayWidget()); // Need to test both valid and display widget because of startup (vm invalid while window is created). const bool visible = force_visible || !hide_window; @@ -2793,14 +2795,6 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b lock.cancelResume(); } - // This is a little bit annoying. Qt will close everything down if we don't have at least one window visible, - // but we might not be visible because the user is using render-to-separate and hide. We don't want to always - // reshow the main window during display updates, because otherwise fullscreen transitions and renderer switches - // would briefly show and then hide the main window. So instead, we do it on shutdown, here. Except if we're in - // batch mode, when we're going to exit anyway. - if (!isRenderingToMain() && isHidden() && !QtHost::InBatchMode() && !s_fullscreen_ui_started) - updateWindowState(true); - // Now we can actually shut down the VM. g_emu_thread->shutdownSystem(save_state, check_memcard_busy); return true; @@ -2814,10 +2808,14 @@ void MainWindow::requestExit(bool allow_confirm /* = true */) // VM stopped signal won't have fired yet, so queue an exit if we still have one. // Otherwise, immediately exit, because there's no VM to exit us later. + m_is_closing = true; if (s_system_valid) - m_is_closing = true; - else - quit(); + return; + + if (s_fullscreen_ui_started) + g_emu_thread->stopFullscreenUI(); + + quit(); } void MainWindow::checkForSettingChanges() @@ -3203,7 +3201,6 @@ MainWindow::SystemLock MainWindow::pauseAndLockSystem() if (dialog_parent->parent()) dialog_parent = this; - return SystemLock(dialog_parent, was_paused, was_fullscreen); } diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index 3d27da81d..41f375088 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -95,6 +95,9 @@ public: /// Force quits the application. void quit(); + /// Returns true if there is any display widget, main or otherwise. + bool hasDisplayWidget() const; + /// Accessors for the status bar widgets, updated by the emulation thread. ALWAYS_INLINE QLabel* getStatusRendererWidget() const { return m_status_renderer_widget; } ALWAYS_INLINE QLabel* getStatusResolutionWidget() const { return m_status_resolution_widget; } @@ -125,7 +128,6 @@ public Q_SLOTS: void checkForUpdates(bool display_message); void recreate(); - void ensureVisible(); void* getNativeWindowId(); diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 186c16b22..1e350fd88 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -723,21 +723,17 @@ void EmuThread::stopFullscreenUI() QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection); // wait until the host display is gone - QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, - []() { return QtHost::IsFullscreenUIStarted(); }); + QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, []() { + return QtHost::IsFullscreenUIStarted() || g_main_window->hasDisplayWidget(); + }); return; } if (m_is_fullscreen_ui_started) { - // Need to switch out of fullscreen before stopping the fullscreen UI, otherwise Qt - // terminates the applcation because briefly there are no windows remaining. - if (m_is_fullscreen) - setFullscreen(false, true); - - GPUThread::StopFullscreenUI(); m_is_fullscreen_ui_started = false; emit fullscreenUIStartedOrStopped(false); + GPUThread::StopFullscreenUI(); } } @@ -751,10 +747,6 @@ void EmuThread::exitFullscreenUI() const bool was_in_nogui_mode = std::exchange(s_nogui_mode, false); - // force the main window to be visible, otherwise qt will terminate the application - QMetaObject::invokeMethod(g_main_window, &MainWindow::ensureVisible, Qt::QueuedConnection); - - // then stop as normal stopFullscreenUI(); // if we were in nogui mode, the game list won't have been populated yet. do it now. @@ -2909,8 +2901,8 @@ bool QtHost::ParseCommandLineParametersAndInitializeConfig(QApplication& app, if (autoboot && autoboot->path.empty() && autoboot->save_state.empty() && !starting_bios) autoboot.reset(); - // nogui implies batch mode if autobooting and not running big picture mode - s_batch_mode = (s_batch_mode || (autoboot && !s_start_fullscreen_ui)); + // nogui implies batch mode if not running big picture mode + s_batch_mode = (s_batch_mode || (s_nogui_mode && !s_start_fullscreen_ui)); // if we don't have autoboot, we definitely don't want batch mode (because that'll skip // scanning the game list).