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