diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp
index d2dd46805..fdcf68423 100644
--- a/src/core/host_interface.cpp
+++ b/src/core/host_interface.cpp
@@ -417,6 +417,8 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetFloatValue("Main", "FastForwardSpeed", 0.0f);
si.SetBoolValue("Main", "IncreaseTimerResolution", true);
si.SetBoolValue("Main", "StartPaused", false);
+ si.SetBoolValue("Main", "StartFullscreen", false);
+ si.SetBoolValue("Main", "PauseOnFocusLoss", false);
si.SetBoolValue("Main", "SaveStateOnExit", true);
si.SetBoolValue("Main", "ConfirmPowerOff", true);
si.SetBoolValue("Main", "LoadDevicesFromSaveStates", false);
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 5c621e18f..611c45adc 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -114,6 +114,7 @@ void Settings::Load(SettingsInterface& si)
increase_timer_resolution = si.GetBoolValue("Main", "IncreaseTimerResolution", true);
start_paused = si.GetBoolValue("Main", "StartPaused", false);
start_fullscreen = si.GetBoolValue("Main", "StartFullscreen", false);
+ pause_on_focus_loss = si.GetBoolValue("Main", "PauseOnFocusLoss", false);
save_state_on_exit = si.GetBoolValue("Main", "SaveStateOnExit", true);
confim_power_off = si.GetBoolValue("Main", "ConfirmPowerOff", true);
load_devices_from_save_states = si.GetBoolValue("Main", "LoadDevicesFromSaveStates", false);
@@ -259,6 +260,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("Main", "IncreaseTimerResolution", increase_timer_resolution);
si.SetBoolValue("Main", "StartPaused", start_paused);
si.SetBoolValue("Main", "StartFullscreen", start_fullscreen);
+ si.SetBoolValue("Main", "PauseOnFocusLoss", pause_on_focus_loss);
si.SetBoolValue("Main", "SaveStateOnExit", save_state_on_exit);
si.SetBoolValue("Main", "ConfirmPowerOff", confim_power_off);
si.SetBoolValue("Main", "LoadDevicesFromSaveStates", load_devices_from_save_states);
diff --git a/src/core/settings.h b/src/core/settings.h
index 75811d1c7..27b9a49be 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -83,6 +83,7 @@ struct Settings
bool increase_timer_resolution = true;
bool start_paused = false;
bool start_fullscreen = false;
+ bool pause_on_focus_loss = false;
bool save_state_on_exit = true;
bool confim_power_off = true;
bool load_devices_from_save_states = false;
diff --git a/src/duckstation-qt/generalsettingswidget.cpp b/src/duckstation-qt/generalsettingswidget.cpp
index 36e8c2cac..ee9e46ff9 100644
--- a/src/duckstation-qt/generalsettingswidget.cpp
+++ b/src/duckstation-qt/generalsettingswidget.cpp
@@ -17,6 +17,8 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW
}
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.pauseOnStart, "Main", "StartPaused", false);
+ SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.pauseOnFocusLoss, "Main", "PauseOnFocusLoss",
+ false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.startFullscreen, "Main", "StartFullscreen",
false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.renderToMain, "Main", "RenderToMainWindow", true);
@@ -87,7 +89,7 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW
"to use XInput over SDL2 for compatibility."));
// Since this one is compile-time selected, we don't put it in the .ui file.
- int current_col = 0;
+ int current_col = 1;
int current_row = m_ui.formLayout_4->rowCount() - current_col;
#ifdef WITH_DISCORD_PRESENCE
{
diff --git a/src/duckstation-qt/generalsettingswidget.ui b/src/duckstation-qt/generalsettingswidget.ui
index b1a0b3637..1ecb084ba 100644
--- a/src/duckstation-qt/generalsettingswidget.ui
+++ b/src/duckstation-qt/generalsettingswidget.ui
@@ -32,7 +32,7 @@
Behaviour
- -
+
-
Confirm Power Off
@@ -53,6 +53,13 @@
+ -
+
+
+ Pause On Focus Loss
+
+
+
-
@@ -60,20 +67,13 @@
- -
+
-
Save State On Exit
- -
-
-
- Load Devices From Save States
-
-
-
-
@@ -88,6 +88,13 @@
+ -
+
+
+ Load Devices From Save States
+
+
+
diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp
index 1d0c22a9c..ec9216bde 100644
--- a/src/duckstation-qt/mainwindow.cpp
+++ b/src/duckstation-qt/mainwindow.cpp
@@ -342,6 +342,31 @@ void MainWindow::onRunningGameChanged(const QString& filename, const QString& ga
m_display_widget->setWindowTitle(windowTitle());
}
+void MainWindow::onApplicationStateChanged(Qt::ApplicationState state)
+{
+ if (!m_emulation_running || !g_settings.pause_on_focus_loss)
+ return;
+
+ const bool focus_loss = (state != Qt::ApplicationActive);
+ if (focus_loss)
+ {
+ if (!m_was_paused_by_focus_loss && !System::IsPaused())
+ {
+ m_host_interface->pauseSystem(true);
+ m_was_paused_by_focus_loss = true;
+ }
+ }
+ else
+ {
+ if (m_was_paused_by_focus_loss)
+ {
+ if (System::IsPaused())
+ m_host_interface->pauseSystem(false);
+ m_was_paused_by_focus_loss = false;
+ }
+ }
+}
+
void MainWindow::onStartDiscActionTriggered()
{
QString filename =
@@ -796,6 +821,8 @@ void MainWindow::connectSignals()
updateEmulationActions(false, false);
onEmulationPaused(false);
+ connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
+
connect(m_ui.actionStartDisc, &QAction::triggered, this, &MainWindow::onStartDiscActionTriggered);
connect(m_ui.actionStartBios, &QAction::triggered, this, &MainWindow::onStartBIOSActionTriggered);
connect(m_ui.actionResumeLastState, &QAction::triggered, m_host_interface,
diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h
index d0c0519c9..4ce0393e0 100644
--- a/src/duckstation-qt/mainwindow.h
+++ b/src/duckstation-qt/mainwindow.h
@@ -60,6 +60,7 @@ private Q_SLOTS:
void onSystemPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time,
float worst_frame_time);
void onRunningGameChanged(const QString& filename, const QString& game_code, const QString& game_title);
+ void onApplicationStateChanged(Qt::ApplicationState state);
void onStartDiscActionTriggered();
void onStartBIOSActionTriggered();
@@ -137,4 +138,5 @@ private:
CheatManagerDialog* m_cheat_manager_dialog = nullptr;
bool m_emulation_running = false;
+ bool m_was_paused_by_focus_loss = false;
};