{ lib, config, ... }: let inherit (lib) mkEnableOption mkOption types trivial strings replaceStrings; cfg = config.horseman.wm.hyprland; keybinding = types.submodule { options = { flags = mkOption { type = types.listOf types.enum [ "l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p" ]; default = []; }; mods = mkOption { type = types.listOf types.str; }; key = mkOption { type = types.str; }; dispatcher = mkOption { type = types.str; }; params = mkOption { type = types.str; }; }; }; in { options = { horseman.wm.hyprland = { enable = mkEnableOption "Hyprland"; config = { execOnce = mkOption { type = types.listOf types.str; }; env = mkOption { type = types.listOf types.str; }; windowrules = mkOption { type = types.listOf types.str; }; workspaces = mkOption { type = types.listOf types.str; }; general = { gapsIn = mkOption { type = types.int; }; gapsOut = mkOption { type = types.int; }; borderSize = mkOption { type = types.int; }; col.activeBorder = mkOption { type = types.str; }; col.inactiveBorder = mkOption { type = types.str; }; resizeOnBorder = mkOption { type = types.bool; }; allowTearing = mkOption { type = types.bool; }; layout = mkOption { type = types.enum ["dwindle" "master"]; }; }; decoration = { rounding = mkOption { type = types.int; }; activeOpacity = mkOption { type = types.float; }; inactiveOpacity = mkOption { type = types.float; }; shadow = { enabled = mkOption { type = types.bool; }; range = mkOption { type = types.int; }; renderPower = mkOption { type = types.int; }; color = mkOption { type = types.str; }; }; blur = { enabled = mkOption { type = types.bool; }; size = mkOption { type = types.int; }; passes = mkOption { type = types.int; }; vibrancy = mkOption { type = types.float; }; }; }; animations = { enabled = mkOption { type = types.bool; }; beziers = mkOption { type = types.listOf (types.submodule { options = { name = mkOption {type = types.str;}; startX = mkOption {type = types.number;}; startY = mkOption {type = types.number;}; endX = mkOption {type = types.number;}; endY = mkOption {type = types.number;}; }; }); }; animations = mkOption { type = types.listOf (types.submodule { options = { name = mkOption {type = types.str;}; on = mkOption {type = types.bool;}; speed = mkOption {type = types.number; default = 0;}; curve = mkOption {type = types.str; default = "";}; style = mkOption {type = types.str; default = "";}; }; }); }; }; dwindle = { pseudotile = mkOption { type = types.bool; }; preserveSplit = mkOption { type = types.bool; }; }; master = { newStatus = mkOption { type = types.enum ["master" "slave" "inherit"]; }; }; misc = { forceDefaultWallpaper = mkOption { type = types.enum [ 0 1 2 (-1) ]; }; }; input = { kbLayout = mkOption { type = types.str; }; repeatRate = mkOption { type = types.int; }; repeatDelay = mkOption { type = types.int; }; followMouse = mkOption { type = types.enum [ 0 1 2 3 ]; }; sensitivity = mkOption { type = types.numbers.between (-1.0) 1.0; }; numlockByDefault = mkOption { type = types.bool; }; touchpad = { naturalScroll = mkOption { type = types.bool; }; }; }; gestures = { workspaceSwipe = mkOption { type = types.bool; }; }; monitors = { defaultMonitor = mkOption { type = types.bool; }; displays = mkOption { type = types.listOf (types.submodule { options = { output = mkOption { type = types.str; }; resolution = mkOption { type = types.str; default = "highres"; }; refreshRate = mkOption { type = types.str; default = "highrr"; }; x = mkOption { type = types.int; }; y = mkOption { type = types.int; }; scale = mkOption { type = types.number; default = 1; }; transform = mkOption { type = types.enum [ 0 1 2 3 4 5 6 7 ]; default = 0; }; }; }); }; }; keybindings = mkOption { type = types.listOf keybinding; }; }; }; }; config = { system.activationScripts.script.text = '' cd /home/horseman/.config rm -r hypr/* touch hypr/hyprland.conf printf "# This file has been auto-generated. ${builtins.concatStringsSep "\n" (map (x: "exec-once = " + x) cfg.config.execOnce)} ${builtins.concatStringsSep "\n" (map (x: "env = " + x) cfg.config.env)} general { gaps_in = ${toString cfg.config.general.gapsIn} gaps_out = ${toString cfg.config.general.gapsOut} border_size = ${toString cfg.config.general.borderSize} col.active_border = ${cfg.config.general.col.activeBorder} col.inactive_border = ${cfg.config.general.col.inactiveBorder} resize_on_border = ${trivial.boolToString cfg.config.general.resizeOnBorder} allow_tearing = ${trivial.boolToString cfg.config.general.allowTearing} layout = ${cfg.config.general.layout} } decoration { rounding = ${toString cfg.config.decoration.rounding} active_opacity = ${strings.floatToString cfg.config.decoration.activeOpacity} inactive_opacity = ${strings.floatToString cfg.config.decoration.inactiveOpacity} shadow { enabled = ${trivial.boolToString cfg.config.decoration.shadow.enabled} range = ${toString cfg.config.decoration.shadow.range} render_power = ${toString cfg.config.decoration.shadow.renderPower} color = ${cfg.config.decoration.shadow.color} } blur { enabled = ${trivial.boolToString cfg.config.decoration.blur.enabled} size = ${toString cfg.config.decoration.blur.size} passes = ${toString cfg.config.decoration.blur.passes} vibrancy = ${strings.floatToString cfg.config.decoration.blur.vibrancy} } } animations { enabled = ${trivial.boolToString cfg.config.animations.enabled} ${builtins.concatStringsSep "\n " (map(bez: "bezier = ${bez.name}, ${strings.floatToString bez.startX}, ${strings.floatToString bez.startY}, ${strings.floatToString bez.endX}, ${strings.floatToString bez.endY}") cfg.config.animations.beziers)} ${builtins.concatStringsSep "\n " (map(anim: "animation = ${anim.name}, ${toString anim.on}, ${strings.floatToString anim.speed}, ${anim.curve}, ${replaceStrings ["%"] ["%%"] anim.style}") cfg.config.animations.animations)} } dwindle { pseudotile = ${trivial.boolToString cfg.config.dwindle.pseudotile} preserve_split = ${trivial.boolToString cfg.config.dwindle.preserveSplit} } master { new_status = ${cfg.config.master.newStatus} } misc { force_default_wallpaper = ${toString cfg.config.misc.forceDefaultWallpaper} } input { kb_layout = ${cfg.config.input.kbLayout} repeat_rate = ${toString cfg.config.input.repeatRate} repeat_delay = ${toString cfg.config.input.repeatDelay} follow_mouse = ${toString cfg.config.input.followMouse} sensitivity = ${strings.floatToString cfg.config.input.sensitivity} numlock_by_default = ${trivial.boolToString cfg.config.input.numlockByDefault} touchpad { natural_scroll = ${trivial.boolToString cfg.config.input.touchpad.naturalScroll} } } gestures { workspace_swipe = ${trivial.boolToString cfg.config.gestures.workspaceSwipe} } ${builtins.concatStringsSep "\n" (map (mon: "monitor = ${mon.output}, ${mon.resolution}@${mon.refreshRate}, ${toString mon.x}x${toString mon.y}, ${strings.floatToString mon.scale}, transform, ${toString mon.transform}") cfg.config.monitors.displays)} ${if cfg.config.monitors.defaultMonitor then "monitor = ,preferred, auto, auto" else ""} ${builtins.concatStringsSep "\n" (map (ws: "workspace = " + ws) cfg.config.workspaces)} ${builtins.concatStringsSep "\n" (map (wr: "windowrule = " + replaceStrings ["%"] ["%%"] wr) cfg.config.windowrules)} " >> hypr/hyprland.conf ''; }; }