Which layer paints a peer’s pointer — a screen position, so only one
layer may place it correctly (an app painting a desktop coordinate into
its own window space is right only at the origin). The compositor owns
desktop-scoped pointers, since it alone spans the strip, chrome and gaps
between windows continuously; an app owns presence inside its own
content (caret, selection, typing swipe), since the compositor has no
access to the text.
What a subscriber still has to do after
PresenceCtx::apply_remote_presence folds a frame in, beyond the
presence stores. A subscriber with no document (the compositor) ignores it.
Every colour a peer can be drawn in: the design language’s twelve
presence hues (tokens::colors::PRESENCE_HUES, 30° apart) at the dark
material’s presence lightness and chroma (OKLCH L 0.74, C 0.14, gamut
mapped), as sRGB. Equal lightness and chroma, so no participant looks
more important than another; a closed ring rather than a hash over all
360 hues, so two people never land a few degrees apart.
Longest a peer’s pointer takes to glide to a newly heard position. Peers
publish at ~30 Hz, so a moving pointer glides over the gap between its
last two samples (~33 ms) and arrives as the next one is due; this caps
the glide after a pause, so a pointer that sat still for a while does
not drift lazily to where it was just put. See
PresenceCtx::pointer_position_at.
How long a peer’s pointer stays painted after it was last heard about.
Comfortably past the ~1s restate interval a live peer keeps, so this
notices a peer gone quiet rather than blinking one whose keepalive was
briefly delayed. See PresenceCtx::prune_pointers.
Black or white ink for text on bg, by luma — a fixed white label is
unreadable on over half the peer palette (11 of 24 entries under 2:1,
palest 1.24:1 against white).
Paint pointers, then tethers, then pills — in that layer order so a
later peer’s halo can’t wash over an earlier peer’s name. viewport
bounds the pills; positions are assumed already filtered to it.
Paint already-resolved peer cursors in one coordinate space. On-screen
peers get moving dots and collision-free name pills; off-screen peers
become directional edge mist. This is the compositor-facing sibling of
draw_remote_presence, which resolves cursors from a PresenceCtx.
Paint every entry in presence.remote_cursors as a dot + name pill, for
non-shell apps drawing cross-process ghost cursors without reimplementing
the geometry. No viewport, so pills are de-overlapped but not clamped —
prefer draw_remote_presence, which keeps names on screen.
The one call the app makes each frame to render all cross-process peer
presence: on-screen peers get a dot + pill, off-screen peers get an edge
mist. viewport is the visible rect in the same (logical) space as
cursor positions.
Place one name pill per peer so none overlap and none leaves viewport.
Each pill tries the four corners around its pointer, taking the first
clear of the viewport and every already-placed pill; only when all four
are taken does it slide along the vertical and get marked tethered.
Placement order is by position, not arrival, so a peer reconnecting
doesn’t reshuffle everyone else’s names.
Stable identity colour for a collaborator who has not chosen one: the
presence hue crate::tokens::PresenceHue::of_identity derives from
their id, as the sRGB colour in PEER_PALETTE. A pure function of the
id alone: two hosts painting the same room see different peer sets
(everyone but themselves), so a colour derived from who’s present
couldn’t agree across machines.