Home | About me | Miniblog | Playground
Español | Italiano

DEMWM

NAME

demwm - Dynamic Explosion-Mental’s Window Manager

SYNOPSIS

demwm [ function ] (argument)

DESCRIPTION

A custom fork of dwm(1), a (tiling) window manager for X. You have customs rules and layouts to use and set that handles clients in different ways.

Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags.

Each monitor has it’s own set of tags and therefore, one window can only belong to one monitor; meaning you can’t view the same window in two different independent monitors, of course this is possible if you mirror in between outputs (monitors).

The status bar text is filled with command outputs (stdout) defined in config.h. demwm will use the greatest common divisor of the interval value of the blocks array to have a constant value in order to call and update blocks that need it, so keep an eye on this. This will only display on the selected monitor.

A note about usage: The status text is done by the poll(3) system call, this exec(3)’s scripts every X (determined by the Greatest Common Divisor) seconds asynchronously, which of course stock dwm doesn’t. You won’t notice any change in resources if you normally use dwmblocks or it’s variants (all of them exec(3) scripts).

If the bar or the statustext it’s hidden, there would be no need to call poll(3) and status blocks won’t ever be exec(3)uted.

demwm also acts as an “client” program, which calls the window manager to do certain actions. See IPC section.

OPTIONS

Without any arguments, the program will try to initialize the window manager. For information about the kind of arguments check out IPC section.

SIGNALS

Earlier versions of demwm used SIGHUP and SIGTERM for restarting and quitting the window manager respectively. This is now handled by the argument restart and quit. See IPC section.

ENVIROMENT

BLOCK_BUTTON

For clicking to do anything you have to make a dedicated script which handles the BLOCK_BUTTON enviromental variable. See EXAMPLES section. To define the value of BLOCK_BUTTON, you have to edit config.h mouse buttons bindings sendstatusbar. This enviromental variable is only set to the script session being called.

CONFIGURATION

dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it simple, since reading a config file isn’t that hard (but adds unneeded complexity), and in many aspects more customizable. I try my best to comment about the variables in config.h, since they don’t do anything crazy, so it should be very straight foward what does what.

STATUS BAR TEXT BLOCKS

Entry Value
scheme Select a scheme to use for the block, can be a default one
(e.g. SchemeTitle) or you can create one by using SchemeLast+X
where X is a number starting from 0, this number increases
depending on how many schemes you make.
command A command (e.g. echo 'Hello World') which output will become
this block text.
interval How many seconds have to pass before updating (running/executing)
the command and update the output. Can be 0, which means never.
signal A number used to manually update the block.
Can be 0, which won’t allow you to signal the block.

IPC

Mostly for scripting or to do certain things without a need of a keybinding, freeing the keyboard with functions that you might use once in a while.

To use this you only need to call demwm with a function and it’s respective argument if any. See FUNCTIONS section for avaliable functions. Some of which aren’t avaliable/intendent to use as an ipc command and thus it’s noted, otherwise the function is included and avaliable to use.

Functions that do take an argument, are (/mostly) bidirectional: this means that number signs define the behaviour of the function. ( -1 / +1 )

FUNCTIONS

cyclelayout

Moves the layouts index depending on the argument.

It takes an integer argument.

combotag

Select multiple tags to tag by pressing all the right keys as a combo: you can press multiple tags by holding the modifier(s) keys (MOD by default).

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: This is not avaliable as an IPC function.

comboview

Select multiple tags to view by pressing all the right keys as a combo: you can press multiple tags by holding the modifier(s) keys (MOD by default).

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: This is not avaliable as an IPC function.

defaultgaps

Set the gaps to the values defined in config.h.

No arguments.

focusmon

Focus monitor

It takes an integer argument.

focusstack

More like, ’focus client’. Focuses the next/prev client (window).

Takes an integer as an argument.

incnmaster

Increase master, sutracts/adds the first stack (slave) window to the master stack (left side on default tile layout).

It takes an integer argument.

incrgaps

Increases or decreses inner, outer, vertical and horizontal gaps by the argument given.

It takes an integer argument.

incrigaps

Increases or decreses the inner, vertical and horizontal gaps by the argument given.

It takes an integer argument.

incrihgaps

Increases or decreses the inner, and horizontal gaps by the argument given.

It takes an integer argument.

incrivgaps

Increases or decreses the inner and vertical gaps by the argument given.

It takes an integer argument.

incrogaps

Increases or decreses the outer, vertical and horizontal gaps by the argument given.

It takes an integer argument.

incrohgaps

Increases or decreses the outer, and horizontal gaps by the argument given.

It takes an integer argument.

incrovgaps

Increases or decreses the outer and vertical gaps by the argument given.

It takes an integer argument.

killclient

The name describe it, kills a window client.

No arguments.

movefh_setmfact

A custom fuction of mine which reuses two functions: movefloathoriz and setmfact This is just because setmfact has no effect if I have a floating window.

It takes an float argument and passes it to setmfact. The argument for the movefloathoriz is defined in config.h as the variable movefloat.

NOTE: This is not avaliable as an IPC function. Since this function is for personal use to be able to reuse the same keybinding.

movefloathorz

Moves the current floating windows horizontaly by the argument given.

It takes an integer argument.

movefloatvert

Moves the current floating windows verticaly by the argument given.

It takes an integer argument.

movefv_pushstack

A custom fuction of mine which reuses two functions: movefloatvert and pushstack This is just because pushstack has no effect if I have a floating window.

It takes an integer argument and passes it to pushstack. The argument for the movefloatvert is defined in config.h as the variable movefloat.

NOTE: This is not avaliable as an IPC function. Since this function is for personal use to be able to reuse the same keybinding.

pushstack

Pushes the current client to be the next/previous client in the stack. Note: Currently with this function the client can become the master, this is not intended since for this we have zoom.

It takes an integer argument.

quit

Quits demwm.

No arguments.

refresh

Restarts or refreshes the current demwm instance. This keeps all clients into their tags and corresponding monitors, as well as leaves the clients in a floating state and fullscreened, in case they have that property. This won’t keep the layouts of the tags, the state of gaps (enabled/disabled), master/slaves relations, etc. If you wish these workspace like feature, checkout dusk(1).

No arguments.

scratchpad_hide

Adds the current client to the dynamic scratchpads list, hiding it. See SCRATCHPADS section.

No arguments.

scratchpad_remove

Removes the current client to the dynamic scratchpads list. See SCRATCHPADS section.

No arguments.

scratchpad_show

Show a dynamic scratchpad from the list. If more than one window exist in the list, this functions cycles between them from first to last added. See SCRATCHPADS section.

No arguments.

setmfact

Sets the master factor area, modifies the mfact (master factor area) value at runtime.

It takes a float argument, between 0.05 and 0.95.

shiftboth

shiftview + shifttag

It takes an integer argument.

shifttag

tag the current window to the next/previous N tag. N being defined by the argument.

It takes an integer argument.

shifttagclients

tag the current window to the next/previous N occupied tag, a tag with at least one client. N being defined by the argument.

It takes an integer argument.

shiftview

view the current window to the next/previous N tag. N being defined by the argument.

It takes an integer argument.

shiftviewclients

view the current window to the next/previous N occupied tag, a tag with at least one client. N being defined by the argument.

It takes an integer argument.

spawn

A wrapper for exec function. This executes shell commands.

It takes a void argument: an array of chars with a last element of NULL. The wrapper macro SHCMD sets /bin/sh -c as the command, which allows you to do shell tricks (&&, ||, &, etc)

NOTE: This is not avaliable as an IPC function.

swaptags

Changes, swaps, the contents (windows) of the current tag with the tag defined in the argument.

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: If used in IPC, the above will be done automatically, e.g.: demwm tag 0 will swap windows with tag 0 (first tag) without the need of manually shifting (1 << 0).

