Tiling Window Managers

Table of Contents

1 Abstract

Many linux users are working textually most of the time and are therefore annoyed when they have to use the mouse.The usual desktop environments like Gnome or KDE can only partly be controlled with the keyboard. And in fact, the model of free floating, overlapping windows doesn't lend itself well to keyboard control. I will now present some alternative window managers that use non-overlapping windows, can completely be controlled with the keyboard and that are, for the most part, extremely configurable.

2 Motivation

When you're working primarily with the keyboard, using the mouse and especially frequently switching between the two input methods can be annoying. What to do about it?

One strategy would be to completely drop GUI applications and X11 altogether and only work on the console. For most common tasks there are equivalent text oriented programs you can use, i. e.

On the other hand, the console only allows for a very limited multimedia experience:

So it seems we cannot completely get by without X, which leads us to the question: how can you work efficiently with windows only with the keyboard? It seems that the model of free floating, overlapping windows can not work well here.

3 Window tiling history

3.1 Early tiling window managers for X11

  • The Siemens RTL WM (1988) was an early one - and you just have to watch this video!
  • Since 2000 we've got larswm, ion und ratpoison, all free software.

4 What does a window manager do, anyway?

As a matter of fact, you don't strictly need a window manager to use X11, and this was how it was in the early days.

A window manager

For demonstration purposes, I'm starting X now with the session called "XClient script", which call this script that I saved as ~/.xession:

# set keyboard layout to US and make "CAPS" an additional Control key
setxkbmap 'en_US' -option ctrl:nocaps
# set the desktop background
qiv --root -m -o '#ffffff' /home/anselm/projects/talks/tiling-wm/ratpoison.png
# a little script to display all key presses on screen
key-status &
# start a terminal
# once the terminal finishes, wait in an infinite loop
while true; do
  sleep 60

5 Requirements

Normale window manager let the user do the work of efficiently placing windows. But what we're looking for is a window manager that we can tell with a few commands where we really want our windows to be.

There are some window managers for X11 that try to always make use of the whole screen. I will now present you some of these.

5.1 My personal requirements for the keyboard bindings

  • Few interferences with common applications (err, cough, Emacs)
  • The bindings should be easy to reach for touch typists, i.e.
    • no function keys, numeric keypad or "Windows" key

5.2 Automatic window placement

  • No fine tuning with the mouse,
  • might not be what you want
  • Window placement is easy when you're working in fullscreen anyway.
  • It's also easy to do for terminal windows - they are usable at almost any size.
    • This doesn't work all the time, e.g. man pages are not reformatted when the window gets narrower.
    • Curses based applications with several panes need a minimum window size to function.
  • It's hard to do for programs that open several windows, e.g. the GIMP.
    • So it would be good to have a floating mode, just in case.

5.3 Say goodbye to Gnome and KDE

Modern desktop environments are quite heavyweight, but it's not just useless baggage that we're now throwing away:

  • The NetworkManager is quite a useful tool, especially for laptops.
    • To use it you need a system tray which is provided by the gnome panel.
  • You also leave behind Power-, Bluetooth-, Volumemanager, desktop search and menus. Of course you still can use all these applications, but you have to how to call them and maybe do additional setup.

6 Explicitly tiling window managers

6.1 ratpoison

Ratpoison is a window manager in the spirit of GNU screen - and it's executable is even smaller than screen is!

