You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdrop-xtoolwait/tdrop

825 lines
26 KiB
Plaintext

8 years ago
#!/usr/bin/env bash
MUTDROP_PATH=/tmp/tdrop_"$USER"
# shellcheck disable=SC2174
mkdir -p "$MUTDROP_PATH" -m 700
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 window 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. 'current' will turn the current window into a dropdown.
usage: tdrop [options] <program or 'current'> or one of <auto_show/auto_hide/toggle_auto_hide>
options:
-h height specify a height for a newly created term (default: 45%)
-w width specify a width for a newly created term (default: 100%)
-x pos specify x offset for a newly created term (default: 0)
-y pos specify y offset for a newly created term (default: 1, see BUGS in man)
-s name name for tmux or tmuxinator session (requires the program to be a supported terminal)
8 years ago
-n num num or extra text; only needed if want multiple dropdowns of same program (default: none)
-p cmd provide a pre-map command to float the window if necessary
-P cmd provide a post-map command to float the window if necessary
-M cmd provide a post-unmap command; can be used for example with a window manager that doesn't support floating to turn fullscreen on when mapping a terminal then off when unmapping it
-O cmd provide a one time command only for when a dropdown is created/initiated (useful for 'tdrop current')
-d XxY give decoration/border size to accurately save position; only applicable with auto_show; on applicable with a few window managers (e.g. blackbox)
-f specify flags/options to be used when creating the term or window (e.g. -f '--title mytitle'; default: none). caution: if there is a tmux/tmuxinator session specified (with -s), the option to execute a program (usually -e for terminal programs) is implicitly added by tdrop!
-a automatically detect window manager and if settings exist for it, automatically set -p, -P, and -d values as necessary; this can have affect when used with a terminal or with auto_show or auto_hide (default: false)
-m for use with multiple monitors and only with dropdowns (not for auto_show or auto_hide); convert percentages used for width or height to values relative to the size of the current monitor and force reszing of the dropdown when the monitor changes (default: false)
-c cmd provide a command to be run after first creating the dropdown
(e.g. to set some window property)
--clear clear saved window id; useful accidentally make a window a dropdown (e.g. '$ tdrop --clear current')
--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
}
#
# Default Options and Option Parsing
#
# xdotool can take percentages; cannot take decimal percentages though
width="100%"
height="45%"
xoff=0
yoff=2
session_name=""
num=""
map_pre=""
map_post=""
unmap_post=""
oneshot_post=""
create_hook=""
map_hook=""
dec_fix=""
program_flags=""
clearwid=false
cancel_auto_show=true
auto_detect_wm=false
monitor_aware=false
while getopts :h:w:x:y:s:n:p:P:M:O:c:d:f:-:am 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) map_pre=$OPTARG;;
P) map_post=$OPTARG;;
M) unmap_post=$OPTARG;;
O) oneshot_post=$OPTARG;;
c) create_hook=$OPTARG;;
d) dec_fix=$OPTARG;;
f) program_flags=$OPTARG;;
a) auto_detect_wm=true;;
m) monitor_aware=true;;
-)
if [[ $OPTARG =~ ^(auto-detect-wm|monitor-aware|clear|no-cancel|help)$ ]] || \
[[ $OPTARG == *=* ]]; then
OPTION=${OPTARG%%=*}
OPTARG=${OPTARG#*=}
else
OPTION=$OPTARG
# shellcheck disable=SC2124
OPTARG=${@:$OPTIND:1}
((OPTIND++))
fi
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) map_pre=$OPTARG;;
post-command) map_post=$OPTARG;;
post-unmap) unmap_post=$OPTARG;;
oneshot-post) oneshot_post=$OPTARG;;
create-hook) create_hook=$OPTARG;;
map-hook) map_hook=$OPTARG;;
decoration-fix) dec_fix=$OPTARG;;
program-flags) program_flags=$OPTARG;;
auto-detect-wm) auto_detect_wm=true;;
monitor-aware) monitor_aware=true;;
clear) clearwid=true;;
no-cancel) cancel_auto_show=false;;
help) print_help;;
*) print_help illegal_opt;;
esac;;
*) print_help illegal_opt;;
esac
done
shift "$((OPTIND-1))"
program=$1
if [[ $# -ne 1 ]]; then
echo >&2 "Exactly 1 positional argument is required." \
"For help use -h or --help or see the manpage." | \
tee -a "$MUTDROP_PATH"/log
exit 1
fi
# validate options that require number values
if [[ ! $height$width$xoff$yoff =~ ^[0-9%-]*$ ]]; then
echo >&2 "The -h, -w, -x, and -y values must be numbers (or percentages)." | \
tee -a "$MUTDROP_PATH"/log
exit 1
fi
if [[ -n $dec_fix ]] && [[ ! $dec_fix =~ ^-?[0-9]+x-?[0-9]+$ ]]; then
echo >&2 "The decoration fix value must have form 'num'x'num'." \
"The numbers can be negative or zero." | tee -a "$MUTDROP_PATH"/log
exit 1
fi
# non-user-settable global vars
# necessary to account for differences in geometry/positioning output from xwininfo
# for different WMs (matters when a window is in a corner or on the side)
subtract_when_same=true
# will be set to true to eliminate or reduce flicker for WMs that alter window
# position when remapping; when true, windowmap and windowmove are combined, so that
# the window is correctly positioned earlier
combine_map_post=false
# set to true if the -m option is being used and the monitor has changed
# in order to force resize the dropdown to the given width/height percentages
# for the current monitor
monitor_changed=false
# used for -m option; at first tdrop assumes that there is a focused window
# on the current desktop; if there isn't (and the WM doesn't have some way to
# query the current monitor), this will be set to false, and tdrop will have to
# find out the current monitor info after opening the dropdown
# (currently, using xwininfo to find the position of a window is the only
# WM-independent way I know to find out what the current monitor is)
focused_window_exists=true
#
# Multiple Monitor Automatic Re-Sizing
#
percent_of_total() { # percent total
awk "BEGIN {printf(\"%.0f\", 0.01*${1%\%}*$2)}"
}
# acts on globals
convert_geometry_to_pixels() {
total_width=$1
total_height=$2
local minus_width minus_height minus_xoff minus_yoff
if [[ $width =~ %$ ]]; then
width=$(percent_of_total "$width" "$total_width")
elif [[ $width =~ ^- ]]; then
minus_width=${width#-}
width=$((total_width-minus_width))
fi
if [[ $height =~ %$ ]]; then
height=$(percent_of_total "$height" "$total_height")
elif [[ $height =~ ^- ]]; then
minus_height=${height#-}
height=$((total_height-minus_height))
fi
if [[ $xoff =~ %$ ]]; then
xoff=$(percent_of_total "$xoff" "$total_width")
elif [[ $xoff =~ ^- ]]; then
minus_xoff=${xoff#-}
xoff=$((total_width-minus_xoff))
fi
if [[ $yoff =~ %$ ]]; then
yoff=$(percent_of_total "$yoff" "$total_height")
elif [[ $yoff =~ ^- ]]; then
minus_yoff=${yoff#-}
yoff=$((total_height-minus_yoff))
fi
}
update_geometry_settings_for_monitor() {
# 1. Correctly interpret width/height percentages when there exist multiple
# monitors so an initially created dropdown is the correct size (xdotool
# would create a dropdown the width of all screens for 100% width)
# 2. Force resize the dropdown to the correct percentage of the current
# monitor IF the monitor has changed since the last time the dropdown
# was used
# it is conceivable that a user may want to use -m but not -a, so
# get the wm from within this function
local wm current_monitor
wm=$(get_window_manager)
if [[ $wm == bspwm ]]; then
current_monitor=$(bspc query -T -m | grep -Po '^{"name":.*?",' | \
awk -F ":" '{gsub("[\",]", ""); print $2}')
elif [[ $wm == i3 ]]; then
# I'd rather not make jq a dependency
current_monitor=$(i3-msg -t get_workspaces | sed 's/{"num"/\n/g' | \
awk -F ',' '/focused":true/ {sub(".*output",""); gsub("[:\"]",""); print $1}')
fi
local monitor_geo x_begin y_begin x_width y_height
if [[ -n $current_monitor ]]; then
monitor_geo=$(xrandr --query | \
awk "/$current_monitor/ {gsub(\"primary \",\"\"); print \$3}")
x_begin=$(echo "$monitor_geo" | awk -F '+' '{print $2}')
y_begin=$(echo "$monitor_geo" | awk -F '+' '{print $3}')
x_width=$(echo "$monitor_geo" | awk -F 'x' '{print $1}')
y_height=$(echo "$monitor_geo" | awk -F 'x|+' '{print $2}')
else
local wid wininfo window_x window_y monitors_info x_end y_end
# determine current monitor in generic way
wid=$(xdotool getactivewindow)
if [[ -z $wid ]]; then
# will try again after remapping or creating the dropdown
return 1
fi
wininfo=$(xwininfo -id "$wid")
window_x=$(echo "$wininfo" | awk '/Absolute.*X/ {print $4}')
window_y=$(echo "$wininfo" | awk '/Absolute.*Y/ {print $4}')
monitors_info=$(xrandr --query | awk '/ connected/ {gsub("primary ",""); print}')
while read -r monitor; do
monitor_geo=$(echo "$monitor" | awk '{print $3}')
if [[ $monitor_geo =~ ^[0-9]+x[0-9]+\+[0-9]+\+[0-9]+$ ]]; then
x_begin=$(echo "$monitor_geo" | awk -F '+' '{print $2}')
y_begin=$(echo "$monitor_geo" | awk -F '+' '{print $3}')
x_width=$(echo "$monitor_geo" | awk -F 'x' '{print $1}')
y_height=$(echo "$monitor_geo" | awk -F 'x|+' '{print $2}')
x_end=$((x_begin+x_width))
y_end=$((y_begin+y_height))
if [[ $window_x -ge $x_begin ]] && [[ $window_x -lt $x_end ]] && \
[[ $window_y -ge $y_begin ]] && [[ $window_y -lt $y_end ]]; then
current_monitor=$(echo "$monitor" | awk '{print $1}')
break
fi
fi
done <<< "$monitors_info"
fi
# convert w/h/x/y percentages/negatives to pixels
convert_geometry_to_pixels "$x_width" "$y_height"
# update x and y offsets, so that will appear on correct screen
# (required for some WMs apparently, but not for others)
((xoff+=x_begin))
((yoff+=y_begin))
# determine if monitor has changed and save current monitor
local last_monitor
last_monitor=$(< "$MUTDROP_PATH"/last_monitor) 2> /dev/null
echo "$current_monitor" > "$MUTDROP_PATH"/last_monitor
if [[ $current_monitor != "$last_monitor" ]]; then
monitor_changed=true
fi
}
set_geometry_for_monitor() {
xdotool windowmove "$1" "$xoff" "$yoff" windowsize "$1" "$width" "$height"
}
#
# WM Detection and Settings
#
get_window_manager() {
# xfwm4 and fvwm at least will give two names (hence piping into head)
xprop -notype -id "$(xprop -root -notype | \
awk '$1=="_NET_SUPPORTING_WM_CHECK:"{print $5}')" \
-f _NET_WM_NAME 8u | awk -F "\"" '/WM_NAME/ {print $2}' | head -n 1
}
# settings that apply for both tdrop <term> and tdrop auto_(hide|show)
# e.g. tilers w/ floating support: settings for floating a window when mapping it
# can set up a rule for always floating a window or term type/class
# alternatively, can use these settings to float just the dropdown
wm_autoset_for_all() {
# bspwm will use previous size when floating already
if [[ $wm == bspwm ]]; then
map_pre() {
class=$1
if [[ $1 =~ ^google-chrome ]]; then
class=google-chrome
elif [[ $1 == st ]]; then
class=st-256color
fi
# newest (using "instance" names)
if [[ $class =~ [A-Z] ]]; then
bspc rule -a "$class" -o state=floating
else
bspc rule -a \*:"$class" -o state=floating
fi
}
elif [[ $wm == awesome ]]; then
# awesome remembers size, but need to float and then set size first
map_post_oneshot() {
echo 'local awful = require("awful") ; awful.client.floating.set(c, true)' | \
awesome-client && \
xdotool windowmove "$1" "$xoff" "$yoff" \
windowsize "$1" "$width" "$height"
}
map_post() {
echo 'local awful = require("awful") ; awful.client.floating.set(c, true)' | \
awesome-client
}
# tilers that won't remember sizing
elif [[ $wm == i3 ]]; then
map_post_oneshot() {
i3-msg "[id=$1] floating enable" > /dev/null && \
xdotool windowmove "$1" "$xoff" "$yoff" \
windowsize "$1" "$width" "$height"
}
map_post() {
i3-msg "[id=$1] floating enable" > /dev/null && \
xdotool windowmove "$1" "$xoff" "$yoff"
}
fi
}
# settings for maintining previous size/placement of windows when unhiding them
wm_autoset_for_hide_show() {
# tilers: is_floating function so that hidden tiling windows don't become floating
if [[ $wm == bspwm ]]; then
subtract_when_same=false
is_floating() {
bspc query -T -n | grep '"state":"floating"'
}
elif [[ $wm == i3 ]]; then
subtract_when_same=false
is_floating() {
# do you even sed?
i3-msg -t get_tree | awk 'gsub(/{"id"/, "\n{\"id\"")' | \
awk '/focused":true.*floating":"user_on/ {print $1}'
}
# settings for stacking/floating wms where can't get right position easily from xwininfo
# take borders into account
elif [[ $wm == Blackbox ]]; then
dec_fix_auto="1x22"
elif [[ $wm =~ ^(Mutter|GNOME Shell)$ ]]; then
dec_fix_auto="-10x-8"
subtract_when_same=false
elif [[ $wm =~ ^(Mutter \(Muffin\))$ ]]; then
dec_fix_auto="-9x-8"
# NOTE:
# pekwm, xfwm4, sawfish, openbox need subtract_when_same to be true (default)
# for fluxbox, blackbox, fvwm, and metacity, the value does not matter
elif [[ $wm == GoomwW ]]; then
subtract_when_same=false
fi
if [[ $wm =~ ^(pekwm|Fluxbox|Blackbox|xfwm4|Metacity|FVWM|Sawfish|GoomwW|Mutter|GNOME Shell|Mutter \(Muffin\)|KWin|Metacity \(Marco\)|[Cc]ompiz)$ ]]; then
combine_map_post=true
map_post() {
xdotool windowmap "$1" windowmove "$1" "$2" "$3" 2> /dev/null
}
fi
}
wm_autoset_for_dropdown() {
# tilers without floating support: can toggle fullscreen instead for the dropdown
if [[ $wm == herbstluftwm ]]; then
map_post() {
herbstclient fullscreen on
}
unmap_post() {
herbstclient fullscreen off
}
# floating window managers that may both move and resize a window after unmapping then mapping it
elif [[ $wm == Openbox ]]; then
# openbox will resize window to be slightly less than the width of the screen when mapping
# this is necessary when want width to be 100%
combine_map_post=true
map_post() {
xdotool windowmap "$1" windowmove "$1" "$xoff" "$yoff" \
windowsize "$1" "$width" "$height" 2> /dev/null
}
# floating window managers that may move a window after unmapping then mapping it
elif [[ $wm =~ ^(pekwm|Fluxbox|Blackbox|xfwm4|Metacity|FVWM|Sawfish|GoomwW|Mutter|GNOME Shell|Mutter \(Muffin\)|KWin|Metacity \(Marco\)|[Cc]ompiz|bspwm)$ ]]; then
# most will center
# mutter/gnome shell will move to top centerish (just below panel on gnome shell)
# xfwm4 will normally move to top left; metacity will move close to top left
# sawfish just moves all over the place
combine_map_post=true
map_post() {
# when first creating, the window will already be mapped before it is run
# suppress the error from trying to map a mapped window
xdotool windowmap "$1" windowmove "$1" "$xoff" "$yoff" 2> /dev/null
}
fi
}
#
# Helper Functions for Specific Dropdowns and Auto Hide/Show
#
get_class_name() {
xprop -id "$1" WM_CLASS | awk '{gsub(/"/, ""); print $4}'
}
get_visibility() {
xwininfo -id "$1" 2> /dev/null | awk '/Map State/ {print $3}'
}
map_pre_command() {
# a user set option has higher priority
if [[ -n $map_pre ]]; then
eval "$map_pre"
# use automatically set function if exists
elif [[ -n $(type map_pre 2> /dev/null) ]]; then
# needed when creating oneshot rules for programs where cmd differs from actual class name
if [[ $1 == gnome-terminal ]]; then
map_pre "Gnome-terminal"
elif [[ $1 == urxvtc ]]; then
map_pre "urxvt"
else
map_pre "$1"
fi
fi
}
map_post_command() {
if [[ -n $oneshot_post ]] && [[ $1 == oneshot ]]; then
eval "$oneshot_post"
elif [[ -n $(type map_post_oneshot 2> /dev/null) ]] && \
[[ $1 == oneshot ]]; then
map_post_oneshot "$2"
elif [[ -n $map_post ]]; then
eval "$map_post"
elif [[ -n $(type map_post 2> /dev/null) ]]; then
map_post "$@"
fi
}
unmap_post_command() {
if [[ -n $unmap_post ]]; then
eval "$unmap_post"
elif [[ -n $(type unmap_post 2> /dev/null) ]]; then
unmap_post
fi
}
run_create_hook() {
if [[ -n $create_hook ]]; then
eval "$create_hook"
fi
}
run_map_hook() {
if [[ -n $map_hook ]]; then
eval "$map_hook"
fi
}
maybe_cancel_auto_show() {
if $cancel_auto_show && \
[[ $1 == $(cat "$MUTDROP_PATH"/auto_hidden/wid 2> /dev/null) ]]; then
> "$MUTDROP_PATH"/auto_hidden/wid
fi
}
#
# Dropdown Initialization
#
create_win_return_wid() {
local blacklist program_command pid visible_wid wids program_wid
# blacklist all existing wids of program
# (for programs where one pid shares all wids)
blacklist=$(xdotool search --classname "$program")
# for programs where $! won't always work (e.g. one pid for all windows)
if [[ $program =~ ^(terminix|xfce4-terminal)$ ]]; then
pid=$(pgrep -x "$program")
elif [[ $program == urxvtc ]]; then
blacklist=$(xdotool search --classname urxvtd)
pid=$(pgrep -x urxvtd)
elif [[ $program == chromium ]]; then
# this may work fine
# pid=$(pgrep -xo chromium)
pid=$(pgrep -xa chromium | awk '!/--type/ {print $1}')
elif [[ $program == chromium-browser ]]; then
pid=$(pgrep -xa chromium-browse | awk '!/--type/ {print $1}')
elif [[ $program =~ ^google-chrome ]]; then
pid=$(pgrep -xa chrome | awk '!/--type/ {print $1}')
fi
# need to redirect stdout or function won't return
eval "$1 > /dev/null &"
if [[ -z $pid ]]; then
# for normal programs
# also for when one of the programs above hadn't already been started
pid=$!
fi
visible_wid=false
while : ; do
if [[ $program == gnome-terminal ]]; then
# only 1 pid; changes at some point after first run
# actual process name for me is gnome-terminal-
pid=$(pgrep gnome-terminal)
fi
wids=$(xdotool search --pid "$pid")
if [[ -n "$wids" ]]; then
while read -r wid; do
if [[ ! $blacklist =~ (^|$'\n')"$wid"($|$'\n') ]] && \
[[ $(get_visibility "$wid") == IsViewable ]]; then
visible_wid=true
program_wid=$wid
fi
done <<< "$wids"
fi
if $visible_wid; then
break
fi
sleep 0.01
done
echo -n "$program_wid"
}
program_start() {
local program_command tmux_command wid
program_command="$program $program_flags"
if [[ -n "$session_name" ]]; then
session_name=$(printf "%q" "$session_name")
tmux_command="'tmux attach-session -dt $session_name || \
tmuxinator start $session_name || \
tmux new-session -s $session_name'"
if [[ $program == urxvt ]]; then
program_command="$program_command -e bash -c $tmux_command"
elif [[ $program == terminix ]]; then
program_command="$program_command -x \"bash -c $tmux_command\""
else
program_command="$program_command -e \"bash -c $tmux_command\""
fi
fi
wid=$(create_win_return_wid "$program_command")
echo "$wid" > "$MUTDROP_PATH/$program$num"
# only will work if a pre-command has been run (e.g. bspwm)
xdotool windowmove "$wid" "$xoff" "$yoff" \
windowsize "$wid" "$width" "$height"
echo -n "$wid"
}
current_create() {
# turns active window into a dropdown
local wid
wid=$(xdotool getactivewindow)
echo "$wid" > "$MUTDROP_PATH"/current"$num"
get_class_name "$wid" > "$MUTDROP_PATH"/current"$num"_type
echo -n "$wid"
}
wid_toggle() {
# deal with percentages/negatives when no -m
if ! $monitor_aware; then
local total_geo total_width total_height
total_geo=$(xwininfo -root | awk '/geometry/ {print $2}')
total_width=$(echo "$total_geo" | awk -F 'x' '{print $1}')
total_height=$(echo "$total_geo" | awk -F 'x|+' '{print $2}')
convert_geometry_to_pixels "$total_width" "$total_height"
fi
# get saved window id if already created
local wid exists visibility
wid=$(< "$MUTDROP_PATH/$program$num") 2> /dev/null
exists=true
if [[ -n $wid ]]; then
visibility=$(get_visibility "$wid")
# sometimes xwininfo will still report a window as existing hence xprop check
if [[ -z $visibility ]] || [[ -z $(xprop -id "$wid" 2> /dev/null) ]]; then
# window no longer exists
exists=false
> "$MUTDROP_PATH/$program$num"
fi
else
exists=false
fi
if $exists; then
if [[ $visibility == IsUnMapped ]]; then
# visibility will be IsUnMapped on most WMs if the dropdown is open
# on another desktop
xdotool set_desktop_for_window "$wid" "$(xdotool get_desktop)"
if [[ $(get_visibility "$wid") == IsUnMapped ]]; then
if [[ $program == current ]]; then
map_pre_command "$(< "$MUTDROP_PATH"/current"$num"_type)"
else
map_pre_command "$program"
fi
else
xdotool windowactivate "$wid"
fi
# update here if possible so this doesn't cause a delay
# between the window being remapped and resized
if $monitor_aware; then
update_geometry_settings_for_monitor || \
focused_window_exists=false
fi
if ! $combine_map_post; then
xdotool windowmap "$wid"
map_post_command "$wid"
else
# combine mapping with resizing/moving when possible to reduce flicker
map_post_command "$wid"
fi
run_map_hook "$wid"
maybe_cancel_auto_show "$wid"
if ! $focused_window_exists; then
# need to use dropdown as active window to get monitor info
update_geometry_settings_for_monitor
fi
# would be much too messy to integrate a resize into existing map_post commands
# or add for those WMs that don't even need an xdotool command
# cleaner to do after any map_post command with the downside of potential
# for minimal flicker or redundancy
if $monitor_changed; then
set_geometry_for_monitor "$wid"
fi
else
xdotool windowunmap "$wid"
fi
else
# necessary to deal with negative width or height
# if creating on an empty desktop and can't determine the monitor,
# must set temporary values for negative width and/or height
local original_width original_height
if $monitor_aware && ! update_geometry_settings_for_monitor; then
focused_window_exists=false
if [[ $width =~ ^- ]]; then
original_width=$width
width=100%
fi
if [[ $height =~ ^- ]]; then
original_height=$height
height=100%
fi
fi
# make it
map_pre_command "$program"
if [[ $program == current ]]; then
wid=$(current_create)
xdotool windowunmap "$wid"
run_create_hook "$wid"
else
wid=$(program_start)
map_post_command oneshot "$wid"
run_create_hook "$wid"
run_map_hook "$wid"
# update window dimensions if necessary
if ! $focused_window_exists; then
width=${original_width:-$width}
height=${original_height:-$height}
update_geometry_settings_for_monitor
set_geometry_for_monitor "$wid"
fi
fi
fi
}
#
# Helper Functions for Auto Hiding/Showing
#
get_geometry() {
# so that won't float a tiled window later when showing
if [[ -n $(type is_floating 2> /dev/null) ]] && \
[[ -z $(is_floating "$1") ]]; then
# window is not floating; don't bother saving geometry
echo -n "false"
else
local wininfo x y rel_x rel_y
wininfo=$(xwininfo -id "$1")
x=$(echo "$wininfo" | awk '/Absolute.*X/ {print $4}')
y=$(echo "$wininfo" | awk '/Absolute.*Y/ {print $4}')
rel_x=$(echo "$wininfo" | awk '/Relative.*X/ {print $4}')
rel_y=$(echo "$wininfo" | awk '/Relative.*Y/ {print $4}')
if $subtract_when_same; then
# behaviour works for most WMs (at least floating ones)
x=$((x-rel_x))
y=$((y-rel_y))
else
# don't subtract when abs and rel values are the same
# necessary for WMs like bspwm and i3
if [[ $x -ne $rel_x ]]; then
x=$((x-rel_x))
fi
if [[ $y -ne $rel_y ]]; then
y=$((y-rel_y))
fi
fi
echo -n -e "X=$x\nY=$y"
fi
}
give_geometry() {
eval "$(< "$MUTDROP_PATH"/auto_hidden/geometry)"
local x_fix y_fix X Y
if [[ -n $dec_fix ]]; then
x_fix=$(echo "$dec_fix" | awk -F "x" '{print $1}')
y_fix=$(echo "$dec_fix" | awk -F "x" '{print $2}')
X=$((X-x_fix))
Y=$((Y-y_fix))
elif [[ -n $dec_fix_auto ]]; then
x_fix=$(echo "$dec_fix_auto" | awk -F "x" '{print $1}')
y_fix=$(echo "$dec_fix_auto" | awk -F "x" '{print $2}')
X=$((X-x_fix))
Y=$((Y-y_fix))
fi
echo -n "$X $Y"
}
set_geometry() {
xdotool windowmove "$1" "$(give_geometry)"
}
toggle_auto_hide() {
local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null
mkdir -p "$MUTDROP_PATH"/auto_hidden
if [[ -z $no_hide ]]; then
echo "true" > "$MUTDROP_PATH"/auto_hidden/no_hide
else
> "$MUTDROP_PATH"/auto_hidden/no_hide
fi
}
#
# Auto Hiding/Showing
#
auto_hide() {
local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null
if [[ -z $no_hide ]]; then
local wid
wid=$(xdotool getactivewindow)
mkdir -p "$MUTDROP_PATH"/auto_hidden
echo "$wid" > "$MUTDROP_PATH"/auto_hidden/wid
get_class_name "$wid" > "$MUTDROP_PATH"/auto_hidden/class
get_geometry "$wid" > "$MUTDROP_PATH"/auto_hidden/geometry
xdotool windowunmap "$wid"
fi
}
auto_show() {
local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null
if [[ -z $no_hide ]]; then
local wid class was_floating
wid=$(< "$MUTDROP_PATH"/auto_hidden/wid)
class=$(< "$MUTDROP_PATH"/auto_hidden/class)
was_floating=$(< "$MUTDROP_PATH"/auto_hidden/geometry)
if [[ $was_floating != false ]]; then
map_pre_command "$class"
fi
if ! $combine_map_post; then
xdotool windowmap "$wid"
fi
if [[ $was_floating != false ]]; then
if $combine_map_post; then
local XY X Y
XY=$(give_geometry "$wid")
X=$(echo "$XY" | awk '{print $1}')
Y=$(echo "$XY" | awk '{print $2}')
map_post_command "$wid" "$X" "$Y"
else
map_post_command "$wid"
set_geometry "$wid"
fi
else
xdotool windowmap "$wid"
fi
fi
}
#
# Main
#
if $auto_detect_wm; then
wm=$(get_window_manager)
wm_autoset_for_all
if [[ $program == auto_show ]] || [[ $program == auto_hide ]]; then
wm_autoset_for_hide_show
else
wm_autoset_for_dropdown
fi
fi
if $clearwid; then
> "$MUTDROP_PATH/$program$num"
elif [[ $program == toggle_auto_hide ]]; then
toggle_auto_hide
elif [[ $program == auto_hide ]]; then
auto_hide
elif [[ $program == auto_show ]]; then
auto_show
else
wid_toggle
fi
# vim is dumb
8 years ago
# vim: set ft=sh noet: