dwm: beauty in simplicity with a window manager
The spirit of dwm is to make its C source simple enough that configuring it means altogether modifying it. Here's some notes of what you can do and how.
1 Development Environment
Configuration may not be as comfortable as editing your window manager's configuration files while using it and being able to restart it on the fly to apply your changes, leaving all your windows where they are. You want to carefully organise your development environment such that trying changes you're making to dwm won't be too disruptive.
In fact, you may want to do the development in a production-quality dwm instance and, to try your changes, run startx -- :1
to test another dwm instance in a different display. It's probably more convenient to fire xterm, then dwm, instead of directly spawning dwm because this leaves you with a terminal to control it. As such, you could populate ~/.xinitrc
with useful commands such as:
xrdb .Xresources
xsetroot -solid black
setxkbmap -option caps:super
xterm
2 Concepts
The dwm code isn't documented, but you can rather easily understand key concepts by scheming through it:
- The top bar is referred to by bar in the code, but I'll be calling it top bar here to tell the difference with the title bar).
- A tag is what e.g. xmonad users call a workspace.
- A
Monitor
is probably whatever is shown on a physical display at a given time. You start having several monitors as soon as you go Xinerama. I don't think you get a different monitor for each tag, because a monitor has aclients
member which seems to point to all tagged clients. - The screen size referred to by
mx
,my
,mw
,mh
inMonitor
is the total area displayed, while the window area referred to bywx
,wy
,ww
,wh
inMonitor
is a subset of the screen size and is the area where windows can be displayed.
3 Events
Here's a list of events which are recognised by dwm. This mapping could be found by running e.g. grep ButtonPress /usr/include/X11/*
and looking them up in /usr/include/X11/X.h
. For some twisted reason, printing the event to stdout
– or just about any file – from run()
seems to hijack the event. Better print feedback from the handlers, then.
Event | Code |
---|---|
ButtonPress |
4 |
ClientMessage |
33 |
ConfigureRequest |
23 |
ConfigureNotify |
22 |
EnterNotify |
7 |
Expose |
12 |
FocusIn |
9 |
KeyPress |
2 |
MappingNotify |
34 |
MapRequest |
20 |
MotionNotify |
6 |
PropertyNotify |
28 |
UnmapNotify |
18 |
4 Ideas About Displaying Windows Decorations
It doesn't seem that anyone has any interest in providing each window with its own title bar. But I do. Three aspects to clarify to achieve this:
- Where (when) should the title bar be drawn?
- When it's created, somewhere in the process of
manage()
. And when it's moved probably too, but surely that must be handled inmanage()
as well since creating a new window may involve shrinking and moving the existing ones already. - How should the title bar be drawn?
- Same way the top bar is, although you'll get to find out this involves creating a window (which is not accounted for by dwm, but it's a window nonetheless). I would feel a tinge of dissatisfaction if I had to create a new window for each title bar. Surely other window managers don't do this. It'd be interesting to see how i3 does it, for instance, since it has title bars by default.
- Reparenting
- The concept of reparenting a window is explained in Adrian Nye's Xlib Programming Manual, § 16.3 Reparenting p. 514. I'm not sure it's the way to go, though, and I'd be interested in seeing what other people do. I should try to look at the code of other Xlib C window managers.
5 References
- dwm – dynamic window manager
startx(1)
- Adrian Nye, Xlib Programming Manual
- Comparison of Tiling Window Managers