river: add systemd.runInService option

Add a runInService option that allows users to run `systemctl --user
start river`. This makes lifecycles of river be managed by systemd and
fixes long shutdown times & graphics-session.target not stopping.
This commit is contained in:
Zoe Roux 2024-07-10 15:24:52 +07:00
parent 465ea1f994
commit 6e9380d426
No known key found for this signature in database
2 changed files with 58 additions and 19 deletions

View file

@ -1,16 +1,14 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (lib) types; inherit (lib) types;
cfg = config.wayland.windowManager.river; cfg = config.wayland.windowManager.river;
# Systemd integration # Systemd integration
variables = builtins.concatStringsSep " " cfg.systemd.variables; variables = builtins.concatStringsSep " " cfg.systemd.variables;
extraCommands = builtins.concatStringsSep " " systemdActivation = builtins.concatStringsSep " && " ([
(map (f: "&& ${f}") cfg.systemd.extraCommands); "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}"
systemdActivation = '' ] ++ (lib.optional cfg.systemd.runInService "systemd-notify --ready")
${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables} ${extraCommands} ++ cfg.systemd.extraCommands);
'';
toValue = val: toValue = val:
if lib.isString val || lib.isDerivation val then if lib.isString val || lib.isDerivation val then
@ -28,7 +26,6 @@ let
# Intermediary function that converts some value (attrs, str, ...) to one or several commands. # Intermediary function that converts some value (attrs, str, ...) to one or several commands.
toArgs = path: value: toArgs = path: value:
let let
stringValue = lib.concatStringsSep " " (path ++ [ (toValue value) ]); stringValue = lib.concatStringsSep " " (path ++ [ (toValue value) ]);
finalValue = if lib.isAttrs value then finalValue = if lib.isAttrs value then
@ -47,7 +44,6 @@ let
toCommand = basePath: attrs: toCommand = basePath: attrs:
lib.concatLists (lib.mapAttrsToList lib.concatLists (lib.mapAttrsToList
(key: value: let path = basePath ++ [ key ]; in toArgs path value) attrs); (key: value: let path = basePath ++ [ key ]; in toArgs path value) attrs);
in { in {
meta.maintainers = [ lib.maintainers.GaetanLepage ]; meta.maintainers = [ lib.maintainers.GaetanLepage ];
@ -81,6 +77,25 @@ in {
''; '';
}; };
runInService = lib.mkEnableOption null // {
default = false;
description = ''
Whether river should run inside systemd (`true`) or outside of systemd
(`false`).
Running inside systemd means river lifecycle is fully known/managed by
systemd. Stopping your computer or river crashing will stop the
appropriate targets and will make sure everything stays in sync.
If river runs inside systemd, river logs will be available with
{command}`journalctl`.
To start river, you will need to run
{command}`systemctl --user start river`
and not run it from the command line.
'';
};
variables = lib.mkOption { variables = lib.mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ default = [
@ -100,10 +115,11 @@ in {
extraCommands = lib.mkOption { extraCommands = lib.mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ default = if (!cfg.systemd.runInService) then [
"systemctl --user stop river-session.target" "systemctl --user stop river-session.target"
"systemctl --user start river-session.target" "systemctl --user start river-session.target"
]; ] else
[ ];
description = "Extra commands to be run after D-Bus activation."; description = "Extra commands to be run after D-Bus activation.";
}; };
}; };
@ -180,16 +196,17 @@ in {
### SHELL VARIABLES ### ### SHELL VARIABLES ###
${config.lib.shell.exportAll cfg.extraSessionVariables} ${config.lib.shell.exportAll cfg.extraSessionVariables}
'' + (lib.optionalString cfg.systemd.enable ''
### SYSTEMD INTEGRATION ###
${systemdActivation}
'') + ''
### CONFIGURATION ### ### CONFIGURATION ###
${lib.concatStringsSep "\n" (toCommand [ "riverctl" ] cfg.settings)} ${lib.concatStringsSep "\n" (toCommand [ "riverctl" ] cfg.settings)}
### EXTRA CONFIGURATION ### ### EXTRA CONFIGURATION ###
${cfg.extraConfig} ${cfg.extraConfig}
'');
'' + (lib.optionalString cfg.systemd.enable ''
### SYSTEMD INTEGRATION ###
${systemdActivation}
''));
# Systemd integration # Systemd integration
systemd.user.targets.river-session = lib.mkIf cfg.systemd.enable { systemd.user.targets.river-session = lib.mkIf cfg.systemd.enable {
@ -197,8 +214,31 @@ in {
Description = "river compositor session"; Description = "river compositor session";
Documentation = [ "man:systemd.special(7)" ]; Documentation = [ "man:systemd.special(7)" ];
BindsTo = [ "graphical-session.target" ]; BindsTo = [ "graphical-session.target" ];
Before = [ "graphical-session.target" ];
Wants = [ "graphical-session-pre.target" ]; Wants = [ "graphical-session-pre.target" ];
After = [ "graphical-session-pre.target" ]; After = [ "graphical-session-pre.target" ];
RefuseManualStart = if cfg.systemd.runInService then "yes" else "no";
StopWhenUnneeded = "yes";
};
};
systemd.user.services.river =
lib.mkIf (cfg.systemd.enable && cfg.systemd.runInService) {
Unit = {
Description = "River compositor";
Documentation = "man:river(1)";
BindsTo = [ "river-session.target" ];
Before = [ "river-session.target" ];
};
Service = {
Type = "notify";
# /bin/sh -lc is used to get env/session vars (and path).
ExecStart = "/bin/sh -lc ${pkgs.river}/bin/river";
TimeoutStopSec = 10;
NotifyAccess = "all";
ExecStopPost =
"${pkgs.systemd}/bin/systemctl --user unset-environment ${variables}";
}; };
}; };

View file

@ -6,6 +6,9 @@ export BAR="bar"
export FOO="foo" export FOO="foo"
export FOURTY_TWO="42" export FOURTY_TWO="42"
### SYSTEMD INTEGRATION ###
@dbus@/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop river-session.target && systemctl --user start river-session.target
### CONFIGURATION ### ### CONFIGURATION ###
riverctl attach-mode bottom riverctl attach-mode bottom
riverctl background-color 0x002b36 riverctl background-color 0x002b36
@ -61,7 +64,3 @@ some
extra config extra config
### SYSTEMD INTEGRATION ###
@dbus@/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop river-session.target && systemctl --user start river-session.target