noctuid / tdrop

A Glorified WM-Independent Dropdown Creator
BSD 2-Clause "Simplified" License
1.09k stars 43 forks source link

[[https://github.com/noctuid/tdrop/actions?query=workflow%3Alint][https://github.com/noctuid/tdrop/workflows/lint/badge.svg]]

[[http://noctuid.github.io/tdrop/assets/termite.gif]]

This is a basic demo where tdrop is used to turn the current window (emacs) into a dropdown and then hide and show it on different desktops/workspaces:

[[http://noctuid.github.io/tdrop/assets/current.gif]]

Optional:

** 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 kitty

+END_EXAMPLE

The positional argument should be the name of a program in =$PATH= (as opposed to the full path to a program). It should always come after any tdrop flags. Flags for the program can come after it (e.g. ~tdrop urxvt -title foo~).

** Basic Flags For a full list of flags and documentation, see the manpage.

=-w= / =--width=, =-h= / =--height=, =-x= / =--xoff=, and =-y= / =--yoff= can be used to set the window size/position. The argument to any of these can be a number (e.g. =-w 800=) or a percentage (e.g. =-w 100%= or =-w 33.3%=) or empty (e.g. =-w "" -h ""= to prevent altering the window's size). Negative numbers correspond to that many pixels less than 100% of the screen width (e.g. =-w -4=). To unmanage all geometry settings, you can specify =-N= / =--no-manage=. This is the same as =-w "" -h "" -x "" -y ""= and should not be used with any other geometry flags.

If you want to be able to resize the dropdown after creating it, you can use the =-r= / =--remember= flag to store/restore the dropdown geometry when hiding/showing.

By default, tdrop will hide the dropdown if it is shown anywhere. =-A= / =--activate= can be used to always activate/show the dropdown if it is not focused.

=-s= / =--session= should only be used for supported terminals and if the user wants to start/attach to a tmux, tmuxinator, tmuxifier or tmxup session. Note that you do not need to use =-s= to start tmux. You can always pass arguments/flags to the program that tdrop runs, e.g. =tdrop kitty tmux=.

Tdrop has basic checks to print errors for malformed commands (e.g. 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.

** Automatic Window Manager Detection (=-a=) =-a= / =--auto-detect-wm= can be specified 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=, =-h=, =-x=, and =-y= to work correctly for tiling window managers with floating support). See the manpage for further details about these flags.

Note that if you've used [[https://tools.suckless.org/x/wmname][wmname]] to change your window manager's name, tdrop will use any settings for that name instead. In this case, you will generally need to specify the real name of your window manager using the =--wm= flag in order for =-a= to work correctly (e.g. if you are using bspwm and have run =wmname LG3D=, you will need to specify =--wm bspwm=).

** Monitor Awareness (=-m=) =-m= / =--monitor-aware= can be specified to automatically resize the dropdown based on the current monitor's size when percentages are used for =-w= and/or =-h=. 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 or directly for its geometry (e.g. bspwm, i3, and herbstluftwm), 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.

** Wayland support Tdrop does not support programs that use Wayland directly, but it does work under Wayland if the program uses XWayland. If your program defaults to using Wayland, you can generally force it to use XWayland by setting the environment variable =WAYLAND_DISPLAY=no=.

Also note that certain tdrop features don't work under Wayland due to limitations of =xdotool=. For instance, =-m= / =--monitor-aware= only works when combined with =-t= / =--pointer-monitor-detection=.

Example:

+begin_example

WAYLAND_DISPLAY=no tdrop -mta alacritty

+end_example

If you are using [[https://github.com/hyprwm/][Hyprland]] then [[https://github.com/Schweber/hdrop/tree/main][hdrop]] can emulate the main feature of tdrop, namely running, showing and hiding a given program depending on its current state.

** Flatpak As [[https://www.flatpak.org/][Flatpak]] jails applications, the PID cannot be used to find the attached window. A class name has to be given in order to find it, with =--class=.

As Flatpak is considered by tdrop as the program to run, tdrop cannot differentiate 2 different flatpak applications. Use the =-n= option for this purpose.

Example:

+begin_example

tdrop -ma -n signal --class=signal flatpak run org.signal.Signal tdrop -ma -n firefox --class=firefox flatpak run org.mozilla.firefox

+end_example

** 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 or name (see =--name=) 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 improve visual flickering regardless of the window manager is to enable fade-in for the compositor. For picom this can be done by setting =fading = true;= and adjusting the =fade-delta= in the =~/.config/picom.conf= accordingly.

** Hooks Tdrop provides hook flags that the user can specify to run commands at various stages during execution. These commands can make use of any global, internal tdrop variable, such as =$width=, =$height=, =$xoff=, =$yoff=, =$class=, and =$wid= (to prevent evaluation of these variables, the user can specify the hook command in single quotes). For example, to set a dropdown as always on top, the user could specify =-P 'wmctrl -i -r $wid -b add,above'=.

Note that for =--pre-map-hook= and =--pre-map-float-command=, the window id is not guarunteed to be known (since the window may not have yet been created), so any script that makes use of these flags should first check if =$wid= is defined. The window id will not be defined for =--pre-create-hook= (even for =current=; I can change this if there is a use case for it).

*** Pre Create =-c= / =--pre-create-hook=

Program The command will run once before the program is started.

Current The command will run once before unmapping the current window.

Hide and Show No effect.

*** Post Create =-C= / =--post-create-hook=

Program The command will run once after the program is started and its window is active.

Current The command will run once after unmapping the current window.

Hide and Show No effect.

*** Pre Map =-p= / =--pre-map-hook=

Program / Current / Show The command will run before creating the window and before subsequently mapping the window.

Hide No effect.

*** Post Map =-P= / =--post-map-hook=

Program / Current / Show The command will run after creating the window and after subsequently mapping the window. Note that unlike the pre-map hook, this will always run when showing the window, even if it was not previously unmapped (e.g. it is just being activated if =-A= is specified, or it is just being moved from another desktop). If you need different behavior (e.g. you need newly added distinct =--(pre|post)-show-hook= flags), please comment on [[https://github.com/noctuid/tdrop/issues/354][this issue]].

Hide No effect.

*** Pre Unmap =-u= / =--pre-unmap-hook=

Program / Current / Hide The command will run before unmapping the window.

Show No effect.

*** Post Unmap =-U= / =--post-unmap-hook=

Program / Current / Hide The command will run after unmapping the window.

Show No effect.

*** Pre Float =-l= / =--pre-map-float-command=

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 run before mapping the window.

Hide No effect.

Show The command will run before mapping the window only if it was previously floating.

*** Post Float =-L= / =--post-map-float-command=

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 run after mapping the window.

Hide No effect.

Show The command will run after mapping the window only if it was previously floating.

** 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

** Other Commands If =hide_all= is given instead of a program name, tdrop will hide all visible dropdowns.

If =foreach= is specified, tdrop will evaluate the following command for each dropdown. Here are some example commands:

+begin_src sh

same as hide_all

tdrop foreach 'unmap $wid'

hide only floating dropdowns on herbstluftwm

tdrop foreach 'herbstclient compare clients.$(printf 0x%x $wid).floating = on && unmap $wid'

+end_src

If your terminal doesn't work with tdrop, feel free to make an issue. Please follow the steps in the [[#troubleshooting][Troubleshooting]] section.

** Other Programs

** 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 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. Previously (=-a=) would automatically do this for herbstluftwm, but it now supports floating.

*** 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:

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:

Awesome support may be buggy; if you encounter problems, please report them.

You can specify the =--debug= flag to have tdrop print more verbose debugging output. Tdrop will automatically also save this output in =/tmp/tdrop"$USER""$DISPLAY"/log=. If tdrop does not appear at all, or there is some error, you can add the =--debug= flag and examine the log file or run the tdrop command in a terminal to see if the issue is obvious (e.g. tdrop will error if you do not have the required dependencies installed).

** Tdrop does not work with some terminal/program Please make an issue. Including the following information would help resolve the problem more quickly.

Basic:

Additional helpful information: