demwm - Dynamic Explosion-Mental’s Window Manager
demwm [ function ] (argument)
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.
Without any arguments, the program will try to initialize the window manager. For information about the kind of arguments check out IPC section.
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.
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.
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.
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. |
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
)
Moves the layouts index depending on the argument.
It takes an integer argument.
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.
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.
Set the gaps to the values defined in config.h.
No arguments.
Focus monitor
It takes an integer argument.
More like, ’focus client’. Focuses the next/prev client (window).
Takes an integer as an argument.
Increase master, sutracts/adds the first stack (slave) window to the master stack (left side on default tile layout).
It takes an integer argument.
Increases or decreses inner, outer, vertical and horizontal gaps by the argument given.
It takes an integer argument.
Increases or decreses the inner, vertical and horizontal gaps by the argument given.
It takes an integer argument.
Increases or decreses the inner, and horizontal gaps by the argument given.
It takes an integer argument.
Increases or decreses the inner and vertical gaps by the argument given.
It takes an integer argument.
Increases or decreses the outer, vertical and horizontal gaps by the argument given.
It takes an integer argument.
Increases or decreses the outer, and horizontal gaps by the argument given.
It takes an integer argument.
Increases or decreses the outer and vertical gaps by the argument given.
It takes an integer argument.
The name describe it, kills a window client.
No arguments.
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.
Moves the current floating windows horizontaly by the argument given.
It takes an integer argument.
Moves the current floating windows verticaly by the argument given.
It takes an integer argument.
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.
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.
Quits demwm.
No arguments.
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.
Adds the current client to the dynamic scratchpads list, hiding it. See SCRATCHPADS section.
No arguments.
Removes the current client to the dynamic scratchpads list. See SCRATCHPADS section.
No arguments.
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.
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
.
It takes an integer argument.
tag
the current window to the next/previous N tag. N being defined by the argument.
It takes an integer argument.
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.
view
the current window to the next/previous N tag. N being defined by the argument.
It takes an integer argument.
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.
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.
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” 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
).
Like tag
but to the other monitor. Sends the window to the next monitor (display 0, 1, etc..).
It takes an integer argument.
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.
(Un)hides the bar.
No arguments.
(Un)hides the bar only for the current tag.
No arguments.
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.
Toggles floating behaviour on windows. This depends on the current state of the window.
No arguments.
Add or remove the fullscreen state property of the client.
No arguments.
(Un)hides the status text blocks, keeping the bar up if active.
No arguments.
Add or remove the sticky state of a client. Sticky means that the window will be visible in all tags.
No arguments.
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
).
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.
(Un)hides the vacant (empty) tags.
No arguments.
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
).
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 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
).
Refreshes or reloads the colors, reads their Xresource value and arranges all the monitors (which actually displays the new colors, if any).
No arguments.
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.
Variation of the zoom
function that maintains the positions of the windows.
No arguments.
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:
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).
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
.
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") },
...
};
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)
...
};
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%]')"
$ demwm incrgaps +10
$ demwm incrgaps -10
$ demwm restart
$ demwm updateblock 8
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},
};
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
dwm(1), poll(3), exec(3)
https://github.com/explosion-mental/demwm https://codeberg.org/explosion-mental/demwm