Jump to content
From ArchWiki

Related articles

- dmenu
- 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 packages dwmAUR or dwm-gitAUR. Make any required configuration changes before building and installing, see makepkg.

Note: 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 },

### 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.

    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.

    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 } },

           ...
    };

### 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

Try setting `export _JAVA_AWT_WM_NONREPARENTING=1`. Setting `wmname "LG3D"` using wmname may help too.

See also 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.

## 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

Categories:

- Dynamic window managers
- Suckless