diff --git a/apps/desktop/src/check-packaging-contract.ts b/apps/desktop/src/check-packaging-contract.ts index 1b22242c..1d64ad1a 100644 --- a/apps/desktop/src/check-packaging-contract.ts +++ b/apps/desktop/src/check-packaging-contract.ts @@ -85,6 +85,8 @@ assert.match(loggerSource, /OPENPETS_LOG_LEVEL/, "desktop logger must support ve assert.match(loggerSource, /normalizeLogLevel\(process\.env\.OPENPETS_LOG_LEVEL\) \?\? "debug"/, "desktop production logger must default to debug for user-sendable diagnostics."); assert.match(loggerSource, /redacted-token/, "desktop logger must redact token-looking values."); assert.match(mainSource, /initializeLogger\(\)/, "desktop startup must initialize logging before subsystem startup."); +assert.match(mainSource, /process\.platform === "linux"[\s\S]*?appendSwitch\("ozone-platform", "x11"\)/, "Linux desktop pets must prefer X11/Xwayland because GNOME Wayland blocks always-on-top and programmatic window dragging."); +assert.match(mainSource, /hasSwitch\("ozone-platform"\)/, "Linux X11 preference must let users override Electron's Ozone backend explicitly."); assert.match(traySource, /Open Logs Folder/, "desktop tray must expose user-sendable logs for bug reports."); assert.match(localIpcSourceForLogging, /request received/, "desktop IPC must log request methods for diagnostics."); assert.match(localIpcPathsSource, /OPENPETS_IPC_BIND[\s\S]*?OPENPETS_IPC_ENDPOINT[\s\S]*?validateBindHost[\s\S]*?validateAdvertisedHost/, "WSL NAT IPC must separate bind and advertised endpoints with validation."); diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 03ec43a3..e5006f19 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -15,6 +15,15 @@ import { installInternalUiHandlers, installInternalUiProtocol, openTaskWindow } app.commandLine.appendSwitch("use-mock-keychain"); app.commandLine.appendSwitch("password-store", "basic"); +// GNOME Wayland does not allow Electron apps to reliably control window +// z-order or absolute position, which breaks the desktop-pet contract: staying +// above normal windows and dragging to a user-chosen screen position. Prefer +// X11/Xwayland on Linux unless the user explicitly chooses another Ozone +// backend at launch. +if (process.platform === "linux" && !app.commandLine.hasSwitch("ozone-platform")) { + app.commandLine.appendSwitch("ozone-platform", "x11"); +} + const gotSingleInstanceLock = app.requestSingleInstanceLock(); if (!gotSingleInstanceLock) { @@ -25,7 +34,7 @@ if (!gotSingleInstanceLock) { app.whenReady().then(async () => { initializeLogger(); app.setName("OpenPets"); - info("app", "startup begin", { version: app.getVersion(), platform: process.platform, arch: process.arch, packaged: app.isPackaged, pid: process.pid }); + info("app", "startup begin", { version: app.getVersion(), platform: process.platform, arch: process.arch, packaged: app.isPackaged, pid: process.pid, ozonePlatform: app.commandLine.getSwitchValue("ozone-platform") || null }); if (process.platform === "darwin") { app.dock?.hide();