Skip to content

ui: add span fit_mode to split one image across outputs - #373

Open
josephdunn wants to merge 1 commit into
hyprwm:mainfrom
josephdunn:span-fit-mode
Open

ui: add span fit_mode to split one image across outputs#373
josephdunn wants to merge 1 commit into
hyprwm:mainfrom
josephdunn:span-fit-mode

Conversation

@josephdunn

Copy link
Copy Markdown

Summary

Adds fit_mode = span, which splits a single wallpaper across every output it
is assigned to so the image is continuous across the physical monitor
arrangement, instead of repeating the whole image on each output (which is what
cover/contain/fill/tile do today).

Optional sub-modes control how the source is fit onto the combined canvas:

  • span / span:cover (default) — fill the canvas, crop overflow
  • span:contain — fit the whole image, letterbox
  • span:stretch — stretch to the canvas aspect

Example

wallpaper {
    monitor =
    path = /path/to/ultrawide.png
    fit_mode = span
}

How it works

  • Outputs resolving to the same wallpaper entry form a span group.
  • The monitor layout is queried from Hyprland over IPC (j/monitors).
  • The image is mapped onto the group's bounding box in logical layout
    coordinates (so mixed-DPI monitors stay continuous in physical size), and
    each output is handed the sub-rectangle its layout rect covers.
  • Slices are rendered with cairo and cached as PNGs under $XDG_RUNTIME_DIR.
  • A group of one output is equivalent to the matching plain fit mode.

Fallback

If the layout can't be read (not under Hyprland, or an output's geometry can't
be resolved), each output falls back to cover with a warning.

Dependencies

Adds cairo, hyprgraphics, libpng, and jsoncpp (CMake + nix).
cairo/hyprgraphics were already transitively present via hyprtoolkit;
libpng and jsoncpp are new.

Testing

  • Verified on a 3-monitor layout (mixed transforms and resolutions): slices are
    geometrically contiguous across seams, and mixed-height/DPI monitors sample
    the correct region.
  • Verified span:cover cropping, the single-output degenerate case, and the
    no-Hyprland cover fallback.

Known limitations

  • An in-place monitor geometry change (resolution/scale/reposition without
    an unplug) doesn't re-slice until the wallpaper is re-set — hyprtoolkit
    exposes no "output changed" signal. Hotplug (add/remove) is handled.
  • Rotated outputs work (logical dimensions handled); flipped transforms (4–7)
    are untested.
  • span is config-file only; the IPC/hyprctl fit-mode enum isn't extended
    (that would be a protocol change).

span slices a single wallpaper across every output it is assigned to, so the
picture is continuous across the physical monitor arrangement instead of
repeating the whole image on each output.

Outputs sharing a wallpaper entry form a span group. The image is mapped onto
the group's bounding box in Hyprland's logical layout coordinates, and each
output shows the sub-rectangle its layout rect covers. Placement within that
canvas is chosen with an optional sub-mode: span / span:cover (default),
span:contain, span:stretch.

The layout is read from Hyprland over its IPC socket; when it is unavailable
(not under Hyprland, or an output's geometry can't be resolved) each output
falls back to cover. A group of one output is equivalent to the matching plain
mode. Slices are rendered with cairo and cached as PNGs under $XDG_RUNTIME_DIR.

Adds cairo, hyprgraphics, libpng and jsoncpp to the build dependencies.
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