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 + ''; + }; }; }; 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") ''; }