diff --git a/src/pages/RemoteDesktop.tsx b/src/pages/RemoteDesktop.tsx index 6a621a0..633d46c 100644 --- a/src/pages/RemoteDesktop.tsx +++ b/src/pages/RemoteDesktop.tsx @@ -64,7 +64,13 @@ export default function RemoteDesktop() { setActiveSessionId(sessionId) const container = document.createElement('div') - container.className = 'h-full w-full overflow-auto' + container.className = 'absolute inset-0 overflow-auto' + container.style.display = 'none' + // Mount the container into the display host ONCE and never move it again — + // re-parenting the Guacamole display between DOM nodes breaks its sync loop, + // which makes guacd drop the user as "not responding". We toggle visibility + // instead (see the activation effect below). + displayHostRef.current?.appendChild(container) const token = getToken() const proto = window.location.protocol === 'https:' ? 'wss' : 'ws' @@ -105,20 +111,16 @@ export default function RemoteDesktop() { }) } - // Show only the active session's display element; keep the rest mounted off-DOM so - // background sessions stay connected while their tab isn't focused. + // Show only the active session's display; keep all others mounted but hidden so + // their sessions stay connected AND their sync loop keeps running (do NOT move + // them out of the DOM — that breaks Guacamole's sync and guacd drops them). useEffect(() => { - const host = displayHostRef.current - if (!host) return - host.innerHTML = '' - const active = activeSessionId ? handlesRef.current.get(activeSessionId) : null - if (active) { - host.appendChild(active.container) - // The display may have received its size while off-DOM (zero-sized), which - // leaves the canvas unscaled / invisible — re-fit now that it's visible. - fitDisplay(active, host) - } - }, [activeSessionId]) + handlesRef.current.forEach((handle, id) => { + const visible = id === activeSessionId + handle.container.style.display = visible ? 'block' : 'none' + if (visible) fitDisplay(handle, displayHostRef.current) + }) + }, [activeSessionId, sessions]) // Keep the active session scaled to the panel as the window/panel resizes. useEffect(() => { @@ -216,7 +218,7 @@ export default function RemoteDesktop() { )} -
+
)