Further optimization passes
This commit is contained in:
parent
ff54140d62
commit
68b4916f64
12 changed files with 574 additions and 881 deletions
9
electron/dist/main.js
vendored
9
electron/dist/main.js
vendored
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
},
|
||||
|
|
|
|||
16
electron/types/types.d.ts
vendored
16
electron/types/types.d.ts
vendored
|
|
@ -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>;
|
||||
|
||||
/**
|
||||
|
|
|
|||
48
electron/whatever.txt
Normal file
48
electron/whatever.txt
Normal 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
|
||||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
21
src/main.rs
21
src/main.rs
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
61
src/state.rs
61
src/state.rs
|
|
@ -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| {
|
||||
|
|
|
|||
524
whatever.txt
524
whatever.txt
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue