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
This commit is contained in:
Evan Simkowitz 2025-01-16 11:37:14 -08:00 committed by GitHub
parent 9dc9066a81
commit b7dca41b9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 81 additions and 6 deletions

View File

@ -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();

View File

@ -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}`);
})
)
);
});

View File

@ -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<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;
}
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,