Support isolated live window ScreenCast streams

Render selected toplevels through a private portal-only capture protocol, preserve logical snapshot geometry, and renegotiate PipeWire video on window resizing. Bound outstanding snapshots and retry temporary contention; stop on source closure and session locking.

Validation: portal unit tests (31), capture budget unit, private-bus portal contracts, and real nested/PipeWire isolation, workspace, resize, close and paused-lock tests pass. Independent review cleared. Monitor restore integration timed out on both this build and the unchanged previous compositor under the current nested host.
This commit is contained in:
Samuel Onoja committed 2026-09-30 04:02:33 +01:00
1 parent 56a888adb3
commit baca852ee9
26 files changed
+1307 -139

No files matched your search

+32 -4
View File
@@ -176,10 +176,38 @@ pub(crate) fn capture_window_buffer(
geometry: Rectangle<i32, Logical>,
scale: f64,
) -> Result<crate::handlers::screenshot::CaptureBuffer, String> {
let snapshot = capture_resize_snapshot(renderer, window, geometry, scale, 128 * 1024 * 1024)
.map_err(|error| error.to_string())?
.ok_or("Window has no capturable content")?;
capture_window_frame(renderer, window, geometry, scale, None)
}
pub(crate) fn capture_window_frame(
renderer: &mut GlesRenderer,
window: &smithay::desktop::Window,
geometry: Rectangle<i32, Logical>,
scale: f64,
cursor: Option<(&Ferese, Rectangle<i32, Logical>)>,
) -> Result<crate::handlers::screenshot::CaptureBuffer, String> {
let mut snapshot =
capture_resize_snapshot(renderer, window, geometry, scale, 128 * 1024 * 1024)
.map_err(|error| error.to_string())?
.ok_or("Window has no capturable content")?;
let size = snapshot.texture.size();
if let Some((state, cursor_geometry)) = cursor {
let elements = cursor_elements(state, renderer, cursor_geometry, scale);
let mut target = renderer
.bind(&mut snapshot.texture)
.map_err(|e| e.to_string())?;
let mut frame = renderer
.render(&mut target, (size.w, size.h).into(), Transform::Normal)
.map_err(|e| e.to_string())?;
draw_render_elements(
&mut frame,
scale,
&elements,
&[Rectangle::from_size((size.w, size.h).into())],
)
.map_err(|e| e.to_string())?;
let _ = frame.finish().map_err(|e| e.to_string())?;
}
let mapping = renderer
.copy_texture(
&snapshot.texture,
@@ -551,7 +579,7 @@ fn blur_damage(
DamageSet::default()
} else {
// A new scene needs its entire sampling halo repainted before capture.
DamageSet::from_slice(&[Rectangle::from_size(size)])
DamageSet::from_slice(&[Rectangle::from_size((size.w, size.h).into())])
}
}