0042: Taking turns and sharing in Pair
On this page
Status: accepted. Guests' screens can now be controlled, given by the guest who shares, and anyone can ask to share: see 0046. Cameras are now sent at the size they're shown, and browser guests can send theirs: see 0048.
Context
Pair's first version (ADRs 0035 to 0040) has one sharer, the host, and one kind of help, remote control. People pairing also need to show their own screen, point at things without taking over, keep some windows private, and work on the host's sites and terminals together. These all reuse the session's trust model (ADR 0038): the host lets people in, and nothing reaches the host's computer without the host saying so.
Decision
- Taking turns. The session has one sharer, the host at first. A guest asks to share; the host lets them, and everyone then watches the guest's screen. The host's own capture stops meanwhile. Remote control only ever applies to the host's screen: it's taken back when a guest starts sharing, and can't be given while a guest shares. The host can return to sharing at any time.
- Drawing. Anyone watching can draw on the shared screen. Marks travel as points on the shared screen, as fractions of it, over each connection's data channel. The sharer's helper draws them on a click-through overlay; each mark fades after a few seconds, and the sharer can clear them. Drawing can't click or type, so it doesn't need the code check.
- Choosing a window. On Windows, Change screen lists screens (Desktop Duplication, as now) and single windows (Windows Graphics Capture, which draws its border because Short Leash isn't a packaged app). On macOS the system's picker already offers windows. While a window is shared, a guest with control can only click and type inside it.
- Hiding apps. Settings › Pair lists apps to hide from the shared screen. Before each frame is encoded, the sharer's helper paints a cover over every window those apps own (now a hatched panel, painted only where nothing is in front of the window, and labeled "Hidden by Short Leash" on Short Leash's own), from the window list the system gives without extra permission. Short Leash's own windows are always hidden.
- Sharing a site with the call. The host picks one of their sites. A guest's Short Leash asks the host for a one-time link, opens it in the browser, and gets a cookie that only that guest holds. The host's Pair tunnel then sends requests with that cookie to the site, through the same access rules and rewriting as sharing a site (ADR 0036, invariant 10). Links work once, for a minute; cookies stop working when the host stops sharing the site, removes the guest, or ends the session.
- Sharing a terminal with the call. The host picks one of a site's terminals. leashd sends its output to the people in the call through the session's signaling (the end of its scrollback first, then each new chunk), and their Short Leash shows it read-only on its Pair screen, at the host's size, rather than over the host's screen in the viewer. The host can give one person the keyboard, only after checking their code as for control; only their input reaches the terminal, and the host takes it back at any time. The host's own typing always works.
- Camera. Off until each person turns theirs on. The helper sends it as a second, small video track (320 × 240, 15 frames a second) and shows the others' cameras as tiles in the call bar. On macOS the camera grant belongs to Short Leash.app, like the microphone (ADR 0039).
- Browser guests. The invite page offers to join in the browser, to watch and talk only: no control, drawing or sharing. leashd serves the page and its script from the Pair tunnel. The browser joins the mesh like a helper, with the same commit before the offer and the same short code, worked out in the browser with WebCrypto. It receives AV1 when the browser can decode it, and VP9 otherwise.
- Shortcuts across systems. Besides the select-all style shortcuts, the common editing and navigation chords map between macOS and Windows: word and line movement, deleting a word, undo and redo, find, and switching tabs.
- MCP.
leash mcpgains tools to read the session, let people in and end the session. It can't give control. - Hardware encoders. Screens stay on software AV1 or VP9. Our libwebrtc build has no H.264 (ADR 0040), the hardware AV1 encoders that exist are only on recent GPUs, and software AV1 measured about 28% of one core in Phase 0, under the plan's 40% limit. Hardware encoding waits until a measurement on a real PC shows it's needed.
Consequences
- Guests' screens are never controlled, which keeps the trust model to one direction: only the host's computer can be driven, and only once the host gives control (0043).
- Drawing and terminal output are new things that reach the host's screen or come from it; each is limited to people the host let in, and the host can stop each one.
- A shared site is reachable only through the Pair tunnel and only with a per-guest cookie, so the invite link alone doesn't open it.
- Browser guests make Pair useful to people without Short Leash, at the cost of a small web client that leashd serves and that has to keep up with the helper's signaling.
- Windows shows a border around a shared window, which Short Leash can't remove without a packaged app.
- Hiding apps covers their windows, not their notifications or anything they draw into other apps' windows.
- During a call the sharer can show or hide single windows on top of the hidden apps: a chip on each hidden window, and Hide a window to pick one by clicking it. These choices name windows by the system's id (a CGWindowID or an HWND), which means nothing after the call, so leashd keeps them only for the call and forgets them when it ends or someone else shares; lasting choices stay in Settings › Pair, which names apps. leashd holds them and sends them to the helper whole after each change, so the helper never shows a choice leashd doesn't have. The chips and the picking layer are the helper's own windows, kept out of the capture like the call bar.