From b08f4efb37cf77b19bb329e046ce81880c3f6334 Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:29:51 +1100 Subject: [PATCH] fix(electron): Win10 HUD click-through recovery --- electron/main.ts | 39 +++++++++++++++++++++++++++++++++++++++ electron/windows.ts | 18 ++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/electron/main.ts b/electron/main.ts index cb98c401..8952cbec 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -166,6 +166,15 @@ function focusOrCreateMainWindow() { win.destroy(); return; } + + // On Win32, calling show/moveTop/focus on the transparent HUD overlay + // permanently corrupts setIgnoreMouseEvents forwarding, making it + // click-through. Only focus the editor window; the HUD is alwaysOnTop + // so it doesn't need explicit focus. + if (process.platform === "win32" && !isEditorWindow(mainWindow)) { + return; + } + mainWindow.show(); if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.moveTop(); @@ -173,6 +182,32 @@ function focusOrCreateMainWindow() { } } +/** + * On Windows 10, focus changes and native notifications can break + * {@link BrowserWindow.setIgnoreMouseEvents} forwarding on the transparent HUD + * overlay, causing it to become permanently click-through. Call this after any + * operation that may alter focus or z-order so that hover detection keeps working. + */ +function reassertHudOverlayMouseState() { + if (process.platform !== "win32") { + return; + } + + const hud = getHudOverlayWindow(); + if (!hud) { + return; + } + + // Toggle off then back on so the native WS_EX_TRANSPARENT flag is fully + // re-initialised rather than merely re-asserted in a potentially broken state. + hud.setIgnoreMouseEvents(false); + setTimeout(() => { + if (!hud.isDestroyed()) { + hud.setIgnoreMouseEvents(true, { forward: true }); + } + }, 50); +} + function isEditorWindow(window: BrowserWindow) { return window.webContents.getURL().includes("windowType=editor"); } @@ -411,6 +446,10 @@ function sendUpdateToastToWindows(channel: "update-toast-state", payload: unknow }); notification.show(); + // On Win10, showing a native notification can break setIgnoreMouseEvents + // forwarding on the transparent HUD overlay. Re-assert it after a short + // delay so the renderer's hover detection keeps working. + reassertHudOverlayMouseState(); activeUpdateNotification = notification; activeUpdateNotificationKey = notificationKey; return true; diff --git a/electron/windows.ts b/electron/windows.ts index df63047c..c4550b40 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -322,6 +322,24 @@ export function createHudOverlayWindow(): BrowserWindow { win.setIgnoreMouseEvents(true, { forward: true }); + // On Windows 10, focus changes (e.g. showing a native notification) can break + // setIgnoreMouseEvents forwarding on a transparent always-on-top window, making + // it permanently click-through without hover detection. Re-initialise the + // pass-through-with-forwarding state whenever the window gains focus by toggling + // the flag off then back on so the native WS_EX_TRANSPARENT flag is fully reset. + if (process.platform === "win32") { + win.on("focus", () => { + if (!win.isDestroyed()) { + win.setIgnoreMouseEvents(false); + setTimeout(() => { + if (!win.isDestroyed()) { + win.setIgnoreMouseEvents(true, { forward: true }); + } + }, 50); + } + }); + } + win.webContents.on("did-finish-load", () => { win?.webContents.send("main-process-message", new Date().toLocaleString()); setTimeout(() => {