blob: 06952731483f3aeda69e9dbc7f7c32e823a45b9e [file] [log] [blame]
Skyler Grey69a999e2024-05-23 00:09:10 +00001{
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}