From e1c27e75b42427efc0fc7af2412bb7a49f74a0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9ana=20=E6=B1=9F?= Date: Fri, 31 Oct 2025 10:44:20 +0800 Subject: [PATCH 1/2] nixos/xscreensaver: add event handler script --- nixos/modules/services/x11/xscreensaver.nix | 66 ++++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/nixos/modules/services/x11/xscreensaver.nix b/nixos/modules/services/x11/xscreensaver.nix index b9523ef2ae53..dbd1a89b5ffd 100644 --- a/nixos/modules/services/x11/xscreensaver.nix +++ b/nixos/modules/services/x11/xscreensaver.nix @@ -13,6 +13,22 @@ in enable = lib.mkEnableOption "xscreensaver user service"; package = lib.mkPackageOption pkgs "xscreensaver" { }; + + hooks = lib.mkOption { + type = with lib.types; attrsOf lines; + description = '' + An attrset of events and commands to run upon each event. + Refer to for supported events. + ''; + defaultText = lib.literalExpression "{ }"; + default = { }; + example = lib.literalExpression '' + # Reconfigure autorandr on screen wake up + { + "RUN" = "''${lib.getExe pkgs.autorandr} --change --ignore-lid"; + }; + ''; + }; }; config = lib.mkIf cfg.enable { @@ -25,14 +41,48 @@ in source = "${pkgs.xscreensaver}/libexec/xscreensaver/xscreensaver-auth"; }; - systemd.user.services.xscreensaver = { - enable = true; - description = "XScreenSaver"; - after = [ "graphical-session-pre.target" ]; - partOf = [ "graphical-session.target" ]; - wantedBy = [ "graphical-session.target" ]; - path = [ cfg.package ]; - serviceConfig.ExecStart = "${cfg.package}/bin/xscreensaver -no-splash"; + systemd.user.services = { + xscreensaver = { + enable = true; + description = "XScreenSaver"; + after = [ "graphical-session-pre.target" ]; + partOf = [ "graphical-session.target" ]; + wantedBy = [ "graphical-session.target" ]; + path = [ cfg.package ]; + serviceConfig.ExecStart = "${cfg.package}/bin/xscreensaver -no-splash"; + }; + + xscreensaver-hooks = lib.mkIf (cfg.enable && cfg.hooks != { }) { + enable = true; + description = "Run commands on XScreenSaver events"; + after = [ + "graphical-session.target" + "xscreensaver.service" + ]; + partOf = [ "graphical-session.target" ]; + wantedBy = [ "graphical-session.target" ]; + path = [ cfg.package ]; + serviceConfig = { + Restart = "always"; + }; + script = + let + handlers = lib.concatMapAttrsStringSep "\n" (event: action: '' + "${event}") + ( ${action} + ) + ;; + '') cfg.hooks; + in + '' + xscreensaver-command -watch | while read event rest; do + echo "XScreenSaver handler script got \"$event\"" + case $event in + ${handlers} + esac + done + ''; + }; }; }; From eec3fb0c3a5d7b3852a9f60d37bab1d424555733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9ana=20=E6=B1=9F?= Date: Sun, 9 Nov 2025 09:47:33 +0800 Subject: [PATCH 2/2] nixosTests.xscreensaver: ensure hooks script behaviour --- nixos/tests/xscreensaver.nix | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/nixos/tests/xscreensaver.nix b/nixos/tests/xscreensaver.nix index 27f496cb9def..9b62bdab07d2 100644 --- a/nixos/tests/xscreensaver.nix +++ b/nixos/tests/xscreensaver.nix @@ -1,6 +1,6 @@ { lib, ... }: { - name = "pass-secret-service"; + name = "xscreensaver"; meta.maintainers = with lib.maintainers; [ vancluever ]; @@ -54,9 +54,25 @@ }) ]; }; + + hooks = + { lib, ... }: + { + imports = [ + ./common/x11.nix + ./common/user-account.nix + ]; + test-support.displayManager.auto.user = "alice"; + services.xscreensaver = { + enable = true; + hooks = { + "UNBLANK" = ":> /home/alice/xscreensaver-works"; + }; + }; + }; }; - testScript = '' + testScript = /* python */ '' ok.wait_for_x() ok.wait_for_unit("xscreensaver", "alice") _, output_ok = ok.systemctl("status xscreensaver", "alice") @@ -77,5 +93,10 @@ assert 'To prevent the kernel from randomly unlocking' in output_bad_wrapperPrefix assert 'your screen via the out-of-memory killer' in output_bad_wrapperPrefix assert '"xscreensaver-auth" must be setuid root' in output_bad_wrapperPrefix + + hooks.wait_for_x() + hooks.wait_for_unit("xscreensaver", "alice") + hooks.wait_for_unit("xscreensaver-hooks", "alice") + hooks.wait_for_file("/home/alice/xscreensaver-works") ''; }