1
0
Fork 1
mirror of https://github.com/Zerodya/hyprfreeze.git synced 2024-09-19 15:33:20 +02:00
hyprfreeze/hyprfreeze

273 lines
6.8 KiB
Text
Raw Permalink Normal View History

2023-10-10 19:51:07 +02:00
#!/usr/bin/env bash
2023-09-02 18:58:22 +02:00
2023-10-13 12:40:12 +02:00
function printHelp() {
cat <<EOF
Usage: hyprfreeze (-a | -p <pid> | -n <name> | -r) [options]
2023-10-13 12:40:12 +02:00
Utility to suspend a game process (and other programs) in Hyprland.
2023-10-13 12:40:12 +02:00
Options:
2024-02-10 22:39:37 +01:00
-h, --help show help message
-a, --active toggle suspend by active window
2024-02-10 22:39:37 +01:00
-p, --pid toggle suspend by process id
-n, --name toggle suspend by process name/command
-r, --prop toggle suspend by clicking on window (hyprprop/swayprop must be installed)
2024-02-10 22:39:37 +01:00
-s, --silent don't send notification
-t, --notif-timeout notification timeout in milliseconds (default 5000)
2024-02-10 22:39:37 +01:00
--info show information about the process
--dry-run doesn't actually suspend/resume a process, useful with --info
--debug enable debug mode
2023-10-13 12:40:12 +02:00
EOF
}
2024-02-10 22:39:37 +01:00
function debugPrint() {
if [ "$DEBUG" -eq 1 ]; then
echo "[DEBUG] $1"
fi
}
function toggleFreeze() {
2024-02-10 22:39:37 +01:00
# Skip this function if --dry-run flag was provided
if [[ $DRYRUN == "1" ]]; then return 0; fi
# Get pids of process tree
2024-02-11 18:01:24 +01:00
PIDS=$(pstree -p "$PID" | grep -oP '\(\K[^\)]+')
2024-02-10 22:39:37 +01:00
debugPrint "PIDs: $PIDS"
# Prevent suspending itself
local pid_of_script=$$
2024-02-11 18:01:24 +01:00
if echo "$PIDS" | grep -q "$pid_of_script"; then
2024-02-10 22:39:37 +01:00
echo "You are trying to suspend the hyprfreeze process."
exit 1
fi
# Suspend or resume processes
2024-02-11 18:01:24 +01:00
if [[ "$(ps -o state= "$PID")" == T ]]; then
2024-02-10 22:39:37 +01:00
debugPrint "Resuming processes..."
kill -CONT $PIDS 2>/dev/null && echo "Resumed $(ps -p "$PID" -o comm= 2>/dev/null) (PID $PID)" || exit 1
2024-02-10 22:39:37 +01:00
else
debugPrint "Suspending processes..."
kill -STOP $PIDS 2>/dev/null && echo "Suspended $(ps -p "$PID" -o comm= 2>/dev/null) (PID $PID)" || exit 1
2024-02-10 22:39:37 +01:00
fi
2023-10-13 12:40:12 +02:00
}
function getPidByActive() {
2024-02-10 22:39:37 +01:00
debugPrint "Getting PID by active window..."
2024-02-12 12:19:58 +01:00
if [[ "hyprland" == "$DESKTOP" ]]; then
PID=$(hyprctl activewindow -j | jq '.pid')
elif [[ "sway" == "$DESKTOP" ]]; then
PID=$(swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true) | .pid')
else
echo "Detecting the active window is currently not supported on $DESKTOP."
exit 1
fi
2024-02-10 22:39:37 +01:00
debugPrint "PID by active window: $PID"
# Die if PID is not numeric (e.g. "null" if there is no active window)
if ! [[ $PID == ?(-)+([[:digit:]]) ]]; then
echo "Cannot freeze window with invalid PID $PID."
exit 1
fi
2023-10-13 12:40:12 +02:00
}
function getPidByPid() {
2024-02-10 22:39:37 +01:00
debugPrint "Getting PID by PID: $1"
# Check if process pid exists
2024-02-11 18:01:24 +01:00
if ! ps -p "$1" &>/dev/null; then
2024-02-10 22:39:37 +01:00
echo "Process ID $1 not found"
exit 1
fi
2023-10-13 12:40:12 +02:00
2024-02-10 22:39:37 +01:00
PID=$1
2023-10-13 12:40:12 +02:00
}
function getPidByName() {
2024-02-10 22:39:37 +01:00
debugPrint "Getting PID by name: $1"
# Check if process name exists
if ! pidof -x "$1" >/dev/null; then
echo "Process name $1 not found"
exit 1
fi
# Get last process if there are multiple
2024-02-11 18:01:24 +01:00
PID=$(pidof "$1" | awk '{print $NF}')
2024-02-10 22:39:37 +01:00
debugPrint "PID by name: $PID"
2023-10-13 12:40:12 +02:00
}
function getPidByProp() {
2024-02-10 22:39:37 +01:00
debugPrint "Getting PID by prop..."
2024-02-12 12:20:51 +01:00
if [[ "hyprland" == "$DESKTOP" ]]; then
2024-02-13 02:07:02 +01:00
if ! [ $(command -v hyprprop) ]; then
2024-02-12 12:20:51 +01:00
echo "You need to install 'hyprprop' to use this feature. (https://github.com/vilari-mickopf/hyprprop)"
exit 1
fi
PID=$(hyprprop | jq '.pid')
2024-02-13 02:07:02 +01:00
elif [[ "sway" == "$DESKTOP" ]]; then
if ! [ $(command -v swayprop) ]; then
echo "You need to install 'swayprop' to use this feature. (https://git.alternerd.tv/alterNERDtive/swayprop)"
exit 1
fi
PID=$(swayprop | jq '.pid')
2024-02-12 12:20:51 +01:00
else
echo "Selecting the target window by mouse is currently not supported on $DESKTOP."
2024-02-10 19:23:05 +01:00
exit 1
fi
2024-02-10 22:39:37 +01:00
debugPrint "PID by prop: $PID"
2023-10-13 12:40:12 +02:00
}
2024-02-12 11:58:21 +01:00
function detectEnvironment() {
if [ $(command -v loginctl) ]; then
local Desktop
eval "$(loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Desktop)"
DESKTOP=$Desktop
fi
if [ -z "$DESKTOP" ]; then
DESKTOP=$XDG_SESSION_DESKTOP
fi
if [ -z "$DESKTOP" ]; then
debugPrint "Could not determine desktop environment via \`loginctl\`, and XDG_SESSION_DESKTOP is not set. Assuming Hyprland."
DESKTOP="hyprland"
fi
# Enforce lowercase for consistent matching
DESKTOP="${DESKTOP,,}"
debugPrint "Desktop: $DESKTOP"
2024-02-12 11:58:21 +01:00
}
function printInfo() {
2024-02-12 11:58:21 +01:00
debugPrint "Printing process info..."
2024-02-10 22:39:37 +01:00
echo -e "$(tput bold)Process tree:$(tput sgr0)"
2024-02-11 18:01:24 +01:00
ps -p "$PID" 2>/dev/null && pstree -p "$PID"
2023-10-13 12:40:12 +02:00
2024-02-10 22:39:37 +01:00
echo -e "\n$(tput bold)Process threads:$(tput sgr0)"
2024-02-11 18:01:24 +01:00
ps -eLo pid,tid,comm | grep "$PID" 2>/dev/null
2023-10-13 12:40:12 +02:00
2024-02-10 22:39:37 +01:00
echo -e "\n$(tput bold)Process ID$(tput sgr0) = $PID \
2024-02-11 18:01:24 +01:00
\n$(tput bold)Process name$(tput sgr0) = $(ps -p "$PID" -o comm= 2>/dev/null) \
\n$(tput bold)Process state$(tput sgr0) = $(ps -o state= -p "$PID" 2>/dev/null)\n"
2023-10-13 12:40:12 +02:00
}
function sendNotification() {
2024-02-10 22:39:37 +01:00
debugPrint "Sending notification..."
2024-02-11 18:01:24 +01:00
local title
title=$( [[ "$(ps -p "$PID" -o state=)" == T ]] &&
echo "Suspended $(ps -p "$PID" -o comm= 2>/dev/null)" ||
echo "Resumed $(ps -p "$PID" -o comm= 2>/dev/null)")
2024-02-11 18:01:24 +01:00
local message="PID $PID"
2024-02-10 22:39:37 +01:00
notify-send "${title}" "${message}" -t "$NOTIF_TIMEOUT" -a Hyprfreeze
}
2023-10-13 12:40:12 +02:00
function args() {
2024-02-10 22:39:37 +01:00
# Track required flags
local required_flag_count=0
# Parse options
local options="hap:n:rst:"
local long_options="help,active,pid:,name:,prop,silent,notif-timeout:,info,dry-run,debug"
2024-02-11 18:01:24 +01:00
local parsed_args
parsed_args=$(getopt -o "$options" --long "$long_options" -n "$(basename "$0")" -- "$@")
2024-02-10 22:39:37 +01:00
eval set -- "$parsed_args"
while true; do
case $1 in
-h | --help)
printHelp
exit 0
;;
-a | --active)
((required_flag_count++))
FLAG_ACTIVE=true
;;
-p | --pid)
((required_flag_count++))
shift
FLAG_PID="$1"
;;
-n | --name)
((required_flag_count++))
shift
NAME_FLAG="$1"
;;
-r | --prop)
((required_flag_count++))
FLAG_PROP=true
;;
-s | --silent)
SILENT=1
;;
-t | --notif-timeout)
shift
NOTIF_TIMEOUT="$1"
;;
--info)
INFO=1
;;
--dry-run)
DRYRUN=1
;;
--debug)
DEBUG=1
;;
--)
shift # Skip -- argument
break
;;
*)
exit 1
;;
esac
shift
done
# Check if more than one required flag is provided, or if none was provided
if [ $required_flag_count -ne 1 ]; then
printHelp
exit 1
fi
2023-10-13 12:40:12 +02:00
}
function main() {
2024-02-10 22:39:37 +01:00
debugPrint "Starting main function..."
# Get pid by a required flag
if [ "$FLAG_ACTIVE" = true ]; then
getPidByActive
elif [ -n "$FLAG_PID" ]; then
getPidByPid "$FLAG_PID"
elif [ -n "$NAME_FLAG" ]; then
getPidByName "$NAME_FLAG"
elif [ "$FLAG_PROP" = true ]; then
getPidByProp
fi
# Suspend or resume process
toggleFreeze
# Run these functions after PID is obtained
if [ $INFO -eq 1 ]; then printInfo; fi
if [ $SILENT -ne 1 ]; then sendNotification; fi
debugPrint "End of main function."
2023-10-13 12:40:12 +02:00
}
SILENT=0
NOTIF_TIMEOUT=5000
2023-10-13 12:40:12 +02:00
INFO=0
DRYRUN=0
2024-02-10 22:39:37 +01:00
DEBUG=0
2023-10-13 12:40:12 +02:00
args "$@"
2024-02-12 11:58:21 +01:00
detectEnvironment
2023-10-13 12:40:12 +02:00
main