diff --git a/modules/wm/hyprland/default.nix b/modules/wm/hyprland/default.nix index eaf6f32..aee2d30 100644 --- a/modules/wm/hyprland/default.nix +++ b/modules/wm/hyprland/default.nix @@ -5,13 +5,14 @@ ... }: let inherit (lib) mkIf; - cfg123 = config.horseman.wm.hyprland; + cfg = config.horseman.wm.hyprland; in { imports = [ ./options.nix + ./keybindings.nix ]; - config = mkIf cfg123.enable { + config = mkIf cfg.enable { programs.hyprland = { enable = true; xwayland.enable = true; @@ -47,12 +48,12 @@ in { "hyprpaper" "swaync" ]; - + env = [ "XCURSOR_SIZE,24" "HYPRCURSOR_SIZE,24" ]; - + windowrules = [ "suppressevent maximize, class:.*" "nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0" @@ -75,7 +76,7 @@ in { resizeOnBorder = true; allowTearing = false; - + col.activeBorder = "rgba(b7bdf8ff)"; col.inactiveBorder = "rgba(b7bdf840)"; diff --git a/modules/wm/hyprland/keybindings.nix b/modules/wm/hyprland/keybindings.nix new file mode 100644 index 0000000..0bfce32 --- /dev/null +++ b/modules/wm/hyprland/keybindings.nix @@ -0,0 +1,445 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + cfg = config.horseman.wm.hyprland; +in { + config = mkIf cfg.enable { + horseman.wm.hyprland.config.keybindings = [ + { + flags = []; + mods = ["SUPER"]; + key = "SPACE"; + dispatcher = "exec"; + params = "(eww close-all && pkill wofi) || (~/.config/eww/scripts/open.sh; wofi --show drun; eww close-all)"; + } + + { + flags = []; + mods = ["SUPER"]; + key = "RETURN"; + dispatcher = "exec"; + params = "kitty"; + } + + { + flags = []; + mods = ["SUPER"]; + key = "Q"; + dispatcher = "killactive"; + params = ""; + } + + { + flags = []; + mods = []; + key = "F11"; + dispatcher = "fullscreen"; + params = ""; + } + { + flags = ["o"]; + mods = ["SUPER"]; + key = "L"; + dispatcher = "exec"; + params = "hyprlock"; + } + { + flags = []; + mods = ["SUPER"]; + key = "F"; + dispatcher = "togglefloating"; + params = ""; + } + { + flags = []; + mods = ["SUPER"]; + key = "P"; + dispatcher = "pin"; + params = ""; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "S"; + dispatcher = "exec"; + params = "hyprshot -m region --clipboard-only"; + } + + { + flags = []; + mods = ["SUPER"]; + key = "H"; + dispatcher = "movefocus"; + params = "l"; + } + { + flags = []; + mods = ["SUPER"]; + key = "L"; + dispatcher = "movefocus"; + params = "r"; + } + { + flags = []; + mods = ["SUPER"]; + key = "K"; + dispatcher = "movefocus"; + params = "u"; + } + { + flags = []; + mods = ["SUPER"]; + key = "J"; + dispatcher = "movefocus"; + params = "d"; + } + + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "H"; + dispatcher = "movewindow"; + params = "l"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "L"; + dispatcher = "movewindow"; + params = "r"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "K"; + dispatcher = "movewindow"; + params = "u"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "J"; + dispatcher = "movewindow"; + params = "d"; + } + + { + flags = ["e"]; + mods = ["SUPER"]; + key = "Left"; + dispatcher = "moveactive"; + params = "-50 0"; + } + { + flags = ["e"]; + mods = ["SUPER"]; + key = "Right"; + dispatcher = "moveactive"; + params = "50 0"; + } + { + flags = ["e"]; + mods = ["SUPER"]; + key = "Up"; + dispatcher = "moveactive"; + params = "0 -50"; + } + { + flags = ["e"]; + mods = ["SUPER"]; + key = "Down"; + dispatcher = "moveactive"; + params = "0 50"; + } + + { + flags = ["e"]; + mods = ["SUPER" "SHIFT"]; + key = "Left"; + dispatcher = "resizeactive"; + params = "-50 0"; + } + { + flags = ["e"]; + mods = ["SUPER" "SHIFT"]; + key = "Right"; + dispatcher = "resizeactive"; + params = "50 0"; + } + { + flags = ["e"]; + mods = ["SUPER" "SHIFT"]; + key = "Up"; + dispatcher = "resizeactive"; + params = "0 -50"; + } + { + flags = ["e"]; + mods = ["SUPER" "SHIFT"]; + key = "Down"; + dispatcher = "resizeactive"; + params = "0 50"; + } + + { + flags = []; + mods = ["SUPER"]; + key = "1"; + dispatcher = "workspace"; + params = "1"; + } + { + flags = []; + mods = ["SUPER"]; + key = "2"; + dispatcher = "workspace"; + params = "2"; + } + { + flags = []; + mods = ["SUPER"]; + key = "3"; + dispatcher = "workspace"; + params = "3"; + } + { + flags = []; + mods = ["SUPER"]; + key = "4"; + dispatcher = "workspace"; + params = "4"; + } + { + flags = []; + mods = ["SUPER"]; + key = "5"; + dispatcher = "workspace"; + params = "5"; + } + { + flags = []; + mods = ["SUPER"]; + key = "6"; + dispatcher = "workspace"; + params = "6"; + } + { + flags = []; + mods = ["SUPER"]; + key = "7"; + dispatcher = "workspace"; + params = "7"; + } + { + flags = []; + mods = ["SUPER"]; + key = "8"; + dispatcher = "workspace"; + params = "8"; + } + { + flags = []; + mods = ["SUPER"]; + key = "9"; + dispatcher = "workspace"; + params = "9"; + } + { + flags = []; + mods = ["SUPER"]; + key = "0"; + dispatcher = "workspace"; + params = "10"; + } + + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "1"; + dispatcher = "movetoworkspace"; + params = "1"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "2"; + dispatcher = "movetoworkspace"; + params = "2"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "3"; + dispatcher = "movetoworkspace"; + params = "3"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "4"; + dispatcher = "movetoworkspace"; + params = "4"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "5"; + dispatcher = "movetoworkspace"; + params = "5"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "6"; + dispatcher = "movetoworkspace"; + params = "6"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "7"; + dispatcher = "movetoworkspace"; + params = "7"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "8"; + dispatcher = "movetoworkspace"; + params = "8"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "9"; + dispatcher = "movetoworkspace"; + params = "9"; + } + { + flags = []; + mods = ["SUPER" "SHIFT"]; + key = "0"; + dispatcher = "movetoworkspace"; + params = "10"; + } + + { + flags = []; + mods = ["SUPER" "CONTROL"]; + key = "Right"; + dispatcher = "workspace"; + params = "e+1"; + } + { + flags = []; + mods = ["SUPER" "CONTROL"]; + key = "Left"; + dispatcher = "workspace"; + params = "e-1"; + } + + { + flags = ["m"]; + mods = ["SUPER"]; + key = "mouse:272"; + dispatcher = "movewindow"; + params = ""; + } + { + flags = ["m"]; + mods = ["SUPER" "SHIFT"]; + key = "mouse:272"; + dispatcher = "resizewindow"; + params = ""; + } + + { + flags = ["e" "l"]; + mods = []; + key = "XF86AudioRaiseVolume"; + dispatcher = "exec"; + params = "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+"; + } + { + flags = ["e" "l"]; + mods = []; + key = "XF86AudioLowerVolume"; + dispatcher = "exec"; + params = "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%-"; + } + { + flags = ["e" "l"]; + mods = ["SHIFT"]; + key = "XF86AudioRaiseVolume"; + dispatcher = "exec"; + params = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+"; + } + { + flags = ["e" "l"]; + mods = ["SHIFT"]; + key = "XF86AudioLowerVolume"; + dispatcher = "exec"; + params = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-"; + } + { + flags = ["e" "l"]; + mods = []; + key = "XF86AudioMute"; + dispatcher = "exec"; + params = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + } + { + flags = ["e" "l"]; + mods = []; + key = "XF86AudioMicMute"; + dispatcher = "exec"; + params = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; + } + { + flags = ["e" "l"]; + mods = []; + key = "XF86MonBrightnessUp"; + dispatcher = "exec"; + params = "brightnessctl s 10%+"; + } + { + flags = ["e" "l"]; + mods = []; + key = "XF86MonBrightnessDown"; + dispatcher = "exec"; + params = "brightnessctl s 10%-"; + } + { + flags = ["l"]; + mods = []; + key = "XF86AudioNext"; + dispatcher = "exec"; + params = "playerctl next"; + } + { + flags = ["l"]; + mods = []; + key = "XF86AudioPause"; + dispatcher = "exec"; + params = "playerctl play-pause"; + } + { + flags = ["l"]; + mods = []; + key = "XF86AudioPlay"; + dispatcher = "exec"; + params = "playerctl play-pause"; + } + { + flags = ["l"]; + mods = []; + key = "XF86AudioPrev"; + dispatcher = "exec"; + params = "playerctl previous"; + } + ]; + }; +} diff --git a/modules/wm/hyprland/options.nix b/modules/wm/hyprland/options.nix index 125c3da..6e541de 100644 --- a/modules/wm/hyprland/options.nix +++ b/modules/wm/hyprland/options.nix @@ -1,21 +1,22 @@ { lib, config, + pkgs, ... }: let - inherit (lib) mkEnableOption mkOption types trivial strings replaceStrings; + inherit (lib) mkEnableOption mkOption mkIf types trivial strings replaceStrings; + inherit (builtins) concatStringsSep elem; 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 = []; + type = types.listOf (types.enum ["l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p"]); }; mods = mkOption { type = types.listOf types.str; }; - + key = mkOption { type = types.str; }; @@ -35,42 +36,42 @@ in { 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; }; + 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"]; }; + 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; }; + 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; }; + 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; }; + enabled = mkOption {type = types.bool;}; + size = mkOption {type = types.int;}; + passes = mkOption {type = types.int;}; + vibrancy = mkOption {type = types.float;}; }; }; @@ -96,9 +97,18 @@ in { 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 = "";}; + speed = mkOption { + type = types.number; + default = 0; + }; + curve = mkOption { + type = types.str; + default = ""; + }; + style = mkOption { + type = types.str; + default = ""; + }; }; }); }; @@ -122,7 +132,7 @@ in { misc = { forceDefaultWallpaper = mkOption { - type = types.enum [ 0 1 2 (-1) ]; + type = types.enum [0 1 2 (-1)]; }; }; @@ -140,7 +150,7 @@ in { }; followMouse = mkOption { - type = types.enum [ 0 1 2 3 ]; + type = types.enum [0 1 2 3]; }; sensitivity = mkOption { @@ -172,13 +182,25 @@ in { 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; }; + 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; + }; }; }); }; @@ -191,96 +213,105 @@ in { }; }; - config = { - system.activationScripts.script.text = '' - cd /home/horseman/.config - rm -r hypr/* - touch hypr/hyprland.conf + config = mkIf cfg.enable { + generatedHyprlandConf = pkgs.writeTextFile { + name = "hyprland.conf"; + text = '' + # This file has been auto-generated. - printf "# This file has been auto-generated. + ${concatStringsSep "\n" (map (kb: "bind${concatStringsSep "" kb.flags} = ${concatStringsSep " " kb.mods}, ${kb.key}, ${kb.dispatcher}${ + if (elem "m" kb.flags) # Mouse binds take one argument less + then "" + else ", ${replaceStrings ["%"] ["%%"] kb.params}" + }") + cfg.config.keybindings)} - ${builtins.concatStringsSep "\n" (map (x: "exec-once = " + x) cfg.config.execOnce)} + ${concatStringsSep "\n" (map (x: "exec-once = " + x) cfg.config.execOnce)} - ${builtins.concatStringsSep "\n" (map (x: "env = " + x) cfg.config.env)} + ${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} - } + 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} + decoration { + rounding = ${toString cfg.config.decoration.rounding} - active_opacity = ${strings.floatToString cfg.config.decoration.activeOpacity} - inactive_opacity = ${strings.floatToString cfg.config.decoration.inactiveOpacity} + 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} - } + 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} - } - } + 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} + 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)} + ${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)} - } + ${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} - } + dwindle { + pseudotile = ${trivial.boolToString cfg.config.dwindle.pseudotile} + preserve_split = ${trivial.boolToString cfg.config.dwindle.preserveSplit} + } - master { - new_status = ${cfg.config.master.newStatus} - } + master { + new_status = ${cfg.config.master.newStatus} + } - misc { - force_default_wallpaper = ${toString cfg.config.misc.forceDefaultWallpaper} - } + 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} + 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} - } - } + touchpad { + natural_scroll = ${trivial.boolToString cfg.config.input.touchpad.naturalScroll} + } + } - gestures { - workspace_swipe = ${trivial.boolToString cfg.config.gestures.workspaceSwipe} - } + 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)} + ${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 ""} + ${ + if cfg.config.monitors.defaultMonitor + then "monitor = ,preferred, auto, auto" + else "" + } - ${builtins.concatStringsSep "\n" (map (ws: "workspace = " + ws) cfg.config.workspaces)} + ${concatStringsSep "\n" (map (ws: "workspace = " + ws) cfg.config.workspaces)} - ${builtins.concatStringsSep "\n" (map (wr: "windowrule = " + replaceStrings ["%"] ["%%"] wr) cfg.config.windowrules)} - " >> hypr/hyprland.conf - ''; + ${concatStringsSep "\n" (map (wr: "windowrule = " + replaceStrings ["%"] ["%%"] wr) cfg.config.windowrules)} + ''; + }; }; }