From e41a79a9033761916fa133260ff1849288db7df1 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Mon, 16 Mar 2026 16:12:46 -0500 Subject: Fix Steam game detection in game mode + add result cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- libs/basic_games_native/src/steamutils.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'libs/basic_games_native/src') 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 s_steamGamesCache; +static bool s_steamGamesCacheValid = false; + QHash findSteamGames() { + if (s_steamGamesCacheValid) + return s_steamGamesCache; + QHash games; for (const auto& steamPath : findSteamPaths()) { @@ -146,11 +167,12 @@ QHash findSteamGames() } } + s_steamGamesCache = games; + s_steamGamesCacheValid = true; return games; } QString findSteamGamePath(int appId) { - auto games = findSteamGames(); - return games.value(appId); + return findSteamGames().value(appId); } -- cgit v1.3.1