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.
655 lines
21 KiB
Bash
655 lines
21 KiB
Bash
#!/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 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: 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, see BUGS in man)
|
|
-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-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)
|
|
-z use a different sleep time to wait for terminal to be created (advanced; see man page)
|
|
-Z use a different sleep time for -W program to be created (advanced; see man page)
|
|
-f specify flags/options to be used when creating the term or window (e.g. -f '--title mytitle', default: none)
|
|
-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)
|
|
-W the given program is not a terminal (or lacks an -e flag) (default: assume it IS a terminal)
|
|
--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
|
|
#
|
|
|
|
# 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=""
|
|
dec_fix=""
|
|
sleep_term_time=0.01
|
|
sleep_term_user_set=false
|
|
sleep_win_time=0.5
|
|
sleep_win_user_set=false
|
|
program_flags=""
|
|
normal_window=false
|
|
clearwid=false
|
|
cancel_auto_show=true
|
|
term=${*:0-1}
|
|
auto_detect_wm=false
|
|
multiple_monitors=false
|
|
while getopts :h:w:x:y:s:n:p:P:M:O:d:z:Z:f:-:Wam 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;;
|
|
d) dec_fix=$OPTARG;;
|
|
z) sleep_term_time=$OPTARG
|
|
sleep_term_user_set=true;;
|
|
Z) sleep_win_time=$OPTARG
|
|
sleep_win_user_set=true;;
|
|
f) program_flags=$OPTARG;;
|
|
W) normal_window=true;;
|
|
a) auto_detect_wm=true;;
|
|
m) multiple_monitors=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) map_pre=$OPTARG;;
|
|
post-command) map_post=$OPTARG;;
|
|
post-unmap) unmap_post=$OPTARG;;
|
|
oneshot-post) oneshot_post=$OPTARG;;
|
|
decoration-fix) dec_fix=$OPTARG;;
|
|
sleep-terminal) sleep_term_time=$OPTARG
|
|
sleep_term_user_set=true;;
|
|
sleep-window) sleep_win_time=$OPTARG
|
|
sleep_win_user_set=true;;
|
|
program-flags) program_flags=$OPTARG;;
|
|
normal-window) normal_window=true;;
|
|
auto-detect-wm) auto_detect_wm=true;;
|
|
multiple-monitors) multiple_monitors=true;;
|
|
clear) clearwid=true;;
|
|
no-cancel) cancel_auto_show=false;;
|
|
help) print_help;;
|
|
esac;;
|
|
*) print_help illegal_opt;;
|
|
esac
|
|
done
|
|
# 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
|
|
|
|
#
|
|
# Multiple Monitor Automatic Re-Sizing
|
|
#
|
|
|
|
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
|
|
|
|
# determine curent monitor
|
|
wininfo=$(xwininfo -id "$(xdotool getactivewindow)")
|
|
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}')
|
|
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
|
|
done <<< "$monitors_info"
|
|
|
|
# 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))
|
|
|
|
# convert w/h percentages to pixels based on size of current screen
|
|
if [[ $height =~ %$ ]]; then
|
|
height=$(awk "BEGIN {printf(\"%.0f\", 0.01*${height%\%}*$y_height)}")
|
|
elif [[ $height =~ ^- ]]; then
|
|
minus_height=${height#-}
|
|
height=$((y_height-minus_height))
|
|
fi
|
|
if [[ $width =~ %$ ]]; then
|
|
width=$(awk "BEGIN {printf(\"%.0f\", 0.01*${width%\%}*$x_width)}")
|
|
elif [[ $width =~ ^- ]]; then
|
|
minus_width=${width#-}
|
|
width=$((x_width-minus_width))
|
|
fi
|
|
|
|
# determine if monitor has changed and save current monitor
|
|
last_monitor=$(< /tmp/tdrop/last_monitor)
|
|
echo "$current_monitor" > /tmp/tdrop/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() {
|
|
bspc rule -a "$1" -o floating=on
|
|
}
|
|
elif [[ $wm == awesome ]]; then
|
|
# awesome remembers size, but need to float and then set size first
|
|
map_post_oneshot() {
|
|
# need sleep time to wait for window be created or will float wrong one.. not sure if way to float by window id
|
|
if ! $sleep_win_user_set; then
|
|
# what I've had best results with
|
|
sleep_win_time=0.1
|
|
fi
|
|
sleep $sleep_win_time && 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
|
|
# need to sleep first time to wait for window to be created
|
|
map_post_oneshot() {
|
|
if ! $sleep_win_user_set; then
|
|
# what I've had best results with
|
|
sleep_win_time=0.1
|
|
fi
|
|
sleep $sleep_win_time && \
|
|
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"
|
|
}
|
|
|
|
# floating WMs that need extra sleep time to wait for dropdown to spawn initially
|
|
elif [[ $wm =~ ^(Fluxbox|Mutter|GNOME Shell|Mutter \(Muffin\)|KWin)$ ]]; then
|
|
if ! $sleep_term_user_set; then
|
|
sleep_term_time=0.05
|
|
fi
|
|
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() {
|
|
# checking if the window id (converted from decimal to hex) is floating; empty if not floating
|
|
bspc query -T | grep -i "$(printf 0x%x "$1").*f-"
|
|
}
|
|
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\))$ ]]; then
|
|
combine_map_post=true
|
|
map_post() {
|
|
xdotool windowmap "$1" windowmove "$1" "$2" "$3"
|
|
}
|
|
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"
|
|
}
|
|
# 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\))$ ]]; 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() {
|
|
xdotool windowmap "$1" windowmove "$1" "$xoff" "$yoff"
|
|
}
|
|
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" | 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"
|
|
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
|
|
}
|
|
|
|
maybe_cancel_auto_show() {
|
|
if $cancel_auto_show && [[ $1 == "$(cat /tmp/tdrop/auto_hidden/wid 2> /dev/null)" ]]; then
|
|
> /tmp/tdrop/auto_hidden/wid
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Dropdown Initialization
|
|
#
|
|
|
|
term_create() {
|
|
if [[ -n $program_flags ]]; then
|
|
term_command="$term $program_flags"
|
|
else
|
|
term_command=$term
|
|
fi
|
|
if [[ -n $session_name ]]; then
|
|
# ugly workarounds due to how different terms different -e flags work
|
|
if [[ $term == urxvt ]]; then
|
|
$term_command -e bash -c "sleep $sleep_term_time && 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_command -e "/bin/bash -c 'sleep $sleep_term_time && 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_command -e bash -c "sleep $sleep_term_time && 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_command -e "/bin/bash -c 'sleep $sleep_term_time && xdotool getactivewindow > /tmp/tdrop/$term$num && xdotool getactivewindow windowmove $xoff $yoff windowsize $width $height && $SHELL'" &
|
|
fi
|
|
fi
|
|
}
|
|
|
|
win_create() {
|
|
if [[ -n $program_flags ]]; then
|
|
win_command="$term $program_flags"
|
|
else
|
|
win_command=$term
|
|
fi
|
|
$win_command &
|
|
# need to wait for window to be created
|
|
sleep $sleep_win_time
|
|
# often pids have two wids
|
|
wids=$(xdotool search --pid $!)
|
|
wid1=$(echo "$wids" | head -n 1)
|
|
wid2=$(echo "$wids" | tail -n 1)
|
|
if [[ -n $wid2 ]]; then
|
|
if [[ $(get_visibility "$wid2") == IsUnMapped ]]; then
|
|
wid=$wid1
|
|
else
|
|
wid=$wid2
|
|
fi
|
|
else
|
|
wid=$wid1
|
|
fi
|
|
# only works with pre-command
|
|
xdotool windowmove "$wid" "$xoff" "$yoff" windowsize "$wid" "$width" "$height"
|
|
echo "$wid" > /tmp/tdrop/"$term$num"
|
|
}
|
|
|
|
current_create() {
|
|
# turns active window into a dropdown
|
|
wid=$(xdotool getactivewindow)
|
|
echo "$wid" > /tmp/tdrop/current"$num"
|
|
get_class_name "$wid" > /tmp/tdrop/current"$num"_type
|
|
echo "$wid"
|
|
}
|
|
|
|
wid_toggle() {
|
|
mkdir -p /tmp/tdrop
|
|
# get saved window id if already created
|
|
wid=$(< /tmp/tdrop/"$term$num")
|
|
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") ]]; then
|
|
# window no longer exists
|
|
exists=false
|
|
fi
|
|
else
|
|
exists=false
|
|
fi
|
|
if $exists; then
|
|
if [[ $visibility == IsUnMapped ]]; then
|
|
if [[ $term == current ]]; then
|
|
map_pre_command "$(< /tmp/tdrop/current"$num"_type)"
|
|
else
|
|
map_pre_command "$term"
|
|
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
|
|
maybe_cancel_auto_show "$wid"
|
|
# 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
|
|
# make it
|
|
map_pre_command "$term"
|
|
if [[ $term == current ]]; then
|
|
wid=$(current_create)
|
|
xdotool windowunmap "$wid"
|
|
else
|
|
if $normal_window; then
|
|
win_create
|
|
else
|
|
term_create
|
|
fi
|
|
# get saved wid of newly created dropdown
|
|
wid=""
|
|
count=0
|
|
while [[ -z $wid ]] && [[ $count -lt 100 ]]; do
|
|
wid=$(< /tmp/tdrop/"$term$num")
|
|
sleep 0.01
|
|
((count++))
|
|
done
|
|
map_post_command oneshot "$wid"
|
|
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 "false"
|
|
else
|
|
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 -e "X=$x\nY=$y"
|
|
fi
|
|
}
|
|
|
|
give_geometry() {
|
|
eval "$(< /tmp/tdrop/auto_hidden/geometry)"
|
|
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 "$X $Y"
|
|
}
|
|
|
|
set_geometry() {
|
|
xdotool windowmove "$1" "$(give_geometry)"
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
#
|
|
# Auto Hiding/Showing
|
|
#
|
|
|
|
auto_hide() {
|
|
no_hide=$(< /tmp/tdrop/auto_hidden/no_hide)
|
|
if [[ -z $no_hide ]]; then
|
|
wid=$(xdotool getactivewindow)
|
|
mkdir -p /tmp/tdrop/auto_hidden
|
|
echo "$wid" > /tmp/tdrop/auto_hidden/wid
|
|
get_class_name "$wid" > /tmp/tdrop/auto_hidden/class
|
|
get_geometry "$wid" > /tmp/tdrop/auto_hidden/geometry
|
|
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)
|
|
was_floating=$(< /tmp/tdrop/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
|
|
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 [[ $term == auto_show ]] || [[ $term == auto_hide ]]; then
|
|
wm_autoset_for_hide_show
|
|
else
|
|
wm_autoset_for_dropdown
|
|
fi
|
|
fi
|
|
|
|
if [[ -n $1 ]]; then
|
|
if $clearwid; then
|
|
> /tmp/tdrop/"$term$num"
|
|
elif [[ $term == toggle_auto_hide ]]; then
|
|
toggle_auto_hide
|
|
elif [[ $term == auto_hide ]]; then
|
|
auto_hide
|
|
elif [[ $term == auto_show ]]; then
|
|
auto_show
|
|
else
|
|
if $multiple_monitors; then
|
|
update_geometry_settings_for_monitor
|
|
fi
|
|
wid_toggle
|
|
fi
|
|
else
|
|
print_help illegal_opt
|
|
fi
|
|
# vim is dumb
|
|
# vim: set ft=sh:
|