diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 84755f4..504bd10 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -21,6 +21,7 @@ import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./ import { mainWin } from "./mainWindow"; import { Settings } from "./settings"; import { handle, handleSync } from "./utils/ipcWrappers"; +import { isDeckGameMode, showGamePage } from "./utils/steamOS"; import { isValidVencordInstall } from "./utils/vencordLoader"; handleSync(IpcEvents.GET_VENCORD_PRELOAD_FILE, () => join(VENCORD_FILES_DIR, "vencordDesktopPreload.js")); @@ -47,11 +48,14 @@ handle(IpcEvents.SET_SETTINGS, (_, settings: typeof Settings.store, path?: strin Settings.setData(settings, path); }); -handle(IpcEvents.RELAUNCH, () => { +handle(IpcEvents.RELAUNCH, async () => { const options: RelaunchOptions = { args: process.argv.slice(1).concat(["--relaunch"]) }; - if (app.isPackaged && process.env.APPIMAGE) { + if (isDeckGameMode) { + // We can't properly relaunch when running under gamescope, but we can at least navigate to our page in Steam. + await showGamePage(); + } else if (app.isPackaged && process.env.APPIMAGE) { execFile(process.env.APPIMAGE, options.args); } else { app.relaunch(options); diff --git a/src/main/utils/makeLinksOpenExternally.ts b/src/main/utils/makeLinksOpenExternally.ts index b30b865..5197261 100644 --- a/src/main/utils/makeLinksOpenExternally.ts +++ b/src/main/utils/makeLinksOpenExternally.ts @@ -7,6 +7,7 @@ import { BrowserWindow, shell } from "electron"; import { Settings } from "../settings"; +import { execSteamURL, isDeckGameMode, steamOpenURL } from "./steamOS"; export function makeLinksOpenExternally(win: BrowserWindow) { win.webContents.setWindowOpenHandler(({ url }) => { @@ -30,9 +31,20 @@ export function makeLinksOpenExternally(win: BrowserWindow) { } // eslint-disable-next-line no-fallthrough case "mailto:": - case "steam:": case "spotify:": - shell.openExternal(url); + if (isDeckGameMode) { + steamOpenURL(url); + } else { + shell.openExternal(url); + } + break; + case "steam:": + if (isDeckGameMode) { + execSteamURL(url); + } else { + shell.openExternal(url); + } + break; } return { action: "deny" }; diff --git a/src/main/utils/steamOS.ts b/src/main/utils/steamOS.ts index feeafe4..44eadac 100644 --- a/src/main/utils/steamOS.ts +++ b/src/main/utils/steamOS.ts @@ -4,16 +4,13 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { exec as callbackExec } from "child_process"; import { BrowserWindow, dialog } from "electron"; -import { sleep } from "shared/utils/sleep"; -import { promisify } from "util"; +import { writeFile } from "fs/promises"; +import { join } from "path"; import { MessageBoxChoice } from "../constants"; import { Settings } from "../settings"; -const exec = promisify(callbackExec); - // Bump this to re-show the prompt const layoutVersion = 2; // Get this from "show details" on the profile after exporting as a shared personal layout or using share with community @@ -42,16 +39,28 @@ function getAppId(): string | null { return null; } -async function execSteamURL(url: string): Promise { - await exec(`steam -ifrunning ${url}`); +export async function execSteamURL(url: string): Promise { + // This doesn't allow arbitrary execution despite the weird syntax. + await writeFile( + join(process.env.HOME || "/home/deck", ".steam", "steam.pipe"), + // replace ' to prevent argument injection + `'${process.env.HOME}/.local/share/Steam/ubuntu12_32/steam' '-ifrunning' '${url.replaceAll("'", "%27")}'\n`, + "utf-8" + ); +} + +export async function steamOpenURL(url: string) { + await execSteamURL(`steam://openurl/${url}`); +} + +export async function showGamePage() { + const appId = getAppId(); + if (!appId) return; + await execSteamURL(`steam://nav/games/details/${appId}`); } async function showLayout(appId: string) { - await execSteamURL(`steam://controllerconfig/${appId}/${layoutId}`); - // because the UI doesn't consistently reload after the data for the config has loaded... - // HOW HAS NOBODY AT VALVE RUN INTO THIS YET - await sleep(100); - await execSteamURL(`steam://controllerconfig/${appId}/${layoutId}`); + execSteamURL(`steam://controllerconfig/${appId}/${layoutId}`); } export async function askToApplySteamLayout(win: BrowserWindow) {