Screen Mirroring
Aqueous can mirror one output to another on the same backend/device. The source keeps its resolution, scale, workspace, and refresh rate. The destination fits the complete source image into its own resolution with black bars where needed, including windows, panels, popups, effects, and the cursor.
Configure a mirror
Section titled “Configure a mirror”Back up outputs.toml. Run aqueousctl outputs --json and replace the connector
names and modes below with your own. Both outputs must share a backend/device.
Add the relationship to ~/.config/aqueous/outputs.toml:
[[output]]name = "DP-1"enabled = truemode = "2560x1440@240"transform = "normal"hdr = falsemirror_of = ""
[[output]]name = "HDMI-A-1"enabled = truemode = "1920x1080@60"mirror_of = "DP-1"adaptive_sync = falsehdr = falsetransform = "normal"Both displays must use SDR and normal orientation. The source can keep adaptive sync; the destination uses fixed refresh and disallows tearing. Refresh rates do not need to be integer multiples. Aqueous copies frames at destination demand, skips intermediate source updates, and retains the latest complete image when the source is idle.
Set compatible SDR modes and normal orientation first. With
[display].apply_on_reload = true, save and press Super+R. Check that the
destination shows the source and reports mirror_status: "active".
Position and scale are retained for a return to extended mode.
File edits have no protected confirmation timer. Physical mirroring previews remain blocked; see Display previews.
Return to an extended desktop
Section titled “Return to an extended desktop”Explicitly clear the relationship in the file that sets it:
[[output]]name = "HDMI-A-1"mirror_of = ""position = [2560, 0]Save and reload, then check mirror_status: "extended" and move the pointer onto
the destination. On failure, check mirror_error and restore your backup.
Adjust position for the source’s logical size after scaling. An omitted
mirror_of inherits policy; an empty string clears it. A value in
outputs.toml takes precedence over wm.toml. Named output profiles accept
the same field.
Status and runtime changes
Section titled “Status and runtime changes”aqueousctl outputs --jsonWith the embedded output service available, each output can report
mirror_of, mirror_status, and mirror_error. Status is starting,
active, waiting_for_source, suspended, error, or extended.
The existing output service accepts
mirror_of in a set request to $XDG_RUNTIME_DIR/aqueous/outputd.sock:
{ "op": "set", "changes": [ { "name": "HDMI-A-1", "mirror_of": "DP-1", "adaptive_sync": false } ]}Use compatible SDR and orientation settings first. Apply responses describe staged changes; the compositor’s output transaction performs the backend commit. Inspect the resulting status to confirm the mirror is active.
Workspace and lock behavior
Section titled “Workspace and lock behavior”A mirror has no independent workspace or pointer area. Existing windows migrate using output-removal policy. Returning to extended mode recreates its workspace space without automatically moving those windows back. Mirrors cannot be layer-shell or input-device mapping targets.
A disconnected or powered-off source leaves the mirror black until a usable source returns. The mirror is also black during session locking and while locked. Cached desktop images are discarded on locking, source changes, and resizing; unlocking waits for fresh source content.
Supported configurations
Section titled “Supported configurations”The first version supports one pair, SDR, normal transforms, and a shared backend/device. Self references, chains, extra pairs, and incompatible settings are rejected. Vulkan requires timeline synchronization support; the diagnostic Pixman build is also supported. HDR mirroring, rotation, cross-device transfer, delay, audio, and wireless transport are outside this version.
