diff --git a/checks/systemd.nix b/checks/systemd.nix index f42b193..9fc04da 100644 --- a/checks/systemd.nix +++ b/checks/systemd.nix @@ -279,10 +279,10 @@ let } ); - readUserService = drv: name: builtins.readFile "${drv}/systemd/user/${name}.service"; - readSystemService = drv: name: builtins.readFile "${drv}/systemd/system/${name}.service"; - readUserTimer = drv: name: builtins.readFile "${drv}/systemd/user/${name}.timer"; - readSystemTimer = drv: name: builtins.readFile "${drv}/systemd/system/${name}.timer"; + readUserService = drv: name: builtins.readFile "${drv}/lib/systemd/user/${name}.service"; + readSystemService = drv: name: builtins.readFile "${drv}/lib/systemd/system/${name}.service"; + readUserTimer = drv: name: builtins.readFile "${drv}/lib/systemd/user/${name}.timer"; + readSystemTimer = drv: name: builtins.readFile "${drv}/lib/systemd/system/${name}.timer"; in pkgs.runCommand "systemd-test" { } '' echo "Testing systemd module..." @@ -314,14 +314,14 @@ pkgs.runCommand "systemd-test" { } '' # Test 3: Service name from binName echo "Test 3: Service name from binName" - test -f "${customBinName.outputs.systemd-user}/systemd/user/my-hello.service" || { + test -f "${customBinName.outputs.systemd-user}/lib/systemd/user/my-hello.service" || { echo "FAIL: user service file should be named my-hello.service" - ls -la "${customBinName.outputs.systemd-user}/systemd/user/" + ls -la "${customBinName.outputs.systemd-user}/lib/systemd/user/" exit 1 } - test -f "${customBinName.outputs.systemd-system}/systemd/system/my-hello.service" || { + test -f "${customBinName.outputs.systemd-system}/lib/systemd/system/my-hello.service" || { echo "FAIL: system service file should be named my-hello.service" - ls -la "${customBinName.outputs.systemd-system}/systemd/system/" + ls -la "${customBinName.outputs.systemd-system}/lib/systemd/system/" exit 1 } echo "PASS: service name from binName" diff --git a/lib/modules/systemd.nix b/lib/modules/systemd.nix index 1993ca9..2bd4a63 100644 --- a/lib/modules/systemd.nix +++ b/lib/modules/systemd.nix @@ -61,7 +61,7 @@ let mkOutput = type: let - unitDir = if type == "user" then "systemd/user" else "systemd/system"; + unitDir = if type == "user" then "lib/systemd/user" else "lib/systemd/system"; serviceFile = pkgs.writeTextDir "${unitDir}/${serviceName}.service" (systemdLib.serviceToUnit svc) .text; diff --git a/modules/niri/module.nix b/modules/niri/module.nix index c7f7ce9..0f47b9b 100644 --- a/modules/niri/module.nix +++ b/modules/niri/module.nix @@ -122,6 +122,7 @@ let in { _class = "wrapper"; + imports = [ wlib.modules.systemd ]; options = { settings = lib.mkOption { type = lib.types.submodule { @@ -304,13 +305,55 @@ in ''; }; }; + # Drop the upstream user unit; we ship our own (below) with ExecReload + # wired up to the niri IPC. Keep the desktop entry patched so display + # managers still pick up the wrapper's binary. + config.filesToExclude = [ + "lib/systemd/user/niri.service" + "share/systemd/user/niri.service" + ]; config.filesToPatch = [ "share/applications/*.desktop" - "share/systemd/user/niri.service" ]; config.package = config.pkgs.niri; - config.env = { - NIRI_CONFIG = toString config."config.kdl".path; + + # Shell-launched wrapper: same behaviour as upstream -- niri reads the + # immutable, build-pinned config straight from /nix/store. + config.env.NIRI_CONFIG = toString config."config.kdl".path; + + # Systemd-launched session: bootstrap a mutable runtime copy under + # $XDG_RUNTIME_DIR (systemd specifier %t) and point niri at it via + # `--config`. ExecReload re-stamps that file with the latest immutable + # snapshot and asks niri to re-read it via IPC, so config-only switches + # apply without dropping the session. + config.systemd = { + description = "A scrollable-tiling Wayland compositor"; + bindsTo = [ "graphical-session.target" ]; + before = [ + "graphical-session.target" + "xdg-desktop-autostart.target" + ]; + wants = [ + "graphical-session-pre.target" + "xdg-desktop-autostart.target" + ]; + after = [ "graphical-session-pre.target" ]; + serviceConfig = { + Slice = "session.slice"; + Type = "notify"; + ExecStartPre = "${config.pkgs.coreutils}/bin/install -Dm644 ${config."config.kdl".path} %t/niri/config.kdl"; + ExecStart = "${config.exePath} --session --config %t/niri/config.kdl"; + ExecReload = [ + "${config.pkgs.coreutils}/bin/install -Dm644 ${config."config.kdl".path} %t/niri/config.kdl" + "${config.exePath} msg action load-config-file" + ]; + }; + # Tell NixOS's switch-to-configuration to convert every "needs + # restart" verdict into `systemctl --user reload niri.service`, so + # config-only switches reload the live session via ExecReload instead + # of killing it. The flag is read out of the unit's [Service] section + # at switch time (X-ReloadIfChanged=true). + reloadIfChanged = true; }; config.meta.maintainers = [ lib.maintainers.zimward