[EXPERIMENTAL] linux apps support

This commit is contained in:
olcxja 2026-10-06 20:54:16 +02:00
commit e7636afe3d
20 changed files with 1377 additions and 101 deletions

View file

@ -108,6 +108,27 @@ function gamesFollowingDefault(running) {
})
}
// Windows is the default: entries written before Linux apps existed have no
// kind at all.
function isLinuxGame(game) {
return !!game && game.kind === 'linux'
}
const ISOLATION_MODES = ['auto', 'off', 'require']
// Only known values reach the registry; anything else falls back to the safe
// default (a typo must not silently disable the sandbox).
function sanitizeLinuxPatch(patch) {
if (!patch) return patch
const out = { ...patch }
if (out.kind !== undefined) out.kind = out.kind === 'linux' ? 'linux' : 'windows'
if (out.isolation !== undefined) {
out.isolation = ISOLATION_MODES.includes(out.isolation) ? out.isolation : 'auto'
}
if (out.forceX11 !== undefined) out.forceX11 = !!out.forceX11
return out
}
function addGame(game) {
const games = loadGames()
games.push(game)
@ -127,7 +148,7 @@ function updateGame(id, patch) {
}
// playSeconds lives in its own file; the registry mirrors it
if (patch.playSeconds !== undefined) writePlaySeconds(id, patch.playSeconds)
Object.assign(g, patch)
Object.assign(g, sanitizeLinuxPatch(patch))
saveGames(games)
return g
}
@ -175,11 +196,12 @@ function newGameId() {
return id
}
function newGame({ id, name, exePath, workdir, mode }) {
function newGame({ id, name, exePath, workdir, mode, kind }) {
return {
id: id || newGameId(),
name,
mode,
kind: kind === 'linux' ? 'linux' : 'windows',
path: workdir,
exePath,
workdir,
@ -189,6 +211,10 @@ function newGame({ id, name, exePath, workdir, mode }) {
dllOverrides: [],
// Proton-only: UMU by default, or the build's steam.exe launcher
disableUmu: false,
// Linux-only: how hard to try the bwrap sandbox before falling back
isolation: 'auto',
// Linux-only: force XWayland, where a window can still carry its icon
forceX11: false,
env: {},
iconSource: '',
playSeconds: 0,
@ -232,4 +258,4 @@ function resolvePrefixDir(game) {
return prefixPath(prefixNameForGame(game))
}
module.exports = { loadGames, saveGames, portableGame, getGame, addGame, updateGame, removeGame, reorderGames, renamePrefixRefs, prefixNameForGame, gamesUsingPrefix, appsUsingPrefix, isPrefixInUse, isWineInUse, gamesFollowingDefault, loadSettings, saveSettings, newGame, newGameId, resolvePrefixDir, clearPlaytime, readPlaySeconds, writePlaySeconds, playtimeFile }
module.exports = { loadGames, saveGames, portableGame, getGame, isLinuxGame, addGame, updateGame, removeGame, reorderGames, renamePrefixRefs, prefixNameForGame, gamesUsingPrefix, appsUsingPrefix, isPrefixInUse, isWineInUse, gamesFollowingDefault, loadSettings, saveSettings, newGame, newGameId, resolvePrefixDir, clearPlaytime, readPlaySeconds, writePlaySeconds, playtimeFile }