tag

“tag” the current window to a tag. Basically like moving the windows to a ’workspace’ or a “different desktop”, which is only a way of thinking since dwm doesn’t implements those.

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: If used in IPC, the above will be done automatically, e.g.: demwm tag 0 will put the current selected window to tag 0 (first tag) without the need of manually shifting (1 << 0).

tagmon

Like tag but to the other monitor. Sends the window to the next monitor (display 0, 1, etc..).

It takes an integer argument.

togglealwaysontop

Add or remove the alwaysontop state of a client. Alwaysontop means to be on top of all windows (including the bar), useful when combined with the sticky flag.

No arguments.

togglebar

(Un)hides the bar.

No arguments.

toggletagbar

(Un)hides the bar only for the current tag.

No arguments.

togglefakefullscreen

Add or remove the fakefullscreen state property of the client. FakeFullScreen means to have the window in a fullscreen state, in a window basis, but treat it as a normal window, in a window manager basis. This results in having fullscreened windows that can be tiled, floating, etc. and the window doesn’t necessarily occupies the hole screen.

No arguments.

togglefloating

Toggles floating behaviour on windows. This depends on the current state of the window.

No arguments.

togglefullscreen

Add or remove the fullscreen state property of the client.

No arguments.

togglestatus

(Un)hides the status text blocks, keeping the bar up if active.

No arguments.

togglesticky

Add or remove the sticky state of a client. Sticky means that the window will be visible in all tags.

No arguments.

toggletag

Like tag but it can stack, meaning you can ’tag’ multiple tags. This is toggleable.

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: If used in IPC, the above will be done automatically, e.g.: demwm toggletag 1 will add the current selected window to tag 1 (second tag) without the need of manually shifting (1 << 1).

toggletopbar

Inverse the position of the bar. If the bar is on the top, puts it on the bottom; if the bar is on the bottom, puts it on the top.

No arguments.

togglevacant

(Un)hides the vacant (empty) tags.

No arguments.

toggleview

Like view but it can stack, meaning you can ’view’ multiple tags. This is toggleable.

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: If used in IPC, the above will be done automatically, e.g.: demwm tag 8 will put the current selected window to tag 8 (ninth tag) without the need of manually shifting (1 << 8).

updateblock

updates a status bar block text.

It takes an (unsigned) integer argument, which correspond to the signal number of the block you wish to update.

Note for usage in config.h: Since the blocks updates are asynchronous (in the background), the signaling is ’instantaneous’. Say you have a same keybinding that executes some command related to the status block, and you also define the same keybinding to update the block using this function; most likely updating the block will be faster and thus the block will not be affected by the other command (doesn’t matter as a demwm argument).

view

View the contents of a tag, you can think of it like moving to a tag.

Takes an (unsigned) int which indicates the tag as an exponent of 2. Just define it as 1 << TAG where TAG is the tag you wish (starting from 0).

NOTE: If used in IPC, the above will be done automatically, e.g.: demwm tag 0 will put the current selected window to tag 0 (first tag) without the need of manually shifting (1 << 0).

xrdb

Refreshes or reloads the colors, reads their Xresource value and arranges all the monitors (which actually displays the new colors, if any).

No arguments.

zoom

Swaps between the first window on the master stack to the current window. If you are already on the first master window, it uses the second master window.

No arguments.

zoomswap

Variation of the zoom function that maintains the positions of the windows.

No arguments.

SCRATCHPADS

I have two patches: scratchpads and dynamic scratchpads. Both of these do different functions so they work well so here goes a bit of explanation:

dynamic scratchpads

Any window can be added or removed as a scratchpad. You can add multiple clients to this “list” of dynamic scratchpads but the catch is that to get to a certain client the binding will cycle through them (meaning more key presses).

static scratchpads

Allows you to store a client on a tag that isn’t visible. When you call that client by pressing a keybinding you basically toggleview that tag and you will see the client store. This scratchpad can be maintained (called) between multiple monitors.

