{ lib, config, theme, my, ... }: let # Minimal Lua value renderer for the generated fragments. toLua = v: if builtins.isString v then ''"${v}"'' else if builtins.isBool v then (if v then "true" else "false") else if builtins.isInt v || builtins.isFloat v then toString v else if v == null then "nil" else if builtins.isList v then "{ " + lib.concatMapStringsSep ", " toLua v + " }" else if builtins.isAttrs v then "{ " + lib.concatStringsSep ", " (lib.mapAttrsToList (k: val: "${k} = ${toLua val}") v) + " }" else throw "toLua: unsupported value type"; themeLua = "return " + toLua { inherit (theme) colors bare; }; monitorsLua = "return " + toLua ( map ( m: { inherit (m) output mode position scale ; } // lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; } ) config.hypr.monitors ); in { # ------------------------------------------------------------------------- # Per-host monitor configuration. # # Hosts declare their displays once, in hosts//default.nix, via: # home-manager.users..hypr.monitors = [ { ... } ]; # The list is rendered to ~/.config/hypr/monitors.lua, which the # hand-maintained hyprland.lua pulls in with require("monitors"). # ------------------------------------------------------------------------- options.hypr.monitors = lib.mkOption { description = "Hyprland monitor rules for this host"; type = lib.types.listOf ( lib.types.submodule { options = { output = lib.mkOption { type = lib.types.str; default = ""; description = "Output name or desc: match. Empty string matches every output."; }; mode = lib.mkOption { type = lib.types.str; default = "preferred"; description = "Resolution@refresh, e.g. \"3840x2160@164.99Hz\" or \"preferred\"."; }; position = lib.mkOption { type = lib.types.str; default = "auto"; }; scale = lib.mkOption { type = lib.types.either lib.types.number lib.types.str; default = "auto"; }; vrr = lib.mkOption { type = lib.types.nullOr (lib.types.either lib.types.number lib.types.str); default = null; description = "Optional per-monitor VRR setting (0/1/on-demand)."; }; }; } ); default = [ { output = ""; mode = "preferred"; position = "auto"; scale = "auto"; } ]; }; config = { # Live, hand-maintained config: symlinked straight to the repo so edits # apply on `hyprctl reload` without a rebuild. xdg.configFile."hypr/hyprland.lua".source = config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/hypr/hyprland.lua"; # Generated fragments required by the live config. xdg.configFile."hypr/theme.lua".text = themeLua; xdg.configFile."hypr/monitors.lua".text = monitorsLua; }; }