mirror of
https://github.com/jimeh/dotfiles.git
synced 2026-02-19 08:26:42 +00:00
Rewrite linux-toggle-app script
Main big change/fix is that it will only activate windows belonging to the specified process. Before it would activate any window with a matching title, regardless of what process it belonged to.
This commit is contained in:
@@ -1,109 +1,149 @@
|
||||
#!/bin/bash
|
||||
#! /usr/bin/env bash
|
||||
if [ -n "$DEBUG" ]; then set -x; fi
|
||||
|
||||
# Borrowed from:
|
||||
# - http://bytefreaks.net/gnulinux/bash/howto-make-terminator-terminal-act-like-guake-terminal-in-fedora-20ubuntu-14-10
|
||||
show-help() {
|
||||
echo "usage: $(basename "$0") [<options>]"
|
||||
echo
|
||||
echo "Toggle visibility of a window belonging to a specific process:"
|
||||
echo " - If not running the <executable> will be launched."
|
||||
echo " - If process is running <window-name> (or first window found) will be"
|
||||
echo " activated and focused."
|
||||
echo " - If process is running and <window-name> is in focus, minimize it."
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " -p (Required) process name given to pgrep to narrow list of"
|
||||
echo " possible target windows."
|
||||
echo " -e Executable name or path used to launch process when it is not"
|
||||
echo " running. If not specified, will attempt to use process name"
|
||||
echo " instead."
|
||||
echo " -w Title/name of window which belongs to process to focus on."
|
||||
echo " Allows regular expression matching. If not specified, the first"
|
||||
echo " window found belonging to process will be used."
|
||||
echo " -b Bring window to current desktop if it is on another one."
|
||||
echo " -a Assign window to all desktops/workspaces after activating it."
|
||||
echo " -h Display this help message."
|
||||
echo
|
||||
echo "Requirements:"
|
||||
echo " - xdotool"
|
||||
echo " - wmctrl"
|
||||
}
|
||||
|
||||
# The purpose of this script is to allow the user to toggle the visibility of
|
||||
# (almost) any window. Please note it will work on the first match, so if there
|
||||
# are multiple instances of an application it would be a random window of them
|
||||
# the one to be affected.
|
||||
error() {
|
||||
echo -e "ERROR: $*" 1>&2
|
||||
}
|
||||
|
||||
# Only checks dependencies on request to keep toggling behavior as fast as
|
||||
# possible.
|
||||
if [ "$1" == "--install-deps" ]; then
|
||||
# Checking that all dependencies are met, since we cannot proceed without
|
||||
# them.
|
||||
DEPENDENCIES=("xdotool" "wmctrl")
|
||||
MANAGERS=("yum" "apt-get")
|
||||
error-help() {
|
||||
error "$@"
|
||||
show-help 1>&2
|
||||
}
|
||||
|
||||
echo "Checking dependencies:"
|
||||
for DEPENDENCY in ${DEPENDENCIES[@]}; do
|
||||
if hash $DEPENDENCY 2>/dev/null; then
|
||||
echo "- $DEPENDENCY: ok"
|
||||
OPT_PROC=""
|
||||
OPT_BIN=""
|
||||
OPT_WIN=""
|
||||
OPT_BRING=""
|
||||
OPT_ALL=""
|
||||
|
||||
parse-arguments() {
|
||||
while getopts ":p:e:w:bah" opt; do
|
||||
case ${opt} in
|
||||
p )
|
||||
OPT_PROC="$OPTARG"
|
||||
;;
|
||||
e )
|
||||
OPT_BIN="$OPTARG"
|
||||
;;
|
||||
w )
|
||||
OPT_WIN="$OPTARG"
|
||||
;;
|
||||
b )
|
||||
OPT_BRING="1"
|
||||
;;
|
||||
a )
|
||||
OPT_ALL="1"
|
||||
;;
|
||||
h )
|
||||
show-help
|
||||
;;
|
||||
\? )
|
||||
error-help "Invalid option: -${OPTARG}\n" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ -z "$OPT_PROC" ]; then
|
||||
error-help "-p option is required."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$OPT_BIN" ]; then
|
||||
OPT_BIN="$OPT_PROC"
|
||||
fi
|
||||
|
||||
if ! command -v "$OPT_BIN" &>/dev/null; then
|
||||
error "\"${OPT_BIN}\" does not seem to be a valid executable."
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local target
|
||||
local pid
|
||||
local win_id
|
||||
local focused_id
|
||||
|
||||
parse-arguments "$@"
|
||||
|
||||
mapfile -t target < <(find-window)
|
||||
pid="${target[0]}"
|
||||
win_id="${target[1]}"
|
||||
|
||||
if [ -z "$pid" ]; then
|
||||
echo "$OPT_PROC not running, launching with: \"$OPT_PROC\""
|
||||
"$OPT_PROC"
|
||||
else
|
||||
echo "$OPT_PROC instance found"
|
||||
focused_id="$(xdotool getactivewindow)"
|
||||
|
||||
if [ "$win_id" == "$focused_id" ]; then
|
||||
echo "Target window is in focus, minimizing"
|
||||
xdotool windowminimize "$win_id"
|
||||
else
|
||||
echo "- $DEPENDENCY: not found"
|
||||
for MANAGER in ${MANAGERS[@]}; do
|
||||
if hash $MANAGER 2>/dev/null; then
|
||||
echo -n "$DEPENDENCY is missing, would you like to try and install " \
|
||||
"it via $MANAGER now? [Y/N] (default is Y): "
|
||||
read ANSWER
|
||||
if [[ "$ANSWER" == "Y" || "$ANSWER" == "y" || "$ANSWER" == "" ]]; then
|
||||
sudo "$MANAGER" install "$DEPENDENCY"
|
||||
else
|
||||
echo "Terminating"
|
||||
exit -1
|
||||
fi
|
||||
if [ -n "$OPT_BRING" ]; then
|
||||
echo "Bring window to current desktop and activate"
|
||||
wmctrl -i -R "$win_id"
|
||||
|
||||
if [ -n "$OPT_ALL" ]; then
|
||||
echo "Assign window to all desktops"
|
||||
xdotool set_desktop_for_window "$win_id" -1
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Activating window triggering desktop switch as needed"
|
||||
xdotool windowactivate "$win_id"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
find-window() {
|
||||
local pid
|
||||
local win_id
|
||||
local opts
|
||||
|
||||
opts=(--all --onlyvisible)
|
||||
|
||||
if [ -n "$OPT_WIN" ]; then
|
||||
opts+=(--name "$OPT_WIN")
|
||||
fi
|
||||
|
||||
for pid in $(pgrep "$OPT_PROC"); do
|
||||
win_id="$(xdotool search --pid "$pid" "${opts[@]}")"
|
||||
if [ -n "$win_id" ]; then
|
||||
echo -e "$pid\n$win_id"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" == "-a" ]; then
|
||||
MOVE_TO="yes"
|
||||
shift 1
|
||||
fi
|
||||
|
||||
APP_NAME="$1"
|
||||
|
||||
if [ -n "$2" ]; then
|
||||
APP_BIN="$2"
|
||||
else
|
||||
APP_BIN="$APP_NAME"
|
||||
fi
|
||||
|
||||
if [ -n "$3" ]; then
|
||||
WIN_NAME="$3"
|
||||
else
|
||||
WIN_NAME="$APP_NAME"
|
||||
fi
|
||||
|
||||
# Checking if the application name provided by the user exists
|
||||
if ! command -v "$APP_BIN" 2>/dev/null; then
|
||||
echo -e "$APP_BIN does not seem to be a valid executable\nTerminating"
|
||||
exit -2
|
||||
fi
|
||||
|
||||
# Check if a process matching APP_NAME exists, and in the case of multiple
|
||||
# processes (for example Slack), limit it to the first process which has a
|
||||
# window who's title matches WIN_NAME.
|
||||
PID=""
|
||||
for pid in $(pgrep "$APP_NAME"); do
|
||||
if xdotool search --all --onlyvisible --pid "$pid" --name "$WIN_NAME" &>/dev/null; then
|
||||
PID="$pid"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# If the application is not running, we will try to launch it.
|
||||
if [ -z "$PID" ]; then
|
||||
echo "$APP_NAME not running, launching it.."
|
||||
"$APP_BIN"
|
||||
else
|
||||
# Since the application has a live instance, we can proceed with the rest of
|
||||
# the code. We will get the PID of the application that is currently focused,
|
||||
# if it is not the application we passed as parameter we will change the focus
|
||||
# to that. In the other case, we will minimize the application.
|
||||
echo -n "$APP_NAME instance found - "
|
||||
FOCUSED="$(xdotool getactivewindow getwindowpid)"
|
||||
if [[ "$PID" == "$FOCUSED" ]]; then
|
||||
echo "It was focused so we are minimizing it"
|
||||
# We minimize the active window which we know in this case that it is the
|
||||
# application we passed as parameter.
|
||||
xdotool getactivewindow windowminimize
|
||||
else
|
||||
echo "We are setting the focus on it"
|
||||
# We set the focus to the application we passed as parameter. If it is
|
||||
# minimized it will be raised as well.
|
||||
if [ "$MOVE_TO" == "yes" ]; then
|
||||
xdotool search --all --onlyvisible --pid "$PID" --name "$WIN_NAME" \
|
||||
windowactivate
|
||||
else
|
||||
# This allows window name to be a regular expression
|
||||
WIN_TITLE="$(xdotool search --all --onlyvisible --pid "$PID" --name "$WIN_NAME" getwindowname)"
|
||||
wmctrl -R "$WIN_TITLE"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user