dot

vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks

161 lines5634 bytesNix
1# The desktop's background programs, as systemd user services. On CachyOS most
2# of these were started by hyprland.lua (hl.exec_cmd at hyprland.start).
3#
4# uwsm starts Hyprland and then graphical-session.target; every service here is
5# wanted by that target and stopped with it, so they come up after the
6# compositor is ready and go away at logout. They are restarted if they crash.
7#
8# systemctl --user status waybar is it running, and its last log lines
9# journalctl --user -u waybar -f follow its log
10# systemctl --user restart waybar e.g. after changing its config
11#
12# Slices are uwsm's: session-graphical for the shell itself (bar, idle, wallpaper,
13# notifications), background-graphical for helpers.
14{
15 config,
16 lib,
17 pkgs,
18 ...
19}:
20let
21 graphical =
22 {
23 description,
24 exec,
25 slice ? "background-graphical.slice",
26 after ? [ ],
27 unit ? { },
28 service ? { },
29 }:
30 {
31 Unit = {
32 Description = description;
33 PartOf = [ "graphical-session.target" ];
34 After = [ "graphical-session.target" ] ++ after;
35 Requisite = [ "graphical-session.target" ];
36 }
37 // unit;
38 Service = {
39 ExecStart = exec;
40 Restart = "on-failure";
41 RestartSec = 2;
42 Slice = slice;
43 }
44 // service;
45 Install.WantedBy = [ "graphical-session.target" ];
46 };
47
48 configDir = "${config.xdg.configHome}";
49in
50{
51 systemd.user.services = {
52 waybar = graphical {
53 description = "Waybar";
54 exec = lib.getExe pkgs.waybar;
55 slice = "session-graphical.slice";
56 service.ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID";
57 };
58
59 hypridle = graphical {
60 description = "Hyprland's idle daemon";
61 exec = lib.getExe pkgs.hypridle;
62 slice = "session-graphical.slice";
63 unit.ConditionEnvironment = "WAYLAND_DISPLAY";
64 };
65
66 hyprpaper = graphical {
67 description = "Hyprland wallpaper daemon";
68 exec = lib.getExe pkgs.hyprpaper;
69 slice = "session-graphical.slice";
70 };
71
72 dunst = graphical {
73 description = "Dunst notification daemon";
74 exec = lib.getExe pkgs.dunst;
75 slice = "session-graphical.slice";
76 service = {
77 Type = "dbus";
78 BusName = "org.freedesktop.Notifications";
79 };
80 };
81
82 # The Waybar flyouts (control centre, notifications). Started with the
83 # session so the first click on the Waybar button opens instantly.
84 eww = graphical {
85 description = "Eww daemon for the Waybar flyouts";
86 exec = "${lib.getExe pkgs.eww} --config ${configDir}/waybar/eww daemon --no-daemonize";
87 };
88
89 hyprpolkitagent = graphical {
90 description = "Hyprland polkit agent";
91 exec = "${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent";
92 slice = "session-graphical.slice";
93 };
94
95 nm-applet = graphical {
96 description = "NetworkManager tray icon";
97 exec = "${pkgs.networkmanagerapplet}/bin/nm-applet --indicator";
98 after = [ "waybar.service" ];
99 };
100
101 # Puts Wine/Proton tray icons (Battle.net) into Waybar's tray, so it needs
102 # the tray to be there first.
103 xembedsniproxy = graphical {
104 description = "XEmbed to StatusNotifierItem tray bridge";
105 exec = lib.getExe pkgs.xembedsniproxy;
106 after = [ "waybar.service" ];
107 # Restarting it while a Wine app is open breaks that app's tray icon until
108 # the app is restarted, so a rebuild leaves the running one alone.
109 unit.X-RestartIfChanged = false;
110 };
111
112 # Forwards the X11 clipboard (Wine/Proton games) to Wayland whatever has
113 # focus. Waits for Xwayland by itself.
114 xwl-clipbridge = graphical {
115 description = "X11 to Wayland clipboard bridge";
116 exec = "${pkgs.python3-desktop}/bin/python3 ${configDir}/hypr/scripts/xwl-clipbridge";
117 service.Environment = [ "PATH=${lib.makeBinPath [ pkgs.wl-clipboard ]}" ];
118 };
119
120 # The apps opened at login (Signal, Discord, Faugus, OpenDeck, WowUp); see
121 # config/hypr/scripts/autostart-apps. It starts each one as its own unit and
122 # exits; the window placement rules for them are in hyprland.lua.
123 autostart-apps = graphical {
124 description = "Open the apps that start at login";
125 exec = "${configDir}/hypr/scripts/autostart-apps";
126 after = [ "waybar.service" ];
127 service = {
128 Type = "oneshot";
129 Restart = "no";
130 # The script finds the apps (and pgrep, uwsm, hyprctl, ...) on the
131 # system and user profiles, whatever environment the session imported.
132 Environment = [
133 "PATH=${
134 lib.makeBinPath [ pkgs.python3-desktop ]
135 }:/etc/profiles/per-user/${config.home.username}/bin:/run/current-system/sw/bin"
136 ];
137 # It waits for the tray and for Signal and Discord to open, up to about
138 # two minutes; more than the 15 s default the CachyOS settings set.
139 TimeoutStartSec = "3min";
140 };
141 unit.X-RestartIfChanged = false;
142 };
143 };
144
145 # The Bluetooth tray icon (blueman-applet) comes from the autostart entry
146 # services.blueman installs, which uwsm also runs as a systemd unit
147 # (app-blueman@autostart.service).
148
149 # Bitwarden at login. This one stays an XDG autostart entry, as on CachyOS
150 # (uwsm runs those as systemd units too: app-bitwarden@autostart.service); the
151 # entry just needs NixOS's name for the program.
152 xdg.configFile."autostart/bitwarden.desktop".text = ''
153 [Desktop Entry]
154 Type=Application
155 Name=Bitwarden
156 Comment=Bitwarden startup script
157 Exec=${lib.getExe pkgs.bitwarden-desktop}
158 StartupNotify=false
159 Terminal=false
160 '';
161}