This repository has been archived on 2025-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
project-client/src/main/utils/steamOS.ts

97 lines
3.6 KiB
TypeScript

/*
* SPDX-License-Identifier: GPL-3.0
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { BrowserWindow, dialog } from "electron";
import { writeFile } from "fs/promises";
import { join } from "path";
import { MessageBoxChoice } from "../constants";
import { State } from "../settings";
// 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
const layoutId = "3080264545"; // Vesktop Layout v2
const numberRegex = /^[0-9]*$/;
let steamPipeQueue = Promise.resolve();
export const isDeckGameMode = process.env.SteamOS === "1" && process.env.SteamGamepadUI === "1";
export function applyDeckKeyboardFix() {
if (!isDeckGameMode) return;
// Prevent constant virtual keyboard spam that eventually crashes Steam.
process.env.GTK_IM_MODULE = "None";
}
// For some reason SteamAppId is always 0 for non-steam apps so we do this insanity instead.
function getAppId(): string | null {
// /home/deck/.local/share/Steam/steamapps/shadercache/APPID/fozmediav1
const path = process.env.STEAM_COMPAT_MEDIA_PATH;
if (!path) return null;
const pathElems = path?.split("/");
const appId = pathElems[pathElems.length - 2];
if (appId.match(numberRegex)) {
console.log(`Got Steam App ID ${appId}`);
return appId;
}
return null;
}
export function execSteamURL(url: string) {
// This doesn't allow arbitrary execution despite the weird syntax.
steamPipeQueue = steamPipeQueue.then(() =>
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 function steamOpenURL(url: string) {
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) {
execSteamURL(`steam://controllerconfig/${appId}/${layoutId}`);
}
export async function askToApplySteamLayout(win: BrowserWindow) {
const appId = getAppId();
if (!appId) return;
if (State.store.steamOSLayoutVersion === layoutVersion) return;
const update = Boolean(State.store.steamOSLayoutVersion);
// Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed.
const { response } = await dialog.showMessageBox(win, {
message: `${update ? "Update" : "Apply"} Vesktop Steam Input Layout?`,
detail: `Would you like to ${update ? "Update" : "Apply"} Vesktop's recommended Steam Deck controller settings?
${update ? "Click yes using the touchpad" : "Tap yes"}, then press the X button or tap Apply Layout to confirm.${
update ? " Doing so will undo any customizations you have made." : ""
}
${update ? "Click" : "Tap"} no to keep your current layout.`,
buttons: ["Yes", "No"],
cancelId: MessageBoxChoice.Cancel,
defaultId: MessageBoxChoice.Default,
type: "question"
});
if (State.store.steamOSLayoutVersion !== layoutVersion) {
State.store.steamOSLayoutVersion = layoutVersion;
}
if (response === MessageBoxChoice.Cancel) return;
await showLayout(appId);
}