Use wayland if possible on linux
All checks were successful
Queue Release Build / prepare (push) Successful in 58s
Deploy Web Apps / deploy (push) Successful in 22m58s
Queue Release Build / build-linux (push) Successful in 1h10m11s
Queue Release Build / build-windows (push) Successful in 32m8s
Queue Release Build / finalize (push) Successful in 3m11s
All checks were successful
Queue Release Build / prepare (push) Successful in 58s
Deploy Web Apps / deploy (push) Successful in 22m58s
Queue Release Build / build-linux (push) Successful in 1h10m11s
Queue Release Build / build-windows (push) Successful in 32m8s
Queue Release Build / finalize (push) Successful in 3m11s
This commit is contained in:
2
dev.sh
2
dev.sh
@@ -33,4 +33,4 @@ fi
|
||||
exec npx concurrently --kill-others \
|
||||
"cd server && npm run dev" \
|
||||
"$NG_SERVE" \
|
||||
"wait-on $WAIT_URL $HEALTH_URL && cross-env NODE_ENV=development SSL=$SSL electron . --no-sandbox --disable-dev-shm-usage"
|
||||
"wait-on $WAIT_URL $HEALTH_URL && cross-env NODE_ENV=development SSL=$SSL node tools/launch-electron.js . --no-sandbox --disable-dev-shm-usage"
|
||||
|
||||
@@ -45,9 +45,9 @@ function linuxSpecificFlags(): void {
|
||||
app.commandLine.appendSwitch('no-sandbox');
|
||||
app.commandLine.appendSwitch('disable-dev-shm-usage');
|
||||
|
||||
// Auto-detect Wayland vs X11 so the xdg-desktop-portal system picker
|
||||
// works for screen capture on Wayland compositors
|
||||
app.commandLine.appendSwitch('ozone-platform-hint', 'auto');
|
||||
// Chromium chooses the Linux Ozone platform before Electron runs this file.
|
||||
// The launch scripts pass `--ozone-platform=wayland` up front for Wayland
|
||||
// sessions so the browser process selects the correct backend early enough.
|
||||
}
|
||||
|
||||
function networkFlags(): void {
|
||||
|
||||
@@ -83,6 +83,57 @@ interface ClipboardFilePayload {
|
||||
path?: string;
|
||||
}
|
||||
|
||||
function resolveLinuxDisplayServer(): string {
|
||||
if (process.platform !== 'linux') {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
const ozonePlatform = app.commandLine.getSwitchValue('ozone-platform')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (ozonePlatform === 'wayland') {
|
||||
return 'Wayland';
|
||||
}
|
||||
|
||||
if (ozonePlatform === 'x11') {
|
||||
return 'X11';
|
||||
}
|
||||
|
||||
const ozonePlatformHint = app.commandLine.getSwitchValue('ozone-platform-hint')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (ozonePlatformHint === 'wayland') {
|
||||
return 'Wayland';
|
||||
}
|
||||
|
||||
if (ozonePlatformHint === 'x11') {
|
||||
return 'X11';
|
||||
}
|
||||
|
||||
const sessionType = String(process.env['XDG_SESSION_TYPE'] || '').trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (sessionType === 'wayland') {
|
||||
return 'Wayland';
|
||||
}
|
||||
|
||||
if (sessionType === 'x11') {
|
||||
return 'X11';
|
||||
}
|
||||
|
||||
if (String(process.env['WAYLAND_DISPLAY'] || '').trim().length > 0) {
|
||||
return 'Wayland';
|
||||
}
|
||||
|
||||
if (String(process.env['DISPLAY'] || '').trim().length > 0) {
|
||||
return 'X11';
|
||||
}
|
||||
|
||||
return 'Unknown (Linux)';
|
||||
}
|
||||
|
||||
function isSupportedClipboardFileFormat(format: string): boolean {
|
||||
return FILE_CLIPBOARD_FORMATS.some(
|
||||
(supportedFormat) => supportedFormat.toLowerCase() === format.toLowerCase()
|
||||
@@ -194,6 +245,10 @@ async function readClipboardFiles(): Promise<ClipboardFilePayload[]> {
|
||||
}
|
||||
|
||||
export function setupSystemHandlers(): void {
|
||||
ipcMain.on('get-linux-display-server', (event) => {
|
||||
event.returnValue = resolveLinuxDisplayServer();
|
||||
});
|
||||
|
||||
ipcMain.handle('open-external', async (_event, url: string) => {
|
||||
if (typeof url === 'string' && (url.startsWith('http://') || url.startsWith('https://'))) {
|
||||
await shell.openExternal(url);
|
||||
|
||||
@@ -83,7 +83,24 @@ export interface DesktopUpdateState {
|
||||
targetVersion: string | null;
|
||||
}
|
||||
|
||||
function readLinuxDisplayServer(): string {
|
||||
if (process.platform !== 'linux') {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
try {
|
||||
const displayServer = ipcRenderer.sendSync('get-linux-display-server');
|
||||
|
||||
return typeof displayServer === 'string' && displayServer.trim().length > 0
|
||||
? displayServer
|
||||
: 'Unknown (Linux)';
|
||||
} catch {
|
||||
return 'Unknown (Linux)';
|
||||
}
|
||||
}
|
||||
|
||||
export interface ElectronAPI {
|
||||
linuxDisplayServer: string;
|
||||
minimizeWindow: () => void;
|
||||
maximizeWindow: () => void;
|
||||
closeWindow: () => void;
|
||||
@@ -139,6 +156,7 @@ export interface ElectronAPI {
|
||||
}
|
||||
|
||||
const electronAPI: ElectronAPI = {
|
||||
linuxDisplayServer: readLinuxDisplayServer(),
|
||||
minimizeWindow: () => ipcRenderer.send('window-minimize'),
|
||||
maximizeWindow: () => ipcRenderer.send('window-maximize'),
|
||||
closeWindow: () => ipcRenderer.send('window-close'),
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
"server:build": "cd server && npm run build",
|
||||
"server:start": "cd server && npm start",
|
||||
"server:dev": "cd server && npm run dev",
|
||||
"electron": "ng build && npm run build:electron && electron . --no-sandbox --disable-dev-shm-usage",
|
||||
"electron:dev": "concurrently \"ng serve\" \"wait-on http://localhost:4200 && npm run build:electron && cross-env NODE_ENV=development electron . --no-sandbox --disable-dev-shm-usage\"",
|
||||
"electron": "ng build && npm run build:electron && node tools/launch-electron.js . --no-sandbox --disable-dev-shm-usage",
|
||||
"electron:dev": "concurrently \"ng serve\" \"wait-on http://localhost:4200 && npm run build:electron && cross-env NODE_ENV=development node tools/launch-electron.js . --no-sandbox --disable-dev-shm-usage\"",
|
||||
"electron:full": "./dev.sh",
|
||||
"electron:full:build": "npm run build:all && concurrently --kill-others \"cd server && npm start\" \"cross-env NODE_ENV=production electron . --no-sandbox --disable-dev-shm-usage\"",
|
||||
"electron:full:build": "npm run build:all && concurrently --kill-others \"cd server && npm start\" \"cross-env NODE_ENV=production node tools/launch-electron.js . --no-sandbox --disable-dev-shm-usage\"",
|
||||
"migration:generate": "typeorm migration:generate electron/migrations/Auto -d dist/electron/data-source.js",
|
||||
"migration:create": "typeorm migration:create electron/migrations/New",
|
||||
"migration:run": "typeorm migration:run -d dist/electron/data-source.js",
|
||||
|
||||
@@ -15,6 +15,10 @@ export interface DebugExportEnvironment {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
interface DebugConsoleElectronApi {
|
||||
linuxDisplayServer?: string;
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DebugConsoleEnvironmentService {
|
||||
private readonly store = inject(Store);
|
||||
@@ -113,19 +117,24 @@ export class DebugConsoleEnvironmentService {
|
||||
if (!navigator.userAgent.includes('Linux'))
|
||||
return 'N/A';
|
||||
|
||||
const electronDisplayServer = this.readElectronDisplayServer();
|
||||
|
||||
if (electronDisplayServer)
|
||||
return electronDisplayServer;
|
||||
|
||||
try {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
|
||||
if (ua.includes('wayland'))
|
||||
return 'Wayland';
|
||||
|
||||
if (ua.includes('x11'))
|
||||
return 'X11';
|
||||
|
||||
const isOzone = ua.includes('ozone');
|
||||
|
||||
if (isOzone)
|
||||
return 'Ozone (Wayland likely)';
|
||||
|
||||
if (ua.includes('x11'))
|
||||
return 'X11';
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
@@ -133,11 +142,22 @@ export class DebugConsoleEnvironmentService {
|
||||
return this.detectDisplayServerFromEnv();
|
||||
}
|
||||
|
||||
private readElectronDisplayServer(): string | null {
|
||||
try {
|
||||
const displayServer = this.getElectronApi()?.linuxDisplayServer;
|
||||
|
||||
return typeof displayServer === 'string' && displayServer.trim().length > 0
|
||||
? displayServer
|
||||
: null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private detectDisplayServerFromEnv(): string {
|
||||
try {
|
||||
// Electron may expose env vars
|
||||
const api = this.getElectronApi() as
|
||||
Record<string, unknown> | null;
|
||||
const api = this.getElectronApi();
|
||||
|
||||
if (!api)
|
||||
return 'Unknown (Linux)';
|
||||
@@ -201,10 +221,10 @@ export class DebugConsoleEnvironmentService {
|
||||
}
|
||||
}
|
||||
|
||||
private getElectronApi(): Record<string, unknown> | null {
|
||||
private getElectronApi(): DebugConsoleElectronApi | null {
|
||||
try {
|
||||
const win = window as Window &
|
||||
{ electronAPI?: Record<string, unknown> };
|
||||
{ electronAPI?: DebugConsoleElectronApi };
|
||||
|
||||
return win.electronAPI ?? null;
|
||||
} catch {
|
||||
|
||||
70
tools/launch-electron.js
Normal file
70
tools/launch-electron.js
Normal file
@@ -0,0 +1,70 @@
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
function isWaylandSession(env) {
|
||||
const sessionType = String(env.XDG_SESSION_TYPE || '').trim().toLowerCase();
|
||||
|
||||
if (sessionType === 'wayland') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return String(env.WAYLAND_DISPLAY || '').trim().length > 0;
|
||||
}
|
||||
|
||||
function hasSwitch(args, switchName) {
|
||||
const normalizedSwitch = `--${switchName}`;
|
||||
|
||||
return args.some((arg) => arg === normalizedSwitch || arg.startsWith(`${normalizedSwitch}=`));
|
||||
}
|
||||
|
||||
function resolveElectronBinary() {
|
||||
const electronModule = require('electron');
|
||||
|
||||
if (typeof electronModule === 'string') {
|
||||
return electronModule;
|
||||
}
|
||||
|
||||
if (electronModule && typeof electronModule.default === 'string') {
|
||||
return electronModule.default;
|
||||
}
|
||||
|
||||
throw new Error('Could not resolve the Electron executable.');
|
||||
}
|
||||
|
||||
function buildElectronArgs(argv) {
|
||||
const args = [...argv];
|
||||
|
||||
if (
|
||||
process.platform === 'linux'
|
||||
&& isWaylandSession(process.env)
|
||||
&& !hasSwitch(args, 'ozone-platform')
|
||||
) {
|
||||
args.push('--ozone-platform=wayland');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const electronBinary = resolveElectronBinary();
|
||||
const args = buildElectronArgs(process.argv.slice(2));
|
||||
const child = spawn(electronBinary, args, {
|
||||
env: process.env,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
child.on('error', (error) => {
|
||||
console.error(error instanceof Error ? error.message : String(error));
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
child.on('exit', (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user