diff --git a/docs/web-ui.md b/docs/web-ui.md index 7a38849a..1a1c2a35 100644 --- a/docs/web-ui.md +++ b/docs/web-ui.md @@ -1055,14 +1055,26 @@ shaped). `wait_for_login` entry. - `GET /events/history` β€” replay buffer for the terminal. - `GET /screen` β€” VNC viewer page (minimal RFB-over-WebSocket - renderer). Only accessible when `hyperhive.gui.enable = true` - in the agent's `agent.nix`; the harness shows a πŸ–₯ screen link - in the state row when `gui_vnc_port` is present. Toolbar: - `β€’ fit` CSS-downscales the canvas to the window; `‑ match size` - sends an RFB `SetDesktopSize` request so the server (weston) - changes its real output resolution to the window dimensions β€” - enabled once the server advertises the `ExtendedDesktopSize` - pseudo-encoding (issue #133). + renderer β€” deliberately thin, just enough to display the + desktop + forward pointer + keyboard. A production-grade viewer + would vendor noVNC; this file ships the minimal in-tree variant). + Only accessible when `hyperhive.gui.enable = true` in the agent's + `agent.nix`; the harness shows a πŸ–₯ screen link in the state row + when `gui_vnc_port` is present. Toolbar: `β€’ fit` CSS-downscales + the canvas to the window via `relayoutCanvas()` setting explicit + pixel dimensions on the canvas β€” *not* CSS `max-width/max-height`, + because a flex item's automatic minimum size (`min-width: auto` + resolves to the canvas's intrinsic framebuffer resolution) silently + clamps `max-*` back up, making fit mode a no-op that just centred + + clipped the oversized canvas. The fit-mode rules pin the canvas + with `flex: none; min-width: 0; min-height: 0` so the JS-set size + sticks. `‑ match size` sends an RFB `SetDesktopSize` request so the + server (weston) changes its real output resolution to the window + dimensions; enabled once the server advertises the + `ExtendedDesktopSize` pseudo-encoding (`-308` rect in the header). + Fit-mode state persists in `localStorage` (`screen-fit`); default + is on. Pointer coordinates are rescaled in `sendPointer` so clicks + land on the right pixel regardless of CSS scale. - `GET /screen/ws` β€” raw RFB byte relay: proxies WebSocket frames to the weston VNC server at `127.0.0.1:`. Transparent to any RFB variant. VNC port comes from diff --git a/frontend/packages/agent/src/screen.html b/frontend/packages/agent/src/screen.html index 702505d2..d9e983ad 100644 --- a/frontend/packages/agent/src/screen.html +++ b/frontend/packages/agent/src/screen.html @@ -62,13 +62,10 @@ html, body { height: 100%; background: var(--base); color: var(--text); fit the wrap) and clip any sub-pixel rounding overflow. */ #canvas-wrap.fit { align-items: center; overflow: hidden; } canvas { display: block; cursor: default; } -/* In fit mode relayoutCanvas() sets the canvas display size explicitly. - The canvas is a flex item, and flex items default to - min-width/min-height: auto β€” which resolves to the canvas's intrinsic - framebuffer resolution and clamps the JS-set size straight back up, - defeating the downscale (the bug behind #133 round 1). Pin the canvas - to exactly the size relayoutCanvas() sets: min-* 0 lifts the clamp, - flex: none stops flex grow/shrink from fighting it. */ +/* Pin the canvas to exactly the size relayoutCanvas() sets. See + docs/web-ui.md::Per-agent endpoints (GET /screen) for the + flex-item min-width:auto clamp that made fit mode a silent + no-op before this pinning. */ #canvas-wrap.fit canvas { flex: none; min-width: 0; min-height: 0; } #msg { position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%); @@ -93,13 +90,11 @@ canvas { display: block; cursor: default; }