Skip to content

Add Sway and Hyprland backends to the Linux host - #2

Merged
FacuM merged 3 commits into
mainfrom
feat/wlroots
Oct 26, 2026
Merged

FacuM merged 3 commits into
mainfrom
feat/wlroots

Conversation

@FacuM

@FacuM FacuM commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #1; retarget to main after #1 merges.

Summary

Adds wlroots-based backends to the Linux host: Sway and Hyprland. Each one creates a virtual output over the compositor's IPC, captures it directly over Wayland (no portal), and maps the uinput input devices to that output. The PipeWire path is unchanged.

Changes

  • Sway (sway.rs): i3-ipc client over $SWAYSOCK. Creates a HEADLESS-n output, sets its mode with mode --custom, unplugs it on exit, and maps each input device with map_to_output.
  • Hyprland (hyprland.rs): socket IPC. Creates ezdisplay-N with output create headless, sets the mode with keyword monitor, removes it with output remove, and maps devices with keyword device[...]:output.
  • Direct Wayland capture (wl_capture.rs): uses ext-image-copy-capture-v1 with an output capture source and a pointer cursor session, so the tablet's local cursor works. Falls back to wlr-screencopy with the cursor painted into the frame. Only wl_shm buffers are used; DMA-BUF is not yet supported.
  • Override: EZD_WL_CAPTURE=ext|wlr|auto selects the capture protocol.
  • Source selection (source.rs): the capture source is now Capture::{Pw, Wl}. The PipeWire path is unchanged.
  • Input mapping: absolute pointers are mapped per device on wlroots. The workspace Mapper is not used there.
  • Diagnostics (diag.rs): reports the compositor, its version, and the capture protocols it advertises.
  • Tests and tooling: fixtures for Sway's get_outputs and get_version, unit tests for the Hyprland IPC parsing, tools/wlroots-headless-test.sh (runs headless Sway in Docker when EZD_WLROOTS_TEST=1), and docs updates in docs/architecture.md, docs/input.md, README.md and packaging/linux/.

Scope notes

  • Hyprland has not been run live. It fails to start headless in a container, so its coverage is unit tests with fixtures.
  • Not tested on real Sway or Hyprland sessions with a GPU.
  • DMA-BUF capture and 10-bit capture are not covered.
  • Live uinput mapping on wlroots compositors is not covered.

Verification

  • cargo fmt --check, cargo clippy -- -D warnings and cargo test --workspace pass.
  • Headless Sway 1.12 in Docker (tools/wlroots-headless-test.sh, EZD_WLROOTS_TEST=1):
    • The output is created at 1280x720@60.
    • Frames are captured with real damage and encoded with libx264.
    • 15–16 cursor updates arrive on ext-image-copy-capture.
    • The cursor is embedded on wlr-screencopy.
    • The output is unplugged afterwards.
    • Sway accepts map_to_output for all devices.
  • Real KDE Plasma session re-checked end to end with ezd-fake-client: no regression. Virtual output is 1920x1080, and touch and pen are mapped.

Create virtual outputs over i3-ipc (Sway) and the Hyprland socket, capture
them through ext-image-copy-capture-v1 (with a pointer cursor session) or
wlr-screencopy over wl_shm, and map the uinput devices to the output per
device. Adds a headless sway test script, fixtures and documentation.
# Conflicts:
#	README.md
@FacuM
FacuM changed the base branch from feat/gnome to main October 26, 2026 02:00
@FacuM
FacuM merged commit 1a68d25 into main Oct 26, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant