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.
This commit is contained in:
Franz Pletz 2017-05-25 19:33:13 +02:00
parent 13f2f8673b
commit 1e95e114e5
No known key found for this signature in database
GPG key ID: 846FDED7792617B4
10 changed files with 35 additions and 25 deletions

View file

@ -240,11 +240,14 @@ in {
};
systemd.user = {
services.pulseaudio = {
restartIfChanged = true;
serviceConfig = {
RestartSec = "500ms";
PassEnvironment = "DISPLAY";
};
environment = { DISPLAY = ":${toString config.services.xserver.display}"; };
restartIfChanged = true;
};
sockets.pulseaudio = {
wantedBy = [ "sockets.target" ];
};
};
})

View file

@ -199,9 +199,8 @@ in
environment.etc."ssh/ssh_known_hosts".text = knownHostsText;
# FIXME: this should really be socket-activated for über-awesomeness.
systemd.user.services.ssh-agent =
{ enable = cfg.startAgent;
description = "SSH Agent";
systemd.user.services.ssh-agent = mkIf cfg.startAgent
{ description = "SSH Agent";
wantedBy = [ "default.target" ];
serviceConfig =
{ ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";

View file

@ -48,7 +48,8 @@ in {
config = mkIf cfg.enable {
systemd.user.services.arbtt = {
description = "arbtt statistics capture service";
wantedBy = [ "default.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig = {
Type = "simple";

View file

@ -208,13 +208,13 @@ in {
config = mkIf cfg.enable {
systemd.user.services.compton = {
description = "Compton composite manager";
wantedBy = [ "default.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/compton --config ${configFile}";
RestartSec = 3;
Restart = "always";
};
environment.DISPLAY = ":0";
};
environment.systemPackages = [ cfg.package ];

View file

@ -122,6 +122,9 @@ let
source ~/.xprofile
fi
# Start systemd user services for graphical sessions
${config.systemd.package}/bin/systemctl --user start graphical-session.target
# Allow the user to setup a custom session type.
if test -x ~/.xsession; then
exec ~/.xsession
@ -164,6 +167,9 @@ let
''}
test -n "$waitPID" && wait "$waitPID"
${config.systemd.package}/bin/systemctl --user stop graphical-session.target
exit 0
'';
@ -325,6 +331,13 @@ in
config = {
services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X";
systemd.user.targets.graphical-session = {
unitConfig = {
RefuseManualStart = false;
StopWhenUnneeded = false;
};
};
};
imports = [

View file

@ -95,7 +95,8 @@ in {
config = mkIf cfg.enable {
systemd.user.services.redshift = {
description = "Redshift colour temperature adjuster";
wantedBy = [ "default.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/redshift \
@ -107,12 +108,6 @@ in {
RestartSec = 3;
Restart = "always";
};
environment = {
DISPLAY = ":${toString (
let display = config.services.xserver.display;
in if display != null then display else 0
)}";
};
};
};

View file

@ -43,7 +43,8 @@ in {
config = mkIf cfg.enable {
systemd.user.services.unclutter-xfixes = {
description = "unclutter-xfixes";
wantedBy = [ "graphical.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig.ExecStart = ''
${cfg.package}/bin/unclutter \
--timeout ${toString cfg.timeout} \

View file

@ -56,19 +56,17 @@ in {
config = mkIf cfg.enable {
systemd.user.services.unclutter = {
description = "unclutter";
wantedBy = [ "default.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig.ExecStart = ''
${cfg.package}/bin/unclutter \
-idle ${toString cfg.timeout} \
-display :${toString (
let display = config.services.xserver.display;
in if display != null then display else 0
)} \
-jitter ${toString (cfg.threeshold - 1)} \
${optionalString cfg.keystroke "-keystroke"} \
${concatMapStrings (x: " -"+x) cfg.extraOptions} \
-not ${concatStringsSep " " cfg.excluded} \
'';
serviceConfig.PassEnvironment = "DISPLAY";
serviceConfig.RestartSec = 3;
serviceConfig.Restart = "always";
};

View file

@ -21,9 +21,8 @@ in {
systemd.user = {
sockets.urxvtd = {
description = "socket for urxvtd, the urxvt terminal daemon";
after = [ "graphical.target" ];
wants = [ "graphical.target" ];
wantedBy = [ "sockets.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
socketConfig = {
ListenStream = "%t/urxvtd-socket";
};

View file

@ -20,7 +20,8 @@ in {
config = mkIf cfg.enable {
systemd.user.services.xbanish = {
description = "xbanish hides the mouse pointer";
wantedBy = [ "default.target" ];
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig.ExecStart = ''
${pkgs.xbanish}/bin/xbanish ${cfg.arguments}
'';