2 Porting and platform support
mikebrandon edited this page 2026-09-04 11:53:49 +00:00

Porting and platform support

docs/PORTING.md is the detailed map: capability by capability across Windows, macOS, X11 and each Wayland compositor, with what changes about the promises. This page is the summary and the reasoning.

Where each platform stands

Windows macOS Linux
All seven signals yes yes no
The pill, tray/menu bar, shortcuts, cards yes yes no
Transport and paths yes yes yes
Everything else not written

Windows is the reference. macOS reached parity signal for signal, with one deliberate difference: the Mac pill never takes a click, so the capture card's two controls live in the menu bar instead of on the card. The pointer is observed by polling its location rather than captured, so a panel sitting in the corner of somebody's screen all day never swallows a click meant for the window underneath.

The seam

crates/here-os is where a port plugs in. It exposes a Capabilities struct per platform and unavailable_signals(), which the gate consults at startup and uses to refuse grants it cannot honour.

That is the important part of the design: a signal that cannot work on this machine is refused, with a reason naming the setting to change, rather than switched on to produce nothing. And there is a separate notion for a signal that works here with less in it — reduced, not refused — because those need different words to the person.

Three rules the seam enforces so a port cannot quietly weaken them:

  • A refusal's reason must be true on every platform that can hit it, and must name that platform's remedy. A Mac user must not be told about someone else's desktop.
  • The clipboard's hash-only rule lives in here-os, above the OS call, so no port can ship a version that stores the text.
  • A capability the gate cannot verify is not a capability. See the indicator rule below.

Two promises that get weaker off Windows, and say so

Network denial. On Windows every collector is blocked by a per-executable outbound firewall rule applied before it starts, and one that could not be blocked is not started. That is the only invariant here that does not depend on collector code being correct.

  • macOS has no per-process rule without a paid network-extension entitlement, so the claim falls back to "a reviewed binary with no network code". Weaker, and stated as weaker.
  • Linux needs root or a network namespace.

Key binding. Hardware-backed on Windows (DPAPI) and macOS (Keychain, once signed). On Linux it is file permissions only.

Both of these are on the app's first screen, not footnoted in a document. A weaker guarantee that is stated is a different product from a weaker guarantee that is implied.

Wayland: the answer is per-compositor, and it is settled

An earlier audit concluded content capture was impossible under Wayland. That was wrong, and the correction is worth keeping because the wrong version is the intuitive one:

  • xdg-desktop-portal ScreenCast takes a window source, and since v4 returns a restore_token, so a grant survives restarts. Content capture is available.
  • wlr-layer-shell makes the indicator guarantee stronger than Windows'. An overlay-layer surface cannot be covered by construction, so there is nothing to poll — the occlusion question that Windows answers with a Z-order check does not arise.

The real split is by compositor:

layer-shell foreign-toplevel data-control Result
wlroots (Sway, river, …) yes yes yes all signals possible
KWin yes yes yes all signals possible
Mutter (GNOME) no no no window activity, screenshots, typed text and clipboard are refused

here-os models this as WaylandProtocolsCapabilities, probed at startup, so a GNOME session gets honest refusals rather than dead switches. Do not redo this audit — it has been done twice and docs/PORTING.md holds the result.

What a Linux port needs, in order

  1. The nine here-win modules moved behind the here-os traits. Every trait now has a working macOS implementation to write against, so the shape is fixed — this is adapting to a known interface rather than inventing one.
  2. The capability probe, which already exists.
  3. The signal bodies, per compositor family.
  4. An honest answer about network denial, since the Windows one does not transfer.

The lesson from the macOS port, which will recur

The session that wrote macOS could not compile anything depending on here-store — SQLite is built from C and wants the Windows SDK headers — edited five Windows-only or shared files anyway, and named them in its handoff as unverified. Both of the faults later found on Windows were in exactly two of those five files.

So: when a session edits a platform it cannot build, its own list of untested files is the next session's search order, and it will be right. Run the other platform's verifier before trusting anything. See Building and verifying.