feat(terminal): add Detach into a separate window like Desktop #89

Merged
Claude-Run merged 1 commit from feat/VAPP-80-terminal-detach-popout into main 2026-07-08 03:56:00 +02:00
Member

Add a Detach control to the Terminal toolbar that moves the live terminal into a separate window, mirroring the Desktop tab: Document Picture-in-Picture on Chromium and a same-origin window.open popout on browsers without it (Firefox), selected via the reused desktop::pip_supported(). The detached window shares this page's JS/wasm context, so moving the wasm-owned xterm host node carries its WebSocket and the PTY with it and the session keeps running with no reconnect or lost scrollback.

To make the move safe against Dioxus (VAPP-70), the xterm host is now wasm-owned: build() creates a host div via create_element and inserts it into the Dioxus mount div, then opens xterm into the host, so reparenting it out of the renderer's document is invisible to Dioxus. move_host_into_window() copies the opener's stylesheets (xterm.css) into the detached document, re-fits the terminal to the new window size (FitAddon), focuses it, and installs the pagehide re-dock listener; the window.open path also installs the install_closed_poll backup so a closed popout re-docks even without pagehide. Re-dock re-fits back and reverts the toolbar; teardown closes any open detached window so no window, interval, or listener leaks.

A terminal_detach_guard test module enforces the load-bearing invariants (wasm-owned host, reparent machinery, window.open popout, stylesheet copy, closed poll, Detach/Re-dock toggle) so they cannot silently regress.

#VAPP-80

Add a Detach control to the Terminal toolbar that moves the live terminal into a separate window, mirroring the Desktop tab: Document Picture-in-Picture on Chromium and a same-origin window.open popout on browsers without it (Firefox), selected via the reused desktop::pip_supported(). The detached window shares this page's JS/wasm context, so moving the wasm-owned xterm host node carries its WebSocket and the PTY with it and the session keeps running with no reconnect or lost scrollback. To make the move safe against Dioxus (VAPP-70), the xterm host is now wasm-owned: build() creates a host div via create_element and inserts it into the Dioxus mount div, then opens xterm into the host, so reparenting it out of the renderer's document is invisible to Dioxus. move_host_into_window() copies the opener's stylesheets (xterm.css) into the detached document, re-fits the terminal to the new window size (FitAddon), focuses it, and installs the pagehide re-dock listener; the window.open path also installs the install_closed_poll backup so a closed popout re-docks even without pagehide. Re-dock re-fits back and reverts the toolbar; teardown closes any open detached window so no window, interval, or listener leaks. A terminal_detach_guard test module enforces the load-bearing invariants (wasm-owned host, reparent machinery, window.open popout, stylesheet copy, closed poll, Detach/Re-dock toggle) so they cannot silently regress. #VAPP-80
feat(terminal): add Detach into a separate window like Desktop
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 3m17s
Create release / Create release from merged PR (pull_request) Has been skipped
2fac66195c
Add a Detach control to the Terminal toolbar that moves the live terminal into a separate window, mirroring the Desktop tab: Document Picture-in-Picture on Chromium and a same-origin window.open popout on browsers without it (Firefox), selected via the reused desktop::pip_supported(). The detached window shares this page's JS/wasm context, so moving the wasm-owned xterm host node carries its WebSocket and the PTY with it and the session keeps running with no reconnect or lost scrollback.

To make the move safe against Dioxus (VAPP-70), the xterm host is now wasm-owned: build() creates a host div via create_element and inserts it into the Dioxus mount div, then opens xterm into the host, so reparenting it out of the renderer's document is invisible to Dioxus. move_host_into_window() copies the opener's stylesheets (xterm.css) into the detached document, re-fits the terminal to the new window size (FitAddon), focuses it, and installs the pagehide re-dock listener; the window.open path also installs the install_closed_poll backup so a closed popout re-docks even without pagehide. Re-dock re-fits back and reverts the toolbar; teardown closes any open detached window so no window, interval, or listener leaks.

A terminal_detach_guard test module enforces the load-bearing invariants (wasm-owned host, reparent machinery, window.open popout, stylesheet copy, closed poll, Detach/Re-dock toggle) so they cannot silently regress.

#VAPP-80
Claude-Run deleted branch feat/VAPP-80-terminal-detach-popout 2026-07-08 03:56:00 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!89
No description provided.