dwm

Related articles
dmenu
dwl
Window manager
dwm
is a dynamic window manager for
Xorg
. It manages windows in tiled, stacked, and full-screen layouts, as well as many others with the help of optional patches. Layouts can be applied dynamically, optimizing the environment for the application in use and the task being performed. dwm is extremely lightweight and fast, written in C and with a stated design goal of remaining under 2000 source lines of code. It provides
multihead
support for
xrandr
and Xinerama.
Installation
dwm can be
installed
with the
dwm
AUR
package. Make any required
configuration
changes
before
building and installing, see
makepkg
.
Tip
Upstream instructions
can also be followed, but will install files without having
pacman
keeping track of them.
Configuration
dwm is configured at compile-time by editing some of its source files, specifically
config.h
. For detailed information on these settings, see the included, well-commented
config.def.h
as well as the
customisation section
on the dwm website.
The official website has a number of
patches
that can add extra functionality to dwm. These patches primarily make changes to the
dwm.c
file but also make changes to the
config.h
file where appropriate. For information on applying patches, see the
Patching packages
article.
Starting
Select
Dwm
from the menu in a
display manager
of choice. Alternatively, to start dwm with
startx
append
exec dwm
to
~/.xinitrc
and prepend other programs to execute them as well, for example:
redshift -O3500; xset r rate 300 50; exec dwm
Usage
See the
dwm tutorial
for information on basic dwm usage.
Tips and tricks
Statusbar configuration
For more examples of status bars, see
[1]
.
Note
The following requires the
xorg-xsetroot
package to be installed.
dwm reads the name of the root window and redirects it to the statusbar. The root window is the window within which all other windows are drawn and arranged by the window manager. Like any other window, the root window has a title/name, but it is usually undefined because the root window always runs in the background.
The information that you want dwm to show in the statusbar should be defined with
xsetroot -name ""
command in
~/.xinitrc
or
~/.xprofile
(if you are using a
display manager
). For example:
xsetroot -name "Thanks for all the fish!"
Dynamically updated information should be put in a loop which is forked to background - see the example below:
# Statusbar loop
while true; do
   xsetroot -name "$( date +"%F %R" )"
   sleep 1m    # Update time every minute
done &

# Autostart section
pcmanfm & 

exec dwm
In this case the date is shown in
RFC:3339
format and
PCManFM
is launched at startup.
Note
It is not recommended to set the update interval equal to zero or remove the "sleep" line entirely since this will cause CPU usage to rise substantially (you can assess the effect with
top
and
powertop
).
Conky statusbar
Conky
can be printed to the statusbar with
xsetroot -name
:
(conky | while read LINE; do xsetroot -name "$LINE"; done) &
exec dwm
If you do not want to spawn too many PIDs by 'xsetroot' command, you can compile this C program:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

int main(int argc, char * argv[])
{
        Display * dpy = NULL;
        Window win = 0;
        size_t length = 0;
        ssize_t bytes_read = 0;
        char * input = NULL;

        dpy = XOpenDisplay(getenv("DISPLAY"));
        if (dpy == NULL)
        {
                fprintf(stderr, "Can't open display, exiting.\n");
                exit(1);
        }
        win = DefaultRootWindow(dpy);

        while ((bytes_read = getline(&input, &length, stdin)) != EOF)
        {
                input[strlen(input) - 1] = '\0';
                XStoreName(dpy, win, input);
                XFlush(dpy);
                fprintf(stderr, "Input: %s", input);
                fprintf(stderr, "\nbytes read: %ld\n", bytes_read);
        }
        free(input);
        return 0;
}
Save this code to file dwm-setstatus.c, compile:
$ gcc dwm-setstatus.c -lX11 -o dwm-setstatus
move 'dwm-setstatus' within your $PATH (
/usr/local/bin
, for example)
# mv dwm-setstatus /usr/local/bin
and run:
$ conky | dwm-setstatus
To do this, conky needs to be told to output text to the console only. The following is a sample conkyrc for a dual core CPU, displaying several usage statistics:
conky.config = {
out_to_console = true,
out_to_x = false,
background = false,
update_interval = 2,
total_run_times = 0,
use_spacer = 'none',
};
conky.text = [[
$mpd_smart :: ${cpu cpu1}% / ${cpu cpu2}%  ${loadavg 1} ${loadavg 2 3} :: ${acpitemp}c :: $memperc% ($mem) :: ${downspeed eth0}K/s ${upspeed eth0}K/s :: ${time %a %b %d %I:%M%P}
]];
For icons and color options, see
dzen
.
Restart dwm
To restart dwm without logging out or closing applications, change or add a startup script so that it loads dwm in a
while
loop, for example:
while true; do
    # Log stderror to a file 
    dwm 2> ~/.dwm.log
    # No error logging
    #dwm >/dev/null 2>&1
