fix: create child windows hidden, show after tauri://created
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m50s

Per Gemini's analysis: WKWebView may reap windows that fail to
establish focus during creation. All WebviewWindow instances now
created with visible: false + focus: true, then wv.show() is
called only after tauri://created confirms the webview is ready.

This prevents the OS window manager from treating the window as
an orphaned popup during the brief initialization period.

Applied to: tool windows, help windows, editor windows, detached
session windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-30 13:40:30 -04:00
parent 10dc3f9cbe
commit d462381cce
2 changed files with 13 additions and 1 deletions

View File

@ -141,8 +141,11 @@ async function detachTab(): Promise<void> {
height: 600, height: 600,
resizable: true, resizable: true,
center: true, center: true,
visible: false,
focus: true,
url: `index.html#/detached-session?sessionId=${session.id}&name=${encodeURIComponent(session.name)}&protocol=${session.protocol}`, url: `index.html#/detached-session?sessionId=${session.id}&name=${encodeURIComponent(session.name)}&protocol=${session.protocol}`,
}); });
wv.once("tauri://created", () => { wv.show(); });
wv.once("tauri://error", (e) => { console.error("Detach window error:", e); }); wv.once("tauri://error", (e) => { console.error("Detach window error:", e); });
} }

View File

@ -375,8 +375,11 @@ async function handleHelpAction(page: string): Promise<void> {
height: 600, height: 600,
resizable: true, resizable: true,
center: true, center: true,
visible: false,
focus: true,
url: `index.html#/tool/help?page=${page}`, url: `index.html#/tool/help?page=${page}`,
}); });
wv.once("tauri://created", () => { wv.show(); });
wv.once("tauri://error", (e) => { console.error("Help window error:", e); alert("Window error: " + JSON.stringify(e.payload)); }); wv.once("tauri://error", (e) => { console.error("Help window error:", e); alert("Window error: " + JSON.stringify(e.payload)); });
} }
@ -413,7 +416,7 @@ async function handleToolAction(tool: string): Promise<void> {
const sessionId = activeSessionId.value || ""; const sessionId = activeSessionId.value || "";
// Open tool in a new Tauri window // Open tool in a new Tauri window create hidden, show after webview confirms ready
const label = `tool-${tool}-${Date.now()}`; const label = `tool-${tool}-${Date.now()}`;
const wv = new WebviewWindow(label, { const wv = new WebviewWindow(label, {
title: `Wraith — ${config.title}`, title: `Wraith — ${config.title}`,
@ -421,8 +424,11 @@ async function handleToolAction(tool: string): Promise<void> {
height: config.height, height: config.height,
resizable: true, resizable: true,
center: true, center: true,
visible: false,
focus: true,
url: `index.html#/tool/${tool}?sessionId=${sessionId}`, url: `index.html#/tool/${tool}?sessionId=${sessionId}`,
}); });
wv.once("tauri://created", () => { wv.show(); });
wv.once("tauri://error", (e) => { console.error("Tool window error:", e); alert("Window error: " + JSON.stringify(e.payload)); }); wv.once("tauri://error", (e) => { console.error("Tool window error:", e); alert("Window error: " + JSON.stringify(e.payload)); });
} }
@ -454,8 +460,11 @@ async function handleOpenFile(entry: FileEntry): Promise<void> {
height: 600, height: 600,
resizable: true, resizable: true,
center: true, center: true,
visible: false,
focus: true,
url: `index.html#/tool/editor?sessionId=${sessionId}&path=${encodeURIComponent(entry.path)}`, url: `index.html#/tool/editor?sessionId=${sessionId}&path=${encodeURIComponent(entry.path)}`,
}); });
wv.once("tauri://created", () => { wv.show(); });
wv.once("tauri://error", (e) => { console.error("Editor window error:", e); alert("Window error: " + JSON.stringify(e.payload)); }); wv.once("tauri://error", (e) => { console.error("Editor window error:", e); alert("Window error: " + JSON.stringify(e.payload)); });
} catch (err) { console.error("Failed to open editor:", err); } } catch (err) { console.error("Failed to open editor:", err); }
} }