wraith/docs/spikes/multi-window-results.md
Vantz Stockwell d42f000f8f spike: multi-window and RDP frame transport research results
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 06:35:00 -04:00

130 lines
4.1 KiB
Markdown

# Spike: Multi-Window Support in Wails v3
**Status:** Research-based (not yet validated on Windows)
**Date:** 2026-03-17
**Target platform:** Windows (developing on macOS)
**Wails version:** v3.0.0-alpha.74
---
## Context
Wraith needs to support detached sessions — users should be able to pop out
an SSH or RDP session into its own window while the main connection manager
remains open. This spike evaluates three approaches, ranked by preference.
---
## Plan A: Wails v3 Native Multi-Window
**Status: LIKELY WORKS** based on API documentation.
### How it works
- `app.Window.NewWithOptions()` creates a new OS-level window at runtime.
- Each window can load a different URL or frontend route (e.g.,
`/session/rdp/3` in one window, `/` in the main window).
- All windows share the same Go backend services — no IPC or inter-process
marshalling required. Bindings registered on the application are callable
from any window.
- Window lifecycle events (`OnClose`, `OnFocus`, etc.) are available for
cleanup.
### Example (pseudocode)
```go
win, err := app.Window.NewWithOptions(application.WindowOptions{
Title: "RDP — server-01",
Width: 1280,
Height: 720,
URL: "/session/rdp/3",
})
```
### Risks
| Risk | Severity | Mitigation |
|------|----------|------------|
| Alpha API — method signatures may change before v3 stable | Medium | Pin to a known-good alpha tag; wrap calls behind an internal interface so migration is a single-file change. |
| Platform-specific quirks on Windows (DPI, focus, taskbar grouping) | Low | Test on Windows during Phase 2. Wails uses webview2 on Windows which is mature. |
| Window count limits or resource leaks | Low | Cap concurrent detached windows (e.g., 8). Ensure `OnClose` releases resources. |
---
## Plan B: Floating Panels (CSS-based)
**Status: FALLBACK** — no external dependency, purely frontend.
### How it works
- Detached sessions render as draggable, resizable `position: fixed` panels
within the main Wails window.
- Each panel contains its own Vue component instance (terminal emulator or
RDP canvas).
- Panels can be minimised, maximised within the viewport, or snapped to
edges.
### Pros
- Zero dependency on Wails multi-window API.
- Works on any platform without additional testing.
- Simpler state management — everything lives in one window context.
### Cons
- Sessions share the same viewport — limited screen real estate.
- Cannot span multiple monitors.
- Feels less native than real OS windows.
### Implementation cost
Small. Requires a `<FloatingPanel>` wrapper component with drag/resize
handlers. Libraries like `vue3-draggable-resizable` exist but a lightweight
custom implementation (~150 LOC) is preferable to avoid dependency churn.
---
## Plan C: Browser Mode
**Status: EMERGENCY** — last resort if both Plan A and Plan B are inadequate.
### How it works
- Wails v3 supports a server mode where the frontend is served over HTTP on
`localhost`.
- Detached sessions open in the user's default browser via
`open(url, '_blank')` or `runtime.BrowserOpenURL()`.
- The browser tab communicates with Go services through the same HTTP
endpoint.
### Pros
- Guaranteed to work — it is just a web page.
- Users can arrange tabs freely across monitors.
### Cons
- Breaks the desktop-app experience.
- Browser tabs lack access to Wails runtime bindings; all communication must
go through HTTP/WebSocket, requiring a parallel transport layer.
- Security surface increases — localhost HTTP server is accessible to other
local processes.
---
## Recommendation
**Start with Plan A.** The Wails v3 `NewWithOptions` API is documented and
consistent with how other multi-window desktop frameworks (Electron,
Tauri v2) work. The alpha stability risk is mitigated by wrapping calls
behind an internal interface.
If Plan A fails during Windows validation, **Plan B requires only frontend
CSS changes** — no backend work is wasted. Plan C is reserved for scenarios
where neither A nor B is viable.
## Next Step
Validate Plan A on Windows during Phase 2 when SSH sessions exist and there
is a real payload to render in a second window.