diff --git a/helper/CouchPlayHelper.h b/helper/CouchPlayHelper.h index e94b15f..6e5451f 100644 --- a/helper/CouchPlayHelper.h +++ b/helper/CouchPlayHelper.h @@ -193,7 +193,7 @@ public Q_SLOTS: * @param username User to run as * @param compositorUid UID of compositor user (for runtime access setup) * @param gamescopeArgs Gamescope command-line arguments - * @param gameCommand Command to run inside gamescope (e.g., "steam -tenfoot") + * @param gameCommand Command to run inside gamescope (e.g., "steam -bigpicture") * @param environment Additional environment variables (VAR=value format) * @param bindPaths Paths to bind-mount into the unit via --property=BindPaths= * @return MainPID of launched process, or 0 on failure diff --git a/src/core/GamescopeInstance.cpp b/src/core/GamescopeInstance.cpp index 599c5c1..f6c1a4d 100644 --- a/src/core/GamescopeInstance.cpp +++ b/src/core/GamescopeInstance.cpp @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: 2025 CouchPlay Contributors #include "GamescopeInstance.h" +#include "PresetManager.h" #include #include @@ -54,7 +55,7 @@ bool GamescopeInstance::start(const QVariantMap &config, int index) // Fallback to Steam Big Picture if no preset configured QString gameCommand = config.value(QStringLiteral("presetCommand")).toString(); if (gameCommand.isEmpty()) { - gameCommand = QStringLiteral("steam -tenfoot -steamdeck"); + gameCommand = PresetManager::defaultSteamCommand(); } // Launch via D-Bus helper for uniform handling across all users (including compositor user) diff --git a/src/core/PresetManager.cpp b/src/core/PresetManager.cpp index 3e75a71..a5bd334 100644 --- a/src/core/PresetManager.cpp +++ b/src/core/PresetManager.cpp @@ -21,6 +21,7 @@ #include static constexpr int CACHE_TTL_HOURS = 24; +static constexpr int FLATPAK_CACHE_VERSION = 2; // bump when builtin preset commands change PresetManager::PresetManager(QObject *parent) : QObject(parent) @@ -113,6 +114,9 @@ void PresetManager::loadFlatpakCache() { KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("couchplayrc")); KConfigGroup cacheGroup = config->group(QStringLiteral("FlatpakCache")); + if (cacheGroup.readEntry(QStringLiteral("version"), 0) != FLATPAK_CACHE_VERSION) { + return; // stale cache (builtin commands changed) - saveFlatpakCache rewrites it + } const QStringList keys = cacheGroup.keyList(); QSet presetIds; @@ -149,6 +153,7 @@ void PresetManager::saveFlatpakCache() { KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("couchplayrc")); KConfigGroup cacheGroup = config->group(QStringLiteral("FlatpakCache")); + cacheGroup.writeEntry(QStringLiteral("version"), FLATPAK_CACHE_VERSION); QString timestamp = QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMddTHHmmss")); for (const auto &preset : m_builtinPresets) { @@ -160,6 +165,10 @@ void PresetManager::saveFlatpakCache() cacheGroup.sync(); } +QString PresetManager::defaultSteamCommand() +{ + return QStringLiteral("steam -bigpicture"); +} void PresetManager::initBuiltinPresets() { m_builtinPresets.clear(); @@ -168,9 +177,9 @@ void PresetManager::initBuiltinPresets() steam.id = QStringLiteral("steam"); steam.name = QStringLiteral("Steam Big Picture"); steam.flatpakAppId = QStringLiteral("com.valvesoftware.Steam"); - steam.flatpakArgs = QStringLiteral("-tenfoot -steamdeck"); + steam.flatpakArgs = QStringLiteral("-bigpicture"); steam.command = resolveLaunchCommand( - QStringLiteral("steam -tenfoot -steamdeck"), + defaultSteamCommand(), steam.flatpakAppId, steam.flatpakArgs); steam.iconName = QStringLiteral("steam"); diff --git a/src/core/PresetManager.h b/src/core/PresetManager.h index 6199232..1b08ad5 100644 --- a/src/core/PresetManager.h +++ b/src/core/PresetManager.h @@ -69,7 +69,7 @@ struct LaunchPreset { LauncherInfo launcherInfo; // Populated by detection for launcher presets QStringList sharedDirectories; // Per-preset shared directories for ACL/mount setup QString flatpakAppId; // e.g., "com.valvesoftware.Steam" (empty = no Flatpak alternative) - QString flatpakArgs; // Extra args for Flatpak launch (e.g., "-tenfoot -steamdeck") + QString flatpakArgs; // Extra args for Flatpak launch (e.g., "-bigpicture") bool operator==(const LaunchPreset &other) const { return id == other.id; } }; @@ -111,6 +111,7 @@ class PresetManager : public QObject Q_INVOKABLE LaunchPreset getPreset(const QString &id) const; Q_INVOKABLE QString getCommand(const QString &id) const; + static QString defaultSteamCommand(); Q_INVOKABLE QString getWorkingDirectory(const QString &id) const; Q_INVOKABLE bool getSteamIntegration(const QString &id) const; Q_INVOKABLE QString getLauncherId(const QString &id) const; diff --git a/src/core/SessionRunner.cpp b/src/core/SessionRunner.cpp index c50e752..1310f7d 100644 --- a/src/core/SessionRunner.cpp +++ b/src/core/SessionRunner.cpp @@ -353,7 +353,7 @@ bool SessionRunner::start() config[QStringLiteral("steamIntegration")] = m_presetManager->getSteamIntegration(presetId); } else { config[QStringLiteral("presetId")] = QStringLiteral("steam"); - config[QStringLiteral("presetCommand")] = QStringLiteral("steam -tenfoot -steamdeck"); + config[QStringLiteral("presetCommand")] = PresetManager::defaultSteamCommand(); config[QStringLiteral("steamIntegration")] = true; } diff --git a/tests/test_couchplayhelper.cpp b/tests/test_couchplayhelper.cpp index 3ac2ce6..738c104 100644 --- a/tests/test_couchplayhelper.cpp +++ b/tests/test_couchplayhelper.cpp @@ -1294,7 +1294,7 @@ void TestCouchPlayHelper::testLaunchInstance_basicLaunch() QStringLiteral("player1"), 1000u, QStringList{QStringLiteral("-W"), QStringLiteral("960")}, - QStringLiteral("steam -tenfoot"), + QStringLiteral("steam -bigpicture"), QStringList{QStringLiteral("ENABLE_GAMESCOPE_WSI=1")}, QStringList()); @@ -1314,7 +1314,7 @@ void TestCouchPlayHelper::testLaunchInstance_basicLaunch() QVERIFY(inv.args.contains(QStringLiteral("/usr/bin/gamescope"))); QVERIFY(inv.args.contains(QStringLiteral("-W"))); QVERIFY(inv.args.contains(QStringLiteral("960"))); - QVERIFY(inv.args.contains(QStringLiteral("steam -tenfoot"))); + QVERIFY(inv.args.contains(QStringLiteral("steam -bigpicture"))); QVERIFY(inv.args.contains(QStringLiteral("-c"))); QVERIFY(inv.args.contains(QStringLiteral("/bin/bash"))); break; diff --git a/tests/test_gamescopeinstance.cpp b/tests/test_gamescopeinstance.cpp index c6c234c..1d5fec0 100644 --- a/tests/test_gamescopeinstance.cpp +++ b/tests/test_gamescopeinstance.cpp @@ -360,7 +360,7 @@ void TestGamescopeInstance::testSteamLaunchMode() QVariantMap config; config[QStringLiteral("presetId")] = QStringLiteral("steam"); - config[QStringLiteral("presetCommand")] = QStringLiteral("steam -tenfoot -steamdeck"); + config[QStringLiteral("presetCommand")] = QStringLiteral("steam -bigpicture"); config[QStringLiteral("steamIntegration")] = true; config[QStringLiteral("steamAppId")] = QStringLiteral("1426210"); // It Takes Two config[QStringLiteral("internalWidth")] = 1920; @@ -390,7 +390,7 @@ void TestGamescopeInstance::testSteamLaunchModeNoAppId() QVariantMap config; config[QStringLiteral("presetId")] = QStringLiteral("steam"); - config[QStringLiteral("presetCommand")] = QStringLiteral("steam -tenfoot -steamdeck"); + config[QStringLiteral("presetCommand")] = QStringLiteral("steam -bigpicture"); config[QStringLiteral("steamIntegration")] = true; // No steamAppId set - this is valid, launches Steam Big Picture config[QStringLiteral("internalWidth")] = 1920; @@ -419,7 +419,7 @@ void TestGamescopeInstance::testSteamModeIsDefault() QSignalSpy errorSpy(m_instance, &GamescopeInstance::errorOccurred); QVariantMap config; - // No presetCommand set - should default to "steam -tenfoot -steamdeck" + // No presetCommand set - should default to "steam -bigpicture" config[QStringLiteral("internalWidth")] = 1920; config[QStringLiteral("internalHeight")] = 1080; diff --git a/tests/test_presetmanager.cpp b/tests/test_presetmanager.cpp index 066334c..8546486 100644 --- a/tests/test_presetmanager.cpp +++ b/tests/test_presetmanager.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2025 CouchPlay Contributors +#include #include #include #include @@ -28,6 +29,7 @@ private Q_SLOTS: void testBuiltinPresetsExist(); void testGetCommand(); + void testStaleFlatpakCacheIgnored(); void testGetWorkingDirectory(); void testGetLauncherId(); void testGetSteamIntegration(); @@ -120,7 +122,7 @@ void TestPresetManager::testGetCommand() PresetManager manager; QString steamCommand = manager.getCommand(QStringLiteral("steam")); - QCOMPARE(steamCommand, QStringLiteral("steam -tenfoot -steamdeck")); + QCOMPARE(steamCommand, QStringLiteral("steam -bigpicture")); QString heroicCommand = manager.getCommand(QStringLiteral("heroic")); QVERIFY(!heroicCommand.isEmpty()); @@ -129,6 +131,27 @@ void TestPresetManager::testGetCommand() QCOMPARE(lutrisCommand, QStringLiteral("lutris")); } +void TestPresetManager::testStaleFlatpakCacheIgnored() +{ + // Pre-seed a stale v1 cache; a fresh timestamp keeps it inside the TTL so + // only the version gate can prevent it from overriding the builtin. + KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("couchplayrc")); + KConfigGroup cacheGroup = config->group(QStringLiteral("FlatpakCache")); + cacheGroup.writeEntry(QStringLiteral("version"), 1); + cacheGroup.writeEntry(QStringLiteral("steam/command"), QStringLiteral("steam -tenfoot -steamdeck")); + cacheGroup.writeEntry(QStringLiteral("steam/timestamp"), + QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMddTHHmmss"))); + cacheGroup.sync(); + + PresetManager manager; + QCOMPARE(manager.getCommand(QStringLiteral("steam")), QStringLiteral("steam -bigpicture")); + + // Constructor rewrote the cache at the current version. + cacheGroup = config->group(QStringLiteral("FlatpakCache")); + QCOMPARE(cacheGroup.readEntry(QStringLiteral("version"), 0), 2); + QCOMPARE(cacheGroup.readEntry(QStringLiteral("steam/command")), QStringLiteral("steam -bigpicture")); +} + void TestPresetManager::testGetWorkingDirectory() { PresetManager manager;