Compare commits

..

49 Commits

Author SHA1 Message Date
KuxaBeast fa494e0e67
Fixed spelling 5 years ago
Jan Kužílek 5a85df2508 Replaced old wid-retrieving method with xtoolwait 5 years ago
Fox Kiester eb09fc22f7
Add shellcheck github action badge 5 years ago
Fox Kiester ffaf358bde
Fix shellcheck github action 5 years ago
Fox Kiester b4ddb1214b
Add github actions shellcheck workflow 5 years ago
Fox Kiester b7afed7b41
Give specific error when illegal opt is given 5 years ago
Fox Kiester 9c75b30212
Add timeout to wait for program window to appear
Also add error helper function and fix option validation.

Addresses #62. Prevents tdrop from spiking CPU forever if a program fails to
start.
5 years ago
Fox Kiester f4f0f34644
Add hide_all command
Fixes #60.
5 years ago
Fox Kiester 24d61bd266
Fix -a for emacsclient (set class as "emacs") 5 years ago
Fox Kiester 59c426dfc0
Remove unnecessary quotes 5 years ago
Fox Kiester 4926be8fcb
Allow specifying program flags after the program
This not working has caused a lot of confusion. Not only is -f not necessary,
but the implementation is worse than just allowing flags after the program.
Deprecate the -f flag. Stop evaling a string; build an array of program options
instead.

Addresses various issues: #6, #17, #52, etc.
5 years ago
Fox Kiester 2b1553090d
Fix shellcheck errors/warnings 5 years ago
Fox Kiester 5a44b827ad
Reindent 5 years ago
Fox Kiester c143104977
Suppress stderr when reading no_hide file 5 years ago
Fox Kiester 216070e29e
Improve performance
- Prefer builtins where possible
  - Use builtin math for percent_of_total
  - Use parameter expansion instead of awk where possible
  - Query specific property that want for xprop instead of using awk
- Avoid extra call to get_window_manager
- Use xrandr's --current flag (doesn't poll for hardware changes; ~0.01 second vs. 0.075 seconds on my comupter)
- Get current monitor name from bspc directly without parsing

Addresses #36.
5 years ago
Fox Kiester d74150f01f
Add support for Trinity's konsole (TDE)
Fixes #58.
5 years ago
Kamil Sołtysik 60435d240f
Pointer-based screen detection 5 years ago
Fox Kiester 183d983e4d
Explicitly use gawk and update dependency list
Fixes #49.
6 years ago
Fox Kiester 7eaa3b517d
Add support for qutebrowser
Fixes #56.
6 years ago
Fox Kiester 89d2e4ffce
Add workaround to support urxvt with tabbed plugin
Fixes #54.
6 years ago
Alexandr Priezzhev 198795c0d2
Fixes running Alacritty with the command shell argument 6 years ago
Fox Kiester 7d3192286a
Add initial support for emacsclient 6 years ago
Fox Kiester d91b1594b1
Add more broad urxvt name check for class inference
Addresses #47.
6 years ago
Fox Kiester 27894d40c3
Fix indentation/newline for --class in manpage 6 years ago
Fox Kiester fc2593f36e
Add initial discord support 6 years ago
Fox Kiester 5396d1bbdf
Mention that tdrop has a Void package
Re #43.
7 years ago
Fox Kiester c3978e3059
Update repository, contact, and version information 7 years ago
noctuid 6c7336d84a Prevent matching multiple monitors
Fixes #44.
7 years ago
noctuid 6adf44ef50 Improve explanation of geometry flags
Mention in basic flags section that geometry options can accept
percentages and negative numbers as arguments.
7 years ago
noctuid b7b529f80f Mention that --wm is needed if wmname has been used
Addresses #40.
7 years ago
noctuid 3f0867e565 Make own heading for -a explanation
Also swap flicker and -m headings.
7 years ago
noctuid 3278f76f9e Silence more irrelevant errors/output 7 years ago
noctuid 306bb984e4 Specify in readme that program arg should be last
Addresses #39.
7 years ago
noctuid ad8c192269 Clarify -f example in manpage
Addresses #39.
7 years ago
noctuid 8808dff04b Add -s support for lilyterm 7 years ago
noctuid 2ea52326bc Add -s support for LXTerminal
Also list related desktop environments for terminals.
7 years ago
noctuid 157ac0c2f1 Mention support for tinyterm/miniterm
Also rearrange terminals alphabetically.
7 years ago
noctuid 14a935ca24 Add support for -s for cool-retro-term 7 years ago
noctuid b1ba3b6129 Add -s support for qterminal 7 years ago
noctuid 498de5706e Fix -s for st and xst
Fixes #29.
7 years ago
noctuid 3aa34f7d21 Update hooks documentation
- More explicitly mention that single quotes should be used to prevent
  variable evaluation
- List hook flags in readme
- Consistently order in the readme and manpage
- Fix typo in manpage (--pre-create-hook -> --post-create-hook)
- Some rewording
7 years ago
noctuid baa61705f6 Update flicker section in readme: mention --name 7 years ago
noctuid 1a22a4158a Update basic flags section in readme
Reword and mention -m flag.
7 years ago
noctuid a6e3dbb7e8 Update/reword advantages section 7 years ago
noctuid ffef664678 Automatically use -d 0 0 with alacritty
Addresses #38.
7 years ago
noctuid 95d742acc0 Add -s support for kitty 7 years ago
noctuid 36995d1090 Fix geometry restoration for auto_show
Geometry restoration broke in 056edc6. Now width and height are also
explicitly restored.
7 years ago
noctuid 0facf21df7 Add tmuxifier support
Addresses #38.
7 years ago
noctuid bf97b17aaf Update demos 7 years ago

@ -0,0 +1,10 @@
name: lint
on: [push, pull_request]
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- name: shellcheck
uses: ludeeus/action-shellcheck@0.1.0

