177 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| {
 | |
|   lib,
 | |
|   config,
 | |
|   pkgs,
 | |
|   ...
 | |
| }: let
 | |
|   inherit (lib) mkIf;
 | |
|   inherit (config.programs) rofi;
 | |
| 
 | |
|   powermenu = pkgs.writeShellApplication {
 | |
|     name = "powermenu";
 | |
|     runtimeInputs = [pkgs.rofi-wayland];
 | |
|     text =
 | |
|       # bash
 | |
|       ''
 | |
| 
 | |
|         pid_file="/tmp/my_countdown.pid"
 | |
| 
 | |
|         DRY=
 | |
|         COUNTDOWN=
 | |
| 
 | |
|         while [ $# -gt 0 ]; do
 | |
|           key="$1"
 | |
|           case $key in
 | |
|           -c | --countdown)
 | |
|             COUNTDOWN=true
 | |
|             shift
 | |
|             ;;
 | |
|           -d | --dry)
 | |
|             DRY=true
 | |
|             shift
 | |
|             ;;
 | |
|           *)
 | |
|             break
 | |
|             ;;
 | |
|           esac
 | |
|         done
 | |
| 
 | |
|         notify() {
 | |
|           notify-send -u critical -a system-notify -t 1000 -h string:x-canonical-private-synchronous:anything "$@"
 | |
|         }
 | |
| 
 | |
|         # Used for development, instead of running command, notifies if command was successful and exits.
 | |
|         dry_success() {
 | |
|           if [ "$DRY" == "true" ]; then
 | |
|             TITLE="Action Successful:"
 | |
|             notify "$TITLE" "$1"
 | |
|             exit 0
 | |
|           fi
 | |
|         }
 | |
| 
 | |
|         cancel() {
 | |
|           if [ -f "$pid_file" ]; then
 | |
|             # Read the process ID from the file and kill the process
 | |
|             kill "$(cat "$pid_file")" &>/dev/null
 | |
|             notify-send "Action canceled"
 | |
|             rm -f "$pid_file"
 | |
|           else
 | |
|             echo "No countdown to cancel."
 | |
|           fi
 | |
|         }
 | |
| 
 | |
|         countdown() {
 | |
|           if [ "$COUNTDOWN" == "true" ]; then
 | |
|             msg="''${1:-doing something}"
 | |
|             echo $$ >"$pid_file"
 | |
|             for i in {5..1}; do
 | |
|               notify-send "$msg in $i" -h string:x-canonical-private-synchronous:anything
 | |
|               sleep 1
 | |
|             done
 | |
|             echo "Countdown done"
 | |
|             rm -f "$pid_file"
 | |
|           fi
 | |
|         }
 | |
| 
 | |
|         action_logout() {
 | |
|           countdown "Logging out"
 | |
|           dry_success "Logged out"
 | |
|           PROCESS="Hyprland|\.Hyprland-wrapp"
 | |
|           if pgrep -x $PROCESS >/dev/null; then
 | |
|             hyprctl dispatch exit 0
 | |
|             sleep 2
 | |
|             if pgrep -x $PROCESS; then
 | |
|               pkill -9 $PROCESS
 | |
|             fi
 | |
|           fi
 | |
| 
 | |
|         }
 | |
| 
 | |
|         action_poweroff() {
 | |
|           countdown "Shutting down"
 | |
|           dry_success "Shutdown"
 | |
|           poweroff
 | |
|         }
 | |
| 
 | |
|         action_lock() {
 | |
|           dry_success "Screen Locked"
 | |
|           hyprlock
 | |
|         }
 | |
| 
 | |
|         action_reboot() {
 | |
|           countdown "Rebooting"
 | |
|           dry_success "Reboot"
 | |
|           reboot
 | |
|         }
 | |
| 
 | |
|         action_suspend() {
 | |
|           countdown "Suspending"
 | |
|           dry_success "Suspend"
 | |
|           suspend
 | |
|         }
 | |
| 
 | |
|         action_dmenu() {
 | |
|           selection=$(echo -e " Reboot\n Lock\n Logout\n Shutdown\n Suspend" | rofi -dmenu -i)
 | |
| 
 | |
|           case "$selection" in
 | |
|           " Shutdown") action_poweroff ;;
 | |
|           " Reboot") action_reboot ;;
 | |
|           " Lock") action_lock ;;
 | |
|           " Logout") action_logout ;;
 | |
|           " Suspend") action_suspend ;;
 | |
|           *)
 | |
|             echo "ERROR" "Invalid option"
 | |
|             exit 1
 | |
|             ;;
 | |
|           esac
 | |
|         }
 | |
|         # Check if the script is already running and decide to cancel or start countdown
 | |
|         if [ -f "$pid_file" ]; then
 | |
|           cancel
 | |
|         else
 | |
|           ACTION=''${1:-usage}
 | |
|           case "$ACTION" in
 | |
|           logout)
 | |
|             action_logout
 | |
|             ;;
 | |
|           poweroff)
 | |
|             action_poweroff
 | |
|             ;;
 | |
|           reboot)
 | |
|             action_reboot
 | |
|             ;;
 | |
|           lock)
 | |
|             action_lock
 | |
|             ;;
 | |
|           usage)
 | |
|             echo " Usage: powermenu [OPTION]... [ACTION usage|dmenu|logout|poweroff|reboot|lock]"
 | |
|             echo ""
 | |
|             echo "Options:"
 | |
|             echo "  -c, --countdown       Enable 5 seconds countdown before action is performed"
 | |
|             echo "  -d, --dry             Print instead of perform action debug/development"
 | |
|             echo ""
 | |
|             echo "Actions:"
 | |
|             echo "  usage                 Print help information"
 | |
|             echo "  dmenu                 Open menu with rofi for selecting action"
 | |
|             echo "  logout                Kills current active Hyprland session"
 | |
|             echo "  poweroff              Shut down current host"
 | |
|             echo "  reboot                Restart current host"
 | |
|             echo "  lock                  Locks current session with hyprlock"
 | |
|             echo ""
 | |
|             ;;
 | |
|           dmenu)
 | |
|             action_dmenu
 | |
|             ;;
 | |
|           *)
 | |
|             echo "Invalid action: $ACTION (expecting: usage|logout|poweroff|reboot|lock)"
 | |
|             ;;
 | |
|           esac
 | |
|         fi
 | |
|       '';
 | |
|   };
 | |
| in {
 | |
|   config = mkIf rofi.enable {
 | |
|     home.packages = [powermenu];
 | |
|     ooknet.binds.powerMenu = "powermenu -c dmenu";
 | |
|   };
 | |
| }
 |