From d0108b3572f5604e9cd3234d8bef86d4d35a0a98 Mon Sep 17 00:00:00 2001 From: jasaaved Date: Wed, 25 Mar 2026 00:39:19 -0700 Subject: [PATCH] Add monitor selector functionality for windowed When using windowed mode, the game will launch on the monitor selected in the Display Monitor setting. If rendering to the main window and the selected monitor differs from the current one, the main window will be moved there and restored to its original position when the game ends. --- Source/Core/Core/Config/MainSettings.cpp | 2 +- Source/Core/Core/Config/MainSettings.h | 2 +- .../Config/Graphics/GeneralWidget.cpp | 11 ++++--- Source/Core/DolphinQt/MainWindow.cpp | 31 ++++++++++++++++++- Source/Core/DolphinQt/MainWindow.h | 1 + Source/Core/DolphinQt/RenderWidget.cpp | 7 +++-- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index f9c0a14a98..74c02db613 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -294,7 +294,7 @@ const Info MAIN_WII_NUS_SHOP_URL{{System::Main, "Core", "WiiNusShop const Info MAIN_FULLSCREEN_DISPLAY_RES{ {System::Main, "Display", "FullscreenDisplayRes"}, "Auto"}; const Info MAIN_FULLSCREEN{{System::Main, "Display", "Fullscreen"}, false}; -const Info MAIN_FULLSCREEN_MONITOR{{System::Main, "Display", "FullscreenMonitor"}, 0}; +const Info MAIN_DISPLAY_MONITOR{{System::Main, "Display", "DisplayMonitor"}, 0}; const Info MAIN_RENDER_TO_MAIN{{System::Main, "Display", "RenderToMain"}, false}; const Info MAIN_RENDER_WINDOW_XPOS{{System::Main, "Display", "RenderWindowXPos"}, -1}; const Info MAIN_RENDER_WINDOW_YPOS{{System::Main, "Display", "RenderWindowYPos"}, -1}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index a4788ad495..205155c18e 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -191,7 +191,7 @@ bool ShouldUseDPL2Decoder(); extern const Info MAIN_FULLSCREEN_DISPLAY_RES; extern const Info MAIN_FULLSCREEN; -extern const Info MAIN_FULLSCREEN_MONITOR; +extern const Info MAIN_DISPLAY_MONITOR; extern const Info MAIN_RENDER_TO_MAIN; extern const Info MAIN_RENDER_WINDOW_XPOS; extern const Info MAIN_RENDER_WINDOW_YPOS; diff --git a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp index fc18cbd57a..e1b225e3b4 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp @@ -98,11 +98,11 @@ void GeneralWidget::CreateWidgets() const QList screens = QGuiApplication::screens(); for (int i = 0; i < screens.size(); i++) m_monitor_combo->addItem(tr("Monitor %1: %2").arg(i + 1).arg(screens[i]->name())); - const int monitor_index = Config::Get(Config::MAIN_FULLSCREEN_MONITOR); + const int monitor_index = Config::Get(Config::MAIN_DISPLAY_MONITOR); if (monitor_index < m_monitor_combo->count()) m_monitor_combo->setCurrentIndex(monitor_index); - video_layout->addWidget(new QLabel(tr("Fullscreen Monitor:")), 4, 0); + video_layout->addWidget(new QLabel(tr("Display Monitor:")), 4, 0); video_layout->addWidget(m_monitor_combo, 4, 1, 1, -1); auto* const basic_grid = new QGridLayout; @@ -171,7 +171,7 @@ void GeneralWidget::ConnectWidgets() emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND))); }); connect(m_monitor_combo, &QComboBox::currentIndexChanged, this, [](int index) { - Config::SetBaseOrCurrent(Config::MAIN_FULLSCREEN_MONITOR, index); + Config::SetBaseOrCurrent(Config::MAIN_DISPLAY_MONITOR, index); }); connect(m_aspect_combo, &QComboBox::currentIndexChanged, this, &GeneralWidget::ToggleCustomAspectRatio); @@ -325,9 +325,10 @@ void GeneralWidget::AddDescriptions() m_adapter_combo->SetTitle(tr("Adapter")); - m_monitor_combo->SetTitle(tr("Fullscreen Monitor")); + m_monitor_combo->SetTitle(tr("Display Monitor")); m_monitor_combo->SetDescription( - tr("Selects which display to use for fullscreen.

" + tr("Selects which display to use when rendering.

" + "When rendering to the main window, the main window will be moved to this display.

" "If unsure, select Primary Monitor.")); m_aspect_combo->SetTitle(tr("Aspect Ratio")); diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 962f75e96c..d4e0c4cb3e 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -900,6 +901,12 @@ void MainWindow::OnStopComplete() { m_stop_requested = false; HideRenderWidget(!m_exit_requested, m_exit_requested); + + if (!m_pre_game_main_window_geometry.isEmpty()) + { + restoreGeometry(m_pre_game_main_window_geometry); + m_pre_game_main_window_geometry.clear(); + } #ifdef USE_DISCORD_PRESENCE if (!m_netplay_dialog->isVisible()) Discord::UpdateDiscordPresence(); @@ -1244,8 +1251,24 @@ void MainWindow::ShowRenderWidget() SetFullScreenResolution(false); Host::GetInstance()->SetRenderFullscreen(false); + const int monitor_index = Config::Get(Config::MAIN_DISPLAY_MONITOR); + const QList screens = QGuiApplication::screens(); + QScreen* const target_screen = (monitor_index > 0 && monitor_index <= screens.size()) + ? screens[monitor_index - 1] + : QGuiApplication::primaryScreen(); + if (Config::Get(Config::MAIN_RENDER_TO_MAIN)) { + // Move the main window to the selected monitor if it isn't already there. + // Guard with isEmpty() so fullscreen toggles don't overwrite the saved geometry. + if (monitor_index > 0 && screen() != target_screen && + m_pre_game_main_window_geometry.isEmpty()) + { + m_pre_game_main_window_geometry = saveGeometry(); + const QRect geo = target_screen->availableGeometry(); + move(geo.x() + (geo.width() - width()) / 2, geo.y() + (geo.height() - height()) / 2); + } + // If we're rendering to main, add it to the stack and update our title when necessary. m_rendering_to_main = true; @@ -1258,11 +1281,17 @@ void MainWindow::ShowRenderWidget() } else { - // Otherwise, just show it. + // Separate window: restore saved size, then center on the selected monitor if one is set. m_rendering_to_main = false; m_render_widget->showNormal(); m_render_widget->restoreGeometry(m_render_widget_geometry); + if (monitor_index > 0) + { + const QRect geo = target_screen->availableGeometry(); + m_render_widget->move(geo.x() + (geo.width() - m_render_widget->width()) / 2, + geo.y() + (geo.height() - m_render_widget->height()) / 2); + } } } diff --git a/Source/Core/DolphinQt/MainWindow.h b/Source/Core/DolphinQt/MainWindow.h index c0d5bd110e..f43fb059cf 100644 --- a/Source/Core/DolphinQt/MainWindow.h +++ b/Source/Core/DolphinQt/MainWindow.h @@ -291,4 +291,5 @@ private: WatchWidget* m_watch_widget; CheatsManager* m_cheats_manager{}; QByteArray m_render_widget_geometry; + QByteArray m_pre_game_main_window_geometry; }; diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index 37ebe5a0be..48c06150ae 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -206,13 +206,16 @@ void RenderWidget::HandleCursorTimer() void RenderWidget::showFullScreen() { - const int monitor_index = Config::Get(Config::MAIN_FULLSCREEN_MONITOR); + const int monitor_index = Config::Get(Config::MAIN_DISPLAY_MONITOR); const QList screens = QGuiApplication::screens(); QScreen* const target_screen = (monitor_index > 0 && monitor_index <= screens.size()) ? screens[monitor_index - 1] : QGuiApplication::primaryScreen(); if (monitor_index > 0) - move(target_screen->availableGeometry().topLeft()); + { + const QRect geo = target_screen->geometry(); + move(geo.x() + (geo.width() - width()) / 2, geo.y() + (geo.height() - height()) / 2); + } QWidget::showFullScreen();