From 0ca4acf2e3615fd5abaadbdb3ba463ef29aa91f8 Mon Sep 17 00:00:00 2001 From: wayne Date: Sat, 4 Jul 2026 14:49:13 +1200 Subject: [PATCH 1/2] fix(windows): keep never-shown Hidden windows' WebView2 controller invisible --- v3/pkg/application/webview_window_windows.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index 021ad45c3e9..f4e1f6229dc 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -2571,6 +2571,16 @@ func (w *windowsWebviewWindow) navigationCompleted( } w.update() } + + // The first-paint nudge above ends with the controller IsVisible=true. For a + // window created Hidden that is never shown (e.g. a pre-created tray popup), + // that leaves a live WINDOW_TO_VISUAL DirectComposition input surface + // hit-testing at the window's location — an invisible desktop right-click + // "dead zone". Re-hide the controller so a never-shown window has no live + // surface; show() re-asserts IsVisible(true) when the window is actually shown. + if w.parent.options.Hidden && !w.windowShown && !w.showRequested { + _ = w.chromium.Hide() + } } func (w *windowsWebviewWindow) processKeyBinding(vkey uint) bool { From 04ec90526e0cb528a3d0e7cca59cf93499901fb3 Mon Sep 17 00:00:00 2001 From: taliesin-ai Date: Sun, 5 Jul 2026 09:39:23 +1000 Subject: [PATCH 2/2] fix(windows): re-hide the controller for any logically hidden window after first paint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review follow-up: the options.Hidden gate missed the symmetric case of a window created visible that the app hides before the first NavigationCompleted — the first-paint nudge deterministically re-showed its controller, leaving the invisible input surface on a hidden HWND with nothing to correct it. windowShown/showRequested alone identify both that case and the never-shown Hidden-window case (showRequested is initialised to !options.Hidden and only show()/hide() flip the flags). --- v3/pkg/application/webview_window_windows.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index f4e1f6229dc..11a80368a4d 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -2572,13 +2572,17 @@ func (w *windowsWebviewWindow) navigationCompleted( w.update() } - // The first-paint nudge above ends with the controller IsVisible=true. For a - // window created Hidden that is never shown (e.g. a pre-created tray popup), - // that leaves a live WINDOW_TO_VISUAL DirectComposition input surface - // hit-testing at the window's location — an invisible desktop right-click - // "dead zone". Re-hide the controller so a never-shown window has no live - // surface; show() re-asserts IsVisible(true) when the window is actually shown. - if w.parent.options.Hidden && !w.windowShown && !w.showRequested { + // The first-paint nudge above ends with the controller IsVisible=true. For + // any window that is not logically visible at this point — one created + // Hidden and never shown (e.g. a pre-created tray popup), or one the app + // hid before this first NavigationCompleted arrived — that leaves a live + // WINDOW_TO_VISUAL DirectComposition input surface hit-testing at the + // window's location: an invisible desktop right-click "dead zone". + // Re-hide the controller so a hidden window has no live surface; show() + // re-asserts IsVisible(true) when the window is actually shown. + // showRequested is initialised to !options.Hidden and only show()/hide() + // flip it, so these two flags alone identify both cases. + if !w.windowShown && !w.showRequested { _ = w.chromium.Hide() } }