What Is The DWM Window Manager?
The dwm window manager for Linux is
an incredibly small and efficient window manager for X. Like ratpoison, it is an
ultra-lite Linux window manager, runs amazingly well in Linux, and in spite of
its small size, has more features than is at first obvious.
Dwm is a tiling window manager, meaning that it arranges the multiple
open windows on a computer screen in a tile manner. The windows fit tightly
together and do not overlap. It's about using up all the screen surface area
with window content -- not frills. It's also about being able to quickly move
between the windows.
Dwm is written entirely in the c programming language. In fact, the
code is entirely in one rather small c file. Yet dwm can do screen display in
three modes: monocle where each window takes the entire computer screen, tiled
where windows take up the entire screen in adjacent tiles, and floating where
windows may be moved, resized, and overlap. Quick key commands make the switch
between these display modes.
The default mode is the tiled mode. While in ratpoison tiles are created
manually, in dwm tiling is automatic. If one computer computer computer
computer computer computer computer computer application is running, its window
takes the entire screen. Add another application and the screen splits into two
columns. The left column, by default, is the master frame. It will
always be full height, and can resized in width. Check the man file for which
are the resize keys. In the source version, the grow and shrink commands are
alt-l and alt-h respectively.
The right column will contain the rest of the open windows in a vertical
stack, with the column divided equally between the number of windows beyond
the one in the master frame. Each newly launched application will occupy
the master frame.
You can swap any focused window with that in the master frame just
by entering alt-enter. Entering alt-space will change the display
mode to floating. In this mode, the mouse can be used to move and resize
windows, letting the windows violate the tiling restrictions. Holding down the
alt key and the mouse button1 will let you move windows. The
alt key and the mouse button3 will let you resize windows.
The alt-m key will switch the display to the monocle mode,
where the screen is taken up by a single window. The alt-j and
alt-k keys are used to step forward and back through the different
windows to let them be the one displayed. In the floating and tile modes,
the alt-j and alt-k keys move focus to the next or previous frame.
Get A Witty Astronomy, Physics, Math, Or Linux T-Shirt, Mug, or Poster At Keen Designs
Dwm supports a multiple workspace concept with its tag system.
When in a tag workspace, newly opened windows will become part of that tag.
The windows will thus be visible only when the user in in that tag. A
focused window can be moved to a different tag with the alt-shift-n
key sequence, where n is the tag number. Entering
alt-shift-0 while on a focused window will make that window visible
on all tags.
To remove a focused window from a tag, enter alt-cntl-shift-n.
You can check the man files and see how to also assign and remove
windows from tags with mouse controls.
One limitation of dwm is that all tags will have the same display mode.
That is, if you switch to the tiled mode in a tag, then move to another
tag, the windows there will also be in the tile mode. This is unlike
the ratpoison augmented with rpws windows manager, in which each
workspace's tile arrangement is retained. But -- check out the patches
section listed later.
In my Debian Etch Linux distribution, I was able to install dwm
by doing apt-get install dwm. But if you want to be able to tune dwm
to your liking, I suggest you get the entire package from the dwm link, from where you can download
the source code and man file. This is useful because the tuning of dwm is
done by making changes to the config.h header file and
recompiling.
You may shudder at the thought of working with source code. I've
had some bad experiences myself. It often seems that getting some
complex, multi-file coded application to successfully compile is a
monumental task. But dwm is different. It's a single file that
compiles quickly and easily.
The DWM Window Control Methods
|
At left is a screenshot of dwm in the tile mode. Clicking
on the image will show a full-sized version. The running applications
include the web browser dillo, the xcalendar utility, and the
xosview utility.
Notice that the left most column is full height. It is the master
frame, adjustable in width. The other windows are stacked vertically in the
right column. Of course if you increase the width of the master frame, you
will decrease the width of the other column as a result.
|
|
This display shows the same loaded windows in the dwm monocle
mode. In this mode, only one window at a time is shown, and it takes the
entire screen. Key sequences alt-j and alt-k step forward or
backward through the other windows, bringing them to the top to be
displayed.
The xcalendar and xosview applications are still running in this example,
but their windows are covered by the full-sized dillo window.
|
|
This display shows the dwm floating window mode. In this mode,
holding down the alt-button1 keys (that's alt on keyboard, button1 on
mouse) allows you to move a window around with the mouse. The
alt-button3 sequence allows mouse motions to resize a window.
In this example, you now see the float-able xosview and xcalendar
windows on top of the dillo display.
|
How To Customize DWM
For such a simple window manager, dwm presents a considerable number of
customizations. Almost any key sequence can be redefined to be more to your
liking. If you download the source package from the dwm web page, you also get the dwm man
page. By editing the config.h file (and recompiling) and editing the man
page to reflect your changes, you'll have a running version tailored to
your needs and documentation to match.
Below is a segment of the config.h file showing some key definitions
that you can easily change:
| static Key keys[] = { |
| /* modifier | key | function | argument */ |
| { MODKEY, | XK_p, | spawn, | {.v = dmenucmd } }, |
| { MODKEY, | XK_x, | spawn, | {.v = termcmd } }, |
| { MODKEY, | XK_b, | togglebar, | {0} }, |
| { MODKEY, | XK_j, | focusstack, | {.i = +1 } }, |
| { MODKEY, | XK_k, | focusstack, | {.i = -1 } }, |
| { MODKEY, | XK_s, | setmfact, | {.f = -0.05} }, |
| { MODKEY, | XK_g, | setmfact, | {.f = +0.05} }, |
| { MODKEY, | XK_Return, | zoom, | {0} }, |
| { MODKEY, | XK_Tab, | view, | {0} }, |
| { MODKEY|ShiftMask, | XK_c, | killclient, | {0} }, |
| { MODKEY, | XK_t, | setlayout, | {.v = &layouts[0]} }, |
| { MODKEY, | XK_f, | setlayout, | {.v = &layouts[1]} }, |
| { MODKEY, | XK_m, | setlayout, | {.v = &layouts[2]} }, |
| { MODKEY, | XK_space, | setlayout, | {0} }, |
| { MODKEY|ShiftMask, | XK_space, | togglefloating, | {0} }, |
| { MODKEY, | XK_0, | view, | {.ui = ~0 } }, |
| { MODKEY|ShiftMask, | XK_0, | tag, | {.ui = ~0 } }, |
| { MODKEY, | XK_comma, | focusmon, | {.i = -1 } }, |
| { MODKEY, | XK_period, | focusmon, | {.i = +1 } }, |
| { MODKEY|ShiftMask, | XK_comma, | tagmon, | {.i = -1 } }, |
| { MODKEY|ShiftMask, | XK_period, | tagmon, | {.i = +1 } }, |
In the code example, the MODKEY definition represents the alt
key. The XK definitions represent keyboard keys. For example, the
XK_j, focusstack line is defining alt-j to focus on the next
window in the stack.
Changing these definitions will let you find a more natural configuration
for you to use. On my old laptop, for example, I use an external mini-track
ball mouse to replace the non-functioning original mouse. With that
arrangement, the alt-button3 resize operation for a floating window was
very awkward to accomplish.
So I modified the config.h definition so the resize operation could be
accomplished with a alt-shift-button1 operation. I also altered the key
sequence designed to launch dmenu to launch ratmenu instead,
since I already had a well defined ratmenu layout to support the ratpoison
window manager.
Get A Witty Astronomy, Physics, Math, Or Linux T-Shirt, Mug, or Poster At Keen Designs
Customizing DWM -- The Next Level
Adding Your Own Shortcut Keys
It's not only possible to change the default control keys and mouse
usage for window controls, you can add some of your own custom shortcut
keys. The following snippet from the config.h file shows the
default command definitions for launching an xterm and for launching
dmenu:
/* ********** Default Command Definitions ********** */
static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
static const char *termcmd[] = { "uxterm", NULL };
/* ********** Some Additional Definitions ********** */
static const char *browsercmd[] = { "/usr/local/seamonkey/seamonkey", NULL };
static const char *packagecmd[] = { "links2", "-g", "http://www.debian.org/distrib/packages", NULL };
/* ********** Attaching A Shortcut Key To The Commands ********* */
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_h, spawn, {.v = dmenucmd } },
{ MODKEY, XK_x, spawn, {.v = termcmd } },
{ MODKEY, XK_w, spawn, {.v = browsercmd } },
{ MODKEY, XK_p, spawn, {.v = packagecmd } },
.
.
.
|
The technique for defining a shortcut key to launch a task in dwm is to
first define a string constant that holds the command, such as the
*dmenucmd string. Then in the static Key keys section,
add the definition that combines the key you want with the spawning of the
application. The launcher for dmenucmd and termcmd were already in the
config.h, and they provide the examples of how it is done.
I just created a couple of other command strings for launching my
favorite applications -- one for launching the seamonkey browser, and one
for launching the links2 browser and passing it the url that has a search
engine for searching the Debian archives. Then in the keys definition
section, I added the necessary lines to spawn my applications. If you
examine the example, you can see that I use alt-w to run my
browser, and alt-p to run the links2 Debian search.
Defining Rules For Specific Applications
Another thing you can do is take advantage of the ability to define
rules for some specific applications. The following is an example of the
rules section of the config.h file:
static const Rule rules[] = {
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, True, -1 },
{ "Seamonkey-bin", NULL, NULL, 0, True, -1 },
{ "XEphem", NULL, NULL, 0, True, -1 },
};
|
Notice the comment line that indicates what the arguments are for the
entries. The Gimp line was already in the original config.h as an example.
Firefox was as well, and I just changed Firefox to
Seamonkey-bin. Then, following the examples, I added an entry for
xephem.
Use the following procedure to get the right string for the class
argument of the rules table:
Run the application
While it's up, in an xterm run the xprop utility, then click on the
application for which you want the class string.
Look for the 2nd string listed in the WM_CLASS parameter.
|
Once you get the proper class name with xprop, enter that into the
class argument of the table.
The tags mask lets you enter 0, which allows the task to open under whatever
tag you're under when you run it, or a binary tag position indicator like
1<<8. The shift nomenclature in this instance puts a 1 in the
ninth binary position. That indicates tag 9, so the launched application would start
in tag 9. A 1<<3 argument would indicate tag 4 for the
application (a 1 in the 4th binary position).
The main reason I use the rules table is to specify that certain
products be ran in floating windows, indicated by True under
the isfloating argument of the table. That way, even though I'm
working in my preferred tile windowing mode, the applications that are
listed in the rules section of the config.h will run as floating windows.
Otherwise I'd have to switch windowing modes to run those products.
You could just as easily use the rules table to make an application
run under a certain tag, or on a specific screen (if you had a multi-monitor
setup). Once you figure out how to use the rules table, you'll find it
a handy extension to the dwm system.
Some More DWM Features
Above you see an expanded section of the upper left-hand corner of the dwm
screen. It's part of the status bar that extends along the top of the screen.
The numbers 1 through 9 are tag numbers. As mentioned earlier in this
article, the tag mechanism functions much like workspaces on more advanced
window managers.
The small square next to numbers 1, 2, and 3 indicate that windows are open
in those workspaces. The tag with the filled in small box indicates that it's
the currently selected tag. Clicking on one of the tag numbers will bring you
to the windows of that tag. The key sequences alt-1 through alt-9
also move you to the respective tags.
The []= symbols on the right side of the image indicate that the
screen is in tile mode. The ><> symbols would
indicate that the screen is in float mode. A number in a bracket, like
[2], would indicate monocle mode, with window 2 of the stack being
displayed.
Some Handy Available Patches
As described in the previous portions of this web page, dwm is amazing for
its ultra-lite size. But it has a couple of limitations that its bigger
brothers have solved. One is that dwm has only one tile mode, with the screen
being broken up to have a master column, and the remainder of the windows
stacked in another column. Second, the selected display mode for dwm is global,
applying to all workspaces.
Luckily, there are many dwm
patches that you can apply to increase dwm's utility or appeal. You can see
the patch options at the top of the indicated link's page.
Add Some New Tiling Layouts
Since I'm using dwm primarily on an old, limited resource laptop, I'm only
interested in increased utility. One patch that I especially like is the bottom stack
subroutines. These are two small c files that you can download, and simply
include by reference in the config.h file. The instructions are pretty clear,
but here's a couple segments of my config.h that handle the inclusion and
utilization of these functions:
In the config.h layouts area:
#include "bstack.c"
#include "bstackhoriz.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "TTT", bstack },
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
{ "===", bstackhoriz },
};
In the keys[] definition area:
{ MODKEY, XK_u, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[3]} },
{ MODKEY, XK_y, setlayout, {.v = &layouts[4]} },
|
The first set of additions are the includes for the new routines
bstack.c and bstackhoriz.c, causing them to be included in future
compiles. Next are additional entries into the layouts[] array for the
new routines. The layouts additions associate 3 character symbols to show on
panel and the code used for the layout modes. I used TTT to indicate the
tiling method that splits into two rows then subdivides the non-master row into
columns, and the === symbol to indicate the all-rows tiling method. You
can certainly your own choice of symbols.
In the keys[] array portion of config.h, I added a couple of key
definitions to trigger my new tiling options. These key definitions refer to
the previously defined layouts table by index. I did a bit of
rearranging here to get one of the horizontal layouts as the default. My new
key definitions are alt-u for the horizontal/vertical tiling method, and
alt-y for the all horizontal tiling method. Recompile and restart dwm,
and you're all set with additional tiling layouts.
|
The image at left is screenshot of the bstack layout routine. It
uses the top row of the screen as the master frame. The bottom row
is then tiled into horizontally separated frames as more applications are
executed.
|
|
This image is a screenshot of the bstackhoriz layout routine. It
breaks the screen repeatedly into rows, with the top row being the master,
resizable (vertically) row. Additional tasks cause more horizontal tiles in the
bottom row.
|
Make Workspaces Retain Their Layout Configuration
Another great patch is the pertag patch. Be sure to pick
the one that matches your version of dwm. This patch is done by downloading
into the directory where your dwm.c file is, and doing a patch
command as indicated in the simple directions that come with the patch. Then,
of course, recompile. With this patch, each dwm workspace retains its own
display configuration.
I, being greedy, wanted both the new layouts, and the utility of having
workspaces (tags) retain their specific layouts. But I found that the two
patches didn't play well together. The make command resulted in many
errors. However, there was a fairly simple way to bring it all together. If
you're not a coder you might be nervous, but you can get this to work. Just
remember to make backup copies of the config.h and dwm.c files before
doing any patches, and you can always get back to square one.
Basically, to get the two patches to work together, you must do 2 things.
Move the #include "bstack.c" and #include
"bstackhoriz.c" lines from the config.h and put in the
dwm.c file just after the struct Monitor{ ... }
definition.
Add prototypes for
the bstack and bstackhoriz routines to the prototype area (near
the beginning) of the dwm.c file. I put mine just after the
restack prototype as follows:
static void restack(Monitor
*m);
/* Added references to bstack and bstackhoriz */
static void bstack(Monitor *m); static void bstackhoriz(Monitor *m);
|
With these small modification, you can get both the new tiling methods,
bstack and bstackhoriz, and the workspace display retention functions to
work in your dwm configuration. And the increase in size is trivial.
What else could you want?
This is admittedly a superficial view of the workings of the dwm window
manager, but hopefully it's enough to give you an idea of whether it's
something for you to try. I tried it, and found it very useful on my old laptop. I switched
from the light-weight fluxbox to the ultra-lite
dwm to complement the ratpoison window manager
that I use on the laptop. While ratpoison gives more elaborate manual control
of the screen tiles and more configuration capability of hot keys, dwm gives the
handiness of auto-tiling and allows floating windows. Between the two, I can do
about anything I want on my laptop without paying the price for even a
light-weight window manager.
|