aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-client
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-07 15:01:12 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-07 15:01:12 +0200
commit8883d60d0afa2ed9dd1ef68bc21fe1b9a65a59ff (patch)
tree5b6ecc0da84227e31dba6547ea81dd55c1894645 /packages/meshbay-client
parent2c0903c648e24b4e2adf20492398e8b67d033b49 (diff)
downloadmeshbay-8883d60d0afa2ed9dd1ef68bc21fe1b9a65a59ff.tar.gz
fix(client): break the Wayland ready-to-show deadlock
Some Wayland compositors never schedule a first paint for an unmapped surface, but the window stays unmapped until show() runs, which was gated entirely on that paint's ready-to-show event — a cycle with no way out on its own. Observed under GNOME/Mutter on a VM whose virtio-gpu device fails command-buffer creation. Add a bounded fallback show(), guarded on isVisible() so it's a no-op once the event has already fired normally and doesn't steal focus back from whatever the person switched to. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHKaCz2gq3ya8t13CvQ7Hp
Diffstat (limited to 'packages/meshbay-client')
-rw-r--r--packages/meshbay-client/src/main.js10
1 files changed, 10 insertions, 0 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js
index de8de8f..27c81b8 100644
--- a/packages/meshbay-client/src/main.js
+++ b/packages/meshbay-client/src/main.js
@@ -453,6 +453,16 @@ function createWindow() {
});
win.once('ready-to-show', () => win.show());
+ // Some Wayland compositors (observed under GNOME/Mutter on a VM with a
+ // virtio-gpu device whose command-buffer creation fails) never schedule a
+ // first paint for a surface that isn't mapped yet — but Electron won't map
+ // it (show()) until `ready-to-show` fires, which waits for that paint. The
+ // two conditions deadlock the window invisible forever. This bounded
+ // fallback breaks the cycle. Guarded on isVisible(): show() also raises
+ // and refocuses an already-visible window, so once the event has fired
+ // normally (real GPU/X11 hosts, well under 2s) this must stay a no-op
+ // rather than yank focus back from whatever the person switched to.
+ setTimeout(() => { if (!win.isDestroyed() && !win.isVisible()) win.show(); }, 2000);
// The hub must never become the document origin. Anything that would navigate
// away from the packaged interface is refused, and an external link opens in