public wiki contents of
git clone git://
Log | Files | Refs (9882B)

      1 # Dynamic, Command-Line Driven Window Swallowing for dwm
      3 This patch introduces "dynamic" window swallowing to dwm. In contrast to the
      4 mechanisms of the existing ("static") [swallow
      5 patch](, dynamic window swallowing is
      6 run-time configurable and fully scriptable via `dwmswallow`, the command-line
      7 tool included with this patch.
      9 ## Download
     11 - [dwm-dynamicswallow-20210221-61bb8b2.diff](dwm-dynamicswallow-20210221-61bb8b2.diff)
     13 ## 1. Usage
     15 Window swallowing is concerned with two scenarios: an existing window may
     16 either swallow another existing window, or it may be registered to swallow
     17 a future window.
     19 ### 1.1 Swallowing Future Windows
     21 Any window managed by dwm may be registered to swallow the next upcoming window
     22 whose attributes match the class name, instance name and window title filters
     23 using the command-line tool `dwmswallow`. Quoting from `dwmswallow -h`:
     25     dwmswallow SWALLOWER [-c CLASS] [-i INSTANCE] [-t TITLE]
     26       Register window SWALLOWER to swallow the next future window whose attributes
     27       match the CLASS name, INSTANCE name and window TITLE filters using basic
     28       string-matching. An omitted filter will match anything.
     30 The next window whose filters match will be swallowed by SWALLOWER, taking its
     31 place. See the following example in which a terminal launches the `surf`
     32 browser and swallows its window, creating the impression of browsing the web
     33 "inside" the terminal. Upon closing the browser the terminal reappears. Note
     34 the symbol in the status bar next to the layout symbol while the swallow is
     35 active.
     37 ![](demo.gif)
     39 This example uses the WINDOWID environment variable to retrieve the terminal's
     40 window id. Some terminals such as `st` or `kitty` export the variable, while
     41 others such as `gnome-terminal` don't.
     43 Note that swallowing is not at all restricted to terminals. Any two windows
     44 managed by dwm may be involved. Also, window swallowing is agnostic towards
     45 layouts, respects your usage of size hints and can be nested to arbitrary
     46 depths.
     48 ### 1.2 Swallowing Existing Windows
     50 Swallowing of existing windows may be performed either from the command-line
     51 (see `dwmswallow -h`) or using drag-and-drop via pointer (*mod+shift+button1*
     52 by default).
     54 See the following example in which a terminal is used to launch an application
     55 whose stdout is considered important during its startup sequence. Once the
     56 startup finishes without errors the stdout is of no interest anymore and the
     57 terminal window is made to swallow the application window by drag-and-dropping
     58 the latter onto the former.
     60 ![](demo2.gif)
     62 Afterwards, the terminal can be remapped at any time by stopping the swallow using
     63 a hotkey (*mod+u* by default), which is not shown in the example.
     65 ### 1.3 Shell Integration
     67 When working in a terminal a shell alias can be used to express whether
     68 a graphical application shall open in a separate window or "inside" the
     69 terminal. Given `alias s='dwmswallow $WINDOWID;'` the command `s myguiprog`
     70 will run the application and swallow its window. Note that this requires the
     71 terminal to export the WINDOWID environment variable.
     73 Alternatively, a shell hotkey may be configured to preface the execution of
     74 a command with `dwmswallow $WINDOWID`. For example, the following zsh
     75 configuration will cause an application to be swallowed by the terminal when
     76 its command is submitted by pressing *CTRL-x + Enter* as opposed to pressing
     77 only *Enter*.
     79     # add to .zshrc
     80     bindkey '^X^m' accept-line-swallow
     81     zle -N accept-line-swallow acceptandswallow
     82     acceptandswallow() {
     83         dwmswallow $WINDOWID
     84         zle accept-line
     85     }
     87 ## 2. Patching Instructions
     89 Unless your fork of dwm is only slighly modified the adaptions to the patch
     90 listed here may be necessary or appropriate to better fit in with your existing
     91 build.
     93 ### 2.1 Patch-Specific Geometry Parameters
     95 When swallowing a window the swallowee copies the swallower's geometry
     96 parameters to reposition itself to where the swallower used to be, creating the
     97 impression of one window incorporating another. There exist patches which add
     98 client-specific parameters that can modify a window's size or behavior. When
     99 applying the dynamicswallow patch these parameters must be configured manually
    100 in two places:
    102 1. Inside `swal()`: during the swallowing of a window the swallowee shall
    103    inherit a copy of the swallower's values of these parameters.
    104 2. Inside `swalstop()`: when swallowing is stopped the swallower is remapped
    105    and the parameters' defaults for its window have to be chosen.
    107 As a representative example consider the
    108 [cfacts]( patch which allows to
    109 configure the relative sizes of windows in tiling mode using the
    110 client-specific parameter `cfact` of type float. The two changes necessary to
    111 accommodate this parameter are:
    113 1. Inside `swal()`: `cfact` shall be copied from the swallower to the swallowee.
    115         /* Configure geometry params obtained from patches (e.g. cfacts) here. */
    116         swee->cfact = swer->cfact;
    118 2. Inside `swalstop()`: the swallower's `cfact` shall be set to a sensible default.
    120         /* Configure geometry params obtained from patches (e.g. cfacts) here. */
    121         swer->cfact = 1.0;
    123 The specific places of where to configure the parameters are marked with
    124 comments included in the patch.
    126 ### 2.2 Inter-Process Communication
    128 In order for `dwmswallow` to communicate with dwm some means of inter-process
    129 communication is required which dwm does not provide by default. To this end,
    130 this patch includes an adaption of the
    131 [fakesignal]( patch which allows
    132 sending commands to dwm by concatenating the command and its parameters into
    133 a specifically formatted string and making it the name of the root window.
    135 The fakesignal patch is lightweight, non-intrusive, easy to use and easy to
    136 extend to other commands. If your build does not include any IPC mechanisms
    137 there's no reason to not use fakesignal as a starting point. Its only downside
    138 is that the communication is unidirectional: one may send commands to dwm but
    139 dwm cannot send a reply in return.
    141 If your build of dwm does contain an IPC mechanism you may, of course, use your
    142 existing communication pathways. While there's nothing wrong with using
    143 fakesignal to try out the patch you will eventually want to seemlessly
    144 integrate everything into your existing build. To achieve this you'll have to
    146 1. relay the execution of `dwmswallow SWALLOWER SWALLOWEE` to a call to `swal()`.
    147 2. relay the execution of `dwmswallow -c CLASS -i INSTANCE -t TITLE` to a call to `swalreg()`.
    148 3. relay the execution of `dwmswallow -s` to a call to `swalstop()`.
    149 4. relay the execution of `dwmswallow -d` to a call to `swalunreg()`.
    151 using your IPC mechanism of choice.
    153 ## 3. Assorted Notes and Implementation Details
    155 Consult this section if you're interested in changing the default behavior or
    156 if you're curious about the internals of the patch. The content herein is
    157 presented in no particular order.
    159 ### 3.1 Swallow Indicator in Status Bar
    161 If the currently selected window on a monitor is being swallowed a
    162 tongue-symbol 👅 (U+1F445) is drawn on the status bar next to the layout
    163 symbol. If this is undesired remove the relevant commented section from
    164 `drawbar()` or change the symbol in your *config.h*.
    166 ### 3.2 Retroactive Swallowing
    168 When registering the swallow of a future window using the window title as
    169 filter the swallowing may fail for some applications if retroactive swallowing
    170 is disabled (set by `swalretroactive`). This is due to the fact these
    171 applications create their window using a default window title and only update
    172 it later to the proper, usage-specific value. When dwm checks whether any
    173 registed swallows match the window's title it finds that none do due to the
    174 usage of the default window title when the window is mapped.
    176 If retroactive swallowing is enabled each time a window changes its title dwm
    177 checks whether a registered swallow instance matches the window and executes it
    178 accordingly. If you find yourself wanting to filter by window title keep
    179 retroactive swallowing enabled. While things are small, as they usually are,
    180 the runtime costs are completely negligible.
    182 An example of this is the PDF viewer zathura. Zathura's window title reflects
    183 the currently viewed file and may be used to register swallows of PDF previews
    184 filtered by filename. However, zathura's startup sequence exhibits the above
    185 behavior and the window title is set to reflect the filename only after a
    186 default window title has been used.
    188     # This requires retroactive swallowing
    189     dwmswallow $WINDOWID -c Zathura -t ~/books/xlib.pdf
    190     zathura ~/books/xlib.pdf
    192 ### 3.3 Decaying of Registered Swallows
    194 It occasionally happens that swallows are registered but not consumed, either
    195 due to misspelling the filters, causing them to never match or because the
    196 user's intention has changed along the way. If `swaldecay` is set to a value
    197 greater than zero any registered swallow instance is deleted if it hasn't been
    198 consumed after so many new windows are mapped, i.e. after *swaldecay*
    199 unsuccessful matches.
    201 ### 3.4 `wintoclient()` vs `wintoclient2()`
    203 Regular clients, swallowees and swallowers each require different handling by
    204 dwm with respect to X request and notify events (map, unmap, delete, configure,
    205 ...) for their respective windows.
    207 In order to distinguish between the three classes of clients during runtime the
    208 function `wintoclient2()` extends the functionality of the built-in
    209 `wintoclient()`. In addition to retrieving the address of a window's client
    210 from the window ID, it also returns the client type. It entails a change in
    211 signature which is responsible for the majority of changes made by the patch
    212 except for self-contained function definitions.
    214 ## Author
    216 - Stanislaw Hüll (