{user}: { lib, pkgs, config, ... }: with lib; let cfg = config.displays; renderDisplaysForHyprland = displays: (map displayHyprlandSetting displays); displayHyprlandSetting = display: specificDisplay display + ", " + resToString display.resolution + ", " + positionToHyprlandString display.position + ", " + toString display.scaling + ", " + "transform," + toString display.rotation; swaybgJob = displays: { Unit = { Description = "SwayBG"; }; Service = { ExecStart = "${pkgs.swaybg}/bin/swaybg " + concatStringsSep " " (map swaybgCmd displays); }; Install = { WantedBy = ["graphical-session.target"]; }; }; swaybgCmd = display: if (display.wallpaper != "") then "-o ${display.name} -i ${display.wallpaper} -m fill" else ""; specificDisplay = display: if display.description == "" then display.name else "desc:" + display.description; positionToHyprlandString = { x, y, }: if (x == -1 || y == -1) then "auto" else toString x + "x" + toString y; renderDisplaysForSway = displays: listToAttrs (map displaySwaySetting displays); displaySwaySetting = display: { name = display.name; value = let res = display.resolution; in { mode = mkIf (!resUnset res) "${toString res.x}x${toString res.y}@${toString res.freq}Hz"; bg = display.wallpaper + " fill"; scale = toString display.scaling; }; }; resolutionType = types.submodule ({ x, y, freq, ... }: { options = { x = mkOption { description = "x"; type = types.int; default = 0; }; y = mkOption { description = "y"; type = types.int; default = 0; }; freq = mkOption { description = "frequency"; type = types.int; default = 0; }; }; }); displayType = types.submodule ({...}: { options = { name = mkOption { description = "name of the display"; }; description = mkOption { description = "description of display from hyprctl monitors"; default = ""; }; scaling = mkOption { type = types.float; default = 1.0; }; rotation = mkOption { type = types.int; default = 0; }; resolution = mkOption { description = "res"; type = resolutionType; default = {}; }; position.x = mkOption { default = -1; type = types.int; }; position.y = mkOption { default = -1; type = types.int; }; wallpaper = mkOption { description = "path to wallpaper"; default = ""; }; }; }); resUnset = res: (res.x == 0 || res.y == 0 || res.freq == 0); resToString = res: if resUnset res then "preferred" else "${toString res.x}x${toString res.y}@${toString res.freq}"; in { options.displays = { enable = mkEnableOption "manage displays"; displays = mkOption { type = types.listOf displayType; default = []; }; }; config = mkIf cfg.enable { home-manager.users.${user}.imports = [ { wayland.windowManager.hyprland.settings.monitor = mkIf (cfg.displays != []) (renderDisplaysForHyprland cfg.displays); systemd.user.services.swaybg = swaybgJob cfg.displays; wayland.windowManager.sway.config.output = mkIf (cfg.displays != []) (renderDisplaysForSway cfg.displays); } ]; }; }