mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 09:36:20 +09:00
nixos/startx: try to improve UX
There are some common pitfalls and no documentation around how to write the .xinitrc to correctly start the window manager, the systemd graphical session and, ideally, cleaning up afterwards. To improve the user experience around startx this change: 1. Adds two options to generate a sane default script and extend it declaratively from NixOS. 2. Adds assertions to graphical-session.target so that it will fail clearly and immediately when users writing their own script forget to import the necessary environment variables.
This commit is contained in:
parent
7252fbc580
commit
e1c3082085
1 changed files with 73 additions and 16 deletions
|
@ -5,12 +5,16 @@
|
|||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.xserver.displayManager.startx;
|
||||
|
||||
# WM session script
|
||||
# Note: this assumes a single WM has been enabled
|
||||
sessionScript = lib.concatMapStringsSep "\n" (
|
||||
i: i.start
|
||||
) config.services.xserver.windowManager.session;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -19,40 +23,93 @@ in
|
|||
|
||||
options = {
|
||||
services.xserver.displayManager.startx = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the dummy "startx" pseudo-display manager,
|
||||
which allows users to start X manually via the "startx" command
|
||||
from a vt shell. The X server runs under the user's id, not as root.
|
||||
The user must provide a ~/.xinitrc file containing session startup
|
||||
commands, see {manpage}`startx(1)`. This is not automatically generated
|
||||
from the desktopManager and windowManager settings.
|
||||
Whether to enable the dummy "startx" pseudo-display manager, which
|
||||
allows users to start X manually via the `startx` command from a
|
||||
virtual terminal.
|
||||
|
||||
::: {.note}
|
||||
The X server will run under the current user, not as root.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
generateScript = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to generate the system-wide xinitrc script (/etc/X11/xinit/xinitrc).
|
||||
This script will take care of setting up the session for systemd user
|
||||
services, running the window manager and cleaning up on exit.
|
||||
|
||||
::: {.note}
|
||||
This script will only be used by `startx` when both `.xinitrc` does not
|
||||
exists and the `XINITRC` environment variable is unset.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
extraCommands = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Shell commands to be added to the system-wide xinitrc script.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.xserver = {
|
||||
exportConfiguration = true;
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.xserver.exportConfiguration = true;
|
||||
|
||||
# Other displayManagers log to /dev/null because they're services and put
|
||||
# Xorg's stdout in the journal
|
||||
#
|
||||
# To send log to Xorg's default log location ($XDG_DATA_HOME/xorg/), we do
|
||||
# not specify a log file when running X
|
||||
services.xserver.logFile = mkDefault null;
|
||||
services.xserver.logFile = lib.mkDefault null;
|
||||
|
||||
# Implement xserverArgs via xinit's system-wide xserverrc
|
||||
environment.etc."X11/xinit/xserverrc".source = pkgs.writeShellScript "xserverrc" ''
|
||||
exec ${pkgs.xorg.xorgserver}/bin/X ${toString config.services.xserver.displayManager.xserverArgs} "$@"
|
||||
exec ${pkgs.xorg.xorgserver}/bin/X \
|
||||
${toString config.services.xserver.displayManager.xserverArgs} "$@"
|
||||
'';
|
||||
|
||||
# Add a sane system-wide xinitrc script
|
||||
environment.etc."X11/xinit/xinitrc".source = lib.mkIf cfg.generateScript (
|
||||
pkgs.writeShellScript "xinitrc" ''
|
||||
${cfg.extraCommands}
|
||||
|
||||
# start user services
|
||||
systemctl --user import-environment DISPLAY XDG_SESSION_ID
|
||||
systemctl --user start nixos-fake-graphical-session.target
|
||||
|
||||
# run the window manager script
|
||||
${sessionScript}
|
||||
wait $waitPID
|
||||
|
||||
# stop services and all subprocesses
|
||||
systemctl --user stop nixos-fake-graphical-session.target
|
||||
kill 0
|
||||
''
|
||||
);
|
||||
|
||||
environment.systemPackages = with pkgs; [ xorg.xinit ];
|
||||
|
||||
# Make graphical-session fail if the user environment has not been imported
|
||||
systemd.user.targets.graphical-session = {
|
||||
unitConfig.AssertEnvironment = [
|
||||
"DISPLAY"
|
||||
"XDG_SESSION_ID"
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue