Home     Blog     Rss     Contact     Donate

OpenBSD’s CWM: An Underrated Window Manager (Plus a Comfy Config)


The first time I tried OpenBSD’s Calm Window Manager, I thought it was really good, but at that point I was merely curious as to what it looked like and didn’t explore all its functionalities. I’ve always been more than satisfied with dwm, and its tiling capabilities are essential to my workflow, so giving cwm a serious look wasn’t a top priority. However, in time, I started developing two separate workflows: one on my desktop, and another on my laptop. The two aren’t that different, but are each influenced by the type of work I do and screen real-estate.

My laptop’s screen is relatively small, even on its dedicated external monitor (just a small, 720p TV I had lying around), and automatic tiling is something I began getting away from on that particular device. On there, I prefer having windows maximized and only splitting them as needed, as you do in Vim and Tmux. Mentioning tmux is also quite relevant. In recent months, it has become an integral part of my workflow and I no longer need to have multiple terminals opened on the same tag/group/workspace, just a single terminal using tmux windows and panes. This does not render automatic tiling useless on my desktop, but it does on my laptop.

Mind you, this is easily achievable on dwm, but I wanted to give cwm a serious look since it’s part of OpenBSD’s base after all (same reason why I tried tmux instead of GNU screen or dvtm + abduco). My philosophy on OpenBSD is that if a program from the base system does what I want, then there’s no need to install something else.

With all that said, what’s so good about cwm? Let’s see.

Quick Notes


A few notes and particularities regarding cwm before we go to the comfy config part.

  1. Made by OpenBSD devs, for OpenBSD: this is pretty much “proof of quality”, be it in terms of usage, simplicity and code quality. No further justifications needed here.
  2. Minimal: no superfluous features. It contains more than stock dwm, but still nothing insane.
  3. Sane config file: cwm’s config file uses a simple <option> <value> format. Can’t get any more straight forward than that.
  4. Keyboard-driven workflow: this is what cwm is geared towards. Whatever you want to do with a window (move, resize, snap, maximize, hide, etc), there’s a keybinding for it. Granted, you can still bind mouse buttons to do things, but I’ve personally omitted that (originally I just forgot to add it, but I don’t actually need to move/resize windows with the mouse, so I’ve left it out completely).
  5. Groups: a more flexible alternative to workspaces. It’s exactly as it sounds. You can group certain windows together and view multiple groups at once if need be. You can still achieve a workflow that’s essentially the same as you would with workspaces by adding sticky yes to .cwmrc. You can also easily set certain programs to open in specific groups by default using the autogroup option. Bonus: you can have both a classic workspace-like workflow AND do it the cwm way.
  6. Menus: there are search and exec menus for windows, groups and programs. This includes a custom menu where you can add specific programs to launch.
  7. Manual tiling: kinda. You can tile 2 windows either horizontally or vertically using htile and vtile.
  8. Gaps: who doesn’t love gaps? Even if you don’t, you’ll need to at least set a gap at the top or bottom of the screen so that windows don’t cover your status bar.
  9. Ignore: cwm can completely ignore specific programs/windows if you tell it to. Useful for statusbars that don’t have an override_redirect option.

Configuration


Cwm’s configuration file is ~/.cwmrc, which is not provided by default. It'll be up to you to create your own config. The cwmrc(5)[1] man page contains everything there is to know, and it can also be useful to start with a pre-existing config and go from there.

My own config file[2], with extra comments:


# CWM config file

# Sticky groups: comment out to disable worskpace-like behavior
sticky			yes

# Default font
fontname		"spleen:pixelsize=14:bold"

# Appearance
borderwidth		1
color activeborder	"#5294E2"
color inactiveborder	"#565656"
color urgencyborder	"#cc241d"

# Menu colors
color font		"#eeeeee"
color selfont		"#eeeeee"
color menubg		"#161616"
color menufg		"#5294E2"

# Size of gaps: top, bottom, left, right
gap			32 8 8 8

# Size of htile and vtile, in %
htile			50
vtile			50

# Move window by #px amount
moveamount		2

# Key bindings.
#
# 4 = Super/Windows key
# M = meta/Alt key
# S = Shift
# 
# Windows are usually handled with the M key,
# but for groups I prefer using Alt.

# Remove all default keybindings
unbind-key		all

# Only show group nr
bind-key M-1		group-only-1
bind-key M-2		group-only-2
bind-key M-3		group-only-3
bind-key M-4		group-only-4
bind-key M-5		group-only-5
bind-key M-6		group-only-6
bind-key M-7		group-only-7
bind-key M-8		group-only-8
bind-key M-9		group-only-9

# Toggle group nr's visibility
bind-key 4M-1		group-toggle-1
bind-key 4M-2		group-toggle-2
bind-key 4M-3		group-toggle-3
bind-key 4M-4		group-toggle-4
bind-key 4M-5		group-toggle-5
bind-key 4M-6		group-toggle-6
bind-key 4M-7		group-toggle-7
bind-key 4M-8		group-toggle-8
bind-key 4M-9		group-toggle-9

# Move window to group nr
bind-key MS-1		window-movetogroup-1
bind-key MS-2		window-movetogroup-2
bind-key MS-3		window-movetogroup-3
bind-key MS-4		window-movetogroup-4
bind-key MS-5		window-movetogroup-5
bind-key MS-6		window-movetogroup-6
bind-key MS-7		window-movetogroup-7
bind-key MS-8		window-movetogroup-8
bind-key 4S-9		window-movetogroup-9

# Toggle visibility for all groups
bind-key 4-a		group-toggle-all

# Add window to current group
bind-key 4-g		window-group

# Options bellow are pretty self-explanatory
bind-key 4-r		restart
bind-key 4-q		quit

bind-key 4-c		window-close
bind-key 4-u		window-hide

bind-key 4-f		window-fullscreen
bind-key 4-m		window-maximize
bind-key 4-t		window-htile
bind-key 4S-t		window-vtile

bind-key 4-j		window-cycle
bind-key 4-k		window-rcycle

bind-key 4S-h		window-move-left
bind-key 4S-j		window-move-down
bind-key 4S-k		window-move-up
bind-key 4S-l		window-move-right

bind-key 4M-h		window-snap-left
bind-key 4M-j		window-snap-down
bind-key 4M-k		window-snap-up
bind-key 4M-l		window-snap-right

bind-key 4M-m		menu-window
bind-key 4M-g		menu-group
bind-key 4M-a		menu-cmd
bind-key 4M-e		menu-exec

# Autogroup some apps
autogroup 1		"st,st"
autogroup 3		"Navigator,firefox-default"

There are other config options I have yet to touch, which I will leave to you to explore.

Linux Availability


A portable version of cwm[3] which can be installed on Linux (as well as the BSDs) exists. Debian (and derivatives), Gentoo, Void Linux, Alpine Linux, NixOS, Fedora all have it in their official repositories.

On Arch Linux, it’s only available in the AUR[4], though I’d personally just fetch its source and compile it myself.

Originally posted on April 29, 2022.
Revised on June 01, 2023.

[1] https://man.openbsd.org/cwmrc.5
[2] https://github.com/IanLeCorbeau/OpenBSD-install/.cwmrc
[3] https://github.com/leahneukirchen/cwm
[4] https://aur.archlinux.org/packages/cwm