Further optimization passes

This commit is contained in:
Allie H 2026-03-11 17:35:46 -04:00
parent ff54140d62
commit 68b4916f64
12 changed files with 574 additions and 881 deletions

View file

@ -235,15 +235,22 @@ function debugLog(...args) {
console.log(...args);
}
debugLog("[Wo] Electron starting, NODE_VERSION=", process.version);
app.commandLine.appendSwitch("use-gl", "angle");
app.commandLine.appendSwitch("use-angle", "vulkan");
app.commandLine.appendSwitch("ozone-platform", "wayland");
app.commandLine.appendSwitch("no-sandbox");
app.commandLine.appendSwitch("disable-gpu-sandbox");
app.commandLine.appendSwitch("ignore-gpu-blocklist");
app.commandLine.appendSwitch("enable-gpu-rasterization");
app.commandLine.appendSwitch("enable-zero-copy");
app.commandLine.appendSwitch("enable-native-gpu-memory-buffers");
app.commandLine.appendSwitch("disable-software-rasterizer");
app.commandLine.appendSwitch("enable-features", "CanvasOopRasterization,Vulkan,VaapiVideoDecoder,VaapiVideoEncoder,SharedArrayBuffer,RawDraw");
app.commandLine.appendSwitch("enable-features", "CanvasOopRasterization,Vulkan,VaapiVideoDecoder,VaapiVideoEncoder,SharedArrayBuffer,RawDraw,DefaultANGLEVulkan,VulkanFromANGLE");
app.commandLine.appendSwitch("enable-accelerated-video-decode");
app.commandLine.appendSwitch("disable-frame-rate-limit");
app.commandLine.appendSwitch("disable-gpu-vsync");
app.commandLine.appendSwitch("num-raster-threads", "4");
app.commandLine.appendSwitch("disable-renderer-backgrounding");
debugLog("[Wo] GPU acceleration flags applied");
var IPC_SOCKET = process.env.WO_IPC_SOCKET || "/run/user/1000/wo-ipc.sock";
debugLog("[Wo] WO_WINDOW_CONFIG env =", process.env.WO_WINDOW_CONFIG);

View file