For this you need to define a Rule for that client (res name or class) and add it to the tag SP(X), which X represents the same index in the array of the scratchpads array. For simpler understanding just use the sample variables I defined which are Sp1 to Sp9 and make sure these match in between the Rule tags, the binding and the definition of the command inside the array scratchpads.

EXAMPLES

Usage of spawn and SHCMD

    static const char *ncmpcpp[] = { "st", "-e", "ncmpcpp", NULL };
    static Key keys[] = {
      /* modifier(s)      key         function        argument        */
      { MODKEY            XK_n,       spawn,      { .v = ncmpcpp }    },
      { MODKEY            XK_m,       SHCMD("st -e ncmpcpp")          },
      ...
    };

Defining a static scratchpad

    static const Rule rules[] = {
      RULE(.instance = "term", .tags = SPTAG(Sp1))
      ...
    };
    static const char *scratchpads[][32] = {
    [Sp1] = { "st", "-n", "term", NULL }, /* terminal */
    ...
    };
    static const Key keys[] = {
      SPKEYS(MOD,    XK_s,    Sp1)
      ...
    };

A script that handles clicking

NOTE: Before calling exit it does echo ''; it is important to echo something (even '') to ’notify’ demwm that the block has changed.

    #!/bin/sh

    # handle demwm blocks
    case $BLOCK_BUTTON in
      1) notify-send "You've clicked mouse button $BLOCK_BUTTON" ;;
      2) notify-send "Right click" ;;
      3) notify-send "Middle click" ;;
      4) pamixer --allow-boost -i 1 ;; # volume up
      5) pamixer --allow-boost -d 1 ;; # volume down
      6) "$TERMINAL" -e "$EDITOR" "$0" ;; # edit the block
      7) "$TERMINAL" -e "$EDITOR" "$0" & ;; # edit the block without locking it
    esac

    # If nothing is playing, don't output anything
    [ "$(mpc status '%state%')" = 'paused' ] && echo '' && exit

    # dislpay text
    echo "Playing: $(mpc current --format '[[%artist% - ]%title%]|[%file%]')"

IPC examples

    $ demwm incrgaps +10
    $ demwm incrgaps -10
    $ demwm restart

Signaling blocks

    $ demwm updateblock 8

Creating a custom scheme for a block

    static const char *colors[][2] = {
        ...
        /* custom block schemes */
        [SchemeLast+0] = { color7,   "#222222" }, /* sb-clock */
        [SchemeLast+1] = { "ffffff", "#525252" }, /* sb-disk  */
        [SchemeLast+2] = { fg_wal,   bg_wal, }, /* sb-volume */
    };

    static const unsigned int alphas[][2] = {
        ...
        /* custom blocks schemes */
        [SchemeLast+0] = { Solid,  baralpha }, /* sb-clock */
        [SchemeLast+1] = { Solid,  baralpha }, /* sb-disk */
        [SchemeLast+1] = { Solid,  baralpha }, /* sb-volume */
    };

    static const Block blocks[] = {
        ...
        { SchemeLast+0, "sb-clock",  20,   1},
        { SchemeLast+1, "sb-disk",   9000, 2},
        { SchemeStatus, "sb-volume", 0,    8},
    };

ISSUES

Java applications which use the XToolkit/XAWT backend may draw grey windows only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds are using JDK 1.4 (which doesn’t contain the XToolkit/XAWT backend) or setting the environment variable AWT_TOOLKIT=MToolkit (to use the older Motif backend instead) or running xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D or wmname LG3D (to pretend that a non-reparenting window manager is running that the XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable _JAVA_AWT_WM_NONREPARENTING=1

SEE ALSO

dwm(1), poll(3), exec(3)

BUGS

https://github.com/explosion-mental/demwm https://codeberg.org/explosion-mental/demwm

This work is licensed under CC-BY-SA 2.0, unless specified otherwise. Year: 2022