Since I first discovered ratpoison in 2005 or so, I've basically exclusively used tiling window managers, going through, over the years, StumpWM, Ion 3, and finally XMonad. They've all had various strengths and weaknesses, but I've never been totally happy with any of them. This blog entry is a writeup of what I want to see as a window manager. It's possible that some day I'll get annoyed enough to write it, but maybe this post will inspire someone else to (Not likely, but I can hope).
Layout 🔗︎
At any given moment, the screen1 is divided into one or more panes. These panes always tile the screen. Each pane may or may not currently be displaying a window. If it is not, then the desktop will be displayed in that pane.
The primitive operations you can perform on the pane include, but are not necessarily limited to:
- Split
- Splits the focused pane into two equally-sized panes, either horizontally or vertically. One of the child panes will display whichever window the previous pane displayed, the other is empty.
- Resize
- Change the relative size of two child windows that were split from the same parent.
- Kill Pane
- Destroy the current pane. If it is displaying a window, that window is not sent a close message. The pane's sibling window expands to consume its space.
- Next/Previous pane
- Focus the next or previous pane. Panes are ordered based on position on the screen, regardless of how they were split to arrive at the current layout.
- Goto Pane
-
Panes are numbered, based on their location on
screen.
Mod-N
focuses the Nth pane.
Selecting windows 🔗︎
There is a global list of all windows. Windows are ordered arbitrarily
in this list (maybe based on the order they were opened?). Every
window has a name, which is initially set to the WM_NAME
property
set by the window's client.
The following operations are available to manipulate windows:
- Next/Previous Window
- Replace the window in the current panel with the next or previous window in the list.
- Rename
-
Prompts for a new name for the current window. If the user
enters an empty string, the window reverts to the default
behavior of using the
WM_NAME
. - Goto Window
- Prompts for the name of a window to switch to. This prompt matches on substrings or even sub-sequences of the window name, displaying the result of the selection as you type. After typing some characters, you can scroll through the list to select an entry, instead of completing typing.
- Kill
- Sends a close message to the window in the focused panel.
Desktops 🔗︎
It seems likely I will want multiple desktops. Each desktop will have
its own pane layout. However, the window list is still global, not
per-desktop. Goto Window
will always operate on the global window
list. Selecting a window that is visible through a pane somewhere else
causes that pane to become empty.
Alternately, there is no concept of multiple desktops. However, there is the ability to save and restore layouts, meaning both the layout of the panels on the screen, and the list of which window is in each pane. The primary difference here is that a window can be associated with multiple panes in different saved layouts, and gets resized/moved as necessary as you switch panes. I suspect I like this model better.
Postscript 🔗︎
If this sounds familiar to you, it probably should. What I've described is essentially identical to how emacs manages buffers and windows (analogous to X windows and panes in the above, respectively), with window-number.el and either iswitchb or ido. I manage hundreds of buffers in emacs this way, and complicated screen layouts, whenever I'm doing any hacking, and I love it.
I would in fact be tempted to write my window manager into emacs itself, except for the annoying fact that emacs is very much single-threaded. It's already annoying enough when network drops and a hung network filesystem takes down my emacs waiting for a timeout; It would be utterly unacceptable if that took down my entire window manager, too.
I'd alternately be tempted to try to make this an XMonad plugin, but I think that it's sufficiently different from XMonad's data model that the impedance mismatch would suck.
Footnotes:
1 I'm only going to consider the single-monitor case for now, but the generalization should be easy.