done
dwm can now be restarted without destroying other X windows by pressing the usual Mod-Shift-Q combination.
It is a good idea to place the above startup script into a separate file,
~/bin/startdwm
for instance, and execute it through
~/.xinitrc
. Consider running the script with
exec
to avoid security implications with remaining logged in after the X server is terminated; see
Xinit#Autostart X at login
for more information. From this point on, when you wish to end the X session, simply execute
pkill dwm
, or bind it to a convenient keybind. Alternatively, you could setup your dwm session script so that it relaunches dwm only if the binary changes.  This could be useful in the case where you change a setting or update the dwm code base.
# relaunch DWM if the binary changes, otherwise bail
csum=""
new_csum=$(sha1sum $(which dwm))
while true
do
    if [ "$csum" != "$new_csum" ]
    then
        csum=$new_csum
        dwm
    else
        exit 0
    fi
    new_csum=$(sha1sum $(which dwm))
    sleep 0.5
done
Bind the right Alt key to Mod4
When using Mod4 (the Super/Windows Key) as the
MODKEY
, it may be equally convenient to have the right
Alt
key (
Alt_R
) act as
Mod4
. This will allow you to perform otherwise awkward keystrokes one-handed, such as zooming with
Alt_R
+
Enter
.
First, find out which keycode is assigned to
Alt_R
:
$ xmodmap -pke | grep Alt_R
Then simply add the following to the startup script (e.g.
~/.xinitrc
), changing the keycode
113
if necessary to the result gathered by the previous
xmodmap
command:
Reassign
Alt_R
to
Super_L
:
xmodmap -e "keycode 113 = Super_L"
Make sure X keeps it out of the "mod1" group:
xmodmap -e "remove mod1 = Super_L"
After doing so, any functions that are triggered by the
Super_L
key press will also be triggered by an
Alt_R
key press.
Note
There is a
#define
option in
config.h
which also allows you to switch the modkey.
Use both Alt keys as Meta in DWM
Use xmodmap to assign
Alt_L
as a secondary meta key in DWM (provided already using Mod1Mask (Alt_R))
~/.xinitrc
/usr/bin/xmodmap -e "clear mod5"
/usr/bin/xmodmap -e "keycode 108 = Alt_L"
Space around font in dwm's bar
By default, dwm's bar adds 2px around the size of the font. To change this, modify the following line:
dwm.c
bh = dc.h = dc.font.height + 2;
Disable focus follows mouse
To disable focus follows mouse behaviour, comment out the following line in definition of struct handler:
dwm.c
[EnterNotify] = enternotify,
Note that this change can cause some difficulties; the first click on an inactive window will only bring the focus to it. To interact with window contents (buttons, fields etc), you need to click again. Also, if you have several monitors, you may notice that the keyboard focus does not switch to another monitor activated by clicking.
Floating layout for some windows
For some windows, such as preferences dialogs, it does not make sense for these windows to be tiled - they should be free-floating instead. For example, to make Firefox's preferences dialog float, add the following to your rules array in
config.h
:
{ "Firefox",     NULL,       "Firefox Preferences",        1 << 8,         True,     -1 },
To get the properties of other Windows, the program xprop can be used.
xprop | awk '
/^WM_CLASS/{sub(/.* =/, "instance:"); sub(/,/, "\nclass:"); print}
/^WM_NAME/{sub(/.* =/, "title:"); print}'
Further information can be found on the
dwm site
.
Using Tilda with dwm
Tilda
works best when added to all tags, and configured to be floating. To do so, add the following to your rules array in
config.h
:
{ "Tilda",        NULL,       NULL,                         0,              True,       -1 },
Launch tilda with
-C
option:
$ tilda -C
Now you can configure Tilda, the following options are provided as a recommendation:
Font: Clean 9
Appearance: Height: 50%, Width: 70%, Centered Horizontally
Extras: Enable Transparency Level 15
Animated Pulldown: 1500 usec, Orientation: Top
Colors: Built-in Scheme "Green on Black"
Scrolling: Scrollbar is on the left, 2000 lines scrollback
Key Binding: F9
It is important you enable the pulldown-animation, otherwise Tilda will keep jumping down each time you unhide it, must be a dwm issue.
Taking screenshots
Install the
scrot
package. Next create two scripts:
/path/to/scripts/screenshot.sh
#!/bin/sh
mkdir -p /path/to/pics && scrot /path/to/pics/%m-%d-%Y-%H%M%S.png
for making screenshots and
/path/to/scripts/screenshotsel.sh
#!/bin/sh
mkdir -p /path/to/pics && scrot /path/to/pics/%m-%d-%Y-%H%M%S.png --select --line mode=edge
for making screenshots with a selection box.
Give them
executable
permissions. In
config.h
add the following:
static const Key keys[] = {
       ...

       { 0,         XK_Print, spawn, SHCMD("/path/to/scripts/screenshot.sh") },
       { ShiftMask, XK_Print, spawn, SHCMD("/path/to/scripts/screenshotsel.sh") },

       ...
};
This maps taking screenshots to the print key and taking screenshots with a selection box to the shift + print keys.
Mapping multimedia keys
Add to the top of
config.h
,
#include <X11/XF86keysym.h>
to
use multimedia keys
. Now we can map common tasks to these keys.
Adjusting volume
Install the
pipewire
package. Now in
config.h
we may add commands for mute and volume increase/decrease.
/* commands */
...

