From b397f4492acabd27a67fe25a9a9fcfeab4ec4c21 Mon Sep 17 00:00:00 2001 From: Kiran Kunigiri Date: Mon, 23 Mar 2026 02:10:22 -0700 Subject: [PATCH] fix(desktop): prevent webview from swallowing mosaic drag events Electron tags create separate compositor layers that capture drag events before they reach react-mosaic drop targets. This made it impossible to drag panes onto browser pane tabs. Set pointer-events:none directly on the element during any HTML5 drag operation so the compositor stops routing events to the guest process, allowing mosaic drop zones to work normally. --- .../usePersistentWebview.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts index 8169e0c1347..02d43b50144 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts @@ -26,6 +26,28 @@ function getHiddenContainer(): HTMLDivElement { return hiddenContainer; } +// --------------------------------------------------------------------------- +// Disable webview interaction during ANY drag operation. +// Electron tags create separate compositor layers that swallow +// drag events before they reach the mosaic drop targets. Setting +// pointer-events:none directly on the element tells the +// compositor to stop routing events to the guest process. +// +// We use native HTML5 drag events (capture phase) rather than the drag pane +// store because the store only covers mosaic pane drags — not tab-bar drags +// or other drag sources. +// --------------------------------------------------------------------------- + +function setWebviewsDragPassthrough(passthrough: boolean) { + for (const webview of webviewRegistry.values()) { + webview.style.pointerEvents = passthrough ? "none" : ""; + } +} + +window.addEventListener("dragstart", () => setWebviewsDragPassthrough(true), true); +window.addEventListener("dragend", () => setWebviewsDragPassthrough(false), true); +window.addEventListener("drop", () => setWebviewsDragPassthrough(false), true); + /** Call from useBrowserLifecycle when a pane is removed. */ export function destroyPersistentWebview(paneId: string): void { const webview = webviewRegistry.get(paneId);