Open Source › xdg-desktop-portal-generic
xdg-desktop-portal-generic
A complete XDG Desktop Portal backend that runs as an ordinary Wayland client. One backend, five portal interfaces, automatic protocol selection.
What's new in 0.5.0
ScreenCast version 6
The backend now advertises ScreenCast v6 and emits the pipewire-serial stream property (the PipeWire node object.serial) alongside the v5 mapping_id. Consumers use it to re-follow a capture stream across an output reconfiguration without depending on the deprecated node id. Validated live on a COSMIC desktop, where the serial the backend emitted matched the live PipeWire node object.serial.
Modernized foundation
PipeWire and libspa 0.10, the reis 0.7 libei bindings (with proper device-release teardown), and a current dependency set across the board. Minimum Rust is 1.87.
Now on crates.io
Published as xdg-desktop-portal-generic 0.5.0 under MIT OR Apache-2.0, with its documentation on docs.rs.
Portal access, without compositor buy-in
xdg-desktop-portal is the Freedesktop spec that lets sandboxed applications (Flatpak, Snap, and increasingly native Wayland apps) ask for privileged capabilities such as screen capture, remote-desktop input, clipboard access, and screenshots through a permission-mediated D-Bus interface. Most compositors ship their own backend implementation (xdg-desktop-portal-gnome, xdg-desktop-portal-kde, xdg-desktop-portal-wlr). A compositor without one cannot offer these capabilities to sandboxed apps.
xdg-desktop-portal-generic fills that gap. It gives sandboxed apps (Flatpak and Snap) and native Wayland apps screen capture, remote-desktop input, clipboard access, screenshots, and desktop settings on any compositor that speaks the standard ext or wlr Wayland protocols, with no compositor-side code and no custom traits. It detects the available protocols at startup and selects the best one per requested portal. One backend, five portal interfaces, automatic protocol selection.
Five portal interfaces
| Portal | Ver | Primary protocol | Fallback |
|---|---|---|---|
| RemoteDesktop | v2 | EIS (libei) bridge | wlr-virtual-pointer + zwp-virtual-keyboard |
| ScreenCast | v6 | ext-image-copy-capture-v1 (emits pipewire-serial) | wlr-screencopy-v1 |
| Clipboard | v1 | ext-data-control-v1 | wlr-data-control-v1 |
| Settings | v2 | Environment variable config | GTK_THEME detection |
| Screenshot | v2 | Single-frame capture to PNG | None |
ext protocols are preferred over their wlr equivalents when both are present. ScreenCast supports hidden, embedded, and metadata cursor modes.
A standard Wayland client, three cooperating threads
The backend connects to the compositor as a standard Wayland client and runs three cooperating threads: a tokio async runtime that serves the portal D-Bus interfaces, a Wayland event loop that handles protocol dispatch and frame capture, and a PipeWire thread that delivers captured frames to the requesting app. For each portal domain it detects the available protocols at startup and selects the best one, preferring the modern ext protocols and falling back to the wlr equivalents.
Capture uses ext-image-copy-capture-v1 with a wlr-screencopy-v1 fallback and supports hidden, embedded, and metadata cursor modes. Input uses an EIS (libei) bridge with a wlr virtual pointer and keyboard fallback, plus an optional kernel uinput backend for compositors without a virtual pointer. Clipboard uses ext-data-control-v1 with a wlr-data-control-v1 fallback. The whole backend is about 16,000 lines of Rust across 38 modules, with no compositor-side code.
Build, install, pick it as your backend
xdg-desktop-portal-generic. Build from source to install the binary, portal config, and D-Bus service together.# Dependencies (Debian / Ubuntu):
sudo apt install libpipewire-0.3-dev libspa-0.2-dev libwayland-dev \
libxkbcommon-dev libclang-dev
# Build and install:
cargo build --release
sudo make install
# Installs binary, portal config, D-Bus service, systemd user unit.
[preferred]
default=gtk
org.freedesktop.impl.portal.RemoteDesktop=generic
org.freedesktop.impl.portal.ScreenCast=generic
org.freedesktop.impl.portal.Clipboard=generic
org.freedesktop.impl.portal.Settings=generic
org.freedesktop.impl.portal.Screenshot=generic
Once configured, xdg-desktop-portal auto-activates the generic backend via D-Bus when a sandboxed app requests one of the supported portals.
Configured via environment variables
Appearance & accessibility
| Variable | Values | Default |
|---|---|---|
| XDP_GENERIC_COLOR_SCHEME | 0 / 1 / 2 (detect / dark / light) | 0 |
| XDP_GENERIC_ACCENT_COLOR | r,g,b floats | 0.21,0.52,0.89 |
| XDP_GENERIC_CONTRAST | 0 / 1 | 0 |
| XDP_GENERIC_REDUCED_MOTION | 0 / 1 | 0 |
Input protocol selection
| Variable | Values | Default |
|---|---|---|
| XDP_GENERIC_INPUT_PROTOCOL | eis / wlr | eis |
| XDP_GENERIC_INPUT_NO_FALLBACK | 1 | unset |
| XDP_GENERIC_EIS_SOCKET | path | auto |
External tools
| Variable | Description |
|---|---|
| XDP_GENERIC_SOURCE_PICKER | External tool for ScreenCast source selection UI. Use fzf, rofi, or anything that speaks stdin/stdout |
| XDP_GENERIC_COLOR_PICKER | External tool for Screenshot color picking |
Where it fits
xdg-desktop-portal-generic is built for Wayland compositors that do not ship their own portal backend: COSMIC, niri, Jay, and other Smithay-based compositors. Because it speaks the standard ext and wlr Wayland protocols, it also runs on wlroots compositors that expose those protocols. GNOME and KDE ship their own portal backends, so those desktops use theirs.
Built for
Runtime needs
- A Wayland session exposing the ext or wlr protocols
- PipeWire (libpipewire 0.3.64 or newer for the
pipewire-serialvalue; older PipeWire works and omits that one property) - The
xdg-desktop-portalfrontend
Related work at Lamco Development LLC
Adjacent. The Rust Wayland capture stack that consumes portals rather than providing them.
Ecosystem. On compositors without a portal backend, pair Lamco RDP Server with this for screen capture.
Background. Why portals exist and how they interact with capture.
Upstream. The frontend daemon this backend plugs into.
Project links: crates.io · Documentation · Source