static const char *up_vol[]   = { "pactl", "set-sink-volume", "@DEFAULT_SINK@", "+10%",   NULL };
static const char *down_vol[] = { "pactl", "set-sink-volume", "@DEFAULT_SINK@", "-10%",   NULL };
static const char *mute_vol[] = { "pactl", "set-sink-mute",   "@DEFAULT_SINK@", "toggle", NULL };
...

static const Key keys[] = {
       ...

       { 0,             XF86XK_AudioMute,         spawn,          {.v = mute_vol } },
       { 0,             XF86XK_AudioLowerVolume,  spawn,          {.v = down_vol } },
       { 0,             XF86XK_AudioRaiseVolume,  spawn,          {.v = up_vol } },

       ... 
};
Adjusting brightness
Install the
brightnessctl
package. Now in
config.h
we may add commands for dimming and brightening the screen.
/* commands */
...

static const char *brighter[] = { "brightnessctl", "set", "10%+", NULL };
static const char *dimmer[]   = { "brightnessctl", "set", "10%-", NULL };
...

static const Key keys[] = {
       ...

       { 0,             XF86XK_MonBrightnessDown, spawn,          {.v = dimmer } },
       { 0,             XF86XK_MonBrightnessUp,   spawn,          {.v = brighter } },

       ...
};
Adjusting keyboard backlight brightness
Install the
brightnessctl
package. Now in
config.h
we may add commands for dimming and brightening the keyboard backlight.
Find the name of your device
brightnessctl --list
Look for
vendor
::kbd_backlight
, where
vendor
is the manufacturer of your device, e. g.
smc
or
apple
for Apple,
asus
for Asus etc.
/* commands */
...

static const char *kbd_up[]   = { "brightnessctl", "--device=
vendor
::kbd_backlight", "set", "+10%", NULL };
static const char *kbd_down[] = { "brightnessctl", "--device=
vendor
::kbd_backlight", "set", "10%-", NULL };
...

static const Key keys[] = {
       ...

       { 0,             XF86XK_KbdBrightnessUp,   spawn,          {.v = kbd_up } },
       { 0,             XF86XK_KbdBrightnessDown, spawn,          {.v = kbd_down } },

       ...
};
Autostart
A
patch
is available. It runs
~/.dwm/autostart_blocking.sh
and
~/.dwm/autostart.sh &
before entering the handler loop. One or both of these files can be omitted.
Troubleshooting
Fixing misbehaving Java applications
See
Java#Gray window, applications not resizing with WM, menus immediately closing
.
Fixing gaps around terminal windows
If there are empty gaps of desktop space outside terminal windows, it is likely due to the terminal's font size. Either adjust the size until finding the ideal scale that closes the gap, or toggle
resizehints
to
0
in
config.h
.
This will cause dwm to ignore resize requests from all client windows, not just terminals. The downside to this workaround is that some terminals may suffer redraw anomalies, such as ghost lines and premature line wraps, among others.
Alternatively, if you use the
st
terminal emulator, you can apply the
anysize
patch and recompile st.
Arabic Letter-shaping
dwm status bar does not have letter-shaping support. However, you can use
tools like|
fribidi
for applying letter-shaping using Unicode Arabic Presentation Form-B. E.g instead of:
xsetroot -name "لِخَـوْلَةَ أطْـلالٌ بِبُرْقَةِ ثَهْمَـدِ"
Use:
xsetroot -name "$(echo "لِخَـوْلَةَ أطْـلالٌ بِبُرْقَةِ ثَهْمَـدِ" | fribidi --nopad)"
See also
dwm's official website
Introduction to dwm video
dmenu
- Simple application launcher from the developers of dwm
The
dwm thread
on the forums
Hacking dwm thread
Wallpaper thread
in the forums for a selection of dwm wallpapers
Show off your dwm configuration forum thread
dwl
the wayland version of dwm