diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-03-16 16:12:46 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-03-16 16:12:46 -0500 |
| commit | e41a79a9033761916fa133260ff1849288db7df1 (patch) | |
| tree | a2e8e45d73fcb12e15cbfaf30e8aa5d02a957481 | |
| parent | 66633ead443819df5aacc87b3fd1fdee85cddfde (diff) | |
Fix Steam game detection in game mode + add result cache
- Prepend STEAM_COMPAT_CLIENT_INSTALL_PATH as first Steam path candidate.
Steam always sets this env var when launching any app (including in
gamescope/game mode), so it reliably points to the correct Steam root
even when $HOME resolves differently inside the gamescope session.
- Canonicalize VDF-sourced library paths before dedup in
getAllLibraryFolders() so /home/ ↔ /var/home/ symlinks (Bazzite/Fedora
immutable distros) don't produce duplicate scan entries.
- Cache findSteamGames() results in a static hash. Previously,
findSteamGamePath() rebuilt the full library scan 45+ times per launch
(once per registered game plugin). Now the scan runs at most once.
Fixes game detection on Bazzite in Steam Game Mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | libs/basic_games_native/src/steamutils.cpp | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/libs/basic_games_native/src/steamutils.cpp b/libs/basic_games_native/src/steamutils.cpp index 28fac2b..ffae0f1 100644 --- a/libs/basic_games_native/src/steamutils.cpp +++ b/libs/basic_games_native/src/steamutils.cpp @@ -20,6 +20,16 @@ static QStringList findSteamPaths() home + "/snap/steam/common/.local/share/Steam", }; + // When Steam launches an app (e.g. in game mode) it sets + // STEAM_COMPAT_CLIENT_INSTALL_PATH to its own root. Add that as a + // candidate so we find the right installation even if $HOME resolves + // differently inside the gamescope session. + const QString steamEnvPath = + QString::fromLocal8Bit(qgetenv("STEAM_COMPAT_CLIENT_INSTALL_PATH")); + if (!steamEnvPath.isEmpty()) { + candidates.prepend(steamEnvPath); + } + for (const auto& candidate : candidates) { QDir dir(candidate); if (dir.exists("steamapps") || QFile::exists(candidate + "/steam.pid")) { @@ -68,8 +78,12 @@ static QStringList getAllLibraryFolders(const QString& steamPath) {"steamapps/libraryfolders.vdf", "config/libraryfolders.vdf"}) { QString vdfPath = steamPath + "/" + vdfName; for (const auto& path : parseLibraryFolders(vdfPath)) { - if (!folders.contains(path)) { - folders.append(path); + // Canonicalize before dedup so /home/ and /var/home/ paths compare equal + QString canonical = QFileInfo(path).canonicalFilePath(); + if (canonical.isEmpty()) + canonical = path; + if (!folders.contains(canonical)) { + folders.append(canonical); } } } @@ -120,8 +134,15 @@ static AppManifest parseAppManifest(const QString& path) return manifest; } +// Cache: built once per process, cleared on explicit refresh. +static QHash<int, QString> s_steamGamesCache; +static bool s_steamGamesCacheValid = false; + QHash<int, QString> findSteamGames() { + if (s_steamGamesCacheValid) + return s_steamGamesCache; + QHash<int, QString> games; for (const auto& steamPath : findSteamPaths()) { @@ -146,11 +167,12 @@ QHash<int, QString> findSteamGames() } } + s_steamGamesCache = games; + s_steamGamesCacheValid = true; return games; } QString findSteamGamePath(int appId) { - auto games = findSteamGames(); - return games.value(appId); + return findSteamGames().value(appId); } |
