Sweets
Running

Desktop Integration

Clipboard, screenshots, idle, gamma, screen lockers, sandbox restrictions, and xdg-desktop-portal support.

Sweets speaks the standard wlroots desktop protocols, so external clipboard managers, screenshot tools, idle daemons, color-temperature tools, and screen lockers work without compositor-side configuration.

Clipboard Managers and Primary Selection

Sweets supports normal Wayland clipboard selection, primary selection, and the data-control protocols used by clipboard managers.

Advertised globals:

  • wl_data_device_manager
  • zwlr_data_control_manager_v1
  • ext_data_control_manager_v1
  • zwp_primary_selection_device_manager_v1
# smoke tests
printf 'hello from sweets\n' | wl-copy
wl-paste

printf 'primary hello\n' | wl-copy --primary
wl-paste --primary

Clipboard managers using either legacy wlr-data-control or newer ext-data-control can observe and restore selections.

Drag and Drop

The same wl_data_device_manager global powers client drag-and-drop. Drag files, text, or other content between native Wayland applications — a folder from a file manager into a browser upload field, for example.

Both pointer and touch drags work. The drag icon, when the source provides one, follows the cursor above all windows.

Keyboard focus does not change during a drag. The window focused before the drag keeps focus after you drop.

Screenshots and screen capture

Sweets implements the standard wlroots screen-capture protocols, so external tools work without configuration:

  • Legacy wlr-screencopy (zwlr_screencopy_manager_v1) — grim, slurp, wf-recorder, older OBS.
  • Modern ext-image-copy-capture with an output capture source — current grim, hyprshot, and other up-to-date tools.
  • Per-window capture via ext-foreign-toplevel-image-capture — captures a single application window instead of a whole output, for window-only screen sharing. Paired with ext-foreign-toplevel-list.
grim screenshot.png                          # whole output
hyprshot -m region --raw | satty --filename - # region into an editor

There is no built-in screenshot keybind or IPC command yet. Bind your tool of choice, e.g. sweets.bind("MOD+Print", "spawn", "grim ...").

Idle tools

Sweets implements ext-idle-notify-v1 and idle-inhibit-v1. Tools like swayidle can observe inactivity, and apps like video players can block idle behavior. Keyboard and pointer input reset the idle timer.

Sweets also implements wlr-output-power-management-unstable-v1. Tools such as wlopm can power outputs directly, and sweetctl exposes the same for scripts:

sweetctl output DP-1 power off
sweetctl output DP-1 power on
sweetctl output all power off

A simple idle recipe:

swayidle -w \
  timeout 300 'sweetctl output all power off' \
  resume 'sweetctl output all power on'

Output power changes are runtime-only and are not written to sweets.lua. A reload or restart restores the file-backed monitor state.

Display Configuration

Sweets implements wlr-output-management-unstable-v1, so output configuration clients can inspect and apply a complete monitor layout. Use wlr-randr for terminal changes or wdisplays for a graphical editor.

# confirm the protocol and inspect the current layout
wayland-info | rg zwlr_output_manager_v1
wlr-randr

# open a graphical layout editor, if installed
wdisplays

The protocol validates a complete requested configuration with the backend before applying it, so unsupported combinations are rejected without a partial rearrangement. Successful changes update sweetctl outputs immediately.

Display-client changes are runtime-only. Sweets keeps them for the session but does not write sweets.lua. A reload or restart restores the Lua rules.

Night Light and Gamma

Sweets implements wlr-gamma-control-unstable-v1, so tools such as wlsunset and gammastep can adjust output color temperature.

# smoke test
wayland-info | rg zwlr_gamma_control_manager_v1

Screen Lockers

Sweets implements ext-session-lock-v1, so lockers such as Veila can take over the session securely. While locked, Sweets covers every output with an opaque black scene, routes input only to lock surfaces, and keeps newly mapped windows behind the lock.

If the locker exits without sending an unlock request, Sweets keeps the session locked and leaves the black covers in place. Starting a new session-lock client can replace that abandoned lock.

Save dialogs and screen sharing (xdg-desktop-portal)

Tools like satty open a Save dialog through xdg-desktop-portal, and browsers and OBS use it for screen sharing. Sweets wires this up automatically, but only for a real session started through sweets-session.

What happens on startup:

  • The session launcher exports XDG_CURRENT_DESKTOP=sweets and SWEETS_SESSION=1.
  • Sweets asks dbus-update-activation-environment to sync WAYLAND_DISPLAY, XDG_CURRENT_DESKTOP, and XDG_SESSION_TYPE into the D-Bus activation environment.
  • On a systemd boot with a live user manager, that sync also updates systemd. Sweets then starts sweets-session.target and refreshes existing portal services. If the activation updater is missing, Sweets starts the target but skips the portal refresh rather than restarting portals with stale state.
  • sweets-portals.conf routes file dialogs to xdg-desktop-portal-gtk and screenshot/screencast to xdg-desktop-portal-wlr.

Install these with dev/install-local or meson install. You need xdg-desktop-portal plus xdg-desktop-portal-gtk and xdg-desktop-portal-wlr. Nested and dev runs skip all of this so they never disturb the host session.

On runit, OpenRC, dinit, and other non-systemd systems, Sweets never invokes systemctl or systemd-run. Portable D-Bus activation syncing still runs when dbus-update-activation-environment is installed. Starting portal services is left to the user session or service manager. The log reports which integrations were requested and which were skipped.

If a save dialog fails with Could not activate ... portal.Desktop after a session of a different compositor, the activation environment was stale. Relaunching through sweets-session resyncs it.

Keyring and secrets (optional)

Most password storage does not involve the compositor. Native apps talk to a keyring daemon over the Secret Service D-Bus API (org.freedesktop.secrets) directly. Install and start gnome-keyring or KeePassXC and it works — Sweets is not in that path.

The org.freedesktop.impl.portal.Secret portal only matters for sandboxed apps that reach a keyring through the portal instead of raw D-Bus. Sweets deliberately does not pin a Secret backend, so xdg-desktop-portal auto-selects whatever keyring is installed and the default stays portable.

To force gnome-keyring, add the line in your user portal config at ~/.config/xdg-desktop-portal/sweets-portals.conf:

[preferred]
default=gtk
org.freedesktop.impl.portal.Screenshot=wlr
org.freedesktop.impl.portal.ScreenCast=wlr
org.freedesktop.impl.portal.Secret=gnome-keyring

gnome-keyring must be installed, running, and unlocked to serve secrets.

Sandboxed applications (security context)

Sweets implements security-context-v1. Sandbox runtimes such as Flatpak attach a security context to the nested Wayland socket they hand a sandboxed app, which lets Sweets recognise that client as sandboxed.

Sandboxed clients are denied the privileged protocols:

  • screen and window capture
  • clipboard data-control
  • layer-shell and the session locker
  • gamma and output management
  • virtual keyboard/pointer input injection and input-method
  • the window-management protocols

So a sandboxed app cannot silently screenshot your screen, read your clipboard, inject input, or spoof a lock screen. Ordinary protocols — app windows, outputs, scaling — stay available, so normal Flatpak apps keep working.

This is enforced compositor-side and needs no configuration. Screen sharing from a sandboxed app still works through xdg-desktop-portal, which brokers capture with your consent instead of handing over the raw protocol.

On this page