nixos/xsession: use graphical systemd user target

While systemd suggests using the pre-defined graphical-session user
target, I found that this interface is difficult to use. Additionally,
no other major distribution, even in their unstable versions, currently
use this mechanism.

The window or desktop manager is supposed to run in a systemd user service
which activates graphical-session.target and the user services that are
binding to this target. The issue is that we can't elegantly pass the
xsession environment to the window manager session, in particular
whereas the PassEnvironment option does work for DISPLAY, it for some
mysterious reason won't for PATH.

This commit implements a new graphical user target that works just like
default.target. Services which should be run in a graphical session just
need to declare wantedBy graphical.target. The graphical target will be
activated in the xsession before executing the window or display manager.

Fixes #17858.

+35 -25
+5 -2
nixos/modules/config/pulseaudio.nix
··· 240 240 }; 241 241 systemd.user = { 242 242 services.pulseaudio = { 243 + restartIfChanged = true; 243 244 serviceConfig = { 244 245 RestartSec = "500ms"; 246 + PassEnvironment = "DISPLAY"; 245 247 }; 246 - environment = { DISPLAY = ":${toString config.services.xserver.display}"; }; 247 - restartIfChanged = true; 248 + }; 249 + sockets.pulseaudio = { 250 + wantedBy = [ "sockets.target" ]; 248 251 }; 249 252 }; 250 253 })
+2 -3
nixos/modules/programs/ssh.nix
··· 199 199 environment.etc."ssh/ssh_known_hosts".text = knownHostsText; 200 200 201 201 # FIXME: this should really be socket-activated for über-awesomeness. 202 - systemd.user.services.ssh-agent = 203 - { enable = cfg.startAgent; 204 - description = "SSH Agent"; 202 + systemd.user.services.ssh-agent = mkIf cfg.startAgent 203 + { description = "SSH Agent"; 205 204 wantedBy = [ "default.target" ]; 206 205 serviceConfig = 207 206 { ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";
+2 -1
nixos/modules/services/monitoring/arbtt.nix
··· 48 48 config = mkIf cfg.enable { 49 49 systemd.user.services.arbtt = { 50 50 description = "arbtt statistics capture service"; 51 - wantedBy = [ "default.target" ]; 51 + wantedBy = [ "graphical-session.target" ]; 52 + partOf = [ "graphical-session.target" ]; 52 53 53 54 serviceConfig = { 54 55 Type = "simple";
+2 -2
nixos/modules/services/x11/compton.nix
··· 208 208 config = mkIf cfg.enable { 209 209 systemd.user.services.compton = { 210 210 description = "Compton composite manager"; 211 - wantedBy = [ "default.target" ]; 211 + wantedBy = [ "graphical-session.target" ]; 212 + partOf = [ "graphical-session.target" ]; 212 213 serviceConfig = { 213 214 ExecStart = "${cfg.package}/bin/compton --config ${configFile}"; 214 215 RestartSec = 3; 215 216 Restart = "always"; 216 217 }; 217 - environment.DISPLAY = ":0"; 218 218 }; 219 219 220 220 environment.systemPackages = [ cfg.package ];
+13
nixos/modules/services/x11/display-managers/default.nix
··· 122 122 source ~/.xprofile 123 123 fi 124 124 125 + # Start systemd user services for graphical sessions 126 + ${config.systemd.package}/bin/systemctl --user start graphical-session.target 127 + 125 128 # Allow the user to setup a custom session type. 126 129 if test -x ~/.xsession; then 127 130 exec ~/.xsession ··· 164 167 ''} 165 168 166 169 test -n "$waitPID" && wait "$waitPID" 170 + 171 + ${config.systemd.package}/bin/systemctl --user stop graphical-session.target 172 + 167 173 exit 0 168 174 ''; 169 175 ··· 325 331 326 332 config = { 327 333 services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X"; 334 + 335 + systemd.user.targets.graphical-session = { 336 + unitConfig = { 337 + RefuseManualStart = false; 338 + StopWhenUnneeded = false; 339 + }; 340 + }; 328 341 }; 329 342 330 343 imports = [
+2 -7
nixos/modules/services/x11/redshift.nix
··· 95 95 config = mkIf cfg.enable { 96 96 systemd.user.services.redshift = { 97 97 description = "Redshift colour temperature adjuster"; 98 - wantedBy = [ "default.target" ]; 98 + wantedBy = [ "graphical-session.target" ]; 99 + partOf = [ "graphical-session.target" ]; 99 100 serviceConfig = { 100 101 ExecStart = '' 101 102 ${cfg.package}/bin/redshift \ ··· 106 107 ''; 107 108 RestartSec = 3; 108 109 Restart = "always"; 109 - }; 110 - environment = { 111 - DISPLAY = ":${toString ( 112 - let display = config.services.xserver.display; 113 - in if display != null then display else 0 114 - )}"; 115 110 }; 116 111 }; 117 112 };
+2 -1
nixos/modules/services/x11/unclutter-xfixes.nix
··· 43 43 config = mkIf cfg.enable { 44 44 systemd.user.services.unclutter-xfixes = { 45 45 description = "unclutter-xfixes"; 46 - wantedBy = [ "graphical.target" ]; 46 + wantedBy = [ "graphical-session.target" ]; 47 + partOf = [ "graphical-session.target" ]; 47 48 serviceConfig.ExecStart = '' 48 49 ${cfg.package}/bin/unclutter \ 49 50 --timeout ${toString cfg.timeout} \
+3 -5
nixos/modules/services/x11/unclutter.nix
··· 56 56 config = mkIf cfg.enable { 57 57 systemd.user.services.unclutter = { 58 58 description = "unclutter"; 59 - wantedBy = [ "default.target" ]; 59 + wantedBy = [ "graphical-session.target" ]; 60 + partOf = [ "graphical-session.target" ]; 60 61 serviceConfig.ExecStart = '' 61 62 ${cfg.package}/bin/unclutter \ 62 63 -idle ${toString cfg.timeout} \ 63 - -display :${toString ( 64 - let display = config.services.xserver.display; 65 - in if display != null then display else 0 66 - )} \ 67 64 -jitter ${toString (cfg.threeshold - 1)} \ 68 65 ${optionalString cfg.keystroke "-keystroke"} \ 69 66 ${concatMapStrings (x: " -"+x) cfg.extraOptions} \ 70 67 -not ${concatStringsSep " " cfg.excluded} \ 71 68 ''; 69 + serviceConfig.PassEnvironment = "DISPLAY"; 72 70 serviceConfig.RestartSec = 3; 73 71 serviceConfig.Restart = "always"; 74 72 };
+2 -3
nixos/modules/services/x11/urxvtd.nix
··· 21 21 systemd.user = { 22 22 sockets.urxvtd = { 23 23 description = "socket for urxvtd, the urxvt terminal daemon"; 24 - after = [ "graphical.target" ]; 25 - wants = [ "graphical.target" ]; 26 - wantedBy = [ "sockets.target" ]; 24 + wantedBy = [ "graphical-session.target" ]; 25 + partOf = [ "graphical-session.target" ]; 27 26 socketConfig = { 28 27 ListenStream = "%t/urxvtd-socket"; 29 28 };
+2 -1
nixos/modules/services/x11/xbanish.nix
··· 20 20 config = mkIf cfg.enable { 21 21 systemd.user.services.xbanish = { 22 22 description = "xbanish hides the mouse pointer"; 23 - wantedBy = [ "default.target" ]; 23 + wantedBy = [ "graphical-session.target" ]; 24 + partOf = [ "graphical-session.target" ]; 24 25 serviceConfig.ExecStart = '' 25 26 ${pkgs.xbanish}/bin/xbanish ${cfg.arguments} 26 27 '';