diff --git a/apps/web/src/browser/HostedBrowserWebview.tsx b/apps/web/src/browser/HostedBrowserWebview.tsx index 42d5bcfb35b86ebaca33067aca9ee9bd32681fd6..6c303afb27e9611a0ea1d50276d82b59b2a57866 100644 --- a/apps/web/src/browser/HostedBrowserWebview.tsx +++ b/apps/web/src/browser/HostedBrowserWebview.tsx @@ -156,9 +156,18 @@ export function HostedBrowserWebview(props: { } }, recovery.delayMs); }; + // A click inside the guest only reaches this document as a webview focus + // event, so open menus and popovers never see the outside press that + // would dismiss them. Replay it as a pointerdown on the webview itself. + const dismissHostPopups = () => { + webview.dispatchEvent( + new PointerEvent("pointerdown", { bubbles: true, pointerType: "mouse" }), + ); + }; webview.addEventListener("did-attach", register); webview.addEventListener("dom-ready", register); webview.addEventListener("render-process-gone", recoverGuest); + webview.addEventListener("focus", dismissHostPopups); register(); return () => { disposed = true; @@ -166,6 +175,7 @@ export function HostedBrowserWebview(props: { webview.removeEventListener("did-attach", register); webview.removeEventListener("dom-ready", register); webview.removeEventListener("render-process-gone", recoverGuest); + webview.removeEventListener("focus", dismissHostPopups); }; }, [clientSettingsHydrated, config, initialSrc, runtimeTabId, webviewGeneration]);