Zoom window share is blank: static window casts send a single frame (plus 1x1 stream Parameters)
Sharing a single window from Zoom (6.7.5, PipeWire mode, xdg-desktop-portal-gnome) on niri shows a blank picture, while sharing a monitor works. Traced it on niri 25.11 (v25.11-131-gd74a4356, NVIDIA, SHM streams); the relevant code is unchanged on main. Two separate things on niri's side, the second is the actual cause.
1. Window streams report a 1x1 Parameters size
src/dbus/mutter_screen_cast.rs, Stream::parameters(), returns size: (1, 1) for StreamTarget::Window with the comment "Does any consumer need this?". xdg-desktop-portal-gnome (gnomescreencast.c, gnome_screen_cast_session_add_stream_properties) copies position and size from that property into the stream properties it hands to the app, so every portal client is told a niri window stream is 1x1. Mutter reports the window's logical size there. Fix: look the window's logical bbox up on the niri thread at RecordWindow time and report it — slynchDev/niri@6d6875b2. (Verified via busctl; on its own it did not unblank Zoom.)
2. Static windows send exactly one frame; Zoom drops it
Casts are damage-driven. A window that isn't changing (a Chrome "New Tab" page, an idle terminal) produces one frame when the consumer connects and nothing afterwards. Zoom evidently discards the first frame and then waits forever, so the share stays blank until the window repaints. Sharing a window with a running btop in it works fine, and monitor shares work because cursor and bar clock damage keep frames flowing.
Measured with a libpipewire client on the Mutter ScreenCast D-Bus API (RecordWindow / RecordMonitor, BGRA/BGRx SHM):
| cast | frames delivered |
|---|---|
| Chrome window, static, 8 s | 1 |
| monitor (3440x1440), 8 s | 51 |
kitty window printing date at 20 Hz, 6 s |
122 |
What fixed it: a 500 ms per-cast timer that, if an active window cast has produced no frame in that time, drops its damage trackers and redraws it (Cast::force_full_redraw() + State::redraw_cast()), so a static window streams at ~2 fps — slynchDev/niri@d76dbbb0. With that, Zoom window shares work on r16 (static Chrome window verified, monitor shares unaffected). Harness on the fixed build: 11 frames in 6 s for the same static window.
I also tried offering + filling SPA_META_VideoCrop (slynchDev/niri@392ca99a, Mutter does this and Zoom requests the meta); it wasn't needed, listed only for completeness.
Happy to turn 1 and 2 into PRs against main if the approach is acceptable — e.g. the keepalive could be limited to window targets as here, or made a config knob. The 1x1 Parameters fix seems worth taking regardless.
Stock config; NVIDIA host running the SHM-only fork (pre-#1791 snapshot) — the window-cast code paths are the same as main.
System Information
- niri version: niri 25.11 (v25.11-131-gd74a4356) + the linked commits; code in question unchanged on main (v26.04-125-g2f87f384 checked)
- Distro: Debian 13 (trixie), xdg-desktop-portal-gnome 48.0-2, PipeWire 1.4.2, Zoom 6.7.5.6891
- GPU: NVIDIA GeForce RTX 4090 (nvidia-open 615.71.09)
- CPU: Intel Core i9-14900KF
Source: niri-wm/niri