Last active
June 21, 2023 22:58
-
-
Save tobek/1710d534fb94ab5688fc47b2e0ba2490 to your computer and use it in GitHub Desktop.
Script for keeping your windows and applications handy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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