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.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 kaleiduxBase = inputs.kaleidux.packages.${pkgs.stdenv.hostPlatform.system}.default;
82 dav1dOverride = old: {
83 buildInputs = (old.buildInputs or [ ]) ++ [ pkgs.dav1d ];
84 };
85 kaleiduxDeps = (builtins.head kaleiduxBase.builtDependencies).overrideAttrs dav1dOverride;
86 kaleidux = kaleiduxBase.overrideAttrs (old: (dav1dOverride old) // {
87 builtDependencies = [ kaleiduxDeps ];
88 });
89 wallpapers = import ./_data/wallpapers.nix;
90 downloads = builtins.concatStringsSep "\n" (
91 map (wp: ''
92 if [ ! -f "$DIR/${wp.filename}" ]; then
93 echo "Downloading ${wp.filename}..."
94 ${pkgs.curl}/bin/curl -fsSL -o "$DIR/${wp.filename}" ${
95 builtins.replaceStrings [ "\"" ] [ "\\\"" ] wp.url
96 } || echo "WARNING: Failed to download ${wp.filename}, skipping"
97 fi
98 '') wallpapers
99 );
100 in
101 {
102 home.packages = with pkgs; [
103 inputs.fsel.packages.${pkgs.stdenv.hostPlatform.system}.default
104 inputs.mako-tui.packages.${pkgs.stdenv.hostPlatform.system}.default
105 bemoji
106 networkmanager_dmenu
107 quickshell
108 kaleidux
109 (import ../packages/cclip.nix { inherit pkgs; })
110 pavucontrol
111 playerctl
112 xwayland-satellite
113 ];
114
115 programs.niri = {
116 enable = true;
117 settings = {
118 window-rules = [
119 {
120 geometry-corner-radius = {
121 top-left = 5.0;
122 top-right = 5.0;
123 bottom-left = 5.0;
124 bottom-right = 5.0;
125 };
126 clip-to-geometry = true;
127 draw-border-with-background = false;
128 }
129 {
130 matches = [ { app-id = "^steam_app_"; } ];
131 border.enable = false;
132 open-fullscreen = true;
133 }
134 {
135 matches = [ { app-id = "^fsel$"; } ];
136 open-floating = true;
137 default-column-width.fixed = 800;
138 default-window-height.fixed = 500;
139 }
140 {
141 matches = [ { app-id = "^mako-tui$"; } ];
142 open-floating = true;
143 default-column-width.fixed = 800;
144 default-window-height.fixed = 500;
145 }
146 ];
147 debug = {
148 honor-xdg-activation-with-invalid-serial = { };
149 };
150 layout = {
151 focus-ring = {
152 width = 2;
153 active.color = "#8caaee";
154 inactive.color = "#414559";
155 };
156 struts = {
157 top = -6;
158 bottom = -6;
159 left = 0;
160 right = 0;
161 };
162 gaps = 8;
163 };
164 gestures = {
165 hot-corners = {
166 enable = false;
167 };
168 };
169 binds = {
170 "Mod+d".action.spawn = [
171 "alacritty"
172 "--class"
173 "fsel"
174 "-e"
175 "fsel"
176 "--detach"
177 ];
178 "Mod+c".action.spawn = [
179 "alacritty"
180 "--class"
181 "fsel"
182 "-e"
183 "fsel"
184 "--cclip"
185 ];
186 "Mod+e".action.spawn = "bemoji";
187 "Mod+n".action.spawn = [
188 "alacritty"
189 "--class"
190 "mako-tui"
191 "-e"
192 "mako-tui"
193 ];
194 "Mod+a".action.spawn = "alacritty";
195 "Mod+h".action = {
196 focus-column-left = { };
197 };
198 "Mod+j".action = {
199 focus-workspace-down = { };
200 };
201 "Mod+k".action = {
202 focus-workspace-up = { };
203 };
204 "Mod+l".action = {
205 focus-column-right = { };
206 };
207 "Mod+Shift+h".action = {
208 move-column-left = { };
209 };
210 "Mod+Shift+j".action = {
211 move-window-down-or-to-workspace-down = { };
212 };
213 "Mod+Shift+k".action = {
214 move-window-up-or-to-workspace-up = { };
215 };
216 "Mod+Shift+l".action = {
217 move-column-right = { };
218 };
219 "Mod+Down".action = {
220 move-workspace-down = { };
221 };
222 "Mod+Up".action = {
223 move-workspace-up = { };
224 };
225 "Mod+p".action = {
226 show-hotkey-overlay = { };
227 };
228 "Mod+o".action = {
229 toggle-overview = { };
230 };
231 "Mod+q".action = {
232 close-window = { };
233 };
234 "Mod+f".action = {
235 toggle-window-floating = { };
236 };
237 "Mod+Shift+f".action = {
238 switch-focus-between-floating-and-tiling = { };
239 };
240 "Mod+m".action = {
241 fullscreen-window = { };
242 };
243 "Mod+s".action = {
244 screenshot = {
245 show-pointer = true;
246 };
247 };
248 "Mod+1".action = {
249 set-column-width = "100%";
250 };
251 "Mod+2".action = {
252 set-column-width = "50%";
253 };
254 "Mod+Minus".action = {
255 set-column-width = "-10%";
256 };
257 "Mod+Equal".action = {
258 set-column-width = "+10%";
259 };
260 "Mod+Shift+q".action = {
261 quit = { };
262 };
263 "Mod+Shift+r".action.spawn = [
264 "systemctl"
265 "--user"
266 "restart"
267 "quickshell.service"
268 ];
269 "XF86AudioPlay".action.spawn = [
270 "playerctl"
271 "play-pause"
272 ];
273 "XF86AudioStop".action.spawn = [
274 "playerctl"
275 "stop"
276 ];
277 "XF86AudioNext".action.spawn = [
278 "playerctl"
279 "next"
280 ];
281 "XF86AudioPrev".action.spawn = [
282 "playerctl"
283 "previous"
284 ];
285 "XF86MonBrightnessDown".action.spawn = [
286 "brightnessctl"
287 "set"
288 "5%-"
289 ];
290 "XF86MonBrightnessUp".action.spawn = [
291 "brightnessctl"
292 "set"
293 "+5%"
294 ];
295 };
296 outputs = {
297 "DP-5" = {
298 scale = 2.0;
299 mode = {
300 width = 5120;
301 height = 2160;
302 refresh = 120.0;
303 };
304 position = {
305 x = 0;
306 y = 0;
307 };
308 };
309 "DP-1" = {
310 scale = 2.0;
311 mode = {
312 width = 5120;
313 height = 2160;
314 refresh = 120.0;
315 };
316 position = {
317 x = 0;
318 y = 0;
319 };
320 };
321 "DP-2" = {
322 scale = 1.0;
323 mode = {
324 width = 5120;
325 height = 2160;
326 refresh = 120.0;
327 };
328 position = {
329 x = 0;
330 y = 0;
331 };
332 };
333 "DP-6" = {
334 scale = 2.0;
335 mode = {
336 width = 5120;
337 height = 2160;
338 refresh = 120.0;
339 };
340 position = {
341 x = 0;
342 y = 0;
343 };
344 };
345 "DP-7" = {
346 scale = 2.0;
347 mode = {
348 width = 5120;
349 height = 2160;
350 refresh = 120.0;
351 };
352 position = {
353 x = 0;
354 y = 0;
355 };
356 };
357 "eDP-1" = {
358 scale = 1.5;
359 mode = {
360 width = 2560;
361 height = 1600;
362 refresh = 165.0;
363 };
364 position = {
365 x = 0;
366 y = 1080;
367 };
368 };
369 };
370 spawn-at-startup = [
371 { command = [ "xwayland-satellite" ]; }
372 { command = [ "cclipd" ]; }
373 ];
374 environment = {
375 DISPLAY = ":0";
376 };
377 };
378 };
379
380 catppuccin = {
381 enable = true;
382 flavor = "frappe";
383 };
384
385 # Wallpaper downloads
386 home.activation.downloadWallpapers =
387 config.lib.dag.entryAfter [ "writeBoundary" ] ''
388 DIR="${config.home.homeDirectory}/Pictures/Wallpapers"
389 mkdir -p "$DIR"
390 ${downloads}
391 '';
392
393 # Kaleidux wallpaper daemon config
394 xdg.configFile."kaleidux/config.toml".text = ''
395 [global]
396 monitor-behavior = "independent"
397 video-ratio = 50
398 sorting = "loveit"
399 transition-time = 1000
400
401 [any]
402 path = "${config.home.homeDirectory}/Pictures/Wallpapers"
403 duration = "15m"
404 transition = { type = "fade" }
405 '';
406
407 # Quickshell status bar
408 xdg.configFile."quickshell" = {
409 source = ./_config/quickshell;
410 recursive = true;
411 };
412
413 systemd.user.services.kaleidux = {
414 Unit = {
415 Description = "Kaleidux dynamic wallpaper daemon";
416 After = [ "graphical-session.target" ];
417 PartOf = [ "graphical-session.target" ];
418 };
419 Service = {
420 ExecStart = "${kaleidux}/bin/kaleidux-daemon";
421 Restart = "on-failure";
422 RestartSec = 2;
423 };
424 Install = {
425 WantedBy = [ "graphical-session.target" ];
426 };
427 };
428
429 systemd.user.services.quickshell = {
430 Unit = {
431 Description = "QuickShell status bar";
432 After = [ "graphical-session.target" ];
433 PartOf = [ "graphical-session.target" ];
434 };
435 Service = {
436 ExecStart = "${pkgs.quickshell}/bin/quickshell";
437 Restart = "on-failure";
438 RestartSec = 2;
439 };
440 Install = {
441 WantedBy = [ "graphical-session.target" ];
442 };
443 };
444
445 systemd.user.services.quickshell-reload = {
446 Unit = {
447 Description = "Reload QuickShell on wake or display change";
448 After = [
449 "quickshell.service"
450 "graphical-session.target"
451 ];
452 PartOf = [ "graphical-session.target" ];
453 };
454 Service = {
455 Type = "simple";
456 ExecStart = "${pkgs.writeShellScript "quickshell-reload" ''
457 LOCKFILE="/tmp/quickshell-reload.lock"
458
459 do_restart() {
460 (
461 ${pkgs.util-linux}/bin/flock -xn 200 || exit 0
462 sleep 2
463 ${pkgs.systemd}/bin/systemctl --user restart quickshell.service
464 sleep 3
465 ) 200>"$LOCKFILE"
466 }
467
468 # Sleep/wake monitor
469 ${pkgs.dbus}/bin/dbus-monitor --system \
470 "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'" 2>/dev/null | \
471 while IFS= read -r line; do
472 if [[ "$line" == *"boolean false"* ]]; then
473 do_restart
474 fi
475 done &
476
477 # Display hotplug monitor
478 ${pkgs.systemd}/bin/udevadm monitor --property --subsystem-match=drm 2>/dev/null | \
479 while IFS= read -r line; do
480 if [[ "$line" == *"HOTPLUG=1"* ]]; then
481 do_restart
482 fi
483 done &
484
485 wait
486 ''}";
487 Restart = "on-failure";
488 RestartSec = 5;
489 };
490 Install = {
491 WantedBy = [ "graphical-session.target" ];
492 };
493 };
494
495 services.udiskie = {
496 enable = true;
497 tray = "never";
498 automount = true;
499 };
500
501 services.mako = {
502 enable = true;
503 settings = {
504 border-radius = 8;
505 border-size = 2;
506 padding = "12";
507 margin = "12";
508 font = "BerkeleyMono Nerd Font 11";
509 on-button-left = "invoke-default-action";
510 on-button-right = "dismiss";
511 };
512 };
513
514 dconf.settings = {
515 "org/gnome/desktop/interface" = {
516 color-scheme = "prefer-dark";
517 enable-hot-corners = false;
518 };
519 };
520
521 home.pointerCursor = {
522 name = "Adwaita";
523 package = pkgs.adwaita-icon-theme;
524 size = 16;
525 x11.enable = true;
526 gtk.enable = true;
527 };
528 };
529}