diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-26 22:59:59 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-26 22:59:59 -0500 |
| commit | 99d9edb81c2f2342eccb3bc6d871b4b21a793636 (patch) | |
| tree | 078419b6982b54b68e4bc51f910b42465c5e19e9 /src | |
| parent | 2f2554e1f4236acf808ea758ab0d0cf4d298b9ee (diff) | |
Force SLR for Proton launches
Diffstat (limited to 'src')
| -rw-r--r-- | src/src/instancemanagerdialog.cpp | 28 | ||||
| -rw-r--r-- | src/src/instancemanagerdialog.ui | 7 | ||||
| -rw-r--r-- | src/src/mainwindow.cpp | 92 | ||||
| -rw-r--r-- | src/src/prefixsetuprunner.cpp | 64 | ||||
| -rw-r--r-- | src/src/prefixsetuprunner.h | 1 | ||||
| -rw-r--r-- | src/src/spawn.cpp | 4 |
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()) { |
