diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-30 13:15:32 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-30 13:15:32 -0500 |
| commit | 5c4603f12a727625ece236fc43846330fad3b9f2 (patch) | |
| tree | aee55f5f15d77d5860a3bfa7d197b6ae0cb78a66 /src | |
| parent | 2464c836085cab832089b0f58c4bd74dfb679603 (diff) | |
Detect Steam Protons across libraries
Diffstat (limited to 'src')
| -rw-r--r-- | src/src/steamdetection.cpp | 64 | ||||
| -rw-r--r-- | src/src/steamdetection.h | 3 | ||||
| -rw-r--r-- | src/src/vdfparser.cpp | 10 |
3 files changed, 62 insertions, 15 deletions
diff --git a/src/src/steamdetection.cpp b/src/src/steamdetection.cpp index 7710edd..512b1fa 100644 --- a/src/src/steamdetection.cpp +++ b/src/src/steamdetection.cpp @@ -2,10 +2,13 @@ #include <QDir> #include <QDirIterator> +#include <QFile> #include <QFileInfo> #include <QStandardPaths> #include <uibase/log.h> +#include "vdfparser.h" + // ============================================================================ // SteamProtonInfo // ============================================================================ @@ -56,6 +59,40 @@ QString findSteamPath() return {}; } +QStringList findSteamLibraryPaths() +{ + QStringList libraries; + + const QString steamPath = findSteamPath(); + if (steamPath.isEmpty()) + return libraries; + + auto addLibrary = [&](const QString& path) { + const QString cleanPath = QDir::cleanPath(path); + if (cleanPath.isEmpty() || libraries.contains(cleanPath)) + return; + if (QFileInfo::exists(QDir(cleanPath).filePath(QStringLiteral("steamapps")))) + libraries.append(cleanPath); + }; + + addLibrary(steamPath); + + QFile libraryFolders(QDir(steamPath).filePath( + QStringLiteral("steamapps/libraryfolders.vdf"))); + if (!libraryFolders.open(QIODevice::ReadOnly | QIODevice::Text)) { + MOBase::log::debug("Steam libraryfolders.vdf not found at '{}'", + libraryFolders.fileName()); + return libraries; + } + + const QString content = QString::fromUtf8(libraryFolders.readAll()); + for (const QString& path : parseLibraryFolders(content)) { + addLibrary(path); + } + + return libraries; +} + // ============================================================================ // Proton Detection // ============================================================================ @@ -143,27 +180,28 @@ QVector<SteamProtonInfo> findSteamProtons() { QVector<SteamProtonInfo> protons; - const QString steamPath = findSteamPath(); - if (steamPath.isEmpty()) + const QStringList steamLibraries = findSteamLibraryPaths(); + if (steamLibraries.isEmpty()) return protons; - // 1. Steam's built-in Protons (only entries starting with "Proton"). - { + // 1. Steam's built-in Protons across every Steam library. Steam may install + // tools like "Proton 10.0" under a secondary library's steamapps/common. + for (const QString& library : steamLibraries) { QVector<SteamProtonInfo> builtin; - scanProtonDir(steamPath + "/steamapps/common", true, builtin); - // Keep only entries whose folder name starts with "Proton". Proton 11 - // had ntsync/futex deadlocks during wineboot -u on modern kernels; the - // workaround now lives in prefixsetuprunner (waitforexitandrun + ntsync - // env nudge) so we no longer blacklist it here. + scanProtonDir(QDir(library).filePath(QStringLiteral("steamapps/common")), true, + builtin); for (auto& p : builtin) { - if (!p.name.startsWith(QStringLiteral("Proton"))) - continue; - protons.append(std::move(p)); + if (p.name.startsWith(QStringLiteral("Proton"))) { + protons.append(std::move(p)); + } } } // 2. Custom Protons in user's compatibilitytools.d. - scanProtonDir(steamPath + "/compatibilitytools.d", false, protons); + for (const QString& library : steamLibraries) { + scanProtonDir(QDir(library).filePath(QStringLiteral("compatibilitytools.d")), + false, protons); + } // 3. System-level Protons. scanProtonDir(QStringLiteral("/usr/share/steam/compatibilitytools.d"), false, protons); diff --git a/src/src/steamdetection.h b/src/src/steamdetection.h index fd8dc3f..4e0368f 100644 --- a/src/src/steamdetection.h +++ b/src/src/steamdetection.h @@ -26,6 +26,9 @@ struct SteamProtonInfo { /// Find the Steam installation path (returns empty string if not found). __attribute__((visibility("default"))) QString findSteamPath(); +/// Find all Steam library root paths, including secondary libraries. +__attribute__((visibility("default"))) QStringList findSteamLibraryPaths(); + /// Find all installed Proton versions (Proton 10+ only, sorted newest first). __attribute__((visibility("default"))) QVector<SteamProtonInfo> findSteamProtons(); diff --git a/src/src/vdfparser.cpp b/src/src/vdfparser.cpp index 1df8fe6..126be63 100644 --- a/src/src/vdfparser.cpp +++ b/src/src/vdfparser.cpp @@ -138,8 +138,14 @@ QStringList parseLibraryFolders(const QString& content) return paths; for (const VdfValue& entry : folders->asObject()) { - const QString path = entry.getString(QStringLiteral("path")); - if (!path.isEmpty()) + QString path; + if (entry.isString()) { + path = entry.asString(); + } else { + path = entry.getString(QStringLiteral("path")); + } + + if (!path.isEmpty() && !paths.contains(path)) paths.append(path); } return paths; |
