diff --git a/tdrop b/tdrop new file mode 100755 index 0000000..8e26209 --- /dev/null +++ b/tdrop @@ -0,0 +1,208 @@ +#!/bin/bash + +print_help() { + echo " + Used for hiding/unhiding programs to acheive quake-dropdown-like-functionality. Can create a dropdown window if one does not already exist and provides options to control the intial size and position, e.g. to leave panels visible. When used with a terminal, provides the option to specify the name of a tmuxinator or tmux session to automatically start or attach to. + + Also supports the ability to auto-hide and auto-show. For example, this can be used to automatically hide a window when opening something, e.g. image viewer, video player, etc. from it, and then re-show the window whenever the image view, video player, etc. is closed. + + Takes a terminal as an argument or one of auto_show, auto_hide, or toggle_auto_hide. 'toggle_auto_hide' toggles whether calling 'auto_hide' or 'auto_show' will have any effect. + +usage: tdrop [options] or +options: + -h height specify a height for a newly created term (default: 100%) + -w width specify a width for a newly created term (default: 45%) + -x pos specify x offset for a newly created term (default: 0) + -y pos specify y offset for a newly created term (default: 1) + -s name name for tmux or tmuxinator session (if not given, will not use tmux) + -n num num or extra text; only needed if want multiple dropdowns of same program (default: "") + -p cmd provide a pre command to float the window if necessary + -P cmd provide a post command to float the window if necessary + -W the given program is not a terminal (or lacks an -e flag) (default: assume it IS terminal) + --no-cancel don't cancel auto-showing + (default is to prevent this when manually toggling a term after it is auto-hidden) + --help print help + +See man page for more details. +" + if [[ $1 == illegal_opt ]]; then + exit 1 + else + exit 0 + fi +} + +# xdotool can take percentages; cannot take decimal percentages though +width="100%" +height="45%" +xoff=0 +yoff=1 +float_pre="" +float_post="" +session_name="" +num="" +normal_window=false +cancel_auto_show=true +term=${*:0-1} +while getopts :h:w:x:y:s:n:p:P:-:W opt +do + case $opt in + h) height=$OPTARG;; + w) width=$OPTARG;; + x) xoff=$OPTARG;; + y) yoff=$OPTARG;; + s) session_name=$OPTARG;; + n) num=$OPTARG;; + p) float_pre=$OPTARG;; + P) float_post=$OPTARG;; + W) normal_window=true;; + -) + OPTION=$(echo "$OPTARG" | awk -F '=' '{print $1}') + OPTARG=$(echo "$OPTARG" | awk -F '=' '{print $2}') + case $OPTION in + height) height=$OPTARG;; + width) width=$OPTARG;; + x-offset) xoff=$OPTARG;; + y-offset) yoff=$OPTARG;; + session) session_name=$OPTARG;; + number) num=$OPTARG;; + pre-command) float_pre=$OPTARG;; + post-command) float_post=$OPTARG;; + normal-window) normal_window=true;; + no-cancel) cancel_auto_show=false;; + help) print_help;; + esac;; + *) print_help illegal_opt;; + esac +done + +float_pre_command() { + if [[ -n $float_pre ]]; then + if [[ $float_pre == bspwm ]]; then + float_pre="bspc rule -a '$1' -o floating=on" + fi + eval "$float_pre" + fi +} + +float_post_command() { + if [[ -n $float_post ]]; then + eval "$float_post" + fi +} + +term_create() { + if [[ -n $session_name ]]; then + # ugly workarounds due to how different terms different -e flags work + if [[ $term == urxvt ]]; then + $term -e bash -c "sleep 0.01 && xdotool getactivewindow > /tmp/tdrop/$term$num && xdotool getactivewindow windowmove $xoff $yoff windowsize $width $height && tmux attach-session -dt $session_name || tmuxinator start $session_name || tmux new-session -s $session_name" & + else + # starting with '/bin/bash -c' because required by termite + $term -e "/bin/bash -c 'sleep 0.01 && xdotool getactivewindow > /tmp/tdrop/$term$num && xdotool getactivewindow windowmove $xoff $yoff windowsize $width $height && tmux attach-session -dt $session_name || tmuxinator start $session_name || tmux new-session -s $session_name'" & + fi + else + # not using hold, because flag is different for different terminals + if [[ $term == urxvt ]]; then + $term -e bash -c "sleep 0.01 && xdotool getactivewindow > /tmp/tdrop/$term$num && xdotool getactivewindow windowmove $xoff $yoff windowsize $width $height && $SHELL" & + else + # not using hold, because flag is different for different terminals + $term -e "/bin/bash -c 'sleep 0.01 && xdotool getactivewindow > /tmp/tdrop/$term$num && xdotool getactivewindow windowmove $xoff $yoff windowsize $width $height && $SHELL'" & + fi + fi +} + +win_create() { + $term & + # need to wait for window to be created + sleep 0.2 + # often pids have two wids; first one has always been the right one for what I've tested + wid=$(xdotool search --pid $! | head -n 1) + echo "$wid" > /tmp/tdrop/"$term$num" + xdotool windowmove "$wid" "$xoff" "$yoff" windowsize "$wid" "$width" "$height" +} + +wid_toggle() { + mkdir -p /tmp/tdrop + # get saved window id if already created + wid=$(< /tmp/tdrop/"$term$num") + exists=true + visibility=$(xwininfo -id "$wid" | awk '/Map State/ {print $3}') + if [[ -z $wid ]] || [[ -z $visibility ]]; then + exists=false + fi + if $exists && [[ $visibility != IsUnviewable ]]; then + if [[ $visibility == IsUnMapped ]]; then + float_pre_command "$term" + xdotool windowmap "$wid" + float_post_command + else + xdotool windowunmap "$wid" + maybe_cancel_auto_show "$wid" + fi + else + # make it + float_pre_command "$term" + if $normal_window; then + win_create + else + term_create + fi + float_post_command + fi +} + +auto_hide() { + no_hide=$(< /tmp/tdrop/auto_hidden/no_hide) + if [[ -z $no_hide ]]; then + wid=$(xdotool getactivewindow) + class_name=$(xprop -id "$(xprop -root _NET_ACTIVE_WINDOW | awk '{print $5}')" WM_CLASS | awk '{ gsub(/"/, ""); print $4}') + mkdir -p /tmp/tdrop/auto_hidden + echo "$wid" > /tmp/tdrop/auto_hidden/wid + echo "$class_name" > /tmp/tdrop/auto_hidden/class + xdotool windowunmap "$wid" + fi +} + +auto_show() { + no_hide=$(< /tmp/tdrop/auto_hidden/no_hide) + if [[ -z $no_hide ]]; then + wid=$(< /tmp/tdrop/auto_hidden/wid) + class=$(< /tmp/tdrop/auto_hidden/class) + float_pre_command "$class" + xdotool windowmap "$wid" + float_post_command + fi +} + +maybe_cancel_auto_show() { + auto_hidden_wid=$(< /tmp/tdrop/auto_hidden/wid) + if $cancel_auto_show && [[ $1 == "$auto_hidden_wid" ]]; then + > /tmp/auto_hidden_terminal/wid + fi +} + +toggle_auto_hide() { + no_hide=$(< /tmp/tdrop/auto_hidden/no_hide) + mkdir -p /tmp/tdrop/auto_hidden + if [[ -z $no_hide ]]; then + echo "true" > /tmp/tdrop/auto_hidden/no_hide + else + > /tmp/tdrop/auto_hidden/no_hide + fi +} + +if [[ -n $1 ]]; then + if [[ $term == toggle_auto_hide ]]; then + toggle_auto_hide + elif [[ $term == auto_hide ]]; then + auto_hide + elif [[ $term == auto_show ]]; then + auto_show + else + wid_toggle + fi +else + print_help illegal_opt +fi +# vim is dumb +# vim: set ft=sh: