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

+50 -4
View File
@@ -1,6 +1,6 @@
# Screen sharing and recording
Share a monitor or window from a Wayland-compatible recording or conferencing app,
Share a monitor, workspace, or window from a Wayland-compatible recording or conferencing app,
or save a video using the panel's Recording control. The
[installation guide](installation.md) covers the portal and PipeWire dependencies.
@@ -24,7 +24,7 @@ If recording fails, a notification reports the error and any unfinished
## Start sharing
Select a Wayland screen-sharing source in your application. In Ferese's picker,
choose a display or window and click **Share**. Nothing is selected initially.
choose a display, workspace, or window and click **Share**. Nothing is selected initially.
Apps requesting multiple sources can select up to eight.
A shared display includes everything visible on it, including notifications.
@@ -39,6 +39,26 @@ At fractional scales, clients can round the two backing dimensions separately.
Capture preserves those pixel dimensions rather than adding a row or column
by applying the larger axis density to both axes, which would soften text.
A shared workspace stays attached to its identity when you switch elsewhere. It
includes that workspace's windows, their popups and decorations, and the wallpaper.
It excludes desktop layers (including panels and notifications), overview, and
windows protected by capture rules. Authentication windows are protected by default.
Scrolling shares the workspace viewport, not the entire offscreen canvas. Capture
does not activate the workspace, move focus, or resize hidden applications.
Workspace video fits a 1920 × 1080 bounding box (1080 × 1920 for portrait displays),
preserving aspect ratio and avoiding upscaling. This bounds capture buffers even
on a desktop using 2× scaling. The canvas is fixed for the session. Changing the
source output's scale, transform, geometry, or workspace ownership ends sharing;
select the workspace again. Removing the workspace or locking also ends sharing.
Window blur and desktop transition effects are omitted from the workspace view.
Workspaces appear when an application requests display sharing. The portal
exposes them as restricted views of an existing monitor using the standard
`MONITOR` source type; it does not advertise a new workspace type or create a
virtual display. Applications requesting only windows still see only windows.
The panel recorder continues to select displays.
The picker follows your shell colors, font, corners, opacity, and blur.
## Stop sharing
@@ -55,7 +75,7 @@ asking**, off by default. Approval lasts for the duration requested by the app.
The portal manages stored permissions and revocation.
A different app, changed display, or changed cursor option needs approval again.
Nested previews and displays without a reliable identity always ask. Window
Nested previews and displays without a reliable identity always ask. Window and workspace
permissions are not saved. Stopping a stream does not erase a saved permission.
## Requirements and limits
@@ -73,7 +93,8 @@ Log into a new Ferese session after installation.
Streams negotiate their frame rate with the recording app, with a default of
30 fps and a ceiling of 60 fps. To set a different ceiling, give the portal
process `FERESE_CAPTURE_MAX_FPS` with an integer from 1 to 240. This controls
capture independently of the display refresh rate; it does not make an idle
capture independently of the display refresh rate; for workspace capture, set
the same ceiling in the compositor environment. It does not make an idle
desktop generate frames.
On supported GPUs, Ferese renders directly into DMA-BUF buffers shared with
@@ -84,6 +105,31 @@ consumer receives an initial image even if the desktop has stayed unchanged.
For troubleshooting, `FERESE_CAPTURE_FORCE_SHM=1` selects shared memory; large
or rapidly changing captures on this path still incur GPU readback costs.
## Workspace capture resources
Workspace sources reuse the existing image-copy-capture and PipeWire transport.
Each workspace/cursor view has one retained GPU image with independent damage
history and render resources. At most one changed workspace is composed per
event-loop dispatch, yielding to input and display deadlines between views. Matching consumers reuse its composition and keep
separate output buffers. Surface commits invalidate only their owning workspace;
layout samples are reused until geometry changes. Consumer demand alone does not
invalidate the image.
Hidden applications receive paced frame callbacks only while their content
contributes to an active capture. An unchanged source waits for damage. A paused
consumer stops capture work without prematurely returning a buffer still owned by
the compositor; its retained capture target is released after two idle seconds.
Closing the last session releases its view immediately on event-loop cleanup.
No workspace capture targets or recurring capture timers exist without sessions.
Persistent capture admission reserves up to 512 MiB of pixel storage across all
sessions, accounting conservatively for eight consumer buffers, a composition
target, a fallback transfer texture, and stride padding. Matching views can use
less than the reservation. This is not a cap on total process RSS, driver
bookkeeping, wallpaper storage, or the recording application's encoder. The
existing per-image and session-count limits also apply. GPU fences remain
asynchronous; slow consumers do not accumulate a queue of rendered frames.
## Troubleshooting
- Confirm PipeWire and WirePlumber are running.