Skip to content

Commit

Permalink
Option to use Flatpaks under Linux
Browse files Browse the repository at this point in the history
This adds a configuration setting "linuxUseFlatpak" which controls
whether Steam should be launched as a Flatpak or not. By default this
is detected automatically based on the path, but an option in the
settings can override the behaviour.

If this option is enabled, we first check if we are able to read from
our config directory. If not, we display an error and ask the user to
give us permission. If we do, then we launch Steam through flatpak
rather than the binary directly.
  • Loading branch information
RossBrunton committed Oct 2, 2024
1 parent 9176b94 commit fa9d082
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 5 deletions.
17 changes: 17 additions & 0 deletions src/components/settings-components/SettingsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,23 @@ import CdnProvider from '../../providers/generic/connection/CdnProvider';
'fa-file-alt',
() => this.emitInvoke('ShowDependencyStrings')
),
new SettingsRow(
'Other',
'Launch as Flatpak (Linux)',
'Launch Steam via flatpak',
async () => {
switch (this.settings.getContext().global.linuxUseFlatpak) {
case null:
return 'Automatic';
case true:
return 'Flatpak';
case false:
return 'Native';
}
},
'fa-exchange-alt',
() => this.emitInvoke('ToggleLinuxUseFlatpak')
),
];
@Watch('search')
Expand Down
7 changes: 7 additions & 0 deletions src/pages/Manager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ import ModalCard from '../components/ModalCard.vue';
this.settings.setFunkyMode(value);
}
setLinuxUseFlatpak(value: boolean) {
this.settings.setLinuxUseFlatpak(value);
}
async exportProfile() {
if (!this.localModList.length) {
const err = new R2Error(
Expand Down Expand Up @@ -569,6 +573,9 @@ import ModalCard from '../components/ModalCard.vue';
case "ToggleFunkyMode":
this.setFunkyMode(!this.settings.getContext().global.funkyModeEnabled);
break;
case "ToggleLinuxUseFlatpak":
this.setLinuxUseFlatpak(!this.settings.getContext().global.linuxUseFlatpak);
break;
case "SwitchTheme":
this.toggleDarkTheme();
document.documentElement.classList.toggle('html--dark', this.settings.getContext().global.darkTheme);
Expand Down
32 changes: 28 additions & 4 deletions src/r2mm/launching/runners/linux/SteamGameRunner_Linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,50 @@ export default class SteamGameRunner_Linux extends GameRunnerProvider {
if (args instanceof R2Error) {
return args
}
return this.start(game, args);
return this.start(game, args, profile.getPathOfProfile());
}

public async startVanilla(game: Game, profile: Profile): Promise<void | R2Error> {
const instructions = await GameInstructions.getInstructionsForGame(game, profile);
return this.start(game, instructions.vanillaParameters);
return this.start(game, instructions.vanillaParameters, null);
}

async start(game: Game, args: string): Promise<void | R2Error> {
async start(game: Game, args: string, profiledir: string | null): Promise<void | R2Error> {

const settings = await ManagerSettings.getSingleton(game);
const steamDir = await GameDirectoryResolverProvider.instance.getSteamDirectory();
if(steamDir instanceof R2Error) {
return steamDir;
}
let as_flatpak = settings.getContext().global.linuxUseFlatpak;
if (as_flatpak === null) {
// Assume that if the path contains the flatpak directory we must want to use flatpak
as_flatpak = steamDir.includes("/com.valvesoftware.Steam/");
}

if (as_flatpak && profiledir) {
// Ensure we have permission to read our config dir
const visible = await new Promise((resolve) => {
const check_cmd = `flatpak run --command='sh' com.valvesoftware.Steam -c 'ls "${profiledir}"'`;
exec(check_cmd).on('close', (error) => {
resolve(error == 0);
});
});
if (!visible) {
throw new R2Error('Flatpak Permissions Error',
`The directory "${profiledir}" is not visible from within the Flatpak container`,
'`flatpak override com.valvesoftware.Steam --user --filesystem="${XDG_CONFIG_HOME:-$HOME/.config}/r2modmanPlus-local"` to grant access, then restart Steam.');
}
}

LoggerProvider.instance.Log(LogSeverity.INFO, `Steam directory is: ${steamDir}`);

try {
const cmd = `"${steamDir}/steam.sh" -applaunch ${game.activePlatform.storeIdentifier} ${args} ${settings.getContext().gameSpecific.launchParameters}`;
let cmd = `"${steamDir}/steam.sh" -applaunch ${game.activePlatform.storeIdentifier} ${args} ${settings.getContext().gameSpecific.launchParameters}`;
if (as_flatpak) {
cmd = `flatpak run com.valvesoftware.Steam ${cmd}`;
}

LoggerProvider.instance.Log(LogSeverity.INFO, `Running command: ${cmd}`);
await exec(cmd);
} catch(err) {
Expand Down
5 changes: 5 additions & 0 deletions src/r2mm/manager/ManagerSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ export default class ManagerSettings {
await this.save();
}

public async setLinuxUseFlatpak(enabled: boolean) {
ManagerSettings.CONTEXT.global.linuxUseFlatpak = enabled;
await this.save();
}

public async expandCards() {
ManagerSettings.CONTEXT.global.expandedCards = true;
await this.save();
Expand Down
4 changes: 3 additions & 1 deletion src/r2mm/manager/SettingsDexieStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export default class SettingsDexieStore extends Dexie {
favouriteGames: [],
defaultGame: undefined,
defaultStore: undefined,
gameSelectionViewMode: GameSelectionViewMode.CARD
gameSelectionViewMode: GameSelectionViewMode.CARD,
linuxUseFlatpak: null,
},
gameSpecific: {
version: 2,
Expand Down Expand Up @@ -197,6 +198,7 @@ export interface ManagerSettingsInterfaceGlobal_V2 {
defaultGame: string | undefined;
defaultStore: StorePlatform | undefined;
gameSelectionViewMode: GameSelectionViewMode;
linuxUseFlatpak: boolean | null;
}

/**
Expand Down

0 comments on commit fa9d082

Please sign in to comment.