Skyler Grey | 69a999e | 2024-05-23 00:09:10 +0000 | [diff] [blame^] | 1 | { |
| 2 | pkgs, |
| 3 | config, |
| 4 | inputs, |
| 5 | system, |
| 6 | lib, |
| 7 | ... |
| 8 | }: { |
| 9 | |
| 10 | options.chimera.niri = { |
| 11 | enable = lib.mkEnableOption "Use Niri as your window manager"; |
| 12 | monitors = lib.mkOption { |
| 13 | type = lib.types.attrsOf (lib.types.submodule { |
| 14 | options = { |
| 15 | enable = lib.mkOption { |
| 16 | type = lib.types.bool; |
| 17 | default = true; |
| 18 | description = "Enable this monitor"; |
| 19 | }; |
| 20 | mode = lib.mkOption { |
| 21 | type = lib.types.nullOr (lib.types.submodule { |
| 22 | options = { |
| 23 | width = lib.mkOption { |
| 24 | type = lib.types.int; |
| 25 | }; |
| 26 | height = lib.mkOption { |
| 27 | type = lib.types.int; |
| 28 | }; |
| 29 | refresh = lib.mkOption { |
| 30 | type = lib.types.nullOr lib.types.float; |
| 31 | default = null; |
| 32 | }; |
| 33 | }; |
| 34 | }); |
| 35 | default = null; |
| 36 | }; |
| 37 | position = lib.mkOption { |
| 38 | type = lib.types.nullOr (lib.types.submodule { |
| 39 | options = { |
| 40 | x = lib.mkOption { |
| 41 | type = lib.types.int; |
| 42 | }; |
| 43 | y = lib.mkOption { |
| 44 | type = lib.types.int; |
| 45 | }; |
| 46 | }; |
| 47 | }); |
| 48 | default = null; |
| 49 | }; |
| 50 | scale = lib.mkOption { |
| 51 | type = lib.types.float; |
| 52 | default = 1.; |
| 53 | }; |
| 54 | transform = { |
| 55 | flipped = lib.mkOption { |
| 56 | type = lib.types.bool; |
| 57 | default = false; |
| 58 | }; |
| 59 | rotation = lib.mkOption { |
| 60 | type = lib.types.enum [ 0 90 180 270 ]; |
| 61 | default = 0; |
| 62 | }; |
| 63 | }; |
| 64 | variable-refresh-rate = lib.mkEnableOption "Enable Variable Refresh Rate (AMD FreeSync / Nvidia G-Sync)"; |
| 65 | }; |
| 66 | }); |
| 67 | description = "Atribute set of monitors"; |
| 68 | default = { }; |
| 69 | }; |
| 70 | }; |
| 71 | |
| 72 | config = lib.mkIf config.chimera.niri.enable { |
| 73 | chimera.wayland.enable = true; |
| 74 | |
| 75 | programs.bash.profileExtra = lib.mkIf config.chimera.shell.bash.enable (lib.mkBefore '' |
| 76 | if [ -z $WAYLAND_DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then |
| 77 | exec ${pkgs.systemd}/bin/systemd-cat -t niri ${pkgs.dbus}/bin/dbus-run-session ${config.programs.niri.package}/bin/niri --session |
| 78 | fi |
| 79 | ''); |
| 80 | |
| 81 | programs.zsh.profileExtra = lib.mkIf config.chimera.shell.zsh.enable (lib.mkBefore '' |
| 82 | if [ -z $WAYLAND_DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then |
| 83 | exec ${pkgs.systemd}/bin/systemd-cat -t niri ${pkgs.dbus}/bin/dbus-run-session ${config.programs.niri.package}/bin/niri --session |
| 84 | fi |
| 85 | ''); |
| 86 | |
| 87 | home.sessionVariables.NIXOS_OZONE_WL = "1"; |
| 88 | |
| 89 | programs.niri = let |
| 90 | mod = "Super"; |
| 91 | mod1 = "Alt"; |
| 92 | terminal = "${pkgs.kitty}/bin/kitty"; |
| 93 | menu = (if config.chimera.runner.anyrun.enable then "${inputs.anyrun.packages.${system}.anyrun}/bin/anyrun" else ""); |
| 94 | |
| 95 | lock = ''${pkgs.swaylock}/bin/swaylock -i ${config.chimera.theme.wallpaper} -s fill''; |
| 96 | in { |
| 97 | enable = true; |
| 98 | package = pkgs.niri-stable; |
| 99 | settings = { |
| 100 | input.keyboard = { |
| 101 | track-layout = "window"; |
| 102 | repeat-delay = 200; |
| 103 | repeat-rate = 25; |
| 104 | xkb = { |
| 105 | layout = config.chimera.input.keyboard.layout; |
| 106 | variant = config.chimera.input.keyboard.variant; |
| 107 | }; |
| 108 | }; |
| 109 | |
| 110 | input.mouse.natural-scroll = config.chimera.input.mouse.scrolling.natural; |
| 111 | input.touchpad.natural-scroll = config.chimera.input.touchpad.scrolling.natural; |
| 112 | |
| 113 | input.warp-mouse-to-focus = true; |
| 114 | input.focus-follows-mouse = true; |
| 115 | |
| 116 | input.power-key-handling.enable = false; |
| 117 | |
| 118 | binds = let |
| 119 | inherit (config.lib.niri) actions; |
| 120 | |
| 121 | generateWorkspaceBindings = workspaceNumber: { |
| 122 | "${mod}+${builtins.toString (lib.mod workspaceNumber 10)}".action = actions.focus-workspace workspaceNumber; |
| 123 | "${mod}+Shift+${builtins.toString (lib.mod workspaceNumber 10)}".action = actions.move-column-to-workspace workspaceNumber; |
| 124 | }; |
| 125 | joinAttrsetList = listOfAttrsets: lib.fold (a: b: a // b) {} listOfAttrsets; |
| 126 | in { # General Keybinds |
| 127 | "${mod}+Q".action = actions.close-window; |
| 128 | "${mod}+Return".action = actions.spawn "${terminal}"; |
| 129 | "${mod}+L".action = actions.spawn ["sh" "-c" "${config.programs.niri.package}/bin/niri msg action do-screen-transition && ${lock}"]; |
| 130 | "${mod}+P".action = actions.power-off-monitors; |
| 131 | |
| 132 | "${mod}+R".action = actions.screenshot; |
| 133 | "${mod}+Ctrl+R".action = actions.screenshot-screen; |
| 134 | "${mod}+Shift+R".action = actions.screenshot-window; |
| 135 | "Print".action = actions.screenshot; |
| 136 | "Ctrl+Print".action = actions.screenshot-screen; |
| 137 | "Shift+Print".action = actions.screenshot-window; |
| 138 | |
| 139 | "${mod}+Space".action = actions."switch-layout" "next"; |
| 140 | "${mod}+Shift+Space".action = actions."switch-layout" "prev"; |
| 141 | |
| 142 | "${mod}+D" = lib.mkIf config.chimera.runner.enable { action = actions.spawn "${menu}"; }; |
| 143 | "Alt+Space" = lib.mkIf ( |
| 144 | config.chimera.runner.enable |
| 145 | && config.chimera.input.keybinds.alternativeSearch.enable |
| 146 | ) { action = actions.spawn "${menu}"; }; |
| 147 | "${mod}+Shift+Slash".action = actions.show-hotkey-overlay; |
| 148 | } // ( # Workspace Keybinds |
| 149 | lib.pipe (lib.range 1 10) [ |
| 150 | (map generateWorkspaceBindings) |
| 151 | joinAttrsetList |
| 152 | ] |
| 153 | ) // ( # Window Manipulation Bindings |
| 154 | { |
| 155 | "${mod}+BracketLeft".action = actions."consume-or-expel-window-left"; |
| 156 | "${mod}+BracketRight".action = actions."consume-or-expel-window-right"; |
| 157 | "${mod}+Shift+BracketLeft".action = actions."consume-window-into-column"; |
| 158 | "${mod}+Shift+BracketRight".action = actions."expel-window-from-column"; |
| 159 | "${mod}+Slash".action = actions."switch-preset-column-width"; |
| 160 | "${mod}+${mod1}+F".action = actions."fullscreen-window"; |
| 161 | |
| 162 | # Focus |
| 163 | "${mod}+Up".action = actions."focus-window-or-workspace-up"; |
| 164 | "${mod}+Down".action = actions."focus-window-or-workspace-down"; |
| 165 | |
| 166 | # Non Jump Movement |
| 167 | "${mod}+Shift+Up".action = actions."move-window-up-or-to-workspace-up"; |
| 168 | "${mod}+Shift+Down".action = actions."move-window-down-or-to-workspace-down"; |
| 169 | "${mod}+Shift+Left".action = actions."consume-or-expel-window-left"; |
| 170 | "${mod}+Shift+Right".action = actions."consume-or-expel-window-right"; |
| 171 | |
| 172 | # To Monitor |
| 173 | "${mod}+Shift+Ctrl+Up".action = actions."move-window-to-monitor-up"; |
| 174 | "${mod}+Shift+Ctrl+Down".action = actions."move-window-to-monitor-down"; |
| 175 | "${mod}+Shift+Ctrl+Left".action = actions."move-window-to-monitor-left"; |
| 176 | "${mod}+Shift+Ctrl+Right".action = actions."move-window-to-monitor-right"; |
| 177 | |
| 178 | # To Workspace |
| 179 | "${mod}+Ctrl+Up".action = actions."move-window-to-workspace-up"; |
| 180 | "${mod}+Ctrl+Down".action = actions."move-window-to-workspace-down"; |
| 181 | |
| 182 | # Sizing |
| 183 | "${mod}+Equal".action = actions."set-window-height" "+5%"; |
| 184 | "${mod}+Minus".action = actions."set-window-height" "-5%"; |
| 185 | }) // ( # Column Manipulation Bindings |
| 186 | { |
| 187 | # Focus |
| 188 | "${mod}+Left".action = actions."focus-column-left"; |
| 189 | "${mod}+Right".action = actions."focus-column-right"; |
| 190 | "${mod}+${mod1}+C".action = actions."center-column"; |
| 191 | "${mod}+F".action = actions."maximize-column"; |
| 192 | |
| 193 | # Non Monitor Movement |
| 194 | "${mod}+${mod1}+Shift+Up".action = actions."move-column-to-workspace-up"; |
| 195 | "${mod}+${mod1}+Shift+Down".action = actions."move-column-to-workspace-down"; |
| 196 | "${mod}+${mod1}+Shift+Left".action = actions."move-column-left"; |
| 197 | "${mod}+${mod1}+Shift+Right".action = actions."move-column-right"; |
| 198 | |
| 199 | # To Monitor |
| 200 | "${mod}+${mod1}+Shift+Ctrl+Up".action = actions."move-column-to-monitor-up"; |
| 201 | "${mod}+${mod1}+Shift+Ctrl+Down".action = actions."move-column-to-monitor-down"; |
| 202 | "${mod}+${mod1}+Shift+Ctrl+Left".action = actions."move-column-to-monitor-left"; |
| 203 | "${mod}+${mod1}+Shift+Ctrl+Right".action = actions."move-column-to-monitor-right"; |
| 204 | |
| 205 | # Sizing |
| 206 | "${mod}+${mod1}+Equal".action = actions."set-column-width" "+5%"; |
| 207 | "${mod}+${mod1}+Minus".action = actions."set-column-width" "-5%"; |
| 208 | }) // ( # Workspace Manipulation Bindings |
| 209 | { |
| 210 | # Focus |
| 211 | "${mod}+Page_Up".action = actions."focus-workspace-up"; |
| 212 | "${mod}+Page_Down".action = actions."focus-workspace-down"; |
| 213 | |
| 214 | # Within Itself |
| 215 | "${mod}+Shift+Page_Up".action = actions."move-workspace-up"; |
| 216 | "${mod}+Shift+Page_Down".action = actions."move-workspace-down"; |
| 217 | |
| 218 | # To Monitor |
| 219 | "${mod}+Shift+Ctrl+Page_Up".action = actions."move-workspace-to-monitor-up"; |
| 220 | "${mod}+Shift+Ctrl+Page_Down".action = actions."move-workspace-to-monitor-down"; |
| 221 | "${mod}+Shift+Ctrl+Home".action = actions."move-workspace-to-monitor-left"; |
| 222 | "${mod}+Shift+Ctrl+End".action = actions."move-workspace-to-monitor-right"; |
| 223 | }) // { # Audio |
| 224 | "XF86AudioRaiseVolume" = { |
| 225 | allow-when-locked = true; |
| 226 | action = actions.spawn "${pkgs.wireplumber}/bin/wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05+"; |
| 227 | }; |
| 228 | "XF86AudioLowerVolume" = { |
| 229 | allow-when-locked = true; |
| 230 | action = actions.spawn "${pkgs.wireplumber}/bin/wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05-"; |
| 231 | }; |
| 232 | "XF86AudioMute" = { |
| 233 | allow-when-locked = true; |
| 234 | action = actions.spawn "${pkgs.wireplumber}/bin/wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; |
| 235 | }; |
| 236 | "XF86AudioMicMute" = { |
| 237 | allow-when-locked = true; |
| 238 | action = actions.spawn "${pkgs.wireplumber}/bin/wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; |
| 239 | }; |
| 240 | }; |
| 241 | |
| 242 | outputs = config.chimera.niri.monitors; |
| 243 | |
| 244 | cursor = { |
| 245 | size = config.chimera.theme.cursor.size; |
| 246 | theme = config.chimera.theme.cursor.name; |
| 247 | }; |
| 248 | |
| 249 | layout = { |
| 250 | gaps = 16; |
| 251 | |
| 252 | center-focused-column = "on-overflow"; |
| 253 | |
| 254 | preset-column-widths = [ |
| 255 | { proportion = 1. / 4.; } |
| 256 | { proportion = 1. / 3.; } |
| 257 | { proportion = 1. / 2.; } |
| 258 | { proportion = 2. / 3.; } |
| 259 | ]; # TODO: clicks to PR a docs update for niri-flake |
| 260 | }; |
| 261 | |
| 262 | prefer-no-csd = true; # No "client-side-decorations" (i.e. client-side window open/close buttons) |
| 263 | hotkey-overlay.skip-at-startup = true; |
| 264 | screenshot-path = null; |
| 265 | |
| 266 | spawn-at-startup = [ |
| 267 | { |
| 268 | command = [ "${pkgs.waybar}/bin/waybar" ]; |
| 269 | } |
| 270 | { |
| 271 | command = [ "${pkgs.swaybg}/bin/swaybg" "-i" "${config.chimera.theme.wallpaper}" "-m" "fill" ]; |
| 272 | } |
| 273 | ]; |
| 274 | }; |
| 275 | }; |
| 276 | }; |
| 277 | } |