aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-26 22:59:59 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-26 22:59:59 -0500
commit99d9edb81c2f2342eccb3bc6d871b4b21a793636 (patch)
tree078419b6982b54b68e4bc51f910b42465c5e19e9
parent2f2554e1f4236acf808ea758ab0d0cf4d298b9ee (diff)
Force SLR for Proton launches
-rw-r--r--src/src/instancemanagerdialog.cpp28
-rw-r--r--src/src/instancemanagerdialog.ui7
-rw-r--r--src/src/mainwindow.cpp92
-rw-r--r--src/src/prefixsetuprunner.cpp64
-rw-r--r--src/src/prefixsetuprunner.h1
-rw-r--r--src/src/spawn.cpp4
6 files changed, 112 insertions, 84 deletions
diff --git a/src/src/instancemanagerdialog.cpp b/src/src/instancemanagerdialog.cpp
index f7b9bb1..06522dd 100644
--- a/src/src/instancemanagerdialog.cpp
+++ b/src/src/instancemanagerdialog.cpp
@@ -231,18 +231,6 @@ InstanceManagerDialog::InstanceManagerDialog(PluginContainer& pc, QWidget* paren
s.setValue("fluorine/steam_drm", checked);
});
- connect(ui->steamLinuxRuntimeCheckBox, &QCheckBox::toggled, [&](bool checked) {
- const auto* inst = singleSelection();
- if (!inst) return;
- const QString ini = inst->iniPath();
- if (ini.isEmpty()) return;
- QSettings s(ini, QSettings::IniFormat);
- s.setValue("fluorine/use_slr", checked);
- if (checked) {
- downloadSLRIfNeeded();
- }
- });
-
connect(ui->vfsRootBuilderCheckBox, &QCheckBox::toggled, [&](bool checked) {
const auto* inst = singleSelection();
if (!inst) return;
@@ -840,7 +828,7 @@ void InstanceManagerDialog::fillData(const Instance& ii)
ui->steamDrmCheckBox->blockSignals(false);
ui->steamLinuxRuntimeCheckBox->blockSignals(true);
- ui->steamLinuxRuntimeCheckBox->setChecked(s.value("fluorine/use_slr", true).toBool());
+ ui->steamLinuxRuntimeCheckBox->setChecked(true);
ui->steamLinuxRuntimeCheckBox->blockSignals(false);
ui->vfsRootBuilderCheckBox->blockSignals(true);
@@ -998,19 +986,7 @@ void InstanceManagerDialog::downloadSLRIfNeeded()
if (!err.isEmpty()) {
MOBase::log::error("[SLR] Download failed: {}", err);
QMessageBox::warning(this, tr("Steam Linux Runtime"),
- tr("Download failed:\n%1\n\nSLR has been disabled for this instance.")
- .arg(err));
- ui->steamLinuxRuntimeCheckBox->blockSignals(true);
- ui->steamLinuxRuntimeCheckBox->setChecked(false);
- ui->steamLinuxRuntimeCheckBox->blockSignals(false);
- const auto* inst = singleSelection();
- if (inst) {
- const QString ini = inst->iniPath();
- if (!ini.isEmpty()) {
- QSettings s(ini, QSettings::IniFormat);
- s.setValue("fluorine/use_slr", false);
- }
- }
+ tr("Download failed:\n%1").arg(err));
} else {
MOBase::log::info("[SLR] Steam Linux Runtime installed successfully");
progress->setLabelText(tr("Steam Linux Runtime is ready."));
diff --git a/src/src/instancemanagerdialog.ui b/src/src/instancemanagerdialog.ui
index 2bf1d0a..6a4e5ee 100644
--- a/src/src/instancemanagerdialog.ui
+++ b/src/src/instancemanagerdialog.ui
@@ -326,11 +326,14 @@
</item>
<item row="11" column="0" colspan="2">
<widget class="QCheckBox" name="steamLinuxRuntimeCheckBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
- <string>Use Steam Linux Runtime (SLR)</string>
+ <string>Steam Linux Runtime (required for Proton)</string>
</property>
<property name="toolTip">
- <string>Run games inside the Steam Linux Runtime container (pressure-vessel). Provides GStreamer, 32-bit libs, and other dependencies for non-FHS distros like NixOS. Requires Steam to be installed.</string>
+ <string>Proton launches always run inside the Steam Linux Runtime container. Native Linux executables are launched directly.</string>
</property>
<property name="checked">
<bool>true</bool>
diff --git a/src/src/mainwindow.cpp b/src/src/mainwindow.cpp
index eb92adf..f8f7e97 100644
--- a/src/src/mainwindow.cpp
+++ b/src/src/mainwindow.cpp
@@ -2400,61 +2400,51 @@ void MainWindow::on_startButton_clicked()
ui->startButton->setEnabled(true);
});
- // Pre-check: if this executable uses Proton and the current instance has SLR
- // enabled, ensure SLR is installed (and up-to-date with the latest steamrt4
- // BUILD_ID) before launching. downloadSlr() short-circuits on BUILD_ID match
- // so once SLR is current this is a single HTTP GET; no UI is shown unless
- // the runtime actually needs (re)downloading.
+ // Pre-check: Proton launches always use SLR. Native Linux executables skip
+ // this branch entirely. downloadSlr() short-circuits on BUILD_ID match, so
+ // once SLR is current this is a single HTTP GET; no UI is shown unless the
+ // runtime actually needs (re)downloading.
if (selectedExecutable->useProton()) {
- const auto* s = Settings::maybeInstance();
- bool useSLR = true;
- if (s) {
- QSettings const instanceIni(s->filename(), QSettings::IniFormat);
- useSLR = instanceIni.value("fluorine/use_slr", true).toBool();
- }
- if (useSLR) {
- const bool freshInstall = !isSlrInstalled();
- // Only show the heavyweight progress dialog on a fresh install.
- // Up-to-date checks happen quietly in the background here so we don't
- // block launch on a remote BUILD_ID fetch — the up-to-date case is
- // handled at startup by OrganizerCore::checkForSlrUpdates().
- if (freshInstall) {
- auto* progress = new QProgressDialog(
- tr("Downloading Steam Linux Runtime (~200 MB)...\n"
- "This is required to launch games. Check the MO2 log for details."),
- tr("Cancel"), 0, 0, this);
- progress->setWindowTitle(tr("Steam Linux Runtime"));
- progress->setWindowModality(Qt::WindowModal);
- progress->setAttribute(Qt::WA_ShowWithoutActivating);
- progress->setMinimumDuration(0);
+ const bool freshInstall = !isSlrInstalled();
+ // Only show the heavyweight progress dialog on a fresh install.
+ // Up-to-date checks happen quietly in the background here so we don't
+ // block launch on a remote BUILD_ID fetch — the up-to-date case is
+ // handled at startup by OrganizerCore::checkForSlrUpdates().
+ if (freshInstall) {
+ auto* progress = new QProgressDialog(
+ tr("Downloading Steam Linux Runtime (~200 MB)...\n"
+ "This is required to launch games. Check the MO2 log for details."),
+ tr("Cancel"), 0, 0, this);
+ progress->setWindowTitle(tr("Steam Linux Runtime"));
+ progress->setWindowModality(Qt::WindowModal);
+ progress->setAttribute(Qt::WA_ShowWithoutActivating);
+ progress->setMinimumDuration(0);
- int cancelFlag = 0;
- connect(progress, &QProgressDialog::canceled, this, [&cancelFlag] {
- cancelFlag = 1;
- });
+ int cancelFlag = 0;
+ connect(progress, &QProgressDialog::canceled, this, [&cancelFlag] {
+ cancelFlag = 1;
+ });
- QFutureWatcher<QString> watcher;
- QEventLoop loop;
- connect(&watcher, &QFutureWatcher<QString>::finished, &loop, &QEventLoop::quit);
- watcher.setFuture(QtConcurrent::run([&cancelFlag]() -> QString {
- return downloadSlr(nullptr, nullptr, &cancelFlag);
- }));
- progress->show();
- loop.exec();
- progress->close();
- progress->deleteLater();
+ QFutureWatcher<QString> watcher;
+ QEventLoop loop;
+ connect(&watcher, &QFutureWatcher<QString>::finished, &loop, &QEventLoop::quit);
+ watcher.setFuture(QtConcurrent::run([&cancelFlag]() -> QString {
+ return downloadSlr(nullptr, nullptr, &cancelFlag);
+ }));
+ progress->show();
+ loop.exec();
+ progress->close();
+ progress->deleteLater();
- const QString err = watcher.result();
- if (cancelFlag) {
- return; // user cancelled, don't launch
- }
- if (!err.isEmpty()) {
- log::error("[SLR] Download failed: {}", err);
- QMessageBox::warning(this, tr("Steam Linux Runtime"),
- tr("Steam Linux Runtime download failed:\n%1\n\n"
- "You can disable SLR in the Instance Manager and try again.").arg(err));
- return;
- }
+ const QString err = watcher.result();
+ if (cancelFlag) {
+ return; // user cancelled, don't launch
+ }
+ if (!err.isEmpty()) {
+ log::error("[SLR] Download failed: {}", err);
+ QMessageBox::warning(this, tr("Steam Linux Runtime"),
+ tr("Steam Linux Runtime download failed:\n%1").arg(err));
+ return;
}
}
}
diff --git a/src/src/prefixsetuprunner.cpp b/src/src/prefixsetuprunner.cpp
index 5ac809b..c317832 100644
--- a/src/src/prefixsetuprunner.cpp
+++ b/src/src/prefixsetuprunner.cpp
@@ -23,6 +23,7 @@
#include <QStandardPaths>
#include <QTemporaryFile>
#include <QThread>
+#include <QTimer>
#include <QUrl>
#include <log.h>
@@ -953,6 +954,10 @@ bool PrefixSetupRunner::stepProtonInit()
// for them. Nothing cleans them up automatically.
killStalePrefixProcesses();
+ if (!ensureSLRRunScript()) {
+ return false;
+ }
+
// Proton-GE invokes `xrandr` during protonfixes at wineboot time. The
// steamrt4 pressure-vessel container ships without it, so back-fill our
// injected copy before init if missing — otherwise the protonfix
@@ -2126,7 +2131,8 @@ QString PrefixSetupRunner::detectSLRRunScript() const
fluorineDataDir() + "/steamrt/SteamLinuxRuntime_sniper/run",
};
for (const QString& p : nakCandidates) {
- if (QFileInfo::exists(p))
+ const QFileInfo fi(p);
+ if (fi.exists() && fi.isExecutable())
return p;
}
@@ -2141,12 +2147,66 @@ QString PrefixSetupRunner::detectSLRRunScript() const
};
for (const QString& p : candidates) {
- if (!p.isEmpty() && QFileInfo::exists(p))
+ const QFileInfo fi(p);
+ if (!p.isEmpty() && fi.exists() && fi.isExecutable())
return p;
}
return {};
}
+bool PrefixSetupRunner::ensureSLRRunScript()
+{
+ if (!m_slrRunScript.isEmpty()) {
+ emit logMessage(
+ QStringLiteral("Using Steam Linux Runtime: %1").arg(m_slrRunScript));
+ return true;
+ }
+
+ emit logMessage(
+ "Steam Linux Runtime is required for Proton prefix initialization; "
+ "installing steamrt4...");
+ emit downloadStarted(QStringLiteral("Steam Linux Runtime"));
+
+ int cancelFlag = 0;
+ QTimer cancelTimer;
+ connect(&cancelTimer, &QTimer::timeout, this, [this, &cancelFlag] {
+ if (isCancelled()) {
+ cancelFlag = 1;
+ }
+ });
+ cancelTimer.start(200);
+
+ const QString err = downloadSlr(
+ nullptr,
+ [this](const QString& msg) { emit logMessage(msg); },
+ &cancelFlag);
+
+ cancelTimer.stop();
+ emit downloadFinished();
+
+ if (cancelFlag != 0) {
+ currentStep().errorMessage = "Steam Linux Runtime download cancelled";
+ return false;
+ }
+
+ if (!err.isEmpty()) {
+ currentStep().errorMessage =
+ QStringLiteral("Steam Linux Runtime install failed: %1").arg(err);
+ return false;
+ }
+
+ m_slrRunScript = detectSLRRunScript();
+ if (m_slrRunScript.isEmpty()) {
+ currentStep().errorMessage =
+ "Steam Linux Runtime installed but run script was not found";
+ return false;
+ }
+
+ emit logMessage(
+ QStringLiteral("Using Steam Linux Runtime: %1").arg(m_slrRunScript));
+ return true;
+}
+
QString PrefixSetupRunner::fluorineBinDir()
{
return fluorineDataDir() + "/bin";
diff --git a/src/src/prefixsetuprunner.h b/src/src/prefixsetuprunner.h
index 88c65ec..0dc5768 100644
--- a/src/src/prefixsetuprunner.h
+++ b/src/src/prefixsetuprunner.h
@@ -141,6 +141,7 @@ private:
QString findProtonScript() const;
static QString detectSteamPath() ;
QString detectSLRRunScript() const;
+ bool ensureSLRRunScript();
static QString fluorineBinDir() ;
static QString fluorineCacheDir() ;
static QString fluorineTmpDir() ;
diff --git a/src/src/spawn.cpp b/src/src/spawn.cpp
index 3163792..ec41221 100644
--- a/src/src/spawn.cpp
+++ b/src/src/spawn.cpp
@@ -416,13 +416,11 @@ int spawn(const SpawnParameters& sp, pid_t& processId)
// Read per-instance settings from the instance INI (not the global QSettings).
const Settings* instanceForLaunch = Settings::maybeInstance();
bool useSteamDrm = true;
- bool useSLR = true;
bool useSteamOverlay = false;
QString storeVariant;
if (instanceForLaunch) {
const QSettings instanceIni(instanceForLaunch->filename(), QSettings::IniFormat);
useSteamDrm = instanceIni.value("fluorine/steam_drm", true).toBool();
- useSLR = instanceIni.value("fluorine/use_slr", true).toBool();
useSteamOverlay = instanceIni.value("fluorine/steam_overlay", false).toBool();
storeVariant = instanceIni.value("game_edition").toString().trimmed();
}
@@ -430,7 +428,7 @@ int spawn(const SpawnParameters& sp, pid_t& processId)
launcher.setSteamDrm(useSteamDrm)
.setSteamOverlay(useSteamOverlay)
.setStoreVariant(storeVariant)
- .setUseSLR(useSLR);
+ .setUseSLR(true);
const QString prefixPath = resolvePrefixPath();
if (prefixPath.isEmpty()) {