# Per-monitor "home" for workspaces. Each rule pins a workspace to a monitor # connector, so it opens there and Hyprland moves it back when that monitor # reappears after an unplug. The connector names are host hardware, so the rule # list is an option a consumer sets from its own host config (see the example in # `hosts/example/home.nix`), not baked in here; empty by default, so the example # host binds nothing. # # Soft binding: when a bound monitor is absent the workspace just falls back to # an active one — every workspace stays reachable, so a laptop-only (no external) # session works unchanged. The `default` keyword marks the workspace a monitor # shows on connect. { config, lib, pkgs, ... }: { options.local.hyprland.workspaceRules = lib.mkOption { type = with lib.types; listOf str; default = [ ]; example = [ "1, monitor:HDMI-A-1, default:true" "6, monitor:LVDS-1, default:true" ]; description = '' Hyprland `workspace` rules binding workspaces to monitor connectors, so each workspace has a home screen. Connector names are host-specific — set this from the inventory rather than here. ''; }; config.wayland.windowManager.hyprland.settings = { workspace = config.local.hyprland.workspaceRules; # With a support monitor whose `default` workspace is high (e.g. a laptop # holding 6-9), a solo session with that monitor as the only screen opens on # that high workspace instead of 1. When rules are in effect, nudge a # single-monitor startup back to workspace 1. No-op with no rules (1 is # already the default). jq is pinned by store path so a consumer needn't # have it installed; hyprctl is bare (a Hyprland session always has it, like # the wallpaper exec-once assumes awww). exec-once = lib.optional (config.local.hyprland.workspaceRules != [ ]) "sh -c '[ \"$(hyprctl monitors -j | ${pkgs.jq}/bin/jq length)\" -eq 1 ] && hyprctl dispatch workspace 1'"; }; }