@ -1,220 +1,5 @@
* Demos * About
A basic demo using tdrop to create a dropdown/scratchpad on the fly with a hotkey. I set the height to be less than max with tdrop to make it more obvious which is the dropdown at which time. First apvlv is turned into a dropdown. Then it is cleared and zathura is turned into a dropdown. One can also have multiple hotkeys to create multiple dropdowns on the fly at a time. This is a tdrop fork but using an external script xtoolwait (on AUR =xtoolwait-git=).
[[http://noctuid.github.io/tdrop/assets/on_the_fly.gif]] It was created to support few programs (like suckless tabbed) which doesn't work yet with the upstream version.
A demo showing tdrop's ability to auto-hide windows when opening things from them. First an image is opened in sxiv from ranger in the dropdown. When sxiv is closed, the dropdown automatically re-appears. The image is opened once again, but this time the dropdown is manually toggled before closing sxiv. This cancels the "re-show". [[http://noctuid.github.io/tdrop/assets/auto_hide.gif]] Just don't forget to install xtoolwait, because I basically replaced hundred lines of code with just one call to this utility.
* Advantages Over Other Dropdown Terminals
- Can be used with any terminal or other program of your choice
- Supports many WMs
- Allows turning any window into a dropdown on the fly
- Allows for control of sizing and placement so that panels aren't hidden
- Supports tiled and floating dropdowns
- Attempts to deal with floating windows on a case by case basis (ability to have a floating dropdown without needing a rule to float all windows of that type)
- Allows for multiple dropdowns of the same type (uses window id)
- Allows for auto-hiding a dropdown when opening programs from it
- Can automatically start programs and tmux or tmuxinator sessions
- Supports automatic resizing based on the current monitor
- Has hooks for executing user commands
* Requirements
- bash and basic utilities (awk, sed, etc.)
- xprop
- xwininfo
- xdotool
Optional:
- xrandr (for -m)
- tmux (for -s)
- tmuxinator (for -s)
* Installation Instructions and Usage
** Installation
Tdrop is in the AUR as =tdrop-git=. It can also be installed by cloning this repo and running ~sudo make install~. One can then bind a key to it (e.g. with sxhkd).
** Basic Sxhkd Example
#+BEGIN_EXAMPLE
# negative -w arg to account for a border width (default: 100%)
alt + s
tdrop -ma -w -4 -y "$PANEL_HEIGHT" -s dropdown termite
#+END_EXAMPLE
The positional argument should be the name of a program in =$PATH= (as opposed to the full path to a program) and should not contain any flags (see =-f= if you want to pass additional flags to the program when running it).
** Basic Flags
=-s= / =--session= should only be used for supported terminals and if the user wants to start a tmux or tmuxinator session. =-a= / =--auto-detect-wm= should be used to automatically set certain options (=-l=, =-L=, =-d=, and/or =-i=) based on the current window manager. These flags (whether automatically or manually set) may be necessary for tdrop to behave correctly (e.g. they are required for =-w= / =--width=, =-h= / =--height=, =-x= / =--xoff=, and =-y= / =--yoff= to work correctly on tiling window managers). See the manpage for these flags for specific details.
Tdrop has basic checks to print errors for malformed commands (for example to require one positional argument). If a tdrop command does not work, please run it in a terminal or check =/tmp/tdrop/log= for error messages and consult the manpage before making an issue. For more information, see the [[#troubleshooting][Troubleshooting]] section.
*** Changes
Long options can now be used with whitespace instead of requiring a ~=~ (i.e. =--long-opt value= and ~--long-opt=value~ are both fine).
Old users please note that =-W|--normal-window=, =-z|--sleep-terminal=, and =-Z|--sleep-window= are no longer necessary and have been removed. Similarly, the old hook flags (=-p=, =-P=, =-M=, and =-O= as well as =--create-hook= and =--map-hook=) have been replaced with more specific and useful versions.
** Flicker
For some window managers that require a window to be repositioned after re-mapping it, some flicker may be noticeable. This flicker has been mostly fixed for some window managers (e.g. in the Gnome Shell and Cinnamon DEs) and improved for others. It is usually worse on tiling managers where the window must be re-floated every time it is mapped. The way around this is to use rules to either always have the class floated or one-time rules to only float the next instance of a class. For example, since bspwm has oneshot rules and generally doesn't alter the size/position of a window, there isn't any movement flicker.
A more consistent workaround to eliminate visual flickering regardless of the window manager is to enable fade-in for the compositor. For compton this can be done by setting =fading = true;= and adjusting the =fade-delta= in the =~/.config/compton.conf= accordingly.
** Monitor Awareness
Using the =-m= / =--monitor-aware= flag will cause the geometry options to act with respect to the current monitor. This may be helpful for users of multiple monitors who don't want dropdowns spanning across monitors.
This is particularly useful when using a percentage or negative value with =-w=, =-h=, =-x=, and/or =-y=. For example, =-w -4= normally corresponds to a width 4 pixels less than 100% of the screen width (potentially the combined width of multiple monitors). With =-m=, the pixel values are calculated using the dimensions of the current monitor alone. Negative values may be useful when the window manager (possibly due to window decorations) causes a dropdown with =-w 100%= to go over the edge of the screen. The =-m= option will also automatically resize and/or reposition the dropdown when opening it on a different monitor when one or more of the geometry arguments are negative or percentages.
Some window managers allow querying what the current monitor is (e.g. bspwm and i3), but for other window managers, tdrop determines the current monitor based on the position of the active window. For these window managers, if the desktop is empty, tdrop must wait for the dropdown to be created or mapped before getting the monitor info. This may cause a slight delay before the dropdown is properly resized. If =-m= does not work at all or there is a specific way to query for the current monitor in your window manager, please make an issue.
See the manpage for more information.
** Hooks
Tdrop provides various hook flags that can be used to run commands at various stages during execution. These commands can make use of any internal tdrop variable, such as =$width=, =$height=, =$xoff=, =$yoff=, =$class=, and =$wid=. For example, to set a dropdown as always on top, "-P 'wmctrl -i -r $wid -b add,above'" could be added to a tdrop command.
Note that for some of the hooks, the window id is not guarunteed to be known (since the window may not have yet been created), so any scripts that make use of these should check if it is defined (pre-map and pre-float; wid will never be known for pre-create).
*** Pre Create
*Program* The hook will be run before the program is started.
*Current* The hook will be run before unmapping the current window.
*Hide and Show* No effect.
*** Post Create
*Program* The hook will be run after the program is started and its window is active.
*Current* The hook will be run after unmapping the current window.
*Hide and Show* No effect.
*** Pre Float
A command specifically meant to float the window. Note that if you specify this, it will override any defaults from =-a=.
*Program* / *Current* The command will be run before mapping the window.
*Hide* No effect.
*Show* Will be used before mapping the window if it was previously floating.
*** Post Float
A command specifically meant to float the window. Note that if you specify this, it will override any defaults from =-a=.
*Program* / *Current* The command will be run after mapping the window.
*Hide* No effect.
*Show* Will be used after mapping the window if it was previously floating.
*** Pre Map
*Program* / *Current* / *Show* The command will be run before mapping the window.
*Hide* No effect.
*** Post Map
*Program* / *Current* / *Show* The command will be run after mapping the window.
*Hide* No effect.
*** Pre Unmap
*Program* / *Current* / *Hide* The command will be run before unmapping the window.
*Show* No effect.
*** Post Unmap
*Program* / *Current* / *Hide* The command will be run after unmapping the window.
*Show* No effect.
** Auto-hiding
In addition to creating dropdowns, tdrop can automatically hide a window and later un-hide it. For example, if gvim is opened to write a git commit message from the terminal, tdrop can automatically hide the terminal (dropdown or not) and restore it after the user is finished writing the commit message:
#+BEGIN_EXAMPLE
hide_on_open() {
tdrop -a auto_hide && "$@" && tdrop -a auto_show
}
alias gc='hide_on_open git commit'
#+END_EXAMPLE
The most useful application of this functionality is probably when opening videos, images, etc. in an external program from a file manager like ranger. For example, in the =rifle.conf=:
#+BEGIN_EXAMPLE
mime ^video, has mpv, X, flag f = tdrop -a auto_hide && mpv -- "$@" && tdrop -a auto_show
#+END_EXAMPLE
* Tested With
** Terminals
These terminals have been tested with tdrop and support the =-s= and =-a= flags unless otherwise specified:
- Termite
- URxvt (including urxvtd)
- XTerm
- Xfce4-terminal
- Gnome-terminal
- Konsole
- Terminology
- Sakura
- Roxterm
- Tilix (previously terminix)
- st (-s does not work)
- Alacritty
- xiate
If your terminal doesn't work with tdrop, feel free to make an issue. Please follow the steps in the [[#troubleshooting][Troubleshooting]] section.
** Window Managers
The primary goal of tdrop is to "just work" with any window manager. The primary differences between how tdrop deals with different window managers is the strategy it takes for floating only the dropdown (as opposed to all instances of the class that the dropdown is). There are three types of window managers as far as tdrop is concerned:
*** Tiling without Floating Support
If your window manager does not support floating, there's nothing to worry about. Binding a key to =tdrop <flags> terminal= should work. Options for resizing and movement that work only with floating window managers are not supported. One can, however, add post-map and post-unmap commands to do something like change the layout to fullscreen when showing a dropdown then revert the layout when hiding the dropdown. Automatic settings exist to do this for the following window managers (=-a=):
- herbstluftwm
*** Floating/Stacking
For floating window managers, tdrop should also generally "just work", but you may need to add the =-a= option for auto-showing to correctly restore the previous geometry.
That said, these are the floating window managers that currently have been tested:
- mutter (gnome shell)
- muffin (cinnamon)
- xfwm4 (xfce)
- metacity (gnome 2)
- marco (mate)
- kwin (kde)
- openbox (lxde)
- compiz (unity)
- pekwm
- fluxbox
- blackbox
- fvwm
- sawfish
- goomwwm
If your dropdown moves out of place when being shown, make an issue, and I will add settings for it.
*** Tiling with Floating Support
These window managers currently will work with =-a= for a floating (instead of tiled) dropdown:
- bspwm (support for versions prior to 0.9.1 was dropped on 2016/09/22)
- i3
- awesome
Awesome support may be buggy; if you encounter problems, please report them.
* Why Not Use wmctrl?
Necessary features don't work on many window managers, including mine.
* Why Not Use wmutils?
Maybe in the future. The only advantage I can see over xdotool is that it can toggle mapping (=mapw -t=), but this wouldn't be used in this script anyway since different code is executed depending on whether or not the window is mapped or unmapped. Also the command names are somewhat cryptic.
* Similar
- [[https://github.com/lharding/lsh-bin/blob/master/drawer][drawer]]
* Troubleshooting
:PROPERTIES:
:CUSTOM_ID: troubleshooting
:END:
** Tdrop does not work with some terminal/program
Please make an issue. Including the following information would help resolve the problem more quickly.
Basic:
- The incorrect behavior: Does the window appear at all? Is the problem that it is not floated correctly in a supported wm? Or is it a feature request for =-a= support?
- Whether things work as expected with a basic =tdrop <terminal>= (no flags) or whether the issue occurs with a specific flag (probably =-s=)
Additional helpful information:
- If the problem only occurs with the =-s= flag, the issue is likely due to the fact that not all terminals have compatible =-e= flags. It would be helpful if information on how the terminal's flag for executing a command works. Is it something other than =-e=? Are quotations required or incorrect ("-e 'command -flags ...'" vs "-e command flags")?
- If the issue is with the dropdown behavior (e.g. tdrop keeps opening new windows for the program), does the program share a PID across all instances (e.g. open several windows and provide the output of =pgrep -l <program>=)? Does the program have a daemon and client?

383
tdrop

@ -1,7 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
PS4='+ $(date "+%s.%N")\011 '
exec 3>&2 2>/tmp/bashstart.$$.log
set -x
MUTDROP_PATH=/tmp/tdrop_"$USER" MUTDROP_PATH=/tmp/tdrop_"$USER"
# shellcheck disable=SC2174 # shellcheck disable=SC2174
@ -9,15 +6,17 @@ mkdir -p "$MUTDROP_PATH" -m 700
print_help() { print_help() {
echo " echo "
usage: tdrop [options] <program> or 'current' or usage: tdrop [options] <program> [program options ...]
one of 'auto_show'/'auto_hide'/'toggle_auto_hide' or 'current'
or one of 'auto_show'/'auto_hide'/'toggle_auto_hide'
or 'hide_all'
options: options:
-h height specify a height for a newly created term (default: 45%) -h height specify a height for a newly created term (default: 45%)
-w width specify a width for a newly created term (default: 100%) -w width specify a width for a newly created term (default: 100%)
-x pos specify x offset for a newly created term (default: 0) -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 man) -y pos specify y offset for a newly created term (default: 1, see man)
-s name name for tmux/tmuxinator session (supported terminal -s name name for tmux/tmuxinator/tmuxifier session (supported
required) terminal required)
-n num num or extra text; only needed if for the purpose of using -n num num or extra text; only needed if for the purpose of using
multiple dropdowns of same program multiple dropdowns of same program
-c cmd provide a pre-create command -c cmd provide a pre-create command
@ -26,18 +25,18 @@ options:
-L cmd provide a command to float the window after it is mapped -L cmd provide a command to float the window after it is mapped
-p cmd provide a pre-map command -p cmd provide a pre-map command
-P cmd provide a post-map command -P cmd provide a post-map command
-u cmd provide a pre-unmap command -u cmd provide a pre-unmap command -U cmd provide a post-unmap command -d XxY give decoration/border size to accurately restore window
-U cmd provide a post-unmap command
-d XxY give decoration/border size to accurately restore window
position; only applicable with auto_show position; only applicable with auto_show
-S cmd can be used to fix saved geometry with auto_hide; see manpage -S cmd can be used to fix saved geometry with auto_hide; see manpage
-i cmd provide a command to detect whether the current window is a -i cmd provide a command to detect whether the current window is a
floating window; on applicable with auto_hide floating window; on applicable with auto_hide
-f flags specify flags/options to be used when creating the term or -f flags specify flags/options to be used when creating the term or
window (e.g. -f '--title mytitle'; default: none). window (e.g. -f '--title mytitle'; default: none).
Caution: if there is a tmux/tmuxinator session specified NOTE: This flag is deprecated. Specify flags after the program name
(with -s), the option to execute a program (usually -e for instead. This flag may be removed in the future.
terminal programs) is implicitly added by tdrop Caution: if there is a tmux 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 set relevant options -a automatically detect window manager and set relevant options
(e.g. this makes specifying -l/-L, -d, and -i uneccessary (e.g. this makes specifying -l/-L, -d, and -i uneccessary
for supported WMs) (default: false) for supported WMs) (default: false)
@ -46,6 +45,8 @@ options:
for width or height to values relative to the size of the for width or height to values relative to the size of the
current monitor and force resizing of the dropdown when current monitor and force resizing of the dropdown when
the monitor changes (default: false) the monitor changes (default: false)
-t use mouse pointer location for detecting which monitor is the current
one
--wm set the window manager name to mimic another window manager --wm set the window manager name to mimic another window manager
(for use with -a) (for use with -a)
--class name manually specify the class of the window (can be obtained with xprop) --class name manually specify the class of the window (can be obtained with xprop)
@ -54,15 +55,18 @@ options:
window a dropdown (e.g. '$ tdrop --clear current') window a dropdown (e.g. '$ tdrop --clear current')
--no-cancel don't cancel auto-showing (default is to prevent this when --no-cancel don't cancel auto-showing (default is to prevent this when
manually toggling a window after it is auto-hidden) manually toggling a window after it is auto-hidden)
--timeout set the timeout (in seconds) that tdrop will wait for a window
to appear before giving up in case the program fails to start
(default: 10)
--help print help --help print help
See man page for more details. See man page for more details.
" "
if [[ $1 == illegal_opt ]]; then }
error() {
echo >&2 "$@" | tee -a "$MUTDROP_PATH"/log
exit 1 exit 1
else
exit 0
fi
} }
# * Default Options and Option Parsing # * Default Options and Option Parsing
@ -86,18 +90,21 @@ dec_fix=
# pekwm, xfwm4, sawfish, openbox need subtract_when_same to be true # pekwm, xfwm4, sawfish, openbox need subtract_when_same to be true
# for awesome, fluxbox, blackbox, mutter, fvwm, and metacity, the value # for awesome, fluxbox, blackbox, mutter, fvwm, and metacity, the value
# does not matter # does not matter
subtract_when_same=true # set in decoration_settings
subtract_when_same=
is_floating= is_floating=
program_flags= program_flags=()
clearwid=false clearwid=false
cancel_auto_show=true cancel_auto_show=true
auto_detect_wm=false auto_detect_wm=false
monitor_aware=false monitor_aware=false
pointer_monitor_detection=false
wm= wm=
user_set_wm=false user_set_wm=false
class= class=
name= name=
while getopts :h:w:x:y:s:n:c:C:l:L:p:P:u:U:d:f:-:am opt timeout=10
while getopts :h:w:x:y:s:n:c:C:l:L:p:P:u:U:d:S:i:f:-:amt opt
do do
case $opt in case $opt in
h) height=$OPTARG;; h) height=$OPTARG;;
@ -117,11 +124,12 @@ do
d) dec_fix=$OPTARG;; d) dec_fix=$OPTARG;;
S) subtract_when_same=false;; S) subtract_when_same=false;;
i) is_floating=$OPTARG;; i) is_floating=$OPTARG;;
f) program_flags=$OPTARG;; f) eval "program_flags=($OPTARG)";;
a) auto_detect_wm=true;; a) auto_detect_wm=true;;
m) monitor_aware=true;; m) monitor_aware=true;;
t) pointer_monitor_detection=true;;
-) -)
if [[ $OPTARG =~ ^(auto-detect-wm|monitor-aware|clear|no-cancel|help)$ ]] || \ if [[ $OPTARG =~ ^(auto-detect-wm|monitor-aware|pointer-monitor-detection|clear|no-cancel|help)$ ]] || \
[[ $OPTARG == *=* ]]; then [[ $OPTARG == *=* ]]; then
OPTION=${OPTARG%%=*} OPTION=${OPTARG%%=*}
OPTARG=${OPTARG#*=} OPTARG=${OPTARG#*=}
@ -149,64 +157,59 @@ do
decoration-fix) dec_fix=$OPTARG;; decoration-fix) dec_fix=$OPTARG;;
no-subtract-when-same) subtract_when_same=false;; no-subtract-when-same) subtract_when_same=false;;
is-floating) is_floating=$OPTARG;; is-floating) is_floating=$OPTARG;;
program-flags) program_flags=$OPTARG;; program-flags) eval "program_flags=($OPTARG)";;
auto-detect-wm) auto_detect_wm=true;; auto-detect-wm) auto_detect_wm=true;;
monitor-aware) monitor_aware=true;; monitor-aware) monitor_aware=true;;
pointer-monitor-detection) pointer_monitor_detection=true;;
wm) wm=$OPTARG wm) wm=$OPTARG
user_set_wm=true;; user_set_wm=true;;
class) class=$OPTARG;; class) class=$OPTARG;;
name) name=$OPTARG;; name) name=$OPTARG;;
clear) clearwid=true;; clear) clearwid=true;;
no-cancel) cancel_auto_show=false;; no-cancel) cancel_auto_show=false;;
timeout) timeout=$OPTARG;;
help) print_help;; help) print_help;;
*) print_help illegal_opt;; *) error "Unknown option --$OPTION." \
"Use --help to see available flags.";;
esac;; esac;;
*) print_help illegal_opt;; *) error "Unknown option -$OPTARG." \
"Use --help to see available flags.";;
esac esac
done done
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
program=$1 program=$1
# check that the program is not a path and does not contain flags if [[ ${#program_flags[@]} -eq 0 ]]; then
if [[ ! $program =~ ^(current|auto_hide|auto_show|toggle_auto_hide)$ ]] && \ program_flags=("${@:2}")
! type "$program" 2> /dev/null; then
echo >&2 "The program should be in PATH and not contain flags." | \
tee -a "$MUTDROP_PATH"/log
exit 1
fi fi
if [[ $# -ne 1 ]]; then if [[ -z $program ]]; then
echo >&2 "Exactly 1 positional argument is required." \ error "Program to run is required as a positional argument." \
"For help use -h or --help or see the manpage." | \ "For help use -h or --help or see the manpage."
tee -a "$MUTDROP_PATH"/log fi
exit 1
# check that the program is in PATH
if [[ ! $program =~ ^(current|auto_hide|auto_show|toggle_auto_hide|hide_all)$ ]] && \
! type "$program" &> /dev/null; then
error "The program should be in PATH."
fi fi
# validate options that require number values # validate options that require number values
if [[ ! $height$width$xoff$yoff =~ ^[0-9%-]*$ ]]; then if [[ ! $height$width$xoff$yoff =~ ^[0-9%-]*$ ]]; then
echo >&2 "The -h, -w, -x, and -y values must be numbers (or percentages)." | \ error "The -h, -w, -x, and -y values must be numbers (or percentages)."
tee -a "$MUTDROP_PATH"/log
exit 1
fi fi
if [[ -n $dec_fix ]] && [[ ! $dec_fix =~ ^-?[0-9]+x-?[0-9]+$ ]]; then if [[ -n $dec_fix ]] && [[ ! $dec_fix =~ ^-?[0-9]+x-?[0-9]+$ ]]; then
echo >&2 "The decoration fix value must have form 'num'x'num'." \ error "The decoration fix value must have form 'num'x'num'." \
"The numbers can be negative or zero." | tee -a "$MUTDROP_PATH"/log "The numbers can be negative or zero."
exit 1
fi fi
# non-user-settable global vars # non-user-settable global vars
wid= wid=
# 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 # * Multiple Monitor Automatic Re-Sizing
percent_of_total() { # percent total percent_of_total() { # percent total
awk "BEGIN {printf(\"%.0f\", 0.01*${1%\%}*$2)}" # gawk "BEGIN {printf(\"%.0f\", 0.01*${1%\%}*$2)}"
echo $((${1%\%} * ${2} / 100))
} }
# acts on globals # acts on globals
@ -240,6 +243,21 @@ convert_geometry_to_pixels() {
fi fi
} }
# meant to set non-local variables
split_geometry() { # <monitor geometry>
monitor_geo=$1
# x_begin=$(echo "$monitor_geo" | gawk -F '+' '{print $2}')
x_begin=${monitor_geo#*+}
x_begin=${x_begin%+*}
# y_begin=$(echo "$monitor_geo" | gawk -F '+' '{print $3}')
y_begin=${monitor_geo##*+}
# x_width=$(echo "$monitor_geo" | gawk -F 'x' '{print $1}')
x_width=${monitor_geo%x*}
# y_height=$(echo "$monitor_geo" | gawk -F 'x|+' '{print $2}')
y_height=${monitor_geo#*x}
y_height=${y_height%%+*}
}
update_geometry_settings_for_monitor() { update_geometry_settings_for_monitor() {
# 1. Correctly interpret width/height percentages when there exist multiple # 1. Correctly interpret width/height percentages when there exist multiple
# monitors so an initially created dropdown is the correct size (xdotool # monitors so an initially created dropdown is the correct size (xdotool
@ -250,49 +268,54 @@ update_geometry_settings_for_monitor() {
# it is conceivable that a user may want to use -m but not -a, so # it is conceivable that a user may want to use -m but not -a, so
# get the wm from within this function # get the wm from within this function
local wm current_monitor local current_monitor
wm=$(get_window_manager)
if [[ $wm == bspwm ]]; then if [[ $wm == bspwm ]]; then
current_monitor=$(bspc query -T -m | grep -Po '^{"name":.*?",' | \ current_monitor=$(bspc query --names --monitors --monitor)
awk -F ":" '{gsub("[\",]", ""); print $2}')
elif [[ $wm == i3 ]]; then elif [[ $wm == i3 ]]; then
# TODO use jq if installed
# I'd rather not make jq a dependency # I'd rather not make jq a dependency
current_monitor=$(i3-msg -t get_workspaces | sed 's/{"num"/\n/g' | \ current_monitor=$(i3-msg -t get_workspaces | sed 's/{"num"/\n/g' | \
awk -F ',' '/focused":true/ {sub(".*output",""); gsub("[:\"]",""); print $1}') gawk -F ',' '/focused":true/ {sub(".*output",""); gsub("[:\"]",""); print $1}')
fi fi
local monitor_geo x_begin y_begin x_width y_height local monitor_geo x_begin y_begin x_width y_height
if [[ -n $current_monitor ]]; then if [[ -n $current_monitor ]]; then
monitor_geo=$(xrandr --query | \ monitor_geo=$(xrandr --current | \
awk "/$current_monitor/ {gsub(\"primary \",\"\"); print \$3}") gawk "/^$current_monitor/ {gsub(\"primary \",\"\"); print \$3}")
x_begin=$(echo "$monitor_geo" | awk -F '+' '{print $2}') split_geometry "$monitor_geo"
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 else
local wid wininfo window_x window_y monitors_info x_end y_end local current_x current_y monitors_info x_end y_end
# determine current monitor in generic way if ! $pointer_monitor_detection; then
# determine current monitor using active window
local wid wininfo
wid=$(xdotool getactivewindow) wid=$(xdotool getactivewindow)
if [[ -z $wid ]]; then if [[ -z $wid ]]; then
# will try again after remapping or creating the dropdown # will try again after remapping or creating the dropdown
return 1 return 1
fi fi
wininfo=$(xwininfo -id "$wid") wininfo=$(xwininfo -id "$wid")
window_x=$(echo "$wininfo" | awk '/Absolute.*X/ {print $4}') current_x=$(echo "$wininfo" | gawk '/Absolute.*X/ {print $4}')
window_y=$(echo "$wininfo" | awk '/Absolute.*Y/ {print $4}') current_y=$(echo "$wininfo" | gawk '/Absolute.*Y/ {print $4}')
monitors_info=$(xrandr --query | awk '/ connected/ {gsub("primary ",""); print}') else
# shellcheck disable=SC2034
local X Y SCREEN WINDOW
# determine current monitor using pointer location
eval "$(xdotool getmouselocation --shell)"
current_x=X
current_y=Y
fi
monitors_info=$(xrandr --current | gawk '/ connected/ {gsub("primary ",""); print}')
while read -r monitor; do while read -r monitor; do
monitor_geo=$(echo "$monitor" | awk '{print $3}') monitor_geo=$(echo "$monitor" | gawk '{print $3}')
if [[ $monitor_geo =~ ^[0-9]+x[0-9]+\+[0-9]+\+[0-9]+$ ]]; then if [[ $monitor_geo =~ ^[0-9]+x[0-9]+\+[0-9]+\+[0-9]+$ ]]; then
x_begin=$(echo "$monitor_geo" | awk -F '+' '{print $2}') split_geometry "$monitor_geo"
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)) x_end=$((x_begin+x_width))
y_end=$((y_begin+y_height)) y_end=$((y_begin+y_height))
if [[ $window_x -ge $x_begin ]] && [[ $window_x -lt $x_end ]] && \ if [[ $current_x -ge $x_begin ]] && [[ $current_x -lt $x_end ]] && \
[[ $window_y -ge $y_begin ]] && [[ $window_y -lt $y_end ]]; then [[ $current_y -ge $y_begin ]] && [[ $current_y -lt $y_end ]]; then
current_monitor=$(echo "$monitor" | awk '{print $1}') # current_monitor=$(echo "$monitor" | gawk '{print $1}')
current_monitor=${monitor%% *}
break break
fi fi
fi fi
@ -314,27 +337,29 @@ map_and_reset_geometry() {
} }
# * WM Detection and Hooks # * WM Detection and Hooks
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
}
set_wm() { set_wm() {
if ! $user_set_wm && $auto_detect_wm; then if ! $user_set_wm && $auto_detect_wm; then
wm=$(get_window_manager) local id
id=$(xprop -root -notype _NET_SUPPORTING_WM_CHECK)
id=${id##* }
# xfwm4 and fvwm at least will give two names (hence piping into head)
wm=$(xprop -notype -id "$id" _NET_WM_NAME | head -n 1)
wm=${wm##* }
wm=${wm//\"/}
fi fi
} }
decoration_settings() { decoration_settings() {
if [[ -z $subtract_when_same ]] && $auto_detect_wm; then if [[ -z $subtract_when_same ]]; then
if [[ $wm =~ ^(Mutter|GNOME Shell|bspwm|i3|GoomwW)$ ]]; then if $auto_detect_wm \
&& [[ $wm =~ ^(Mutter|GNOME Shell|bspwm|i3|GoomwW)$ ]]; then
subtract_when_same=false subtract_when_same=false
else
subtract_when_same=true
fi fi
fi fi
if [[ -z "$dec_fix" ]] && $auto_detect_wm; then if [[ -z $dec_fix ]] && $auto_detect_wm; then
# settings for stacking/floating wms where can't get right position # settings for stacking/floating wms where can't get right position
# easily from xwininfo; take borders into account # easily from xwininfo; take borders into account
if [[ $wm == Blackbox ]]; then if [[ $wm == Blackbox ]]; then
@ -348,14 +373,16 @@ decoration_settings() {
} }
set_class() { set_class() {
if [[ -z "$class" ]]; then if [[ -z $class ]]; then
if [[ $program =~ ^google-chrome ]]; then if [[ $program =~ ^emacsclient ]]; then
class=emacs
elif [[ $program =~ ^google-chrome ]]; then
class=google-chrome class=google-chrome
elif [[ $program == st ]]; then elif [[ $program == st ]]; then
class=st-256color class=st-256color
elif [[ $program == gnome-terminal ]]; then elif [[ $program == gnome-terminal ]]; then
class=Gnome-terminal class=Gnome-terminal
elif [[ $program == urxvtc ]]; then elif [[ $program =~ ^urxvt.* ]]; then
class=urxvt class=urxvt
elif [[ $program == xiatec ]]; then elif [[ $program == xiatec ]]; then
class=xiate class=xiate
@ -375,8 +402,8 @@ is_floating() {
elif $auto_detect_wm; then elif $auto_detect_wm; then
if [[ $wm == i3 ]]; then if [[ $wm == i3 ]]; then
# TODO make sure this returns 1 on failure # TODO make sure this returns 1 on failure
i3-msg -t get_tree | awk 'gsub(/{"id"/, "\n{\"id\"")' | \ i3-msg -t get_tree | gawk 'gsub(/{"id"/, "\n{\"id\"")' | \
awk '/focused":true.*floating":"user_on/ {print $1}' gawk '/focused":true.*floating":"user_on/ {print $1}'
elif [[ $wm == bspwm ]]; then elif [[ $wm == bspwm ]]; then
bspc query -T -n | grep '"state":"floating"' bspc query -T -n | grep '"state":"floating"'
else else
@ -486,11 +513,15 @@ unmap() {
# * General Helper Functions # * General Helper Functions
get_class_name() { get_class_name() {
xprop -id "$1" WM_CLASS | awk '{gsub(/"/, ""); print $4}' local class
class=$(xprop -id "$1" WM_CLASS 2> /dev/null)
class=${class##* }
class=${class//\"/}
echo "$class"
} }
get_visibility() { get_visibility() {
xwininfo -id "$1" 2> /dev/null | awk '/Map State/ {print $3}' xwininfo -id "$1" 2> /dev/null | gawk '/Map State/ {print $3}'
} }
maybe_cancel_auto_show() { maybe_cancel_auto_show() {
@ -501,77 +532,33 @@ maybe_cancel_auto_show() {
fi fi
} }
# * Dropdown Initialization
create_win_return_wid() {
local blacklist program_command pid visible_wid wids wid 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 =~ ^(tilix|xfce4-terminal)$ ]]; then
pid=$(pgrep -x "$program")
elif [[ $program == urxvtc ]]; then
blacklist=$(xdotool search --classname urxvtd)
pid=$(pgrep -x urxvtd)
elif [[ $program == xiatec ]]; then
pid=$(pgrep -x xiate)
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() { program_start() {
local program_command tmux_command wid local program_command tmux_command wid
program_command="$program $program_flags" program_command=("$program")
if [[ -n "$session_name" ]]; then if [[ $program == alacritty ]]; then
# prevent alacritty from resizing the terminal to 80x24
program_command+=(-d 0 0)
fi
program_command+=("${program_flags[@]}")
if [[ -n $session_name ]]; then
session_name=$(printf "%q" "$session_name") session_name=$(printf "%q" "$session_name")
tmux_command="'tmux attach-session -dt $session_name || \ tmux_command="tmux attach-session -dt $session_name || \
tmuxifier load-session $session_name || \
tmuxinator start $session_name || \ tmuxinator start $session_name || \
tmux new-session -s $session_name'" tmux new-session -s $session_name"
if [[ $program =~ ^(urxvt|alacritty|xiatec$) ]]; then # note: st will work with or without the -e flag (like kitty)
program_command="$program_command -e bash -c $tmux_command" # note: regular console works with or without quotes, but trinity's
# konsole only works without quotes
if [[ $program =~ ^(urxvt|alacritty|xiatec|st|lxterminal|qterminal|cool-retro-term|lilyterm|konsole$) ]]; then
program_command+=(-e bash -c "$tmux_command")
elif [[ $program == kitty ]]; then
program_command+=(bash -c "$tmux_command")
else else
program_command="$program_command -e \"bash -c $tmux_command\"" program_command+=(-e "\"bash -c $tmux_command\"")
fi fi
fi fi
wid=$(create_win_return_wid "$program_command") wid=$(xtoolwait -wid "${program_command[@]}")
if [[ -n "$name" ]]; then if [[ -n $name ]]; then
xdotool set_window --name "$name" "$wid" xdotool set_window --name "$name" "$wid"
fi fi
echo "$wid" > "$MUTDROP_PATH/$program$num" echo "$wid" > "$MUTDROP_PATH/$program$num"
@ -584,19 +571,30 @@ current_create() {
wid=$(xdotool getactivewindow) wid=$(xdotool getactivewindow)
echo "$wid" > "$MUTDROP_PATH"/current"$num" echo "$wid" > "$MUTDROP_PATH"/current"$num"
get_class_name "$wid" > "$MUTDROP_PATH"/current"$num"_class get_class_name "$wid" > "$MUTDROP_PATH"/current"$num"_class
if [[ -n "$name" ]]; then if [[ -n $name ]]; then
xdotool set_window --name "$name" "$wid" xdotool set_window --name "$name" "$wid"
fi fi
echo -n "$wid" echo -n "$wid"
} }
wid_toggle() { wid_toggle() {
# 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)
local focused_window_exists
focused_window_exists=true
# deal with percentages/negatives when no -m # deal with percentages/negatives when no -m
if ! $monitor_aware; then if ! $monitor_aware; then
local total_geo total_width total_height local total_geo total_width total_height
total_geo=$(xwininfo -root | awk '/geometry/ {print $2}') total_geo=$(xwininfo -root | gawk '/geometry/ {gsub("+*",""); print $2}')
total_width=$(echo "$total_geo" | awk -F 'x' '{print $1}') # total_width=$(echo "$total_geo" | gawk -F 'x' '{print $1}')
total_height=$(echo "$total_geo" | awk -F 'x|+' '{print $2}') total_width=${total_geo%x*}
# total_height=$(echo "$total_geo" | gawk -F 'x' '{print $2}')
total_height=${total_geo#*x}
convert_geometry_to_pixels "$total_width" "$total_height" convert_geometry_to_pixels "$total_width" "$total_height"
fi fi
# get saved window id if already created # get saved window id if already created
@ -607,7 +605,7 @@ wid_toggle() {
if [[ -n $wid ]]; then if [[ -n $wid ]]; then
visibility=$(get_visibility "$wid") visibility=$(get_visibility "$wid")
# sometimes xwininfo will still report a window as existing hence xprop check # sometimes xwininfo will still report a window as existing hence xprop check
if [[ -z $visibility ]] || [[ -z $(xprop -id "$wid" 2> /dev/null) ]]; then if [[ -z $visibility ]] || ! xprop -id "$wid" &> /dev/null; then
# window no longer exists # window no longer exists
exists=false exists=false
# shellcheck disable=SC2188 # shellcheck disable=SC2188
@ -685,14 +683,14 @@ wid_toggle() {
# * Helper Functions for Auto Hiding/Showing # * Helper Functions for Auto Hiding/Showing
get_geometry() { get_geometry() {
# so that won't float a tiled window later when showing # so that won't float a tiled window later when showing
if is_floating "$1"; then if is_floating "$1" &> /dev/null; then
local wininfo x y rel_x rel_y local wininfo x y rel_x rel_y width height
wininfo=$(xwininfo -id "$1") wininfo=$(xwininfo -id "$1")
x=$(echo "$wininfo" | awk '/Absolute.*X/ {print $4}') x=$(echo "$wininfo" | gawk '/Absolute.*X/ {print $4}')
y=$(echo "$wininfo" | awk '/Absolute.*Y/ {print $4}') y=$(echo "$wininfo" | gawk '/Absolute.*Y/ {print $4}')
rel_x=$(echo "$wininfo" | awk '/Relative.*X/ {print $4}') rel_x=$(echo "$wininfo" | gawk '/Relative.*X/ {print $4}')
rel_y=$(echo "$wininfo" | awk '/Relative.*Y/ {print $4}') rel_y=$(echo "$wininfo" | gawk '/Relative.*Y/ {print $4}')
if $subtract_when_same; then if [[ $subtract_when_same != false ]]; then
# behaviour works for most WMs (at least floating ones) # behaviour works for most WMs (at least floating ones)
x=$((x-rel_x)) x=$((x-rel_x))
y=$((y-rel_y)) y=$((y-rel_y))
@ -706,28 +704,32 @@ get_geometry() {
y=$((y-rel_y)) y=$((y-rel_y))
fi fi
fi fi
echo -n -e "X=$x\nY=$y" width=$(xwininfo -id "$(xdotool getactivewindow)" | \
gawk '/Width/ {print $2}')
height=$(xwininfo -id "$(xdotool getactivewindow)" | \
gawk '/Height/ {print $2}')
echo -n -e "xoff=$x\nyoff=$y\nwidth=$width\nheight=$height"
else else
# window is not floating; don't bother saving geometry # window is not floating; don't bother saving geometry
echo -n "false" echo -n "false"
fi fi
} }
retrieve_geometry() { # set global xoff, yoff, width, and height based on stored values
restore_geometry() {
local x_fix y_fix
eval "$(< "$MUTDROP_PATH"/auto_hidden/geometry)" eval "$(< "$MUTDROP_PATH"/auto_hidden/geometry)"
local x_fix y_fix X Y
if [[ -n $dec_fix ]]; then if [[ -n $dec_fix ]]; then
x_fix=$(echo "$dec_fix" | awk -F "x" '{print $1}') x_fix=$(echo "$dec_fix" | gawk -F "x" '{print $1}')
y_fix=$(echo "$dec_fix" | awk -F "x" '{print $2}') y_fix=$(echo "$dec_fix" | gawk -F "x" '{print $2}')
X=$((X-x_fix)) xoff=$((xoff-x_fix))
Y=$((Y-y_fix)) yoff=$((yoff-y_fix))
fi fi
echo -n "$X $Y"
} }
toggle_auto_hide() { toggle_auto_hide() {
local no_hide local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null)
mkdir -p "$MUTDROP_PATH"/auto_hidden mkdir -p "$MUTDROP_PATH"/auto_hidden
if [[ -z $no_hide ]]; then if [[ -z $no_hide ]]; then
echo "true" > "$MUTDROP_PATH"/auto_hidden/no_hide echo "true" > "$MUTDROP_PATH"/auto_hidden/no_hide
@ -740,7 +742,7 @@ toggle_auto_hide() {
# * Auto Hiding/Showing # * Auto Hiding/Showing
auto_hide() { auto_hide() {
local no_hide local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null)
if [[ -z $no_hide ]]; then if [[ -z $no_hide ]]; then
wid=$(xdotool getactivewindow) wid=$(xdotool getactivewindow)
mkdir -p "$MUTDROP_PATH"/auto_hidden mkdir -p "$MUTDROP_PATH"/auto_hidden
@ -753,20 +755,31 @@ auto_hide() {
auto_show() { auto_show() {
local no_hide local no_hide
no_hide=$(< "$MUTDROP_PATH"/auto_hidden/no_hide) 2> /dev/null no_hide=$(cat "$MUTDROP_PATH"/auto_hidden/no_hide 2> /dev/null)
if [[ -z $no_hide ]]; then if [[ -z $no_hide ]]; then
local was_floating XY local was_floating
wid=$(< "$MUTDROP_PATH"/auto_hidden/wid) wid=$(< "$MUTDROP_PATH"/auto_hidden/wid)
class=$(< "$MUTDROP_PATH"/auto_hidden/class) class=$(< "$MUTDROP_PATH"/auto_hidden/class)
was_floating=$(< "$MUTDROP_PATH"/auto_hidden/geometry) was_floating=$(< "$MUTDROP_PATH"/auto_hidden/geometry)
XY=$(retrieve_geometry "$wid") restore_geometry "$wid"
xoff=$(echo "$XY" | awk '{print $1}')
yoff=$(echo "$XY" | awk '{print $2}')
pre_map "$was_floating" pre_map "$was_floating"
map_and_post_map "$was_floating" map_and_post_map "$was_floating"
fi fi
} }
# * Hide All
hide_all() {
shopt -s nullglob dotglob
local dropdowns
dropdowns=("$MUTDROP_PATH"/*)
for dropdown in "${dropdowns[@]}"; do
# cat to silence errors
wid=$(cat "$dropdown" 2> /dev/null)
unmap "$wid" 2> /dev/null
done
shopt -u nullglob dotglob
}
# * Main # * Main
# ** Setup # ** Setup
set_wm set_wm
@ -783,11 +796,11 @@ elif [[ $program == auto_hide ]]; then
auto_hide auto_hide
elif [[ $program == auto_show ]]; then elif [[ $program == auto_show ]]; then
auto_show auto_show
elif [[ $program == hide_all ]]; then
hide_all
else else
wid_toggle wid_toggle
fi fi
# vim is dumb # vim is dumb
# vim: set ft=sh noet: # vim: set ft=sh noet:
set +x
exec 2>&3 3>&-

@ -1,16 +1,19 @@
.\" Manpage for tdrop. .\" Man page for tdrop.
.\" Please make an issue on the online repository if you find errors or typos. .\" Please make an issue on the online repository if you find errors or typos.
.TH TDROP 1 "11 February 2015" "tdrop 0.1" "tdrop man page" .TH TDROP 1 "11 February 2015" "tdrop 0.2" "tdrop man page"
.SH NAME .SH NAME
Tdrop - make dropdown terminals and windows Tdrop - make dropdown terminals and windows
.SH SYNOPSIS .SH SYNOPSIS
tdrop [\fIOPTIONS\fR] [program name or cmd] tdrop [\fIOPTIONS\fR] [program name or cmd] [program options ...]
.SH DESCRIPTION .SH DESCRIPTION
Tdrop is used for hiding/unhiding programs to acheive quake/dropdown functionality. It can create a dropdown window if one does not already exist or turn the current window into a dropdown on the fly. It provides options to control the intial size and position of dropdowns, for example to leave panels visible or to deal with window borders. When used with a terminal, it provides an option to specify the name of a tmuxinator or tmux session to automatically start. It also allows the user to specify arbitrary options/flags to be used when starting programs. It uses window IDs as opposed to classes, so it can be used with multiple windows of the same program. Tdrop is used for hiding/unhiding programs to acheive quake/dropdown functionality. It can create a dropdown window if one does not already exist or turn the current window into a dropdown on the fly. It provides options to control the intial size and position of dropdowns, for example to leave panels visible or to deal with window borders. When used with a terminal, it provides an option to specify the name of a tmux session to automatically start. It also allows the user to specify arbitrary options/flags to be used when starting programs. It uses window IDs as opposed to classes, so it can be used with multiple windows of the same program.
It also has the ability to automatically hide and automatically show dropdowns. For example, it can be used to automatically hide a terminal when opening something from it, e.g. an image viewer, video player, etc. Tdrop can then automatically bring back the terminal whenever the image view, video player, etc. is closed. See the Examples section for more information. It also has the ability to automatically hide and automatically show dropdowns. For example, it can be used to automatically hide a terminal when opening something from it, e.g. an image viewer, video player, etc. Tdrop can then automatically bring back the terminal whenever the image view, video player, etc. is closed. See the Examples section for more information.
.SH Commands .SH Commands
Tdrop expects the name of a program or 'current' (to use the current window) as the last argument to create a dropdown. Alternatively, it can take one of auto_show, auto_hide, or toggle_auto_hide. Neither functionality is particularly useful called directly from the command line; the former should be bound to a key, and the latter is better used in shell functions/aliases or with a file opener (e.g. in the rifle.conf). Tdrop expects the name of a program or 'current' (to use the current window) as the last argument to create a dropdown (optionally followed by any flags to that program). Alternatively, it can take one of auto_show, auto_hide, toggle_auto_hide, or hide_all. If hide_all is given instead of a program name, tdrop will hide all visible dropdowns.
Tdrop's functionality is not particularly useful called directly from the command line. Commands should either be bound to a key, used in shell functions/aliases, or used with a file opener (e.g. in the rifle.conf).
.SH OPTIONS .SH OPTIONS
.br .br
E.g. E.g.
@ -36,7 +39,7 @@ Specify the x position for a created window as a number or percentage. (default:
Specify the y position for a created window as a number or percentage. (default: 1, see BUGS) Specify the y position for a created window as a number or percentage. (default: 1, see BUGS)
.TP .TP
\fB-s NAME\fR, \fB --session=NAME\fR \fB-s NAME\fR, \fB --session=NAME\fR
Specify a tmuxinator or tmux session name to start. An existing tmux session has highest precedence and will be connected to with '-d', detaching other attached clients. If a there is no tmuxinator session of the given name, a normal tmux session with the name will be created. If this option is not given, tmux will not be used. Note that this option requires that the program be a supported terminal. (default: none) Specify a tmuxinator, tmuxifier, or tmux session name to start. An existing tmux session has highest precedence and will be connected to with '-d', detaching other attached clients. If a there is no tmuxinator/tmuxifier/etc. session of the given name, a normal tmux session with the name will be created. If this option is not given, tmux will not be used. Note that this option requires that the program be a supported terminal. (default: none)
.TP .TP
\fB-n NUMBER\fR, \fB --number=NUMBER\fR \fB-n NUMBER\fR, \fB --number=NUMBER\fR
Specify a number (or any extra text) to differentiate between dropdowns of the same program (this is only needed when using multiple dropdowns of the same program). This flag can also be used for creating multiple different dropdowns on the fly ('current'). Note that it is not necessary to use this to deal with multi-user systems as tdrop stores dropdown information separately for each user. (default: none) Specify a number (or any extra text) to differentiate between dropdowns of the same program (this is only needed when using multiple dropdowns of the same program). This flag can also be used for creating multiple different dropdowns on the fly ('current'). Note that it is not necessary to use this to deal with multi-user systems as tdrop stores dropdown information separately for each user. (default: none)
@ -44,8 +47,8 @@ Specify a number (or any extra text) to differentiate between dropdowns of the s
\fB-c COMMAND\fR, \fB --pre-create-hook=COMMAND\fR \fB-c COMMAND\fR, \fB --pre-create-hook=COMMAND\fR
Specify a command to execute before first creating or initializing a dropdown (before mapping a normal dropdown or before unmapping the 'current' window). This flag has no effect for the auto_(hide|show) commands. (default: none) Specify a command to execute before first creating or initializing a dropdown (before mapping a normal dropdown or before unmapping the 'current' window). This flag has no effect for the auto_(hide|show) commands. (default: none)
.TP .TP
\fB-C\fR, \fB --pre-create-hook=COMMAND\fR \fB-C\fR, \fB --post-create-hook=COMMAND\fR
NDSpecify a command to execute after first creating or initializing a dropdown (after mapping a normal dropdown or after unmapping the 'current' window). This flag has no effect for the auto_(hide|show) commands. (default: none) Specify a command to execute after first creating or initializing a dropdown (after mapping a normal dropdown or after unmapping the 'current' window). This flag has no effect for the auto_(hide|show) commands. (default: none)
.TP .TP
\fB-p COMMAND\fR, \fB --pre-map-hook=COMMAND\fR \fB-p COMMAND\fR, \fB --pre-map-hook=COMMAND\fR
Specify a command to execute before showing/mapping a dropdown. Note that this will run when showing a dropdown for the first time even when --pre-create-hook is used. (default: none) Specify a command to execute before showing/mapping a dropdown. Note that this will run when showing a dropdown for the first time even when --pre-create-hook is used. (default: none)
@ -53,18 +56,18 @@ Specify a command to execute before showing/mapping a dropdown. Note that this w
\fB-P COMMAND\fR, \fB --post-map-hook=COMMAND\fR \fB-P COMMAND\fR, \fB --post-map-hook=COMMAND\fR
Specify a command to execute after showing/mapping a dropdown. Note that this will run when hiding a dropdown for the first time even when --post-create-hook is used. (default: none) Specify a command to execute after showing/mapping a dropdown. Note that this will run when hiding a dropdown for the first time even when --post-create-hook is used. (default: none)
.TP .TP
\fB-l COMMAND\fR, \fB --pre-map-float-command=COMMAND\fR
Specify a command execute before showing/mapping a dropdown in order to float the dropdown (e.g. a bspwm oneshot rule). This may be useful if you don't want to float all windows of a given program and tdrop doesn't automatically support this for your window manager with the -a flag. This will override any default floating command when used with -a.
.TP
\fB-L COMMAND\fR, \fB --post-map-float-command=COMMAND\fR
Specify a command execute after showing/mapping a dropdown in order to float the dropdown. This may be useful if you don't want to float all windows of a given program and tdrop doesn't automatically support this for your window manager with the -a flag. This can be used if your window manager does not support floating rules at all; for example, it can be used to fake a key combination (e.g. using xdotool) that will float the current window. This will override any default floating command when used with -a.
.TP
\fB-u COMMAND\fR, \fB --pre-unmap-hook=COMMAND\fR \fB-u COMMAND\fR, \fB --pre-unmap-hook=COMMAND\fR
Specify a command to execute before hiding/unmapping a dropdown. (default: none) Specify a command to execute before hiding/unmapping a dropdown. (default: none)
.TP .TP
\fB-U COMMAND\fR, \fB --post-unmap-hook=COMMAND\fR \fB-U COMMAND\fR, \fB --post-unmap-hook=COMMAND\fR
Specify a command to execute after hiding/unmapping a dropdown. (default: none) Specify a command to execute after hiding/unmapping a dropdown. (default: none)
.TP .TP
\fB-l COMMAND\fR, \fB --pre-map-float-command=COMMAND\fR
Specify a command execute before showing/mapping a dropdown in order to float the dropdown (e.g. a bspwm oneshot rule). This may be useful if you don't want to float all windows of a given program and tdrop doesn't automatically support this for your window manager with the -a flag. This will override any default floating command when used with -a.
.TP
\fB-L COMMAND\fR, \fB --post-map-float-command=COMMAND\fR
Specify a command execute after showing/mapping a dropdown in order to float the dropdown. This may be useful if you don't want to float all windows of a given program and tdrop doesn't automatically support this for your window manager with the -a flag. This can be used if your window manager does not support floating rules at all; for example, it can be used to fake a key combination (e.g. using xdotool) that will float the current window. This will override any default floating command when used with -a.
.TP
\fB-d DEC_SIZE\fR, \fB --decoration-fix=DEC_SIZE\fR \fB-d DEC_SIZE\fR, \fB --decoration-fix=DEC_SIZE\fR
Specify a window decoration/border size in the form <x decoration size>x<y decoration size> to be taken into account when saving window position. This should not be necessary for most window managers and is only used with 'auto_show', e.g. 'tdrop -d 1x22 auto_show' for blackbox. (default: none) Specify a window decoration/border size in the form <x decoration size>x<y decoration size> to be taken into account when saving window position. This should not be necessary for most window managers and is only used with 'auto_show', e.g. 'tdrop -d 1x22 auto_show' for blackbox. (default: none)
.TP .TP
@ -75,7 +78,11 @@ This option is a more complicated companion to -d that is also unlikely to be ne
Specify a command that will determine whether the current window is floating ($wid can be used in the command instead). Only used for the auto_hide command. This will be used to save whether the current window is floating or not. When restoring the window, if there is a float command and the window was previously floating, it will be floated. (default: none) Specify a command that will determine whether the current window is floating ($wid can be used in the command instead). Only used for the auto_hide command. This will be used to save whether the current window is floating or not. When restoring the window, if there is a float command and the window was previously floating, it will be floated. (default: none)
.TP .TP
\fB-f\fR, \fB --program-flags\fR \fB-f\fR, \fB --program-flags\fR
Specify flags/options that the terminal or program should be called with. For example, to set the title of the terminal, something like '-f "--title mytitle"' can be used. 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! (default: none) NOTE: Using this flag is deprecated; it may be removed in the future. Instead, specify program flags after the program (e.g. "tdrop kitty --name foo").
Specify flags/options that the terminal or program should be called with. For example, to set the title of the terminal, something like 'tdrop -f "--title mytitle" <program>' can be used.
Caution: If there is a tmux session specified (with -s), the option to execute a program (usually -e for terminal programs) is implicitly added by tdrop! (default: none)
.TP .TP
\fB-a\fR, \fB --auto-detect-wm\fR \fB-a\fR, \fB --auto-detect-wm\fR
If there are available settings for the detected window manager for the -l, -L, -d, and/or -i options, automatically set them. Takes no argument. Manually specified settings take precedence. This can be used both for dropdowns and the auto_(hide|show) commands. Takes no argument. (default: false) If there are available settings for the detected window manager for the -l, -L, -d, and/or -i options, automatically set them. Takes no argument. Manually specified settings take precedence. This can be used both for dropdowns and the auto_(hide|show) commands. Takes no argument. (default: false)
@ -83,9 +90,12 @@ If there are available settings for the detected window manager for the -l, -L,
\fB-m\fR, \fB --monitor-aware\fR \fB-m\fR, \fB --monitor-aware\fR
This option only applies for dropdowns (not auto-hiding and auto-showing). Specify that geometry values should be relative to the current monitor. For example, if the width is a percentage or negative value, the pixel width will be calculated as a percentage of the current monitor's width (instead of the combined width of all monitors). If the monitor changes, this option will cause a dropdown to be resized to fit the given percentages. Note that this option assumes xrandr is being used and requires xrandr to work. (default: false) This option only applies for dropdowns (not auto-hiding and auto-showing). Specify that geometry values should be relative to the current monitor. For example, if the width is a percentage or negative value, the pixel width will be calculated as a percentage of the current monitor's width (instead of the combined width of all monitors). If the monitor changes, this option will cause a dropdown to be resized to fit the given percentages. Note that this option assumes xrandr is being used and requires xrandr to work. (default: false)
.TP .TP
\fB-t\fR, \fB --pointer-monitor-detection\fR
Use mouse pointer location for detecting which monitor is the current one so terminal will be displayed on it. Without this option, the monitor with currently active window is considered the current one. This option is only effective if -m / --monitor-aware option is enabled.
.TP
\fB --wm=NAME\fR \fB --wm=NAME\fR
Specify the window manager name (which determines the default settings when -a is specified). This may be useful if you've change the name of your window manager using wmname as this will prevent tdrop from correctly detecting the real window manager name. This could also potentially be useful if the all the default -a settings for another window manager work with the current one (e.g. if using a similar but differently named fork of some window manager). (default: automatically detected)
.TP .TP
Mimic another WM's rules with -a. This is unlikely to be useful. It could potentially be used in the case where a similar fork of a window manager had a different name. (default: automatically detected)
\fB --class=NAME\fR \fB --class=NAME\fR
Providing this option lets tdrop know what the class (or classname) of the window is (it does not actually set the class for a window). This is used for window managers like bspwm that use the class for floating rules. For some commonly used programs, tdrop will already use the correct class. This option is useful when the program name and class are not the same and there is not already a default mapping between the two. (default: the program name or a known substitution) Providing this option lets tdrop know what the class (or classname) of the window is (it does not actually set the class for a window). This is used for window managers like bspwm that use the class for floating rules. For some commonly used programs, tdrop will already use the correct class. This option is useful when the program name and class are not the same and there is not already a default mapping between the two. (default: the program name or a known substitution)
@ -99,6 +109,8 @@ Used to clear a saved window id for the given program or 'current' instead of cr
.TP .TP
\fB --no-cancel\fR \fB --no-cancel\fR
Specifies that manually re-showing an auto-hidden window with tdrop should not cancel an auto_show. Takes no argument. See the examples. Specifies that manually re-showing an auto-hidden window with tdrop should not cancel an auto_show. Takes no argument. See the examples.
\fB --timeout\fR
Specifies the timeout in to wait for a window to appear when starting a program before giving up. This prevents a tdrop process from sticking around forever if a program fails to start. (default: 10)
.TP .TP
\fB --help\fR \fB --help\fR
Print basic help information. Takes no argument. Print basic help information. Takes no argument.
@ -123,7 +135,7 @@ Tdrop supports controlling the initial size and placement of a terminal. The bor
.br .br
$ tdrop -a -w 1362 -y 14 xterm $ tdrop -a -w 1362 -y 14 xterm
Tdrop can also create a tmux or tmuxinator session if it does not exist: Tdrop can also create a tmux session if it does not exist:
.br .br
$ tdrop -a -w 1362 -y 14 -s dropdown xterm $ tdrop -a -w 1362 -y 14 -s dropdown xterm
@ -180,9 +192,9 @@ mime ^image, has sxiv, X, flag f = tdrop auto_hide ; sxiv -a -- "$@" && tdrop -a
If -y is set to 0, a window may be subsequently moved to the middle when showing/mapping it with xdotool. This may have to do with the window border. If -y is set to 0, a window may be subsequently moved to the middle when showing/mapping it with xdotool. This may have to do with the window border.
.SH AUTHOR .SH AUTHOR
Fox Kiester <noct@openmailbox\&.org> Fox Kiester <noct at posteo\&.net>
.br .br
Source: https://github.com/noct/tdrop Source: https://github.com/noctuid/tdrop
.SH SEE ALSO .SH SEE ALSO
xdotool(1), sxhkd(1), xprop(1), xwininfo(1), tmux(1) xdotool(1), sxhkd(1), xprop(1), xwininfo(1), tmux(1)

Loading…
Cancel
Save