{ config, lib, pkgs, ... }: # The lock screen: a hyprlock session-lock surface the compositor owns. let sleepIcon = builtins.fromJSON ''"\udb81\udcb2"''; sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"''; idleLockToggle = pkgs.writeShellScript "lockscreen-idle-inhibit-toggle" '' unit=lockscreen-idle-inhibit.service refresh_waybar() { ${lib.getExe' pkgs.procps "pkill"} -RTMIN+9 waybar >/dev/null 2>&1 || true } if ${lib.getExe' pkgs.systemd "systemctl"} --user is-active --quiet "$unit"; then ${lib.getExe' pkgs.systemd "systemctl"} --user stop "$unit" refresh_waybar ${lib.getExe' pkgs.swayosd "swayosd-client"} --custom-message "${sleepIcon}" exit 0 fi if ${lib.getExe' pkgs.systemd "systemd-run"} \ --user \ --collect \ --unit=lockscreen-idle-inhibit \ --description="Disable idle-triggered screen locking" \ ${lib.getExe' pkgs.systemd "systemd-inhibit"} \ --what=idle \ --who=lockscreen-hotkey \ --why="lock screen disabled by hotkey" \ ${lib.getExe' pkgs.coreutils "sleep"} infinity >/dev/null; then refresh_waybar ${lib.getExe' pkgs.swayosd "swayosd-client"} --custom-message "${sleepOffIcon}" fi ''; in { options.modules.desktop.session.hyprland.hyprlock.enable = lib.mkEnableOption "the hyprlock lock screen"; config = lib.mkIf config.modules.desktop.session.hyprland.hyprlock.enable { home-manager.users.${config.user.name} = { # Colors and the lock-screen background come from Stylix's hyprlock target, # so only geometry and behaviour are set here. programs.hyprlock = { enable = true; settings = { general = { hide_cursor = true; # No progress bar flashes before the field is ready to take input. disable_loading_bar = true; }; # A centered password field. # Its colors come from the Stylix hyprlock target. input-field = { size = "260, 52"; rounding = 8; position = "0, -100"; halign = "center"; valign = "center"; }; # The current time, above the field. label = { text = "$TIME"; font_size = 48; position = "0, 120"; halign = "center"; valign = "center"; }; }; }; }; registry.keybind.${config.networking.hostName} = { hyprlock-lock = { keys = "SUPER + X"; action = { kind = "exec"; # The guard drops the call when a locker is already up, so no manual # trigger stacks a second hyprlock over the first. command = "${lib.getExe' pkgs.procps "pidof"} hyprlock || ${lib.getExe pkgs.hyprlock}"; }; }; hyprlock-toggle-idle-inhibit = { keys = "SUPER + CTRL + X"; action = { kind = "exec"; command = "${idleLockToggle}"; }; }; }; }; }