Environment
- Ubuntu 26.04 LTS, GNOME Shell 50.1, Wayland
- xdg-desktop-portal-gnome 50.0, ScreenCast portal v5 (
AvailableCursorModes = 7)
- Tauri 2.11.5, tao 0.35.3
- Intel Iris Xe (TigerLake-LP) + NVIDIA RTX 3050 Mobile
Symptom
On Wayland, no recording ever gets a cursor track:
cursor.json contains "samples": []
- The editor's Cursor panel shows "No cursor track for this recording. Record with cursor capture enabled."
- Every pointer style / size / motion-blur / click-bounce control is inert
- Follow-cursor zoom holds centre instead of following
The portal reports that Metadata cursor mode was negotiated successfully, so nothing in the logs indicates a failure.
Root cause
build_cursor_meta_pod() in src-tauri/src/recorder/backend/portal_backend.rs declares
SPA_PARAM_META_size as an exact integer:
let meta_size = (size_of::<spa_meta_cursor>()
+ size_of::<spa_meta_bitmap>()
+ 64 * 64 * 4) as i32; // 16432
SPA negotiates meta sizes by intersection. That size embeds a cursor bitmap
dimension which each side chooses independently, we hardcode 64×64, the
compositor picks its own maximum cursor size. Two different exact values
intersect to nothing, so the meta is dropped from the buffer while the session
itself still reports Metadata mode as negotiated.
Evidence
Logging the metas actually attached to each buffer:
INFO portal cursor mode cursor_mode=Metadata cursor_via_metadata=true
INFO portal stream selected source_type=Some(Monitor) size=Some((1920, 1080))
WARN buffer metas present (type, size) present=[(7, 8), (1, 32)] want_type=5 want_size=28
INFO portal negotiated Metadata but buffers carry no SPA_META_Cursor
SPA_META_Header (type 1) negotiates fine because its size is
sizeof(spa_meta_header), a struct size, identical on both sides, so it always
agrees. SPA_META_Cursor (type 5) is absent. That asymmetry isolates the cause
to how the size is expressed, not to whether the request reaches the compositor.
Fix
Declare the size as a range, which is what OBS does for this same meta SPA_META_Header should stay an exact int, its size genuinely is fixed.
Verification
INFO portal cursor metadata flowing
cursor.json for a 10.9 s take: 482 samples, t spanning 0.18 to 10.86 s,
normalised x/y. The full cursor style panel and follow-cursor zoom become live.
Scope
Confined to portal_backend.rs, already behind the portal-capture feature.
No effect on macOS or Windows.
Environment
AvailableCursorModes = 7)Symptom
On Wayland, no recording ever gets a cursor track:
cursor.jsoncontains"samples": []The portal reports that Metadata cursor mode was negotiated successfully, so nothing in the logs indicates a failure.
Root cause
build_cursor_meta_pod()insrc-tauri/src/recorder/backend/portal_backend.rsdeclaresSPA_PARAM_META_sizeas an exact integer:SPA negotiates meta sizes by intersection. That size embeds a cursor bitmap
dimension which each side chooses independently, we hardcode 64×64, the
compositor picks its own maximum cursor size. Two different exact values
intersect to nothing, so the meta is dropped from the buffer while the session
itself still reports Metadata mode as negotiated.
Evidence
Logging the metas actually attached to each buffer:
SPA_META_Header(type 1) negotiates fine because its size issizeof(spa_meta_header), a struct size, identical on both sides, so it alwaysagrees.
SPA_META_Cursor(type 5) is absent. That asymmetry isolates the causeto how the size is expressed, not to whether the request reaches the compositor.
Fix
Declare the size as a range, which is what OBS does for this same meta
SPA_META_Headershould stay an exact int, its size genuinely is fixed.Verification
cursor.jsonfor a 10.9 s take: 482 samples,tspanning 0.18 to 10.86 s,normalised x/y. The full cursor style panel and follow-cursor zoom become live.
Scope
Confined to
portal_backend.rs, already behind theportal-capturefeature.No effect on macOS or Windows.