#!/usr/bin/env bash STATUS_FILE=/dev/shm/polybar_task_manager BAR_CONFIG_FILE=~/.config/polybar/bar.ini MODULES_LEFT_FILE=~/.config/polybar/modules-left.ini REFRESH=1 TASK_MENU=" Open a new one # Close" update_bar_config() { base_config=$(grep -e "^modules-left-dynamic *= *" $BAR_CONFIG_FILE | cut -f 3- -d " " ) new_config="taskslabel" for task in $(seq 1 "$1"); do cat <<MODULE_TEMPLATE [module/taskbar$task] type = custom/ipc hook-0 = echo "" hook-1 = ~/.config/polybar/scripts/task_manager --set-task $task hook-2 = ~/.config/polybar/scripts/task_manager --show-or-minimize-window $task hook-3 = ~/.config/polybar/scripts/task_manager --close-window $task hook-4 = ~/.config/polybar/scripts/task_manager --show-menu $task click-left = polybar-msg -p %pid% hook taskbar$task 3 click-middle = polybar-msg -p %pid% hook taskbar$task 4 click-right = polybar-msg -p %pid% hook taskbar$task 5 MODULE_TEMPLATE new_config="$new_config taskbar$task" done echo "modules-left = $base_config $new_config" > $MODULES_LEFT_FILE } create_module_tasklabel() { cat <<TASKLABEL_TEMPLATE [module/taskslabel] type = custom/ipc hook-0 = echo "%{T4}Tasks:%{T-}" hook-1 = echo "" ; click-left = rofi -modi window -show window -theme $ROFI_THEME -show-icons -location 1 -yoffset +45 -xoffset +20 click-left = dbus-send --session --type=method_call \ --dest=org.gnome.Shell /org/gnome/Shell org.gnome.Shell.Eval string:'Main.overview.show();' TASKLABEL_TEMPLATE } get_icon_by_name() { name=$(echo "$1" | tr '[:upper:]' '[:lower:]') declare -A ICON_MAP=( [tilix]= [code]= [brave-browser]= [firefox]= [chromium]= [tor]= [nextcloud]= [gnome-calculator]= [gnome-calendar]= [gnome-control-center]= [gnome-terminal]= [gpaste-ui]= [eog]= [evince]= [gimp-210]= [nautilus]= [file-roller]= [keepassxc]= [steam]= [skype]= [slack]= [spotify]= [telegramdesktop]= ) if [ ${ICON_MAP[$name]+_} ]; then echo "${ICON_MAP[$name]}" else echo "$name" | cut -c 1 | tr '[:lower:]' '[:upper:]' fi } show_tasks() { max_tasks=$(grep -cE "^\[module/taskbar[0-9]+]" ~/.config/polybar/task_manager.ini) wmctrl -lxp | awk '{if ($2 > -1) print $4,$1,$3}' \ | sed -r 's/([0-9])\.([0-9])/\1\2/g' \ | awk -F'.' '{ print $NF }' \ | tail -"$max_tasks" | sort > $STATUS_FILE.current if [ -f $STATUS_FILE.active ]; then if [ "$(get_task_id "$(cat $STATUS_FILE.active)")" = "$(get_active_window)" ]; then diff -q $STATUS_FILE $STATUS_FILE.current > /dev/null 2>&1 if [ $? -ne 1 ]; then rm -rf $STATUS_FILE.current return 0 fi fi fi mv $STATUS_FILE.current $STATUS_FILE num_windows=$(wc -l $STATUS_FILE | cut -f 1 -d " ") if [ "$num_windows" -eq 0 ]; then polybar-msg hook taskslabel 2 > /dev/null else polybar-msg hook taskslabel 1 > /dev/null fi for counter in $(seq 1 "$max_tasks"); do if [ "$counter" -le "$num_windows" ]; then polybar-msg hook taskbar"$counter" 2 > /dev/null else polybar-msg hook taskbar"$counter" 1 > /dev/null fi sleep 0.1 done } print_task_icon() { name=$(sed "${1}q;d" $STATUS_FILE | cut -f 1 -d " " | tr '[:upper:]' '[:lower:]') icon=$(get_icon_by_name "$name") if [ "$(get_task_id "$1")" = "$(get_active_window)" ]; then echo '%{T6}%{F#F5A70A}'"$icon"'%{F-}%{T-}' if [ -f $STATUS_FILE.active ]; then polybar-msg hook "taskbar$(cat $STATUS_FILE.active)" 2 > /dev/null fi echo "$1" > $STATUS_FILE.active else echo '%{T6}'"$icon"'%{T-}' fi } show_task_menu() { pid=$(get_task_pid "$1") cmd=$(ps --no-headers -o cmd "$pid" \ | sed 's/--gapplication-service//g' \ | tr -d '\n') offset=$(( ($1 * 65) )) ROFI="rofi -dmenu -sep # -theme $ROFI_THEME -location 1 -width 8 -yoffset +45 -xoffset +${offset}" choice=$(echo "$TASK_MENU" | $ROFI -theme-str 'inputbar { children: [];}' \ | sed 's/^[[:space:]]*//' | cut -f 1 -d " ") case "$choice" in Open) $cmd &>/dev/null & ;; Close) id=$(get_task_id "$1") wmctrl -ic "$id" ;; esac print_task_icon "$1" } get_active_window() { echo 0x0"$(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2 | cut -f 2 -d 'x')" } get_task_id() { sed "${1}q;d" $STATUS_FILE | cut -f 2 -d " " } get_task_pid() { sed "${1}q;d" $STATUS_FILE | cut -f 3 -d " " } daemon() { while true; do show_tasks sleep $REFRESH done } case "$1" in --daemon) > /dev/shm/polybar_task_manager daemon ;; --generate-config) create_module_tasklabel > ~/.config/polybar/task_manager.ini update_bar_config "$2" >> ~/.config/polybar/task_manager.ini ;; --set-task) print_task_icon "$2" ;; --show-menu) show_task_menu "$2" ;; --show-or-minimize-window) id=$(get_task_id "$2") if [ "$id" = "$(get_active_window)" ]; then xdotool getactivewindow windowminimize else wmctrl -ia "$id" fi print_task_icon "$2" ;; --close-window) id=$(get_task_id "$2") wmctrl -ic "$id" ;; esac exit 0