6.1.1 Demo

  • help (C-t ?)
  • open two windows (C-t c, C-t !)
  • show splits (C-t s, C-t S, C-t Q)
  • move windows between frames (C-t C-Cursortaste)
  • start the GIMP (oh shit, that's a crappy interface!)
  • window list (C-t C-w)

Simple commands can be issued at a prompt (C-t :) or via the command line (ratpoison -c).

 C-t : getenv PATH
 ratpoison -c "echo This message will show in the echo area"
 ratpoison -c "prompt Please enter some text here: "

6.1.2 Conclusion


  • does not interfere much with keyboard bindings.


  • no floating layout available as a fallback (for Gimp, or browser popups)
  • no system tray, no dockapps, no status bar, no program launcher
  • splits are too transient
  • groups, which are roughly equivalent to workspaces, are awkward to use, this makes it hard to manage lots of windows
    • possible workaround: heavy use of screen, emacs' buffer management or firefox' tabs

When you're only using applications that work best in fullscreen and don't have to many windows to manage, ratpoison is a decent solution.

6.2 Stumpwm

Stumpwm is the successor to ratpoison by the same author.

The feel of stumpwm is very similar to ratpoison, but it's more "hackable" since it is written in Common Lisp. But this also means that you need much more memory for the lisp runtime/compiler.

6.2.1 Demo

 M-x slime-connect

(in-package :stumpwm)

;; prompt the user for an interactive command. The first arg is an
;; optional initial contents.
(defcommand colon1 (&optional (initial "")) (:rest)
  (let ((cmd (read-one-line (current-screen) ": " initial)))
    (when cmd
      (eval-command cmd t))))

;; Browse somewhere
(define-key *root-map* (kbd "b") "colon1 exec x-www-browser http://www.")

6.3 Ion

The ion window manager is under development since 2000, the current version is ion3. Ion uses workspaces, frames (which are created explicitly by splitting) and tabs. Windows that are set to fullscreen are handled much like a workspace. This also makes the numbering of the workspaces unstable. Ion is configured and scriptable in Lua.

6.3.1 Demo

  • Alt-<N>: switch Workspace
  • Alt-Return: toggle fullscreen mode for the current window
  • F9 creates a new Workspace
  • F2 starts a terminal
  • Alt-M: gives you a textual context menu, with tab completion
  • Alt-F3: a Lua console
  • Alt-K <N>: switches between tabs
  • Alt-S/Alt-K S/X: split/delete frames
  • Alt-N/P/TAB/Shift-TAB: move between frames
  • Alt-C: closes the current window

Please note that splits are always explicit.

Unfortunately there are some problems with ion's license, and for that reason ion is no longer available in the repositories of Arch Linux and the FreeBSD ports.

The extensive Lua API looks like a lot of fun. There's no support for a system tray but for WindowMaker dock apps, so you can use "stalonetray -w" to get a usable tray.

To do this, press Alt-F3 and enter

Alt-D will then toggle the dock's visibility.
 stalonetray -w &
 nm-applet &

7 Dynamically tiling window managers

7.1 Larswm

  • first released on Jun 3, 2000
  • based on code from 9wm, a UNIX port of Plan9's 8 1/2 window manager
  • inspired by Plan9/Acme

Larswm support multiple screens and virtual desktops. On every desktop there are two "subdesktops", the floating and the tiling subdesktop. The tiling subdesktop has to columns or "tracks".

Only a few applications are put into tiling, you have to configure these explicitly (whitelisting). But it's also possible to put an existing window into tiling with Alt-Shift-SPACE.

  • the configuration file follows the format of an X resource file
    ! .larswmrc !
    ! These are the windows I want tiled
    larswm.dotileclass.0: XTerm~xterm
    larswm.dotileclass.1: navigator:browser~Mozilla
    larswm.dotileclass.2: Mozilla-bin
    larswm.dotileclass.3: URxvt~urxvt
    larswm.dotileclass.4: Emacs~emacs
    ! Some tool windows
    larswm.toolclass.0: XLoad~xload
    larswm.toolclass.1: XBiff~xbiff
    larswm.toolclass.2: XClock~xclock
    ! Windows that should always stay above other windows
    larswm.floatclass.0: XCalc~xcalc
    larswm.floatclass.1: Gaim
    larswm.floatclass.2: larsmenu~larsmenu
    ! Windows that should be visible on all virtual desktops
    larswm.stickyclass.0: larsmenu~larsmenu
    ! Assign all new web browser windows to the WWW desktop
    larswm.dtclass.0: navigator:browser~Mozilla
    larswm.dtnum.0: 1
    larswm.dtclass.1: Mozilla-bin
    larswm.dtnum.1: 1
    ! Use a wider left track on the WWW desktop
    larswm.?.1.left_track_width: 80
    ! Do not resize windows on the WWW desktop
    larswm.?.1.tile_resize: False
    ! Automatically shift focused window to the left track on WWW desktop
    larswm.?.1.skip_focus: False
    ! larswm Menu - Middle Mousebutton
    larswm.button2.application: larsmenu -popup '*  LARSWM  *:exit' 'R E S T A R T:larsremote restart' 'E X I T:larsremote exit' '*  Exit Menu  *:exit'
    ! [...]
    • This is not very flexible and a bit awkward.
    • Not everything is configurable.
    • There is advanced stuff like differing configurations per desktop.
    • You can make an application open on a specific virtual desktop.
  • Larswm has a built in status bar.
    • You can set the text with `larsremote message "text"'.
    • "larsremote" can also trigger `exit' and `restart', that's it.

7.1.1 Demo

  • Shift-Ctrl-Return opens a new terminal
  • Alt-Shift-Space toggles tiling
  • Ctrl-Shift-left/right switch workspaces
  • Shift-Ctrl-BS toggle between floating/tiling subdesktop

The method for moving and resizing windows is a bit odd, you don't click on the window but on the status bar to manipulate the currently active window with these shortcuts:

  • Alt-Shift+Click1: move
  • Alt-Ctrl-Shift-Click1: resize
  • Ctrl-Shift-Click1: make smaller
  • Ctrl-Shift-Click3: enlarge
  • Alt-Shift+Wheel: move horizontally
  • Alt-Ctrl-Shift+Wheel: move vertically
  • Ctrl-Shift+Wheel: resize

Using the status bar makes sense: look up "Fitt's Law".

7.2 wmii

Configuration of and interaction with wmii is done via the 9p file system (ported from Plan9) or the `wmiir' tool, if 9p is not available. Every programming language can be used for configuration, you get full control over the event loop. This script is called a "wmiirc", in the standard distribution it is a shell script, but there are also scripts in ruby and emacs lisp.

  • Layout is done in columns + a floating layer
  • Columns have one of three layouts: default/max/stacked
  • Vertical splitting is explicit, horizontal splitting is automatic
  • Uses the "stacked" layout instead of tabs
  • "Tags" are used instead of workspaces, they are more flexible

7.2.1 Demo

  • Alt-Enter opens a new terminal
  • Alt-F toggles fullscreen
  • Alt-s/m/d switches the column layout
  • Alt-Shift-[hjkl]: moves windows, new columns are created automatically when needed
  • Alt-[hjkl]: jump between windows
  • Alt-Shift-space: toggle tiling for the active window

7.3 dwm

Dwm is wmii's little brother. Its window model is similar to larswm's and it's also got a builtin status bar. Dwm is configured by editing a C header file and recompiling. While this is secure and efficient, it doesn't make sense to use prebuilt binary packages of dwm - these cannot be configured anymore. The text to display in the status bar is read from the root window's name. Dwm is very small, the executable is only 28k and the source code is less than 2000 LOC. Here's a listing of a directory with a freshly compiled dwm:

   -rw-r--r--  1 anselm anselm  5468 2009-03-21 14:59 config.def.h
   -rw-r--r--  1 anselm anselm  5468 2009-03-21 14:59 config.h
   -rw-r--r--  1 anselm anselm   650 2009-03-21 14:59 config.mk
   -rwxr-xr-x  1 anselm anselm 27748 2009-03-21 14:59 dwm
   -rw-r--r--  1 anselm anselm  4663 2009-03-21 14:59 dwm.1
   -rw-r--r--  1 anselm anselm 41576 2009-03-21 14:59 dwm.c
   -rw-r--r--  1 anselm anselm   373 2008-07-17 17:07 dwm.png
   -rw-r--r--  1 anselm anselm  1593 2009-03-21 14:59 LICENSE
   -rw-r--r--  1 anselm anselm  1462 2008-07-17 17:07 Makefile
   -rw-r--r--  1 anselm anselm  1259 2009-03-21 14:59 README

7.3.1 Demo

  • right clicking a tag in the status bar toggles it
  • Alt-<N>: switch on a tag
  • Alt-Shift-<N>: tag a window
  • Alt-Ctrl-Shift-<N>: toggle tag
  • Alt-t/f/m: set layout to tiled/float/monocle (fullscreen)
  • Alt-P: call dmenu

7.3.2 Forks

Because dwm is so small and cleanly implemented it served as a foundation and inspiration for several other window managers. Some notable forks are awesome, echinus and scrotwm. It also inspired the following projects:

  • XMonad is written in Haskell and has many extensions and better modularity.
  • dvtm is transferring the concept of dwm to the console.
  • bug.n is a similar piece of software for windows.

7.4 XMonad

XMonad is a clone of dwm, written in Haskell. In the spirit of dwm the configuration file is also written in Haskell. Recompiling and restarting XMonad is happening in the background and can be done without disturbing the current window arrangement. The existing Ubuntu package is user-configurable, the resulting executable is placed in the user's home directory. For this to work XMonad needs a Haskell development environment which includes the compiler and the necessary libraries. XMonad supports Xinerama and EWMH.

It has no built-in status bar, you can use one of these stand-alone programs:

  • dzen2
  • xmobar
  • Gnome Panel
  • KDE Kicker

Here's an example from my .xsession with configuration for dzen2:

xsetroot -solid black
[ -r ~/.$(hostname -s).png ] && qiv -x ~/.$(hostname -s).png
setxkbmap 'en_US,de' -variant ',nodeadkeys' -option ctrl:nocaps -option grp:ctrls_toggle 
export PATH=/var/lib/gems/1.8/bin:${PATH}:${HOME}/.local/bin

mocp_info() {
    if ps -C mocp > /dev/null && mocp -i | grep -q 'State: PLAY'; then
        title=$(mocp -i | grep '^Title: ')
        echo ${title#*: } \|
load() {
    while read f s t r; do
        echo $f $s $t
    done < /proc/loadavg

disk() {
    df -h / | { \
        read rest
        read mount size used avail rest
        echo $avail/$size

cpu_temp() {
  local t=$(cat /sys/class/hwmon/hwmon0/device/temp2_input)
  echo $(expr $t / 1000)"°C"

xscreensaver -no-splash &

while true; do
    echo '^fg(#222222)^bg(#eeeeee)' $(mocp_info) $(cpu_temp) \| $(disk) \| $(load) \| $(date '+%Y-%m-%d %a | %R') '^fg()^bg()'
    sleep 5
done | dzen2 -fn fixed -x 600 -w 1080 -ta r -fg '#ffffff' -bg '#006699' -e '' & 

xmonad | dzen2 -fn fixed -w 600 -ta l -fg '#ffffff' -bg '#006699' -e '' 

XMonad has many extension modules in XmonadContrib, they are divided in

  • Actions
  • Prompts
  • Layouts (everything that changes the window layout)
  • Hooks (give information about XMonad's status to the outside world)


  • high modularity, many modules available
  • good support for Xinerama and EWMH => you can use Gnome components together with XMonad
  • Haskell - it's a pro if you like Haskell, or like to learn it


  • Haskell - it is just too strange and hard to understand "for the rest of us"
  • relatively big executable (ca. 1.8 MB, GHC does not do dynamic linking yet)

7.4.1 Demo

Show interaction with Gnome (EWMH)

  • can interact with the Workspace Switcher
    • ewmhDesktopsLayout (a LayoutHook) allows for moving windows inside the Workspace Switcher
    • EwmhLogHook tells the Workspace Switcher the current position of a window
  • leaves enough space for the gnome panel
    • you can also move the task bar
  • wmctl is a command line tool to control EWMH compatible window managers
    • e.g. "wmctrl -a emacs"

7.5 awesome

Awesome started out as a fork of dwm. The keyboard bindings and general usage are similar, but it's not minimalistic anymore:

  • implements Xinerama, EWMH, System Tray and more
  • uses the more modern libxcb instead of Xlib (should be faster)
  • is configured and scriptable with Lua
  • can be controlled from the shell with `awesome-control'
  • the built-in status bar is built around a concept of `widgets' like text, images, the system tray, etc.

Because it depends on so many libraries the memory footprint is comparatively huge. This does not make so much of a difference if you need the libraries anyway for the applications you run.

7.5.1 Demo

  • Usage similar to dwm, uses the windows key as default modifier
  • show the configuration file

8 Some utilities

Useful extensions for Firefox:

You can also use Conkeror, Vimperator, or emacs-w3m.

9 Is it worth it?

You also have to ask yourself if you really want to miss out on all the UI improvements that Gnome and Ubuntu are bringing you. If you need an easily accessible desktop you will more likely prefer a standard gnome session. But you can choose how far away from the gnome desktop you want to be: