mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-24 15:01:37 +02:00
- docs/mac-space.md: what Vision Pro's Mac Virtual Display does, what the Frame allows (another process can't move SteamVR's panels: verified, PermissionDenied), and why a WebXR page comes first. - ui/mac-stream.js: the stream protocol shared by the viewers (connect, clock sync, decode, acks/reports, reconnect, input); mac-view.html uses it. - ui/mac-space.html: WebXR (passthrough behind) or an in-page preview. Desktop panel with a Vision Pro-style bar and close button; laser clicks, thumbstick scrolls, squeeze or the bar grabs; dragging a window's title bar off the desktop opens it on its own display as a new panel that follows the pointer; dropping it back sends it home. - Agent: space tickets -> a space key (/space/key) that lists windows and displays (/space/windows, now with positions) and opens any stream; Stop All revokes it. Serves /space and /mac-stream.js. - Frame Control: "Open Mac space" in the Tools card. Verified on the Mac (preview in headless Chrome, lab agent): the main display streams into the panel; a test window detached onto its own display and streamed; dropped back, it returned to its exact frame and the display was removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
5.6 KiB
5.6 KiB
Mac space: the Mac's desktop and its windows, placed in the room
Design notes, started 2026-09-28. The goal is Apple Vision Pro's Mac Virtual Display, plus something Vision Pro can't do: pulling any Mac window out to float on its own. Labels as in ssh.md: verified, documented, reported, inferred.
What to match (Vision Pro's Mac Virtual Display)
Researched 2026-09-28. Sources: Apple Support 118521 and the Vision Pro guide; 9to5Mac, UploadVR and AppleInsider.
- Connecting. Look at the Mac and a Connect button floats above it. There's also a Control Center route. The Mac's own screen goes dark (documented/reported).
- Placement. The display appears where you were looking, near the Mac, at a large-monitor size. After that it stays put in the room: moving the laptop doesn't move it. Holding the Digital Crown recenters everything (documented).
- Handling.
- A window bar under the display moves it, with pinch and drag, and also moves it nearer or farther.
- Its bottom corners resize it.
- Close sits to the left of the bar (documented).
- Modes. Standard (16:9), Wide (21:9) and Ultrawide (32:9, about 10K pixels across). All are curved since visionOS 2.2 (documented).
- Input.
- The Mac's keyboard and trackpad drive it.
- The pointer moves to whichever window you look at (Universal Control).
- Mac audio plays in the headset (documented).
- What it can't do. You can't pull a single Mac window out of the virtual display (reported, several sources). That's our differentiator.
What the Frame allows
- Moving SteamVR's panels from our own process: no (verified
2026-09-28).
FindOverlay("valve.steam.desktopgame.<id>")works from a separate OpenVR app, butSetOverlayTransformAbsolutereturns 12 (VROverlayError_PermissionDenied). The panel reported transform type 5 (dashboard tab). Only SteamVR's dashboard, which runs invrwebhelper, moves them, through its privilegedVRHTML.VROverlay, and it has no DevTools port. See/tmp/fmv-space/ovprobe.pyfor the probe, which stays outside the repo. - WebXR in Chromium XR: yes (verified 2026-09-26/27,
webxr-chromium.md).
immersive-vrruns at 72–75 fps.- Passthrough shows wherever the page leaves pixels transparent.
- Controllers are
tracked-pointers withxr-standardgamepads, and squeeze events arrive. - Hands are tracked with 25 joints.
- Our own OpenVR overlays: possible, but most work. We would own their transforms and get laser input as mouse events for free. But the Frame would need native H.264 decoding and texture upload.
Decision: a WebXR "Mac space" page first
The WebXR page (ui/mac-space.html) holds everything, with passthrough
behind it:
- The desktop. A large curved panel shows the Mac's main display, placed above the laptop. The first time, you place it yourself; after that it's remembered in the room.
- Windows. Each separated window gets its own panel.
- Grabbing. A bar under each panel moves it (squeeze, or pinch with a hand). Its corners resize it, and there's a close button to the bar's left, as on Vision Pro.
- Pulling a window out. Grab a window's title bar on the desktop panel
and drag it off the edge. The page starts a
separate:<window id>stream, the window moves to its own display on the Mac, and its new panel follows your hand until you let go. Dropping a panel back onto the desktop panel stops the stream, and the window goes back. - Input. The laser and trigger click and drag, the thumbstick scrolls, and the Mac's keyboard types, as today.
Trade-offs:
- It's the headset's active app while you use it. Other VR apps pause, but SteamVR's own overlays still draw on top.
- Text sharpness depends on how the page renders. WebXR quad layers (the
layersfeature) would let SteamVR's compositor sample each panel directly, so they're worth checking first.
Building blocks
- One module for the protocol.
ui/mac-stream.jsholds the stream protocol (connect, clock sync, decoding, acks and reports, input), shared bymac-view.html(the 2D panel) andmac-space.html. - A space key from the agent. Frame Control gets a ticket with
src=space, and the page trades it once for a space key, kept in memory. That key lists the windows and displays (with their positions, for picking the one under the pointer) and opens streams for any of them. Stop All revokes it. - Anchoring.
- v1: manual placement, remembered in the room (to be checked: whether
local-floorstays put between sessions on the Frame). - v2: the Mac shows a marker on its screen for a moment, and the headset
finds it. That needs camera access, which is unknown on the Frame:
the passthrough cameras are monochrome, and
IVRTrackedCamerahasn't been tried.
- v1: manual placement, remembered in the room (to be checked: whether
Open questions
- Frame rate with several software-decoded streams at once.
- Whether
local-floorplacements survive restarts. - Whether WebXR quad layers work in Chromium XR's OpenXR path.
- Whether Chromium grants
requestSessionwithout a click in the page (needed for a one-click "Open Mac space").