@ -2,6 +2,7 @@ import { app, BrowserWindow, ipcMain } from 'electron';
import { createConnection, createServer, Socket, Server } from 'net';
import { fileURLToPath } from 'url';
import { dirname, resolve as resolvePath, join as joinPath } from 'path';
import { randomUUID } from 'crypto';
import fs from 'fs';
import { createRequire } from 'module';
import { MAGIC, stringToBuffer } from './protocol.js';
@ -44,18 +45,25 @@ function debugLog(...args: any[]) {
debugLog('[Wo] Electron starting, NODE_VERSION=', process.version);
// GPU acceleration & rendering performance flags (must be set before app 'ready')
// Note: core flags (--in-process-gpu, --use-gl=egl, --ozone-platform=wayland)
// are set on the command line in the Rust spawn(). Flags below augment those.
// Chromium flags MUST go through appendSwitch — process argv flags are not
// reliably forwarded by Electron to Chromium's command-line parser.
app.commandLine.appendSwitch('use-gl', 'angle');
app.commandLine.appendSwitch('use-angle', 'vulkan');
app.commandLine.appendSwitch('ozone-platform', 'wayland');
app.commandLine.appendSwitch('no-sandbox');
app.commandLine.appendSwitch('disable-gpu-sandbox');
app.commandLine.appendSwitch('ignore-gpu-blocklist');
app.commandLine.appendSwitch('enable-gpu-rasterization');
app.commandLine.appendSwitch('enable-zero-copy');
app.commandLine.appendSwitch('enable-native-gpu-memory-buffers');
app.commandLine.appendSwitch('disable-software-rasterizer');
app.commandLine.appendSwitch('enable-features',
'CanvasOopRasterization,Vulkan,VaapiVideoDecoder,VaapiVideoEncoder,SharedArrayBuffer,RawDraw');
'CanvasOopRasterization,Vulkan,VaapiVideoDecoder,VaapiVideoEncoder,SharedArrayBuffer,RawDraw,DefaultANGLEVulkan,VulkanFromANGLE');
app.commandLine.appendSwitch('enable-accelerated-video-decode');
app.commandLine.appendSwitch('disable-frame-rate-limit');
app.commandLine.appendSwitch('disable-gpu-vsync');
app.commandLine.appendSwitch('num-raster-threads', '4');
app.commandLine.appendSwitch('disable-renderer-backgrounding');
debugLog('[Wo] GPU acceleration flags applied');
type ClientWindowInfo = {
@ -84,8 +92,8 @@ let ipcSocket: Socket | null = null;
let portalUiServer: Server | null = null;
type PendingPortalRequest = {
socket: Socket;
kind: 'screen_share';
sessionId: string;
requestId: string;
payload: any;
};
const portalPendingRequests = new Map<string, PendingPortalRequest>();
const PORTAL_UI_SOCKET = '/tmp/wo-portal-ui.sock';
@ -202,7 +210,7 @@ function getOrCreateSab(windowName: string, width: number, height: number, strid
surfaceSabCache.set(windowName, entry);
// Tell renderer about the new SAB so it can reference it
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.postMessage('wo:surface-sab', {
mainWindow.webContents.send('wo:surface-sab', {
name: windowName,
sab,
width,
@ -231,7 +239,8 @@ let pointerX = 0;
let pointerY = 0;
function respondToPortalRequest(requestId: string, params: {
allowed: boolean;
response?: unknown;
allowed?: boolean;
type?: string;
windowName?: unknown;
}): { ok: boolean; error?: string } {
@ -240,19 +249,22 @@ function respondToPortalRequest(requestId: string, params: {
return { ok: false, error: `No pending portal request: ${requestId}` };
}
let response: Record<string, unknown>;
if (pending.kind === 'screen_share') {
response = {
allowed: Boolean(params.allowed),
sourceType: params.type === 'window' ? 'Window' : 'Monitor',
windowName: typeof params.windowName === 'string' ? params.windowName : null,
};
} else {
response = { allowed: false };
const responsePayload =
params.response !== undefined
? params.response
: {
allowed: Boolean(params.allowed),
sourceType: params.type === 'window' ? 'Window' : 'Monitor',
windowName: typeof params.windowName === 'string' ? params.windowName : null,
};
if (responsePayload === undefined) {
portalPendingRequests.delete(requestId);
return { ok: false, error: 'Missing portal response payload' };
}
try {
pending.socket.write(`${JSON.stringify(response)}\n`);
pending.socket.write(`${JSON.stringify(responsePayload)}\n`);
pending.socket.end();
portalPendingRequests.delete(requestId);
return { ok: true };
@ -276,64 +288,59 @@ function startPortalUiBridge() {
socket.on('data', (chunk: Buffer) => {
received += chunk.toString('utf8');
const nl = received.indexOf('\n');
if (nl < 0) return;
let nl = received.indexOf('\n');
while (nl >= 0) {
const line = received.slice(0, nl).trim();
received = received.slice(nl + 1);
const line = received.slice(0, nl).trim();
received = received.slice(nl + 1);
if (!line) return;
if (line.length > 0) {
try {
const req = JSON.parse(line) as Record<string, unknown>;
const requestId = String(
(req?.requestId as string | undefined)
?? (req?.sessionId as string | undefined)
?? (req?.id as string | undefined)
?? randomUUID(),
);
try {
const req = JSON.parse(line) as {
type?: string;
appName?: string;
sessionId?: string;
};
portalPendingRequests.set(requestId, { socket, requestId, payload: req });
if (req.type !== 'screen_share_request' || !req.sessionId) {
socket.end('{"allowed":false,"reason":"invalid_request"}\n');
return;
}
// Auto-timeout if UI does not respond within 90s
socket.setTimeout(90_000, () => {
const pending = portalPendingRequests.get(requestId);
if (pending) {
portalPendingRequests.delete(requestId);
pending.socket.end(JSON.stringify({ error: 'timeout', requestId }) + '\n');
}
});
const requestId = req.sessionId;
portalPendingRequests.set(requestId, {
socket,
kind: 'screen_share',
sessionId: req.sessionId,
});
// Auto-deny if UI does not respond within 90s
socket.setTimeout(90_000, () => {
const pending = portalPendingRequests.get(requestId);
if (pending) {
portalPendingRequests.delete(requestId);
pending.socket.end('{"allowed":false,"reason":"timeout"}\n');
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('wo:portal-request', {
requestId,
payload: req,
kind: typeof req?.type === 'string'
? (req.type as string)
: typeof req?.kind === 'string'
? (req.kind as string)
: undefined,
});
} else {
portalPendingRequests.delete(requestId);
socket.end(JSON.stringify({ error: 'no_ui', requestId }) + '\n');
}
} catch {
socket.end('{"error":"invalid_json"}\n');
}
});
if (mainWindow && !mainWindow.isDestroyed()) {
const payload = {
requestId,
kind: 'screen_share',
appName: req.appName || 'Application',
sessionId: req.sessionId,
};
mainWindow.webContents.send('wo:portal-request', payload);
} else {
portalPendingRequests.delete(requestId);
socket.end('{"allowed":false,"reason":"no_ui"}\n');
}
} catch {
socket.end('{"allowed":false,"reason":"invalid_json"}\n');
nl = received.indexOf('\n');
}
});
socket.on('close', () => {
for (const [sessionId, pending] of portalPendingRequests.entries()) {
for (const [requestId, pending] of portalPendingRequests.entries()) {
if (pending.socket === socket) {
portalPendingRequests.delete(sessionId);
portalPendingRequests.delete(requestId);
break;
}
}
@ -356,7 +363,7 @@ function startPortalUiBridge() {
function stopPortalUiBridge() {
for (const pending of portalPendingRequests.values()) {
try {
pending.socket.end('{"allowed":false,"reason":"shutdown"}\n');
pending.socket.end(JSON.stringify({ error: 'shutdown', requestId: pending.requestId }) + '\n');
} catch {
// ignore
}
@ -402,321 +409,22 @@ let clientWindows: ClientWindowInfo[] = parseClientWindows();
// Live window list received from the compositor via WOWM metadata messages.
let compositorWindows: Record<string, unknown>[] = [];
type StatusNotifierTrayItem = {
id: string;
title: string;
status: 'active' | 'passive' | 'attention';
icon: string;
iconDataUrl?: string;
service: string;
objectPath: string;
menuPath?: string;
hasMenu: boolean;
};
function parseQuotedStrings(output: string): string[] {
const matches = output.matchAll(/"((?:[^"\\]|\\.)*)"/g);
const values: string[] = [];
for (const match of matches) {
const raw = match[1];
values.push(raw.replace(/\\"/g, '"').replace(/\\\\/g, '\\'));
}
return values;
}
function runBusctlUser(args: string[]): string {
type DbBus = 'user' | 'system';
function runBusctl(bus: DbBus, args: string[]): { ok: boolean; stdout: string; stderr: string; exitCode: number } {
try {
const { execFileSync } = require('child_process') as typeof import('child_process');
return execFileSync('busctl', ['--user', ...args], {
const { spawnSync } = require('child_process') as typeof import('child_process');
const res = spawnSync('busctl', [bus === 'system' ? '--system' : '--user', ...args], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim();
} catch {
return '';
}
}
function parseServiceAndPath(itemRef: string): { service: string; objectPath: string } | null {
const slashIdx = itemRef.indexOf('/');
if (slashIdx > 0) {
return {
service: itemRef.slice(0, slashIdx),
objectPath: itemRef.slice(slashIdx),
};
}
if (!itemRef) {
return null;
}
return {
service: itemRef,
objectPath: '/StatusNotifierItem',
};
}
function parseBusctlStringValue(output: string): string {
const quoted = parseQuotedStrings(output);
if (quoted.length > 0) {
return quoted[0];
}
const parts = output.split(/\s+/);
return parts.length >= 2 ? parts.slice(1).join(' ').trim() : '';
}
function getBusProperty(service: string, objectPath: string, iface: string, prop: string): string {
const out = runBusctlUser(['get-property', service, objectPath, iface, prop]);
return out ? parseBusctlStringValue(out) : '';
}
function mapTrayIcon(iconName: string, title: string): string {
const n = iconName.toLowerCase();
const t = title.toLowerCase();
if (n.includes('network') || t.includes('network') || t.includes('wifi')) return 'mdi:wifi';
if (n.includes('audio') || n.includes('volume') || t.includes('volume')) return 'mdi:volume-high';
if (n.includes('battery') || t.includes('battery')) return 'mdi:battery';
if (n.includes('bluetooth') || t.includes('bluetooth')) return 'mdi:bluetooth';
if (n.includes('telegram') || t.includes('telegram')) return 'mdi:telegram';
if (n.includes('discord') || t.includes('discord')) return 'mdi:discord';
if (n.includes('steam') || t.includes('steam')) return 'mdi:steam';
if (n.includes('dropbox') || t.includes('dropbox')) return 'mdi:dropbox';
if (n.includes('mail') || t.includes('mail')) return 'mdi:email-outline';
if (n.includes('kde') || t.includes('kde')) return 'mdi:kde';
return 'mdi:circle-medium';
}
function iconPathCandidates(iconName: string): string[] {
const direct = iconName.startsWith('/') ? [iconName] : [];
if (iconName.startsWith('/')) {
return direct;
}
const exts = ['png', 'svg'];
const bases = [
'/usr/share/pixmaps',
'/usr/share/icons/hicolor/16x16/apps',
'/usr/share/icons/hicolor/22x22/apps',
'/usr/share/icons/hicolor/24x24/apps',
'/usr/share/icons/hicolor/32x32/apps',
'/usr/share/icons/hicolor/48x48/apps',
'/usr/share/icons/hicolor/scalable/apps',
'/usr/share/icons/breeze/apps/22',
'/usr/share/icons/breeze/apps/24',
'/usr/share/icons/breeze/apps/32',
];
const results: string[] = [];
for (const base of bases) {
for (const ext of exts) {
results.push(`${base}/${iconName}.${ext}`);
}
}
return results;
}
function toDataUrlForIconFile(iconPath: string): string | undefined {
try {
if (!fs.existsSync(iconPath)) {
return undefined;
}
const lower = iconPath.toLowerCase();
const mime = lower.endsWith('.svg') ? 'image/svg+xml' : lower.endsWith('.png') ? 'image/png' : '';
if (!mime) {
return undefined;
}
const base64 = fs.readFileSync(iconPath).toString('base64');
return `data:${mime};base64,${base64}`;
} catch {
return undefined;
}
}
function resolveTrayIconDataUrl(iconName: string): string | undefined {
for (const candidate of iconPathCandidates(iconName)) {
const dataUrl = toDataUrlForIconFile(candidate);
if (dataUrl) {
return dataUrl;
}
}
return undefined;
}
function getStatusNotifierTrayItems(): StatusNotifierTrayItem[] {
const watcherCall = runBusctlUser([
'call',
'org.kde.StatusNotifierWatcher',
'/StatusNotifierWatcher',
'org.kde.StatusNotifierWatcher',
'RegisteredStatusNotifierItems',
]);
if (!watcherCall) {
return [];
}
const refs = parseQuotedStrings(watcherCall);
const results: StatusNotifierTrayItem[] = [];
for (const itemRef of refs) {
const parsed = parseServiceAndPath(itemRef);
if (!parsed) {
continue;
}
const statusRaw = getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'Status');
const title =
getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'Title')
|| getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'Id')
|| parsed.service;
const iconName =
getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'AttentionIconName')
|| getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'IconName');
const menuPath = getBusProperty(parsed.service, parsed.objectPath, 'org.kde.StatusNotifierItem', 'Menu');
const iconDataUrl = iconName ? resolveTrayIconDataUrl(iconName) : undefined;
let status: StatusNotifierTrayItem['status'] = 'active';
const s = statusRaw.toLowerCase();
if (s.includes('passive')) {
status = 'passive';
} else if (s.includes('attention') || s.includes('needsattention')) {
status = 'attention';
}
results.push({
id: `${parsed.service}${parsed.objectPath}`,
title,
status,
icon: mapTrayIcon(iconName || title, title),
iconDataUrl,
service: parsed.service,
objectPath: parsed.objectPath,
menuPath: menuPath || undefined,
hasMenu: Boolean(menuPath && menuPath !== '/NO_DBUSMENU'),
stdio: ['ignore', 'pipe', 'pipe'],
});
}
return results;
}
function activateStatusNotifierItem(service: string, objectPath: string): boolean {
const out = runBusctlUser([
'call',
service,
objectPath,
'org.kde.StatusNotifierItem',
'Activate',
'ii',
'0',
'0',
]);
return out.length > 0;
}
function secondaryActivateStatusNotifierItem(service: string, objectPath: string): boolean {
const out = runBusctlUser([
'call',
service,
objectPath,
'org.kde.StatusNotifierItem',
'SecondaryActivate',
'ii',
'0',
'0',
]);
return out.length > 0;
}
function openStatusNotifierContextMenu(service: string, objectPath: string, x: number, y: number): boolean {
const out = runBusctlUser([
'call',
service,
objectPath,
'org.kde.StatusNotifierItem',
'ContextMenu',
'ii',
String(Math.trunc(x)),
String(Math.trunc(y)),
]);
return out.length > 0;
}
type DBusMenuItem = {
id: string;
label: string;
enabled: boolean;
children?: DBusMenuItem[];
};
function getDBusMenuLayout(service: string, menuPath: string): DBusMenuItem[] {
try {
const out = runBusctlUser([
'call',
service,
menuPath.startsWith('/') ? menuPath : '/com/canonical/dbusmenu',
'com.canonical.dbusmenu',
'GetLayout',
'u',
'0',
]);
if (!out) {
return [];
}
const lines = out.split('\n').filter(l => l.trim().length > 0);
const items: DBusMenuItem[] = [];
let depth = 0;
for (const line of lines) {
const trimmed = line.trim();
const newDepth = (line.match(/^\s*/)?.[0]?.length ?? 0) / 2;
if (trimmed.startsWith('(') && trimmed.includes('"')) {
const quoted = parseQuotedStrings(trimmed);
if (quoted.length > 0) {
const label = quoted[0];
const item: DBusMenuItem = {
id: label,
label,
enabled: !line.toLowerCase().includes('disabled'),
};
if (newDepth === 0) {
items.push(item);
} else if (items.length > 0 && newDepth > depth) {
const parent = items[items.length - 1];
if (!parent.children) {
parent.children = [];
}
parent.children.push(item);
}
}
depth = newDepth;
}
}
return items;
} catch {
return [];
}
}
function triggerDBusMenuEvent(service: string, menuPath: string, menuId: string): boolean {
try {
const out = runBusctlUser([
'call',
service,
menuPath.startsWith('/') ? menuPath : '/com/canonical/dbusmenu',
'com.canonical.dbusmenu',
'Event',
'sis',
menuId,
'clicked',
'',
]);
return out.length > 0;
} catch {
return false;
return {
ok: res.status === 0,
stdout: (res.stdout as string | undefined)?.trim?.() || '',
stderr: (res.stderr as string | undefined)?.trim?.() || '',
exitCode: res.status ?? -1,
};
} catch (error: any) {
return { ok: false, stdout: '', stderr: String(error), exitCode: -1 };
}
}
@ -1263,17 +971,56 @@ function connectToCompositor(): Promise<void> {
const dmabufFormat = compositorRxBuffer.readUInt32LE(off); off += 4;
const numPlanes = compositorRxBuffer.readUInt32LE(off); off += 4;
const totalSize = (off - rxReadOffset) + (numPlanes * 24);
const planeSectionSize = numPlanes * 24;
const totalSize = (off - rxReadOffset) + planeSectionSize;
if (rxAvailable() < totalSize) break;
const planes: Array<{ offset: bigint; stride: number; modifier: bigint }> = [];
let planeOff = off;
for (let i = 0; i < numPlanes; i++) {
planeOff += 4; // fd placeholder
const planeOffset = compositorRxBuffer.readBigUInt64LE(planeOff); planeOff += 8;
const planeStride = compositorRxBuffer.readUInt32LE(planeOff); planeOff += 4;
const modifier = compositorRxBuffer.readBigUInt64LE(planeOff); planeOff += 8;
planes.push({ offset: planeOffset, stride: planeStride, modifier });
}
try {
if (nativeDmabuf && ipcSocket) {
const socketFd = (ipcSocket as any)?._handle?.fd;
if (typeof socketFd === 'number' && socketFd >= 0) {
const dmabufFd = nativeDmabuf.recvFd(socketFd);
if (dmabufFd >= 0) {
const planeFds: number[] = [];
for (let i = 0; i < numPlanes; i++) {
const fd = nativeDmabuf.recvFd(socketFd);
if (fd >= 0) planeFds.push(fd);
}
const primaryFd = planeFds.find((fd) => fd >= 0);
const primaryPlane = planes[0];
const stride = primaryPlane?.stride || dmabufW * 4;
const offset = primaryPlane ? Number(primaryPlane.offset) : 0;
if (primaryFd !== undefined) {
try {
const textureInfo = nativeDmabuf.importDmabufTexture(dmabufName, dmabufFd, dmabufW, dmabufH, dmabufFormat);
// Map DMABUF into SAB so renderer can reuse existing surface path
const sabEntry = getOrCreateSab(dmabufName, dmabufW, dmabufH, stride);
const copySize = offset + stride * dmabufH;
nativeDmabuf.copyMmapToSab(primaryFd, sabEntry.sab, copySize, offset);
surfaceUpdatePending.set(dmabufName, {
name: dmabufName,
width: dmabufW,
height: dmabufH,
stride,
generation: ++surfaceUpdateGeneration,
});
if (!surfaceUpdateFlushScheduled) {
surfaceUpdateFlushScheduled = true;
setImmediate(flushSurfaceUpdates);
}
// Preserve existing DMABUF texture notification for any consumers
const textureInfo = nativeDmabuf.importDmabufTexture(dmabufName, primaryFd, dmabufW, dmabufH, dmabufFormat);
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('wo:dmabuf-frame', {
name: dmabufName,
@ -1283,7 +1030,9 @@ function connectToCompositor(): Promise<void> {
});
}
} finally {
fs.closeSync(dmabufFd);
for (const fd of planeFds) {
try { fs.closeSync(fd); } catch { /* ignore */ }
}
}
}
}
@ -1701,64 +1450,8 @@ function setupIpcHandlers() {
timestamp: Date.now(),
});
}
return { ok: true };
}
case 'tray_list': {
return getStatusNotifierTrayItems();
}
case 'tray_activate': {
const service = String(params.service || '');
const objectPath = String(params.objectPath || '');
if (!service || !objectPath) {
return { ok: false, error: 'Missing service or objectPath' };
return { ok: true };
}
const ok = activateStatusNotifierItem(service, objectPath);
return ok ? { ok: true } : { ok: false, error: 'Activation failed' };
}
case 'tray_secondary_activate': {
const service = String(params.service || '');
const objectPath = String(params.objectPath || '');
if (!service || !objectPath) {
return { ok: false, error: 'Missing service or objectPath' };
}
const ok = secondaryActivateStatusNotifierItem(service, objectPath);
return ok ? { ok: true } : { ok: false, error: 'Secondary activation failed' };
}
case 'tray_context_menu': {
const service = String(params.service || '');
const objectPath = String(params.objectPath || '');
const x = Number(params.x ?? 0);
const y = Number(params.y ?? 0);
if (!service || !objectPath) {
return { ok: false, error: 'Missing service or objectPath' };
}
const ok = openStatusNotifierContextMenu(service, objectPath, x, y);
return ok ? { ok: true } : { ok: false, error: 'Context menu failed' };
}
case 'tray_menu_items': {
const service = String(params.service || '');
const menuPath = String(params.menuPath || '');
if (!service || !menuPath) {
return [];
}
return getDBusMenuLayout(service, menuPath);
}
case 'tray_menu_event': {
const service = String(params.service || '');
const menuPath = String(params.menuPath || '');
const menuId = String(params.menuId || '');
if (!service || !menuPath || !menuId) {
return { ok: false, error: 'Missing parameters' };
}
const ok = triggerDBusMenuEvent(service, menuPath, menuId);
return ok ? { ok: true } : { ok: false, error: 'Menu event failed' };
}
case 'portal_respond': {
const requestId = String(params.requestId || '');
@ -1766,12 +1459,65 @@ function setupIpcHandlers() {
return { ok: false, error: 'Missing portal requestId' };
}
return respondToPortalRequest(requestId, {
allowed: Boolean(params.allowed),
response: params.response,
allowed: params.allowed,
type: typeof params.type === 'string' ? params.type : undefined,
windowName: params.windowName,
});
}
case 'dbus_call': {
const bus: DbBus = params.bus === 'system' ? 'system' : 'user';
const service = String(params.service || '');
const objectPath = String(params.objectPath || '');
const iface = String(params.interface || params.iface || '');
const method = String(params.method || '');
const signature = typeof params.signature === 'string' ? params.signature : '';
const argList: any[] = Array.isArray(params.args) ? params.args : [];
if (!service || !objectPath || !iface || !method) {
return { ok: false, error: 'Missing dbus parameters' };
}
const args = ['call', service, objectPath, iface, method, signature || ''];
if (signature) {
args.push(...argList.map((v) => String(v)));
}
const result = runBusctl(bus, args);
return result;
}
case 'dbus_get_property': {
const bus: DbBus = params.bus === 'system' ? 'system' : 'user';
const service = String(params.service || '');
const objectPath = String(params.objectPath || '');
const iface = String(params.interface || params.iface || '');
const prop = String(params.property || params.prop || '');
if (!service || !objectPath || !iface || !prop) {
return { ok: false, error: 'Missing dbus parameters' };
}
const result = runBusctl(bus, ['get-property', service, objectPath, iface, prop]);
return result;
}
case 'load_local_file': {
const filePath = String(params.path || '');
if (!filePath) {
return { ok: false, error: 'Missing path' };
}
if (!fs.existsSync(filePath)) {
return { ok: false, error: `Path does not exist: ${filePath}` };
}
if (!mainWindow || mainWindow.isDestroyed()) {
return { ok: false, error: 'Main window unavailable' };
}
try {
debugLog('[Wo] Loading local file:', filePath);
await mainWindow.loadFile(filePath);
return { ok: true };
} catch (error) {
return { ok: false, error: String(error) };
}
}
default:
return { ok: false, error: `Unknown syscall: ${type}` };
}
@ -1830,11 +1576,15 @@ async function createWindow() {
}
// In offscreen mode, we need actual content to trigger paint events
// Load the configured URL or fallback to minimal page
debugLog('[Wo] Loading content URL: ' + (url || 'minimal fallback'));
// Load the configured URL/file or fallback to minimal page
debugLog('[Wo] Loading content URL: ' + (url || html || 'minimal fallback'));
try {
const pageUrl = url || 'data:text/html,<!DOCTYPE html><html><head><style>body{background:white;margin:0;}</style></head><body></body></html>';
const loadPromise = mainWindow!.loadURL(pageUrl);
const pageUrl = url
|| (html ? `file://${html}` : null)
|| 'data:text/html,<!DOCTYPE html><html><head><style>body{background:white;margin:0;}</style></head><body></body></html>';
const loadPromise = pageUrl.startsWith('file://')
? mainWindow!.loadURL(pageUrl)
: mainWindow!.loadURL(pageUrl);
// Give it time to load but don't wait forever
await Promise.race([
loadPromise,

View file

@ -120,15 +120,13 @@ const compositorAPI: CompositorAPI = {
// Generic portal request event for client-provided popup/approval handlers
onPortalRequest: (callback: (data: {
requestId: string;
kind: string;
appName?: string;
sessionId?: string;
payload: any;
kind?: string;
}) => void) => {
const handler = (_event: Electron.IpcRendererEvent, data: {
requestId: string;
kind: string;
appName?: string;
sessionId?: string;
payload: any;
kind?: string;
}) => callback(data);
ipcRenderer.on('wo:portal-request', handler);
return () => ipcRenderer.removeListener('wo:portal-request', handler);

View file

@ -2,7 +2,7 @@
"name": "@wl-wo/wo-types",
"module": "index.ts",
"type": "module",
"version": "1.0.0",
"version": "1.0.1",
"devDependencies": {
"@types/bun": "latest"
},

View file

@ -88,7 +88,10 @@ export interface SyscallLogoutParams { [key: string]: any; }
export interface SyscallLockParams { [key: string]: any; }
export interface SyscallSleepParams { [key: string]: any; }
export interface SyscallNotifyParams { id?: string; title: string; body?: string; icon?: string; timeout?: number; [key: string]: any; }
export interface SyscallPortalRespondParams { requestId: string; allowed: boolean; type?: string; windowName?: string | null; [key: string]: any; }
export interface SyscallPortalRespondParams { requestId: string; response?: any; allowed?: boolean; type?: string; windowName?: string | null; [key: string]: any; }
export interface SyscallDbusCallParams { service: string; objectPath: string; interface: string; method: string; signature?: string; args?: any[]; bus?: 'user' | 'system'; [key: string]: any; }
export interface SyscallDbusGetPropertyParams { service: string; objectPath: string; interface: string; property: string; bus?: 'user' | 'system'; [key: string]: any; }
export interface SyscallLoadLocalFileParams { path: string; [key: string]: any; }
export interface SyscallLaunchResult { ok: boolean; pid?: number; error?: string; }
export interface SyscallExecResult { ok: boolean; pid?: number; error?: string; }
@ -102,12 +105,14 @@ export interface SyscallLockResult { ok: boolean; error?: string; }
export interface SyscallSleepResult { ok: boolean; error?: string; }
export interface SyscallNotifyResult { ok: boolean; error?: string; }
export interface SyscallPortalRespondResult { ok: boolean; error?: string; }
export interface SyscallDbusCallResult { ok: boolean; stdout?: string; stderr?: string; exitCode?: number; error?: string; }
export interface SyscallDbusGetPropertyResult { ok: boolean; stdout?: string; stderr?: string; exitCode?: number; error?: string; }
export interface SyscallLoadLocalFileResult { ok: boolean; error?: string; }
export interface PortalRequestEvent {
requestId: string;
kind: string;
appName?: string;
sessionId?: string;
payload: any;
kind?: string;
}
export interface ScreencopyEvent {
@ -217,6 +222,9 @@ export interface Compositor {
syscall(type: 'sleep', params?: SyscallSleepParams): Promise<SyscallSleepResult>;
syscall(type: 'notify', params: SyscallNotifyParams): Promise<SyscallNotifyResult>;
syscall(type: 'portal_respond', params: SyscallPortalRespondParams): Promise<SyscallPortalRespondResult>;
syscall(type: 'dbus_call', params: SyscallDbusCallParams): Promise<SyscallDbusCallResult>;
syscall(type: 'dbus_get_property', params: SyscallDbusGetPropertyParams): Promise<SyscallDbusGetPropertyResult>;
syscall(type: 'load_local_file', params: SyscallLoadLocalFileParams): Promise<SyscallLoadLocalFileResult>;
syscall(type: string, params?: any): Promise<any>;
/**
@ -453,4 +461,4 @@ export interface DamageFramePayload {
fullFrame?: Uint8Array;
fullStride?: number;
patches?: DamagePatch[];
}
}

48
electron/whatever.txt Normal file
View file

@ -0,0 +1,48 @@
Finished `release` profile [optimized] target(s) in 0.12s
Finished `release` profile [optimized] target(s) in 0.12s
Running `/home/hellings/Documents/wo/target/release/wo`
Running `/home/hellings/Documents/wo/target/release/wo`
Xwayland glamor: GBM Wayland interfaces not available
Failed to initialize glamor, falling back to sw
Xwayland glamor: GBM Wayland interfaces not available
Failed to initialize glamor, falling back to sw
(II) IGLX: Loaded and initialized swrast
(II) GLX: Initialized DRISWRAST GL provider for screen 0
(II) IGLX: Loaded and initialized swrast
(II) GLX: Initialized DRISWRAST GL provider for screen 0
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Multiple symbols for level 1/group 1 on key <FK23>
> The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Multiple symbols for level 1/group 1 on key <FK23>
> Using F23, ignoring XF86TouchpadOff
> Warning: Symbol map for key <FK23> redefined
> Using last definition for conflicting fields
> Warning: Symbol map for key <FK24> redefined
> Using last definition for conflicting fields
Using F23, ignoring XF86TouchpadOff
> Warning: Symbol map for key <FK23> redefined
> Using last definition for conflicting fields
> Warning: Symbol map for key <FK24> redefined
> Using last definition for conflicting fields
Errors from xkbcomp are not fatal to the X server
Errors from xkbcomp are not fatal to the X server
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Unsupported maximum keycode 709, clipping.
> X11 cannot support keycodes above 255.
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Unsupported maximum keycode 709, clipping.
> X11 cannot support keycodes above 255.
> Warning: Virtual modifier Hyper multiply defined
> Using 0, ignoring 0
> Warning: > Warning: Virtual modifier Hyper multiply defined
> Using 0, ignoring 0
> Warning: Virtual modifier ScrollLock multiply defined
> Using 0, ignoring 0
Virtual modifier ScrollLock multiply defined
> Using 0, ignoring 0
Errors from xkbcomp are not fatal to the X server
Errors from xkbcomp are not fatal to the X server
[4120:0311/124914.666158:ERROR:gpu/ipc/service/gpu_init.cc:209] Vulkan not supported with in process gpu
[4120:0311/124914.666158:ERROR:gpu/ipc/service/gpu_init.cc:209] Vulkan not supported with in process gpu
(EE) failed to read Wayland events: Broken pipe
(EE) failed to read Wayland events: Broken pipe

View file

@ -296,6 +296,8 @@ impl ElectronClientConnection {
// Get buffer properties
let num_planes = dmabuf.num_planes();
let offsets: Vec<u32> = dmabuf.offsets().collect();
let strides: Vec<u32> = dmabuf.strides().collect();
let (w, h) = {
let size = dmabuf.size();
(size.w as u32, size.h as u32)
@ -330,15 +332,14 @@ impl ElectronClientConnection {
// For each plane: fd(4) + offset(8) + stride(4) + modifier(8)
// Note: We'll collect actual plane data from dmabuf handles iterator
for _handle in dmabuf.handles() {
// fd: will be sent via ancillary data, so we put 0 as placeholder
for plane_idx in 0..num_planes {
// fd placeholder — actual fds are sent via SCM_RIGHTS ancillary data
buf[off..off + 4].copy_from_slice(&0u32.to_le_bytes());
off += 4;
// offset: 0 for now (can be extended later)
buf[off..off + 8].copy_from_slice(&0u64.to_le_bytes());
let offset = offsets.get(plane_idx).copied().unwrap_or(0);
buf[off..off + 8].copy_from_slice(&(offset as u64).to_le_bytes());
off += 8;
// stride: will depend on format (approximate)
let stride = (w * 4) as u32; // ARGB8888 = 4 bytes/pixel, adjust as needed
let stride = strides.get(plane_idx).copied().unwrap_or(w * 4);
buf[off..off + 4].copy_from_slice(&stride.to_le_bytes());
off += 4;
// modifier (8 bytes) - DrmModifier converts to u64
@ -595,43 +596,30 @@ impl ElectronProcess {
let main_js = app_dir.join("dist/main.js");
let child = Command::new(electron_bin)
.arg(&main_js)
.env("WO_IPC_SOCKET", ipc_socket)
.env("WO_WINDOW_CONFIG", &serialized)
.env("WO_DRM_RENDER_NODE", render_node)
// Wayland Ozone platform: Electron connects to our own Wayland
// compositor (WAYLAND_DISPLAY is already set in the env) for
// GPU/EGL initialisation. This gives Chromium a proper
// wayland-egl display so hardware-accelerated rasterisation
// works. The BrowserWindow still uses `offscreen: true`, so
// no Wayland surfaces are mapped — the connection is used
// solely for the EGL context.
// ── Chromium flags ──────────────────────────────────────
// These MUST appear before the app script on the command
// line. Electron treats everything after the script path
// as application arguments (process.argv), NOT Chromium
// switches. Flags here also reach the GPU subprocess
// (critical for --in-process-gpu and --use-gl).
//
// The previous `--ozone-platform=headless` approach failed
// because headless Ozone has no EGL display, causing the GPU
// subprocess to crash with "gl=none,angle=none not found" and
// silently falling back to ~1 FPS software rasterisation.
// Wayland Ozone platform: Electron connects to our own
// Wayland compositor (WAYLAND_DISPLAY is already set in
// the env) for GPU/EGL initialisation.
.arg("--ozone-platform=wayland")
.arg("--no-sandbox")
.arg("--disable-gpu-sandbox")
// Run GPU code in the main Electron process to avoid the
// separate GPU subprocess which adds IPC overhead and can
// fail to initialise independently.
.arg("--in-process-gpu")
// Use native EGL (provided by wayland-egl through the Ozone
// Wayland platform) for Chromium's compositor.
.arg("--use-gl=egl")
// Disable GPU vsync — we are rendering offscreen, there is
// no physical display to synchronise with.
.arg("--use-gl=angle")
.arg("--use-angle=vulkan")
.arg("--disable-gpu-vsync")
// Enable GPU-accelerated rasterization and zero-copy features
// so OSR paint callbacks deliver GPU-backed bitmaps instead
// of slow CPU readbacks.
.arg("--enable-features=CanvasOopRasterization,Vulkan,VaapiVideoDecoder,RawDraw,SharedArrayBuffer")
// Use multiple raster threads for parallelised tile painting.
.arg("--enable-features=CanvasOopRasterization,Vulkan,VaapiVideoDecoder,RawDraw,SharedArrayBuffer,DefaultANGLEVulkan,VulkanFromANGLE")
.arg("--num-raster-threads=4")
// Don't throttle renderers that lose focus.
.arg("--disable-renderer-backgrounding")
// ── App entry point (must come after Chromium flags) ────
.arg(&main_js)
.stdin(Stdio::null())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())

View file

@ -165,7 +165,7 @@ impl WoState {
self.pointer_location = new_pos;
// Process active grab (interactive move/resize) before normal dispatch
if let Some(ref grab) = self.grab_state.clone() {
if let Some(grab) = self.grab_state.clone() {
match grab {
GrabState::Move {
window,
@ -178,7 +178,18 @@ impl WoState {
initial_window_location.x + dx as i32,
initial_window_location.y + dy as i32,
);
let prev_loc = self
.space
.element_location(&window)
.unwrap_or(initial_window_location);
self.space.map_element(window.clone(), new_loc, false);
self.translate_dialog_children(
&window,
new_loc.0 - prev_loc.x,
new_loc.1 - prev_loc.y,
);
self.metadata_dirty = true;
}
GrabState::Resize {
surface,
@ -192,11 +203,11 @@ impl WoState {
let dx = (self.pointer_location.x - initial_pointer.x) as i32;
let dy = (self.pointer_location.y - initial_pointer.y) as i32;
let (mut new_w, mut new_h) = *initial_window_size;
let (mut new_w, mut new_h) = initial_window_size;
let (mut new_x, mut new_y) =
(initial_window_location.x, initial_window_location.y);
match *edges {
match edges {
ResizeEdge::Right | ResizeEdge::TopRight | ResizeEdge::BottomRight => {
new_w = (new_w + dx).max(1);
}
@ -206,7 +217,7 @@ impl WoState {
}
_ => {}
}
match *edges {
match edges {
ResizeEdge::Bottom | ResizeEdge::BottomLeft | ResizeEdge::BottomRight => {
new_h = (new_h + dy).max(1);
}
@ -218,14 +229,24 @@ impl WoState {
}
// Respect client min/max size constraints.
let (clamped_w, clamped_h) = self.clamp_to_size_hints(window, new_w, new_h);
let (clamped_w, clamped_h) = self.clamp_to_size_hints(&window, new_w, new_h);
surface.with_pending_state(|s| {
s.size = Some((clamped_w, clamped_h).into());
});
surface.send_configure();
let prev_loc = self
.space
.element_location(&window)
.unwrap_or(initial_window_location);
self.space
.map_element(window.clone(), (new_x, new_y), false);
self.translate_dialog_children(
&window,
new_x - prev_loc.x,
new_y - prev_loc.y,
);
self.metadata_dirty = true;
}
}
return;
@ -243,7 +264,7 @@ impl WoState {
self.pointer_location = new_pos;
// Process active grab (interactive move/resize) before normal dispatch
if let Some(ref grab) = self.grab_state.clone() {
if let Some(grab) = self.grab_state.clone() {
match grab {
GrabState::Move {
window,
@ -256,7 +277,17 @@ impl WoState {
initial_window_location.x + dx as i32,
initial_window_location.y + dy as i32,
);
let prev_loc = self
.space
.element_location(&window)
.unwrap_or(initial_window_location);
self.space.map_element(window.clone(), new_loc, false);
self.translate_dialog_children(
&window,
new_loc.0 - prev_loc.x,
new_loc.1 - prev_loc.y,
);
self.metadata_dirty = true;
}
GrabState::Resize {
surface,
@ -270,11 +301,11 @@ impl WoState {
let dx = (self.pointer_location.x - initial_pointer.x) as i32;
let dy = (self.pointer_location.y - initial_pointer.y) as i32;
let (mut new_w, mut new_h) = *initial_window_size;
let (mut new_w, mut new_h) = initial_window_size;
let (mut new_x, mut new_y) =
(initial_window_location.x, initial_window_location.y);
match *edges {
match edges {
ResizeEdge::Right | ResizeEdge::TopRight | ResizeEdge::BottomRight => {
new_w = (new_w + dx).max(1);
}
@ -284,7 +315,7 @@ impl WoState {
}
_ => {}
}
match *edges {
match edges {
ResizeEdge::Bottom | ResizeEdge::BottomLeft | ResizeEdge::BottomRight => {
new_h = (new_h + dy).max(1);
}
@ -296,14 +327,24 @@ impl WoState {
}
// Respect client min/max size constraints.
let (clamped_w, clamped_h) = self.clamp_to_size_hints(window, new_w, new_h);
let (clamped_w, clamped_h) = self.clamp_to_size_hints(&window, new_w, new_h);
surface.with_pending_state(|s| {
s.size = Some((clamped_w, clamped_h).into());
});
surface.send_configure();
let prev_loc = self
.space
.element_location(&window)
.unwrap_or(initial_window_location);
self.space
.map_element(window.clone(), (new_x, new_y), false);
self.translate_dialog_children(
&window,
new_x - prev_loc.x,
new_y - prev_loc.y,
);
self.metadata_dirty = true;
}
}
return;

View file

@ -1708,6 +1708,14 @@ fn run_drm(mut config: Config) -> Result<(), anyhow::Error> {
}
}
// Bind the Wayland listening socket BEFORE spawning Electron so that
// Chromium's Ozone/Wayland backend can connect immediately. Without
// this, `--ozone-platform=wayland` fails with "Connection refused"
// because the socket is not yet accepting connections.
let wayland_socket =
ListeningSocket::bind(&config.compositor.socket_name).context("binding Wayland socket")?;
info!(socket = %config.compositor.socket_name, "Wayland socket bound");
std::env::set_var("WAYLAND_DISPLAY", &config.compositor.socket_name);
// Propagate now; DISPLAY will be re-propagated once XWayland is ready.
crate::state::propagate_environment(&["WAYLAND_DISPLAY"]);
@ -1805,10 +1813,6 @@ fn run_drm(mut config: Config) -> Result<(), anyhow::Error> {
};
let last_render = std::time::Instant::now();
let wayland_socket =
ListeningSocket::bind(&config.compositor.socket_name).context("binding Wayland socket")?;
info!(socket = %config.compositor.socket_name, "Wayland socket bound");
// Register the Wayland display fd with calloop so that client messages
// (surface commits, etc.) wake the event loop. Without this, the loop
// only wakes on DRM VBlank / libinput / session events and rendering
@ -2167,7 +2171,14 @@ fn run_drm(mut config: Config) -> Result<(), anyhow::Error> {
.and_then(|p| p.get("y"))
.and_then(|v| v.as_i64())
.unwrap_or(0) as i32;
data.state.space.map_element(window, (x, y + th), false);
let prev_loc = data.state.space.element_location(&window).unwrap_or_default();
data.state.space.map_element(window.clone(), (x, y + th), false);
data.state.translate_dialog_children(
&window,
x - prev_loc.x,
y + th - prev_loc.y,
);
data.state.metadata_dirty = true;
}
"resize" => {
let new_w = payload_json.as_ref()

View file

@ -1310,7 +1310,14 @@ fn process_electron_message(
.unwrap_or(0) as i32;
// comraw reports the MacWindow origin (title bar top);
// the Wayland surface sits th pixels below that.
state.space.map_element(window, (x, y + th), false);
let prev_loc = state.space.element_location(&window).unwrap_or_default();
state.space.map_element(window.clone(), (x, y + th), false);
state.translate_dialog_children(
&window,
x - prev_loc.x,
y + th - prev_loc.y,
);
state.metadata_dirty = true;
}
"resize" => {
let new_w = payload_json

View file

@ -19,7 +19,7 @@ use smithay::{
relative_pointer::RelativePointerManagerState,
pointer_constraints::{self, PointerConstraintsHandler, PointerConstraintsState},
keyboard_shortcuts_inhibit::{KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor},
shell::xdg::{XdgShellState, decoration::XdgDecorationState}, shm::ShmState, single_pixel_buffer::SinglePixelBufferState, tablet_manager::TabletSeatHandler, viewporter::ViewporterState, xdg_activation::{XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData}, xwayland_shell::XWaylandShellState
shell::xdg::{XdgShellState, XdgToplevelSurfaceData, decoration::XdgDecorationState}, shm::ShmState, single_pixel_buffer::SinglePixelBufferState, tablet_manager::TabletSeatHandler, viewporter::ViewporterState, xdg_activation::{XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData}, xwayland_shell::XWaylandShellState
},
xwayland::{XWayland, xwm::X11Wm},
};
@ -558,6 +558,65 @@ impl WoState {
None
}
/// Return the stable parent name (Wayland or X11) for a window, if any.
pub fn parent_name_for_window(&self, window: &Window) -> Option<String> {
if let Some(x11) = window.x11_surface() {
if let Some(parent_id) = x11.is_transient_for() {
return self.x11_window_names.get(&parent_id).cloned();
}
}
let parent_surface = window.toplevel().and_then(|t| {
with_states(t.wl_surface(), |states| {
states
.data_map
.get::<XdgToplevelSurfaceData>()
.and_then(|d| d.lock().ok().and_then(|data| data.parent.clone()))
})
});
if let Some(parent_wl) = parent_surface {
use smithay::reexports::wayland_server::Resource;
return self.wayland_window_names.get(&parent_wl.id()).cloned();
}
None
}
/// Translate all dialog/transient children of `parent` by (dx, dy) to keep them anchored.
pub fn translate_dialog_children(&mut self, parent: &Window, dx: i32, dy: i32) {
if dx == 0 && dy == 0 {
return;
}
let parent_name = match self.wayland_window_name(parent) {
Some(name) => name.clone(),
None => return,
};
let children: Vec<_> = self
.all_windows
.iter()
.cloned()
.filter(|win| {
if let Some(child_parent) = self.parent_name_for_window(win) {
child_parent == parent_name
} else {
false
}
})
.collect();
for child in children {
if let Some(loc) = self.space.element_location(&child) {
self.space
.map_element(child.clone(), (loc.x + dx, loc.y + dy), false);
}
}
self.metadata_dirty = true;
}
/// Find a Wayland or X11 Window element by its stable name (even if minimized).
pub fn find_wayland_window(&self, name: &str) -> Option<Window> {
self.all_windows.iter().find(|w| {

View file

@ -1,337 +1,7 @@
warning: unused import: `Buffer as BufferCoord`
--> src/cursor.rs:10:22
|
10 | use smithay::utils::{Buffer as BufferCoord, Size};
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: unused import: `std::os::unix::io::AsRawFd`
--> src/dmabuf.rs:51:13
|
51 |warning: unused import: `Buffer as BufferCoord`
--> src/cursor.rs:10:22
|
10 | use smithay::utils::{Buffer as BufferCoord, Size};
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: unused import: `std::os::unix::io::AsRawFd`
--> src/dmabuf.rs:51:13
|
51 | use std::os::unix::io::AsRawFd;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `smithay::utils::Rectangle`
--> src/dmabuf.rs:280:9
|
280 | use smithay::utils::Rectangle;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `std::collections::HashMap`
--> src/handlers/screencopy.rs:6:5
|
6 | use std::collections::HashMap;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `wl_output::WlOutput`
--> src/handlers/screencopy.rs:15:37
|
15 | protocol::{wl_buffer::WlBuffer, wl_output::WlOutput, wl_shm},
| ^^^^^^^^^^^^^^^^^^^
use std::os::unix::io::AsRawFd;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `smithay::utils::Rectangle`
--> src/dmabuf.rs:280:9
|
280 | use smithay::utils::Rectangle;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `std::collections::HashMap`
--> src/handlers/screencopy.rs:6:5
|
6 | use std::collections::HashMap;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `wl_output::WlOutput`
--> src/handlers/screencopy.rs:15:37
|
15 | protocol::{wl_buffer::WlBuffer, wl_output::WlOutput, wl_shm},
| ^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `smithay::desktop::Window::new`
--> src/handlers/xdg_shell.rs:53:30
|
53 | let window = Window::new(surface);
| ^^^
|
= notewarning: use of deprecated associated function `smithay::desktop::Window::new`
--> src/handlers/xdg_shell.rs:53:30
|
53 | let window = Window::new(surface);
| ^^^
|
= note: `#[warn(deprecated)]` on by default
: `#[warn(deprecated)]` on by default
warning: use of deprecated associated function `smithay::utils::Rectangle::<N, Kind>::from_loc_and_size`: use new or from_size
--> src/handlers/xwayland.rs:258:58
|
258 |warning: use of deprecated associated function `smithay::utils::Rectangle::<N, Kind>::from_loc_and_size`: use new or from_size
--> src/handlers/xwayland.rs:258:58
|
258 | if let Err(e) = window.configure(Some(Rectangle::from_loc_and_size((0, y_offset), (ow, content_h)))) {
| ^^^^^^^^^^^^^^^^^
if let Err(e) = window.configure(Some(Rectangle::from_loc_and_size((0, y_offset), (ow, content_h)))) {
| ^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `smithay::utils::Rectangle::<N, Kind>::from_loc_and_size`: use new or from_size
--> src/handlers/xwayland.rs:303:58
|
303 | if let Err(e) = window.configure(Some(Rectangle::from_loc_and_size((0, 0), (suggest_w, suggest_h)))) {
| ^^^^^^^^^^^^^^^^^
warning: variable `plane_idx` is assigned to, but never used
--> src/electron.rs:332:13
|
332 | let mut plane_idx = 0;
| ^^^^^^^^^^^^^
|
warning: use of deprecated associated function `smithay::utils::Rectangle::<N, Kind>::from_loc_and_size`: use new or from_size
--> src/handlers/xwayland.rs:303:58
|
303 | if let Err(e) = window.configure(Some(Rectangle::from_loc_and_size((0, 0), (suggest_w, suggest_h)))) {
| ^^^^^^^^^^^^^^^^^
warning: variable `plane_idx` is assigned to, but never used
--> src/electron.rs:332:13
|
332 | let mut plane_idx = 0;
| ^^^^^^^^^^^^^
|
= note: consider using `_plane_idx` instead
= note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
= note: consider using `_plane_idx` instead
= note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
warning: value assigned to `plane_idx` is never read
--> src/electron.rs:348:13
|
348 | plane_idx += 1;
| ^^^^^^^^^^^^^^
|
= help: maybe it is overwritten before being read?
= notewarning: value assigned to `plane_idx` is never read
--> src/electron.rs:348:13
|
348 | plane_idx += 1;
| ^^^^^^^^^^^^^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
warning: unreachable pattern
--> src/electron.rs:1259:46
|
1259 | Err(nix::errno::Errno::EAGAIN) | Err(nix::errno::Errno::EWOULDBLOCK) => Ok(()),
| ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
| warning: unreachable pattern
--> src/electron.rs:1259:46
|
1259 | Err(nix::errno::Errno::EAGAIN) | Err(nix::errno::Errno::EWOULDBLOCK) => Ok(()),
| ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
| |
| matches all the relevant values
|
= note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default
|
| matches all the relevant values
|
= note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default
warning: unreachable pattern
--> src/electron.rs:1286:42
|
1286 | Err(nix::errno::Errno::EAGAIN) | Err(nix::errno::Errno::EWOULDBLOCK) => Ok(()),
| ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unreachable pattern
--> src/electron.rs:1286:42
|
1286 | Err(nix::errno::Errno::EAGAIN) | Err(nix::errno::Errno::EWOULDBLOCK) => Ok(()),
| ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
| |
| matches all the relevant values
no value can reach this
| |
| matches all the relevant values
warning: unused variable: `surface_loc`
--> src/handlers/input.rs:439:42
|
439 | if let Some((window, surface_loc)) = under_surface {
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_surface_loc`warning: unused variable: `surface_loc`
--> src/handlers/input.rs:439:42
|
439 | if let Some((window, surface_loc)) = under_surface {
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_surface_loc`
warning: unused variable: `window`
--> src/handlers/xdg_shell.rs:249:21
|
249 | if let Some(window) = window {
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_window`
warning: unused variable: `window`
--> src/handlers/xdg_shell.rs:249:21
|
249 | if let Some(window) = window {
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_window`
warning: unused variable: `event`
--> src/state.rs:615:9
|
615 | event: &smithay::backend::input::InputEvent<B>,
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_event`
warning: unused variable: `event`
--> src/state.rs:615:9
|
615 | event: &smithay::backend::input::InputEvent<B>,
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_event`
warning: `wo` (lib) generated 15 warnings (run `cargo fix --lib -p wo` to apply 8 suggestions)
warning: `wo` (lib) generated 15 warnings (run `cargo fix --lib -p wo` to apply 8 suggestions)
warning: unused import: `nix::sys::memfd::MFdFlags`
--> src/nested.rs:8:5
|
8warning: unused import: `nix::sys::memfd::MFdFlags`
--> src/nested.rs:8:5
|
8 | use nix::sys::memfd::MFdFlags;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| use nix::sys::memfd::MFdFlags;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `std::os::unix::io::AsRawFd`
--> src/main.rs:773:17
|
773 warning: unused import: `std::os::unix::io::AsRawFd`
--> src/main.rs:773:17
|
773 | use std::os::unix::io::AsRawFd;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| use std::os::unix::io::AsRawFd;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `nix::sys::memfd::MFdFlags`
--> src/main.rs:774:17
|
774 warning: unused import: `nix::sys::memfd::MFdFlags`
--> src/main.rs:774:17
|
774 | use nix::sys::memfd::MFdFlags;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| use nix::sys::memfd::MFdFlags;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `RenderElement`
--> src/main.rs:18:52
|
18warning: unused import: `RenderElement`
--> src/main.rs:18:52
|
18 | use smithay::backend::renderer::element::{Element, RenderElement};
| ^^^^^^^^^^^^^
| use smithay::backend::renderer::element::{Element, RenderElement};
| ^^^^^^^^^^^^^
warning: trait `RenderBackend` is never used
--> src/backend.rs:11:11
|
11warning: trait `RenderBackend` is never used
--> src/backend.rs:11:11
|
11 | pub trait RenderBackend {
| ^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
| pub trait RenderBackend {
| ^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: struct `Frame` is never constructed
--> src/backend.rs:39:12
|
39warning: struct `Frame` is never constructed
--> src/backend.rs:39:12
|
39 | pub struct Frame {
| ^^^^^
| pub struct Frame {
| ^^^^^
warning: associated function `new` is never used
--> src/backend.rs:45:12
|
44 warning: associated function `new` is never used
--> src/backend.rs:45:12
|
44 | impl Frame {
| ---------- associated function in this implementation
45 | pub fn new(output_rect: Rectangle<i32, Physical>) -> Self {
| ^^^
| impl Frame {
| ---------- associated function in this implementation
45 | pub fn new(output_rect: Rectangle<i32, Physical>) -> Self {
| ^^^
warning: function `reimport_cached_frame` is never used
--> src/dmabuf.rs:212:8
|
212 warning: function `reimport_cached_frame` is never used
--> src/dmabuf.rs:212:8
|
212 | pub fn reimport_cached_frame(
| ^^^^^^^^^^^^^^^^^^^^^
| pub fn reimport_cached_frame(
| ^^^^^^^^^^^^^^^^^^^^^
warning: struct `PlaneInfoWire` is never constructed
--> src/electron.rs:57:12
|
warning: struct `PlaneInfoWire` is never constructed
--> src/electron.rs:57:12
|
57 | pub struct PlaneInfoWire {
| ^^^^^^^^^^^^^
57 | pub struct PlaneInfoWire {
| ^^^^^^^^^^^^^
warning: `wo` (bin "wo") generated 24 warnings (15 duplicates) (run `cargo fix --bin "wo" -p wo` to apply 3 suggestions)
warning: `wo` (bin "wo") generated 24 warnings (15 duplicates) (run `cargo fix --bin "wo" -p wo` to apply 3 suggestions)
Finished `release` profile [optimized] target(s) in 0.20s
Finished `release` profile [optimized] target(s) in 0.20s
Compiling wo v0.1.0 (/home/hellings/Documents/wo)
Compiling wo v0.1.0 (/home/hellings/Documents/wo)
Finished `release` profile [optimized] target(s) in 2m 21s
Finished `release` profile [optimized] target(s) in 2m 21s
Running `target/release/wo`
Running `target/release/wo`
Xwayland glamor: GBM Wayland interfaces not available
@ -374,73 +44,179 @@ The XKEYBOARD keymap compiler (xkbcomp) reports:
> Using 0, ignoring 0
Errors from xkbcomp are not fatal to the X server
Errors from xkbcomp are not fatal to the X server
[75913:0310/190621.144695:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75913:0310/190621.144695:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75913:0310/190621.145938:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
[75913:0310/190621.145938:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
[75933:0310/190621.205869:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75933:0310/190621.205869:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75933:0310/190621.207105:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
[75933:0310/190621.207105:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
[75966:0310/190621.260351:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75966:0310/190621.260351:ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[75966:0310/190621.261808:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
[75966:0310/190621.261808:ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization
(node:75859) DeprecationWarning: getBitmap() is deprecated, use toBitmap() instead.
(Use `electron --trace-deprecation ...` to show where the warning was created)
(node:75859) DeprecationWarning: getBitmap() is deprecated, use toBitmap() instead.
(Use `electron --trace-deprecation ...` to show where the warning was created)
Error sending from webFrameMain: Error: Failed to serialize arguments
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Gtk-Message: 13:58:16.908: Failed to load module "appmenu-gtk-module"
Gtk-Message: 13:58:16.908: Failed to load module "appmenu-gtk-module"
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
[24415:0311/135817.250839:ERROR:ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc:250] '--ozone-platform=wayland' is not compatible with Vulkan. Consider switching to '--ozone-platform=x11' or disabling Vulkan
[24415:0311/135817.250839:ERROR:ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc:250] '--ozone-platform=wayland' is not compatible with Vulkan. Consider switching to '--ozone-platform=x11' or disabling Vulkan
[24415:0311/135817.264878:ERROR:components/viz/service/display_embedder/skia_output_device_vulkan.cc:301] Failed to create vulkan surface.
[24415:0311/135817.264878:ERROR:components/viz/service/display_embedder/skia_output_device_vulkan.cc:301] Failed to create vulkan surface.
[24330:0311/135939.036070:ERROR:content/browser/network_service_instance_impl.cc:613] Network service crashed, restarting service.
[24330:0311/135939.036070:ERROR:content/browser/network_service_instance_impl.cc:613] Network service crashed, restarting service.
[24330:0311/135939.185963:ERROR:content/browser/gpu/gpu_process_host.cc:999] GPU process exited unexpectedly: exit_code=15
[24330:0311/135939.185963:ERROR:content/browser/gpu/gpu_process_host.cc:999] GPU process exited unexpectedly: exit_code=15
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at getOrCreateSab (file:///home/hellings/Documents/wo/electron/dist/main.js:318:28)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1251:30)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Failed to serialize arguments
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at getOrCreateSab (file:///home/hellings/Documents/wo/electron/dist/main.js:318:28)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1251:30)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Failed to serialize arguments
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at getOrCreateSab (file:///home/hellings/Documents/wo/electron/dist/main.js:318:28)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1251:30)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Failed to serialize arguments
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at getOrCreateSab (file:///home/hellings/Documents/wo/electron/dist/main.js:318:28)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1251:30)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1213:36)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
at s.send (node:electron/js2c/browser_init:2:100266)
at b.send (node:electron/js2c/browser_init:2:84687)
at Socket.<anonymous> (file:///home/hellings/Documents/wo/electron/dist/main.js:1235:40)
at Socket.emit (node:events:519:28)
at addChunk (node:internal/streams/readable:561:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
at Readable.push (node:internal/streams/readable:392:5)
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)
Key repeat discarded, Wayland compositor doesn't seem to be processing events fast enough!
Key repeat discarded, Wayland compositor doesn't seem to be processing events fast enough!
(EE) failed to read Wayland events: Broken pipe
(EE) failed to read Wayland events: Broken pipe
[75859:0310/190654.025906:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 0 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.025906:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 0 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.035184:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 4 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.035184:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 4 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.058269:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 5 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.058269:ERROR:mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:732] Message 5 rejected by interface blink.mojom.WidgetHost
[75859:0310/190654.068805:ERROR:content/browser/network_service_instance_impl.cc:613] Network service crashed, restarting service.
[75859:0310/190654.068805:ERROR:content/browser/network_service_instance_impl.cc:613] Network service crashed, restarting service.
[75859:0310/190654.077683:ERROR:content/browser/gpu/gpu_process_host.cc:999] GPU process exited unexpectedly: exit_code=15
[75859:0310/190654.077683:ERROR:content/browser/gpu/gpu_process_host.cc:999] GPU process exited unexpectedly: exit_code=15