me like nix
1{ inputs, ... }:
2
3{
4 flake.modules.nixos.desktop =
5 { pkgs, lib, ... }:
6 {
7 programs.niri.enable = true;
8
9 catppuccin = {
10 enable = true;
11 flavor = "frappe";
12 };
13
14 programs.regreet = {
15 enable = true;
16 cageArgs = [
17 "-s"
18 "-d"
19 ];
20 settings.GTK.application_prefer_dark_theme = true;
21 theme = {
22 package = pkgs.catppuccin-gtk.override {
23 variant = "frappe";
24 accents = [ "lavender" ];
25 size = "standard";
26 };
27 name = "catppuccin-frappe-lavender-standard";
28 };
29 iconTheme = {
30 package = pkgs.catppuccin-papirus-folders.override {
31 flavor = "frappe";
32 accent = "lavender";
33 };
34 name = "Papirus-Dark";
35 };
36 cursorTheme = {
37 package = pkgs.catppuccin-cursors.frappeDark;
38 name = "catppuccin-frappe-dark-cursors";
39 };
40 };
41
42 # Scale regreet's greeter for HiDPI displays
43 services.greetd.settings.default_session.command = lib.mkForce
44 "${pkgs.dbus}/bin/dbus-run-session ${lib.getExe pkgs.cage} -s -d -- env GDK_SCALE=2 ${lib.getExe pkgs.greetd.regreet}";
45
46 # ZSA Keyboard udev rules for Oryx web flashing and live training
47 services.udev.extraRules = ''
48 # Rules for Oryx web flashing and live training
49 KERNEL=="hidraw*", ATTRS{idVendor}=="16c0", MODE="0664", GROUP="plugdev"
50 KERNEL=="hidraw*", ATTRS{idVendor}=="3297", MODE="0664", GROUP="plugdev"
51
52 # Legacy rules for live training over webusb (Not needed for firmware v21+)
53 # Rule for all ZSA keyboards
54 SUBSYSTEM=="usb", ATTR{idVendor}=="3297", GROUP="plugdev"
55 # Rule for the Moonlander
56 SUBSYSTEM=="usb", ATTR{idVendor}=="3297", ATTR{idProduct}=="1969", GROUP="plugdev"
57 # Rule for the Ergodox EZ
58 SUBSYSTEM=="usb", ATTR{idVendor}=="feed", ATTR{idProduct}=="1307", GROUP="plugdev"
59 # Rule for the Planck EZ
60 SUBSYSTEM=="usb", ATTR{idVendor}=="feed", ATTR{idProduct}=="6060", GROUP="plugdev"
61
62 # Wally Flashing rules for the Ergodox EZ
63 ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1"
64 ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1"
65 SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", MODE:="0666"
66 KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", MODE:="0666"
67
68 # Keymapp / Wally Flashing rules for the Moonlander and Planck EZ
69 SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666", SYMLINK+="stm32_dfu"
70 # Keymapp Flashing rules for the Voyager
71 SUBSYSTEMS=="usb", ATTRS{idVendor}=="3297", MODE:="0666", SYMLINK+="ignition_dfu"
72 # USB serial device access via Chrome/Chromium
73 KERNEL=="ttyUSB[0-9]*", MODE:="0666", GROUP="dialout"
74 KERNEL=="ttyACM[0-9]*", MODE:="0666", GROUP="dialout"
75 '';
76 };
77
78 flake.modules.homeManager.desktop =
79 { pkgs, config, ... }:
80 let
81 wallpapers = import ./_data/wallpapers.nix;
82 downloads = builtins.concatStringsSep "\n" (
83 map (wp: ''
84 if [ ! -f "$DIR/${wp.filename}" ]; then
85 echo "Downloading ${wp.filename}..."
86 ${pkgs.curl}/bin/curl -fsSL -o "$DIR/${wp.filename}" ${
87 builtins.replaceStrings [ "\"" ] [ "\\\"" ] wp.url
88 } || echo "WARNING: Failed to download ${wp.filename}, skipping"
89 fi
90 '') wallpapers
91 );
92 in
93 {
94 home.packages = with pkgs; [
95 inputs.fsel.packages.${pkgs.system}.default
96 inputs.mako-tui.packages.${pkgs.system}.default
97 bemoji
98 networkmanager_dmenu
99 quickshell
100 inputs.kaleidux.packages.${pkgs.system}.default
101 (import ../packages/cclip.nix { inherit pkgs; })
102 pavucontrol
103 playerctl
104 xwayland-satellite
105 ];
106
107 programs.niri = {
108 enable = true;
109 settings = {
110 window-rules = [
111 {
112 geometry-corner-radius = {
113 top-left = 5.0;
114 top-right = 5.0;
115 bottom-left = 5.0;
116 bottom-right = 5.0;
117 };
118 clip-to-geometry = true;
119 draw-border-with-background = false;
120 }
121 {
122 matches = [ { app-id = "^steam_app_"; } ];
123 border.enable = false;
124 open-fullscreen = true;
125 }
126 {
127 matches = [ { app-id = "^fsel$"; } ];
128 open-floating = true;
129 default-column-width.fixed = 800;
130 default-window-height.fixed = 500;
131 }
132 {
133 matches = [ { app-id = "^mako-tui$"; } ];
134 open-floating = true;
135 default-column-width.fixed = 800;
136 default-window-height.fixed = 500;
137 }
138 ];
139 debug = {
140 honor-xdg-activation-with-invalid-serial = { };
141 };
142 layout = {
143 focus-ring = {
144 width = 2;
145 active.color = "#8caaee";
146 inactive.color = "#414559";
147 };
148 struts = {
149 top = -6;
150 bottom = -6;
151 left = 0;
152 right = 0;
153 };
154 gaps = 8;
155 };
156 gestures = {
157 hot-corners = {
158 enable = false;
159 };
160 };
161 binds = {
162 "Mod+d".action.spawn = [
163 "alacritty"
164 "--class"
165 "fsel"
166 "-e"
167 "fsel"
168 "--detach"
169 ];
170 "Mod+c".action.spawn = [
171 "alacritty"
172 "--class"
173 "fsel"
174 "-e"
175 "fsel"
176 "--cclip"
177 ];
178 "Mod+e".action.spawn = "bemoji";
179 "Mod+n".action.spawn = [
180 "alacritty"
181 "--class"
182 "mako-tui"
183 "-e"
184 "mako-tui"
185 ];
186 "Mod+a".action.spawn = "alacritty";
187 "Mod+h".action = {
188 focus-column-left = { };
189 };
190 "Mod+j".action = {
191 focus-workspace-down = { };
192 };
193 "Mod+k".action = {
194 focus-workspace-up = { };
195 };
196 "Mod+l".action = {
197 focus-column-right = { };
198 };
199 "Mod+Shift+h".action = {
200 move-column-left = { };
201 };
202 "Mod+Shift+j".action = {
203 move-window-down-or-to-workspace-down = { };
204 };
205 "Mod+Shift+k".action = {
206 move-window-up-or-to-workspace-up = { };
207 };
208 "Mod+Shift+l".action = {
209 move-column-right = { };
210 };
211 "Mod+Down".action = {
212 move-workspace-down = { };
213 };
214 "Mod+Up".action = {
215 move-workspace-up = { };
216 };
217 "Mod+p".action = {
218 show-hotkey-overlay = { };
219 };
220 "Mod+o".action = {
221 toggle-overview = { };
222 };
223 "Mod+q".action = {
224 close-window = { };
225 };
226 "Mod+f".action = {
227 toggle-window-floating = { };
228 };
229 "Mod+Shift+f".action = {
230 switch-focus-between-floating-and-tiling = { };
231 };
232 "Mod+m".action = {
233 fullscreen-window = { };
234 };
235 "Mod+s".action = {
236 screenshot = {
237 show-pointer = true;
238 };
239 };
240 "Mod+1".action = {
241 set-column-width = "100%";
242 };
243 "Mod+2".action = {
244 set-column-width = "50%";
245 };
246 "Mod+Minus".action = {
247 set-column-width = "-10%";
248 };
249 "Mod+Equal".action = {
250 set-column-width = "+10%";
251 };
252 "Mod+Shift+q".action = {
253 quit = { };
254 };
255 "Mod+Shift+r".action.spawn = [
256 "systemctl"
257 "--user"
258 "restart"
259 "quickshell.service"
260 ];
261 "XF86AudioPlay".action.spawn = [
262 "playerctl"
263 "play-pause"
264 ];
265 "XF86AudioStop".action.spawn = [
266 "playerctl"
267 "stop"
268 ];
269 "XF86AudioNext".action.spawn = [
270 "playerctl"
271 "next"
272 ];
273 "XF86AudioPrev".action.spawn = [
274 "playerctl"
275 "previous"
276 ];
277 "XF86MonBrightnessDown".action.spawn = [
278 "brightnessctl"
279 "set"
280 "5%-"
281 ];
282 "XF86MonBrightnessUp".action.spawn = [
283 "brightnessctl"
284 "set"
285 "+5%"
286 ];
287 };
288 outputs = {
289 "DP-5" = {
290 scale = 2.0;
291 mode = {
292 width = 5120;
293 height = 2160;
294 refresh = 120.0;
295 };
296 position = {
297 x = 0;
298 y = 0;
299 };
300 };
301 "DP-1" = {
302 scale = 2.0;
303 mode = {
304 width = 5120;
305 height = 2160;
306 refresh = 120.0;
307 };
308 position = {
309 x = 0;
310 y = 0;
311 };
312 };
313 "DP-2" = {
314 scale = 1.0;
315 mode = {
316 width = 5120;
317 height = 2160;
318 refresh = 120.0;
319 };
320 position = {
321 x = 0;
322 y = 0;
323 };
324 };
325 "DP-6" = {
326 scale = 2.0;
327 mode = {
328 width = 5120;
329 height = 2160;
330 refresh = 120.0;
331 };
332 position = {
333 x = 0;
334 y = 0;
335 };
336 };
337 "DP-7" = {
338 scale = 2.0;
339 mode = {
340 width = 5120;
341 height = 2160;
342 refresh = 120.0;
343 };
344 position = {
345 x = 0;
346 y = 0;
347 };
348 };
349 "eDP-1" = {
350 scale = 1.5;
351 mode = {
352 width = 2560;
353 height = 1600;
354 refresh = 165.0;
355 };
356 position = {
357 x = 0;
358 y = 1080;
359 };
360 };
361 };
362 spawn-at-startup = [
363 { command = [ "xwayland-satellite" ]; }
364 { command = [ "cclipd" ]; }
365 ];
366 environment = {
367 DISPLAY = ":0";
368 };
369 };
370 };
371
372 catppuccin = {
373 enable = true;
374 flavor = "frappe";
375 };
376
377 # Wallpaper downloads
378 home.activation.downloadWallpapers =
379 config.lib.dag.entryAfter [ "writeBoundary" ] ''
380 DIR="${config.home.homeDirectory}/Pictures/Wallpapers"
381 mkdir -p "$DIR"
382 ${downloads}
383 '';
384
385 # Kaleidux wallpaper daemon config
386 xdg.configFile."kaleidux/config.toml".text = ''
387 [global]
388 monitor-behavior = "independent"
389 video-ratio = 50
390 sorting = "loveit"
391 transition-time = 1000
392
393 [any]
394 path = "${config.home.homeDirectory}/Pictures/Wallpapers"
395 duration = "15m"
396 transition = { type = "fade" }
397 '';
398
399 # Quickshell status bar
400 xdg.configFile."quickshell" = {
401 source = ./_config/quickshell;
402 recursive = true;
403 };
404
405 systemd.user.services.kaleidux = {
406 Unit = {
407 Description = "Kaleidux dynamic wallpaper daemon";
408 After = [ "graphical-session.target" ];
409 PartOf = [ "graphical-session.target" ];
410 };
411 Service = {
412 ExecStart = "${inputs.kaleidux.packages.${pkgs.system}.default}/bin/kaleidux-daemon";
413 Restart = "on-failure";
414 RestartSec = 2;
415 };
416 Install = {
417 WantedBy = [ "graphical-session.target" ];
418 };
419 };
420
421 systemd.user.services.quickshell = {
422 Unit = {
423 Description = "QuickShell status bar";
424 After = [ "graphical-session.target" ];
425 PartOf = [ "graphical-session.target" ];
426 };
427 Service = {
428 ExecStart = "${pkgs.quickshell}/bin/quickshell";
429 Restart = "on-failure";
430 RestartSec = 2;
431 };
432 Install = {
433 WantedBy = [ "graphical-session.target" ];
434 };
435 };
436
437 systemd.user.services.quickshell-reload = {
438 Unit = {
439 Description = "Reload QuickShell on wake or display change";
440 After = [
441 "quickshell.service"
442 "graphical-session.target"
443 ];
444 PartOf = [ "graphical-session.target" ];
445 };
446 Service = {
447 Type = "simple";
448 ExecStart = "${pkgs.writeShellScript "quickshell-reload" ''
449 LOCKFILE="/tmp/quickshell-reload.lock"
450
451 do_restart() {
452 (
453 ${pkgs.util-linux}/bin/flock -xn 200 || exit 0
454 sleep 2
455 ${pkgs.systemd}/bin/systemctl --user restart quickshell.service
456 sleep 3
457 ) 200>"$LOCKFILE"
458 }
459
460 # Sleep/wake monitor
461 ${pkgs.dbus}/bin/dbus-monitor --system \
462 "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'" 2>/dev/null | \
463 while IFS= read -r line; do
464 if [[ "$line" == *"boolean false"* ]]; then
465 do_restart
466 fi
467 done &
468
469 # Display hotplug monitor
470 ${pkgs.systemd}/bin/udevadm monitor --property --subsystem-match=drm 2>/dev/null | \
471 while IFS= read -r line; do
472 if [[ "$line" == *"HOTPLUG=1"* ]]; then
473 do_restart
474 fi
475 done &
476
477 wait
478 ''}";
479 Restart = "on-failure";
480 RestartSec = 5;
481 };
482 Install = {
483 WantedBy = [ "graphical-session.target" ];
484 };
485 };
486
487 services.udiskie = {
488 enable = true;
489 tray = "never";
490 automount = true;
491 };
492
493 services.mako = {
494 enable = true;
495 settings = {
496 border-radius = 8;
497 border-size = 2;
498 padding = "12";
499 margin = "12";
500 font = "BerkeleyMono Nerd Font 11";
501 on-button-left = "invoke-default-action";
502 on-button-right = "dismiss";
503 };
504 };
505
506 dconf.settings = {
507 "org/gnome/desktop/interface" = {
508 color-scheme = "prefer-dark";
509 enable-hot-corners = false;
510 };
511 };
512
513 home.pointerCursor = {
514 name = "Adwaita";
515 package = pkgs.adwaita-icon-theme;
516 size = 16;
517 x11.enable = true;
518 gtk.enable = true;
519 };
520 };
521}