From b7dca41b9c67c17caf3f502a6c00399ddd73c19e Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 16 Jan 2025 11:37:14 -0800 Subject: [PATCH] Correct XDG_CURRENT_DESKTOP env var (#1754) Electron sets XDG_CURRENT_DESKTOP for better Chromium compatibility on Linux. We need to unset this for `wavesrv` and for any calls to open a file or URL externally in `emain`. See https://www.electronjs.org/docs/latest/api/environment-variables#original_xdg_current_desktop There's a bug open in Electron related to this: https://github.com/electron/electron/issues/45129 closes #1733 --- emain/emain-wavesrv.ts | 5 ++++ emain/emain.ts | 19 +++++++++---- emain/platform.ts | 63 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/emain/emain-wavesrv.ts b/emain/emain-wavesrv.ts index b77e90929..beca7d684 100644 --- a/emain/emain-wavesrv.ts +++ b/emain/emain-wavesrv.ts @@ -14,6 +14,7 @@ import { getWaveDataDir, getWaveSrvCwd, getWaveSrvPath, + getXdgCurrentDesktop, WaveConfigHomeVarName, WaveDataHomeVarName, } from "./platform"; @@ -53,6 +54,10 @@ export function runWaveSrv(handleWSEvent: (evtMsg: WSEventType) => void): Promis pReject = argReject; }); const envCopy = { ...process.env }; + const xdgCurrentDesktop = getXdgCurrentDesktop(); + if (xdgCurrentDesktop != null) { + envCopy["XDG_CURRENT_DESKTOP"] = xdgCurrentDesktop; + } envCopy[WaveAppPathVarName] = getElectronAppUnpackedBasePath(); envCopy[WaveAuthKeyEnv] = AuthKey; envCopy[WaveDataHomeVarName] = getWaveDataDir(); diff --git a/emain/emain.ts b/emain/emain.ts index 969e25822..6c9c58f96 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -47,6 +47,7 @@ import { getLaunchSettings } from "./launchsettings"; import { log } from "./log"; import { makeAppMenu } from "./menu"; import { + callWithOriginalXdgCurrentDesktopAsync, checkIfRunningUnderARM64Translation, getElectronAppBasePath, getElectronAppUnpackedBasePath, @@ -121,9 +122,13 @@ function handleWSEvent(evtMsg: WSEventType) { // Listen for the open-external event from the renderer process electron.ipcMain.on("open-external", (event, url) => { if (url && typeof url === "string") { - electron.shell.openExternal(url).catch((err) => { - console.error(`Failed to open URL ${url}:`, err); - }); + fireAndForget(() => + callWithOriginalXdgCurrentDesktopAsync(() => + electron.shell.openExternal(url).catch((err) => { + console.error(`Failed to open URL ${url}:`, err); + }) + ) + ); } else { console.error("Invalid URL received in open-external event:", url); } @@ -347,9 +352,11 @@ electron.ipcMain.on("quicklook", (event, filePath: string) => { electron.ipcMain.on("open-native-path", (event, filePath: string) => { console.log("open-native-path", filePath); fireAndForget(() => - electron.shell.openPath(filePath).then((excuse) => { - if (excuse) console.error(`Failed to open ${filePath} in native application: ${excuse}`); - }) + callWithOriginalXdgCurrentDesktopAsync(() => + electron.shell.openPath(filePath).then((excuse) => { + if (excuse) console.error(`Failed to open ${filePath} in native application: ${excuse}`); + }) + ) ); }); diff --git a/emain/platform.ts b/emain/platform.ts index 58ce99a2e..714316b93 100644 --- a/emain/platform.ts +++ b/emain/platform.ts @@ -194,13 +194,76 @@ ipcMain.on("get-config-dir", (event) => { event.returnValue = getWaveConfigDir(); }); +/** + * Gets the value of the XDG_CURRENT_DESKTOP environment variable. If ORIGINAL_XDG_CURRENT_DESKTOP is set, it will be returned instead. + * This corrects for a strange behavior in Electron, where it sets its own value for XDG_CURRENT_DESKTOP to improve Chromium compatibility. + * @see https://www.electronjs.org/docs/latest/api/environment-variables#original_xdg_current_desktop + * @returns The value of the XDG_CURRENT_DESKTOP environment variable, or ORIGINAL_XDG_CURRENT_DESKTOP if set, or undefined if neither are set. + */ +function getXdgCurrentDesktop(): string { + if (process.env.ORIGINAL_XDG_CURRENT_DESKTOP) { + return process.env.ORIGINAL_XDG_CURRENT_DESKTOP; + } else if (process.env.XDG_CURRENT_DESKTOP) { + return process.env.XDG_CURRENT_DESKTOP; + } else { + return undefined; + } +} + +/** + * Calls the given callback with the value of the XDG_CURRENT_DESKTOP environment variable set to ORIGINAL_XDG_CURRENT_DESKTOP if it is set. + * @see https://www.electronjs.org/docs/latest/api/environment-variables#original_xdg_current_desktop + * @param callback The callback to call. + */ +function callWithOriginalXdgCurrentDesktop(callback: () => void) { + const currXdgCurrentDesktopDefined = "XDG_CURRENT_DESKTOP" in process.env; + const currXdgCurrentDesktop = process.env.XDG_CURRENT_DESKTOP; + const originalXdgCurrentDesktop = getXdgCurrentDesktop(); + if (originalXdgCurrentDesktop) { + process.env.XDG_CURRENT_DESKTOP = originalXdgCurrentDesktop; + } + callback(); + if (originalXdgCurrentDesktop) { + if (currXdgCurrentDesktopDefined) { + process.env.XDG_CURRENT_DESKTOP = currXdgCurrentDesktop; + } else { + delete process.env.XDG_CURRENT_DESKTOP; + } + } +} + +/** + * Calls the given async callback with the value of the XDG_CURRENT_DESKTOP environment variable set to ORIGINAL_XDG_CURRENT_DESKTOP if it is set. + * @see https://www.electronjs.org/docs/latest/api/environment-variables#original_xdg_current_desktop + * @param callback The async callback to call. + */ +async function callWithOriginalXdgCurrentDesktopAsync(callback: () => Promise) { + const currXdgCurrentDesktopDefined = "XDG_CURRENT_DESKTOP" in process.env; + const currXdgCurrentDesktop = process.env.XDG_CURRENT_DESKTOP; + const originalXdgCurrentDesktop = getXdgCurrentDesktop(); + if (originalXdgCurrentDesktop) { + process.env.XDG_CURRENT_DESKTOP = originalXdgCurrentDesktop; + } + await callback(); + if (originalXdgCurrentDesktop) { + if (currXdgCurrentDesktopDefined) { + process.env.XDG_CURRENT_DESKTOP = currXdgCurrentDesktop; + } else { + delete process.env.XDG_CURRENT_DESKTOP; + } + } +} + export { + callWithOriginalXdgCurrentDesktop, + callWithOriginalXdgCurrentDesktopAsync, getElectronAppBasePath, getElectronAppUnpackedBasePath, getWaveConfigDir, getWaveDataDir, getWaveSrvCwd, getWaveSrvPath, + getXdgCurrentDesktop, isDev, isDevVite, unameArch,