Skip to content

Instantly share code, notes, and snippets.

@tobek
Last active June 21, 2023 22:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tobek/1710d534fb94ab5688fc47b2e0ba2490 to your computer and use it in GitHub Desktop.
Save tobek/1710d534fb94ab5688fc47b2e0ba2490 to your computer and use it in GitHub Desktop.
Script for keeping your windows and applications handy
#!/bin/bash
usage()
{
cat << EOF
usage: thewindow [OPTIONS] SEARCH_STRING COMMAND
This script will search the X window manager for any open window containing SEARCH_STRING and, if found, will move to the containing desktop, raise that window, and give it focus.
If a matching window on the current desktop is found, that will be focused first instead of any matching windows on other desktops.
If the matching window already has focus, and another window on the same desktop matches SEARCH_STRING, that other window will be focused. This way you can cycle between multiple instances of the same application open on one desktop (currently, however, it will only cycle you between the first 2 windows listed by wmctrl).
If no matching window is found, COMMAND is run.
Good for keeping handy your browser, terminal, code editor, chat application, file manager, etc.
OPTIONS:
-h Show this message
-c Only activate a matching window on current desktop, otherwise run COMMAND
-v Verbose mode (logs to /tmp/thewindow.log for easy use via shortcut)
EOF
}
only_curr_desktop=
verbose=
while getopts "hcv" OPTION
do
case $OPTION in
h)
usage
exit 2
;;
c)
only_curr_desktop=1
;;
v)
verbose=1
;;
?)
usage
exit 2
;;
esac
done
win_search=${@:$OPTIND:1}
command=${@:$OPTIND+1:1}
if [[ ( -z $win_search ) || ( -z $command ) ]]; then
usage
exit 2
fi
[ $verbose ] && echo searching for \""$win_search"\" >> /tmp/thewindow.log
curr_desktop=`wmctrl -d | grep '*' | cut -c 1`
focused_win_id=`echo "obase=16; $(xdotool getwindowfocus)" | bc | tr '[:upper:]' '[:lower:]'`
already_focused=
desktop_filter=
if [[ -n $only_curr_desktop ]]
then
# Not a perfect filter (could false positive match desktop number window title) but goal is just to cut down number of windows we check, cause it's slow, actually
desktop_filter=" $curr_desktop"
[ $verbose ] && echo desktop filter: \"$desktop_filter\" >> /tmp/thewindow.log
fi
# First look for window with matching name on the current desktop
while read win_info ; do
[ $verbose ] && echo checking $win_info >> /tmp/thewindow.log
win_desktop=`echo $win_info | cut -d " " -f 2`
win_id=`echo $win_info | cut -d " " -f 1`
if [[ $win_id == *"$focused_win_id"* ]]; then
# This window is already focused - let's keep looking for another one that matches search, if any, so user can cycle between multiple matching windows
[ $verbose ] && echo found match $win_id but it\'s already focused >> /tmp/thewindow.log
already_focused=1 # If none, this flag will ensure we don't run the command to create a new process for no reason
only_curr_desktop=1 # Never jump to another desktop when cycling through multiple matching windows
continue
fi
if [ $curr_desktop == $win_desktop ]
then
# Found matching window on current desktop
[ $verbose ] && echo found match $win_id on current desktop >> /tmp/thewindow.log
wmctrl -ia $win_id
exit 0
fi
done < <(wmctrl -l | grep "$win_search" | grep "$desktop_filter") # could use `wmctrl -lx` to search WM_CLASS too
if [[ ( $only_curr_desktop -ne 1 ) && ( -n $win_id ) ]]
then
# We found a window with right name but wasn't on matching desktop, switch to it:
[ $verbose ] && echo found match $win_id on another desktop >> /tmp/thewindow.log
wmctrl -ia $win_id
exit 0
fi
if [[ -z $already_focused ]]
then
# Didn't find a match, launch it!
[ $verbose ] && echo found no match, running \""$command"\" >> /tmp/thewindow.log
bash -c "$command" &
else
[ $verbose ] && echo only match we found on this desktop was already focused, doing nothing >> /tmp/thewindow.log
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment