Add workspace screen sharing (#64)

Add workspace selection to the screen-sharing picker with pinned capture, privacy filtering and bounded capture resources. Refresh captured tab labels when title or app-ID metadata changes.
This commit is contained in:
Samuel Onoja authored and GitHub committed 2026-10-25 13:59:34 +01:00
1 parent e64ab52190
commit ab11269246
32 files changed
+2125 -165

No files matched your search

+63 -3
View File
@@ -6,7 +6,7 @@ use std::time::{Duration, Instant};
use ferese_protocols::window_capture::v1::client::ferese_window_capture_manager_v1 as window_manager;
use serde::{Deserialize, Serialize};
use wayland_client::protocol::{wl_output, wl_registry, wl_shm};
use wayland_client::{Connection, Dispatch, EventQueue, QueueHandle, WEnum};
use wayland_client::{Connection, Dispatch, EventQueue, Proxy, QueueHandle, WEnum};
use wayland_protocols_wlr::screencopy::v1::client::zwlr_screencopy_manager_v1 as manager;
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -20,9 +20,62 @@ pub struct Source {
pub scale: i32,
}
/// Decode opaque worker names in one place. Unknown/malformed private names
/// must never fall through to monitor capture or remembered display consent.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum SourceKind {
Monitor,
Window(u64),
Workspace(u64),
Invalid,
}
impl SourceKind {
pub fn parse(name: &str) -> Self {
if let Some(id) = name.strip_prefix("window:") {
id.parse().map(Self::Window).unwrap_or(Self::Invalid)
} else if let Some(id) = name.strip_prefix("workspace:") {
id.parse().map(Self::Workspace).unwrap_or(Self::Invalid)
} else {
Self::Monitor
}
}
pub fn label(self) -> &'static str {
match self {
Self::Monitor => "Displays",
Self::Window(_) => "Windows",
Self::Workspace(_) => "Workspaces",
Self::Invalid => "Unavailable",
}
}
pub fn category(self) -> u8 {
match self {
Self::Monitor => 0,
Self::Workspace(_) => 1,
Self::Window(_) => 2,
Self::Invalid => 3,
}
}
}
impl Source {
pub fn kind(&self) -> SourceKind {
SourceKind::parse(&self.name)
}
pub fn is_monitor(&self) -> bool {
self.kind() == SourceKind::Monitor
}
pub fn window_id(&self) -> Option<u64> {
self.name.strip_prefix("window:")?.parse().ok()
if let SourceKind::Window(id) = self.kind() {
Some(id)
} else {
None
}
}
pub fn workspace_id(&self) -> Option<u64> {
if let SourceKind::Workspace(id) = self.kind() {
Some(id)
} else {
None
}
}
}
@@ -85,6 +138,13 @@ impl Capture {
Ok(())
}
pub fn supports_workspaces(&self) -> bool {
self.state
.window_manager
.as_ref()
.is_some_and(|manager| manager.version() >= 3)
}
pub fn supports_windows(&self) -> bool {
self.state.window_manager.is_some()
}
@@ -195,7 +255,7 @@ impl Dispatch<wl_registry::WlRegistry, ()> for State {
},
}),
"ferese_window_capture_manager_v1" => {
state.window_manager = Some(registry.bind(name, 1, qh, ()))
state.window_manager = Some(registry.bind(name, version.min(3), qh, ()))
}
"wl_shm" => state.shm = Some(registry.bind(name, 1, qh, ())),
"zwlr_screencopy_manager_v1" => {