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

+22 -10
View File
@@ -71,9 +71,7 @@ pub fn run() -> Result<(), Box<dyn std::error::Error>> {
}
let prompt: Prompt = serde_json::from_str(&input)?;
if prompt.sources.is_empty()
|| prompt.sources.len() > if prompt.window_capture { 128 } else { 16 }
{
if prompt.sources.is_empty() || prompt.sources.len() > 144 {
return Err("No shareable displays".into());
}
@@ -187,6 +185,9 @@ impl cosmic::Application for Picker {
if self.selected.contains(&index) {
self.selected.retain(|i| *i != index);
} else {
if self.prompt.multiple && self.selected.len() >= 8 {
return Task::none();
}
if !self.prompt.multiple {
self.selected.clear();
}
@@ -244,7 +245,7 @@ impl cosmic::Application for Picker {
self.text(if self.prompt.window_capture {
"Choose a window"
} else {
"Choose a display"
"Choose what to share"
})
.size(18),
self.text(format!(
@@ -264,16 +265,27 @@ impl cosmic::Application for Picker {
.align_y(Alignment::Center),
);
let mut sources = column([]).spacing(6);
let mut previous_kind = None;
for (index, source) in self.prompt.sources.iter().enumerate() {
let is_window = self.prompt.window_capture || source.window_id().is_some();
if !self.prompt.window_capture && previous_kind != Some(is_window) {
sources = sources.push(
self.text(if is_window { "Windows" } else { "Displays" })
.size(12),
);
previous_kind = Some(is_window);
}
let selected = self.selected.contains(&index);
let mut entry = row![
glyph(ferese_theme::icons::DISPLAY, 24),
column![
self.text(if self.prompt.window_capture {
&source.label
} else {
&source.name
})
self.text(
if self.prompt.window_capture || source.window_id().is_some() {
&source.label
} else {
&source.name
}
)
.size(14),
self.text(format!("{} × {}", source.width, source.height))
.size(12)
@@ -305,7 +317,7 @@ impl cosmic::Application for Picker {
self.text(if self.prompt.window_capture {
"Only the selected window will be captured."
} else {
"Everything on this display, including notifications, is visible."
"Displays share everything visible. Windows share only their own content."
})
.size(12)
.width(Length::Fill),