I recently released Vivarium, a dynamic tiling
wayland compositor built using the wlroots library. Going from zero to compositing was interesting,
there are good libraries available but everything has moved very fast in the last couple
of years so it can be hard to know where to start. I especially wanted to write the
equivalent of an X window manager that only really cares about window layout and wants
everything else to Just Work.
Wlroots is a library created to support this use case. To quote its own README, it
provides "pluggable, composable, unopinionated modules for building a Wayland compositor;
or about 50,000 line of code you were going to write anyway". For me it’s fulfilled that
goal very well, and Vivarium probably wouldn’t exist without it. Still, while there are
many good development resources around it wasn’t always straightforward to get up to speed
so I thought I should write the blog post I would have loved to read at the start, setting
out the broad ideas and good resources for each development step. This is that post.
(If you’ve got this far you probably have some idea what Wayland is about already, but
here’s an unnecessarily long summary for general background purposes.)
Any modern desktop utilises some kind of display server, a program that brings together
the disparate components of desktop input and output to allow a consistent desktop
experience. In broad terms the display server keeps track of system outputs (an
abstraction that for the most part means physical monitors), and the applications that
want to draw to them, and via some set of rules draws the window images to them. This
means the display server also has to care about all sorts of other details: it must track
system inputs (keyboard, mouse) and pass their events through to applications; it must
deal with hardware details like monitor framerates, dpi scaling and rotation including
potentially passing these details to applications; and it may need to do drawing of its
own such as window decorations if the clients have not drawn their own. These are just
examples, the definition of the display manager is not rigid and these tasks can be
divided up in more than one different way, but you can’t think about implementing display
server functionality without worrying about them.
For a very long time the display server on almost all linux systems has been X.Org, implementing the X11 protocol. X has the problem that its
design is old and crufty, there are many details of its architecture that do not map well
to how modern software wants to work. For this reason there has been growing development
effort behind an alternative, the Wayland protocol. It’s been a long time coming, Wayland first became
a named thing somewhere around 2008, but nowadays the big desktop environments (Gnome,
KDE) are providing Wayland servers, many applications toolkits support it, and some big
distros are supporting Wayland by default.
Much has been written about this, some people think it’s incredibly terrible for various
reasons and others don’t. For what it’s worth I’m in the latter camp, I think Wayland will
improve the Linux desktop experience. Still, changing such a big desktop component is a
complicated process and personally I have one particular problem: what about my window manager?
The problem here is that under X it’s been normal that the X server exists and handles all
the core display server functionality, but other applications can control a lot of its
behaviour. A special example is the window manager, the program that looks at the open
windows and actually decides where to draw them. In a big desktop environment like
Gnome/KDE the window manager is a small part of a larger desktop architecture, but it’s
also totally practical and quite common to run a standalone window manager and there are
many popular ones for X11. As a quick reference, the Arch Linux wiki lists about 60
different options, and these are
just the ones that people have bothered to list there. Personally I’ve used xmonad for many years, not because I think its particular brand of
tiling window management is the one true way, but I like it and it’s been super stable.
With Wayland the situation is different. It isn’t an irreconcilable change, you could
certainly write a Wayland server that lets you hotplug all the functionality a window
manager needs (and probably e.g. Gnome/KDE plugins already can do a lot of that, I’m not
sure), but in practice different projects have implemented their own Wayland display
servers. A window manager in this environment really has its work cut out, instead of
focusing on implementing window positioning logic it would need to implement the entire
wayland protocol, all those hardware interfaces, and all the additional protocols you
want to use such as the xdg-shell protocol applications use to actually tell the
Wayland server they want to display stuff.
Thankfully there has been much developer effort to rally around libraries and tooling to
make Wayland window manager equivalents easy. The most popular example is almost certainly
wlroots, a library for creating Wayland
compositors. Effectively wlroots can be used to write a window manager under Wayland
without worrying directly about the core Wayland functionality, although the final result is a
standalone binary that implements a full Wayland compositor as opposed to the X model of
window managers plugging into a separate server. Wlroots is still under development but is
nowadays quite stable and complete for every core task I’ve worked through. There are many
technical details of interest, I want to cover here how I got started learning about the
key ideas and writing a useful compositor that I now use full time.
How to get started with wlroots
The following is entirely my opinion and perspective. There is no single correct path to
take and I’m sure there are other great resources I didn’t even notice or pay attention to.
Before anything else you may want to ask whether you really need to write a Wayland
compositor. Window management functionality can potentially be achieved just as well
(maybe more easily!) as a plugin to another compositor, if it supports such an
interface. Some possibilities include:
- Write a Wayfire plugin. Wayfire is an
existing Wayland compositor using wlroots and its plugin system seems extensive enough
to cover a lot of window manager functionality. There are also other similar options
like writing a KWin or Gnome Shell script, but I don’t know much about what these
- Use an existing tiling window manager. Sway is mostly a
drop-in replacement for the i3 window manager and is popular and well supported, with
some scripting functionality. River supports a
system of user-provided executables that makes its layouts quite flexible. Indeed
Vivarium itself supports customisable
layouts, but those other projects are much more established and perhaps more flexible.
- Obviously I wrote Vivarium despite these alternative possibilities. I did that because
I wanted to learn from the project and see how practical it was. Without that
motivation, I’d probably be a happy Sway/River/other user.
- Hang around and see if wlroots grows a higher level API, or if another project/library starts
to provide one. As it stands I think wlroots is a step more technically involved than it
needs to be for most window management purposes - it isn’t hard, but I feel like
different wlroots compositors tend to implement some things in similar ways, which
supports the idea that a better abstraction layer isn’t quite there yet. Examples
include damage tracking and the abstraction of views to provide a consistent
api for views managed via different protocols, especially xdg-shell/xwayland. This isn’t a
criticism, just a feature that I think will eventually exist but doesn’t yet.
I think ultimately there will naturally end up being multiple active compositor projects,
some of which support easily creating distinct window managers via extensive plugin
APIs, although it’s of course impossible to know which projects will ultimately be
successful. See Should you write a Wayland compositor by tudor for
another overview discussing these questions. Of course, there’s never anything wrong with
starting another project.
So, if you do want to write a wlroots compositor…how to get started? Here’s what I found
useful, in rough order. I started Vivarium without any specific knowledge about wlroots or
wayland, so that’s the direction I’m coming from below.
- Drew DeVault’s Writing a Wayland compositor blog posts
are an excellent introduction to how to think about Wayland. Don’t worry too much about
the code itself, I think it’s outdated for current wlroots and the repository is
archived, but the overview of key ideas will take you a long way.
- Fork tinywl. This
tiny example is shipped with wlroots and is an excellent base for a serious
compositor. Although short it implements in a basic way almost every core
functionality you’ll need, and implicitly teaches a lot about Wayland API interaction
(especially if using the C interface to events, listeners etc.) which scales very well
when branching out into other protocols. Since tinywl is within the wlroots tree it is
also guaranteed to be up to date.
- Watch (and join in on) the #sway and #sway-dev irc channels on irc.freenode.net. Seeing
how other people think about things is always invaluable.
- Don’t be afraid to actually read the wayland protocol definitions - the other linked
resources also say this but it bears repeating. They are often surprisingly straightforward.
- Read the Wayland Book. This is a much more thorough (but
not complete) overview of the Wayland protocols and way of working. I’ve found this more
useful as a reference to revisit than a direct learning tool, mostly because much of the
detail isn’t actually necessary to sit down and write code, but it’s very nice for
formalising knowledge to really do things right.
- Read the Sway source code. Sway doubles as a
thorough reference for how to do just about anything with wlroots, since it’s an active
and fairly complete project that has tackled most issues you’re likely to run into.
- Make use of the wlroots examples. When testing individual
protocols/features these save a lot of time writing your own test code!
One issue I’ve sometimes hit is that wlroots doesn’t always have much in-code
documentation. However, it mostly makes up for this in general design consistency, and
this is a big part of the value of tinywl: the methodology it demonstrates is widely
applicable throughout wlroots. For instance, supporting a new protocol is likely to come
down to a _create function call returning a manager object with an obvious-looking
API, whose events you can probably read the protocol documentation to understand, and
tinywl demonstrates this process.
It’s also worth looking through the list of projects which use wlroots. Between them these
demonstrate many different things, especially where they focus on functionality that is
not so core to Sway.
There are many other useful resources scattered around, such as some posts on the blogs of
Drew DeVault (sway and wlroots creator) and Simon Ser (sway and wlroots current maintainer), but I’ve generally
found these by googling keywords when stuck rather than from any specific catalogue.
And with all that…this is pretty much where I am. I’m no expert, but Vivarium works and
it was fun to write. Thanks to the Wayland developer community for creating all these