UI:
- sec-screen-share: 'share screen' button visible only when canSpeak
(host/cohost/speaker). On click: getDisplayMedia({video, audio}).
- sec-screens: video tile per active screen share; auto-shows when
the first tile arrives, auto-hides when the last leaves.
- Each tile has a 'fullscreen' button.
Publish:
- sfuPublishScreen opens a SEPARATE sfuScreenPC, adds the
display-media tracks (video + optional audio), POSTs
/publish?kind=screen so the SFU's TrackLocal streamID gets a
':screen' suffix.
- Browser-native 'stop sharing' bar fires the video track's 'ended'
event — we trap it to do a clean sfuUnpublishScreen.
Subscribe:
- sfuSubscribe ontrack checks streams[0].id for the ':screen' suffix
— screen streams route to renderScreenTile (creates / updates a
<video> element). Mic streams continue down the existing audio
path. The label uses the publisher's handle from the room state.
- Cleanup paths: peer-left (drops the matching pubHex's tile),
self-boot, self-blocked, leave button — all call
sfuUnpublishScreen + removeScreenTile.
CSS: screen-tile has its own 1fr grid, max-height 70vh so a screen
share never bullies the controls column off the page on a small
display.
Pairs with the multi-track + kind=screen support that just landed in
zebra-spaces-sfu (b7c5a8a).