Hello World

Each chapter's code contents will have its own folder with a name prefixed by the chapter number. For example, this chapter's code is stored in 1-hello-world/. The code can be found here.

The only dependency used, apart from the standard library, will be wlroots. A more useful compositor will want to use other libraries, but it is not done here in order to avoid choosing favorites while also being self contained and complete.

An important note to copy pasters: This document as well as the example code base is under the CC0 license.

So copy and paste liberally, you can use this code as a jumping off point.

This does not apply to wlroots-rs or wlroots, both of which are under the MIT license.

Boring setup

wlroots-rs is in crates.io. If you want to install it, simply add this to your Cargo.toml:

[dependencies]
wlroots = {version = "0.2", features = ["unstable", "static"]}

The "unstable" feature flag enables the wlroots features whose API hasn't stabilized yet. For now, this is necessary to build a compositor. In the future this restriction will be gradually lifted as the library matures.

The "static" feature flag statically links the wlroots library to the binary. This is optional, but encouraged since there's no stable ABI guarantee and it makes it easier to distribute the compositor to others.

Because the library is changing constantly however, it is suggested you add it as a git submodule to your project instead of using crates.io.

A minimal compositor

Here is the smallest, simplest compositor you can make with wlroots:

extern crate wlroots;

use wlroots::{compositor, utils::log::{WLR_DEBUG, init_logging}};

fn main() {
    init_logging(WLR_DEBUG, None);
    compositor::Builder::new().build_auto(()).run()
}

This compositor is useless. In fact, it's dangerously useless. However it's also very instructive considering how short it is.

You can compile and run1 the above in any existing X11 window manager or Wayland compositor and it will run in a nested window.2 However if you run it in a separate TTY it will use the DRM backend. This is usually the backend that will be used when you're not testing the compositor. If you run this code on DRM, you can't escape the compositor. If you do this you will need to reboot to escape.

Because no callbacks were set up for the events the compositor will just keep running forever doing nothing. You can't even switch TTYs because that's a feature that the compositor needs to implement itself.

This example is a little silly, but it highlights just how much needs to be implemented -- our compositor can't even shut itself off.


1 If you are running on a system with systemd and have the feature enabled (it is by default) it should "just work". If not, you'll need set the setuid bit on the binary with chmod u+s.

2 This is a wlroots feature that is built into the build_auto function. It is very useful for debugging.