Writing a Wayland Compositor, Part 2: Rigging up the server February 22, 2018 on Drew DeVault's blog

This is the second in a series of articles on the subject of writing a Wayland compositor from scratch using wlroots. Check out the first article if you haven’t already. Last time, we ended up with an application which fired up a wlroots backend, enumerated output devices, and drew some pretty colors on the screen. Today, we’re going to start accepting Wayland client connections, though we aren’t going to be doing much with them yet.

The commit that this article dissects is b45c651.

A quick aside on the nature of these blog posts: it’s going to take a lot of these articles to flesh out our compositor. I’m going to be publishing these more frequently than usual, probably 1-2 per week, and continue posting my usual articles at the typical rate. Okay? Cool.

So we’ve started up the backend and we’re rendering something interesting, but we still aren’t running a Wayland server – Wayland clients aren’t connecting to our application. Adding this is actually quite easy:

@@ -113,12 +113,18 @@ int main(int argc, char **argv) {
        server.new_output.notify = new_output_notify;
        wl_signal_add(&server.backend->events.new_output, &server.new_output);
+       const char *socket = wl_display_add_socket_auto(server.wl_display);
+       assert(socket);
        if (!wlr_backend_start(server.backend)) {
                fprintf(stderr, "Failed to start backend\n");
                return 1;
+       printf("Running compositor on wayland display '%s'\n", socket);
+       setenv("WAYLAND_DISPLAY", socket, true);
        return 0;

That’s it! If you run McWayface again, it’ll print something like this:

Running compositor on wayland display 'wayland-1'

Weston, the Wayland reference compositor, includes a number of simple reference clients. We can use weston-info to connect to our server and list the globals:

$ WAYLAND_DISPLAY=wayland-1 weston-info
interface: 'wl_drm', version: 2, name: 1

If you recall from my Introduction to Wayland, the Wayland server exports a list of globals to clients via the Wayland registry. These globals provide interfaces the client can utilize to interact with the server. We get wl_drm for free with wlroots, but we have not actually wired up anything useful yet. Wlroots provides many “types”, of which the majority are implementations of Wayland global interfaces like this.

Some of the wlroots implementations require some rigging from you, but several of them just take care of themselves. Rigging these up is easy:

        printf("Running compositor on wayland display '%s'\n", socket);
        setenv("WAYLAND_DISPLAY", socket, true);
+       wl_display_init_shm(server.wl_display);
+       wlr_gamma_control_manager_create(server.wl_display);
+       wlr_screenshooter_create(server.wl_display);
+       wlr_primary_selection_device_manager_create(server.wl_display);
+       wlr_idle_create(server.wl_display);

Note that some of these interfaces are not necessarily ones that you typically would want to expose to all Wayland clients - screenshooter, for example, is something that should be secured. We’ll get to security in a later article. For now, if we run weston-info again, we’ll see a few more globals have appeared:

$ WAYLAND_DISPLAY=wayland-1 weston-info
interface: 'wl_shm', version: 1, name: 3
	formats: XRGB8888 ARGB8888
interface: 'wl_drm', version: 2, name: 1
interface: 'gamma_control_manager', version: 1, name: 2
interface: 'orbital_screenshooter', version: 1, name: 3
interface: 'gtk_primary_selection_device_manager', version: 1, name: 4
interface: 'org_kde_kwin_idle', version: 1, name: 5

You’ll find that wlroots implements a variety of protocols from a variety of sources - here we see protocols from Orbital, GTK, and KDE represented. Wlroots includes an example client for the orbital screenshooter - we can use it now to take a screenshot of our compositor:

$ WAYLAND_DISPLAY=wayland-1 ./examples/screenshot
cannot set buffer size

Ah, this is a problem - you may have noticed that we don’t have any wl_output globals, which the screenshooter client relies on to figure out the resolution of the screenshot buffer. We can add these, too:

@@ -95,6 +99,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) {
        wl_signal_add(&wlr_output->events.destroy, &output->destroy);
        output->frame.notify = output_frame_notify;
        wl_signal_add(&wlr_output->events.frame, &output->frame);
+       wlr_output_create_global(wlr_output);

Running weston-info again will give us some info about our outputs now:

$ WAYLAND_DISPLAY=wayland-1 weston-info
interface: 'wl_drm', version: 2, name: 1
interface: 'wl_output', version: 3, name: 2
	x: 0, y: 0, scale: 1,
	physical_width: 0 mm, physical_height: 0 mm,
	make: 'wayland', model: 'wayland',
	subpixel_orientation: unknown, output_transform: normal,
		width: 952 px, height: 521 px, refresh: 0.000 Hz,
		flags: current
interface: 'wl_shm', version: 1, name: 3
	formats: XRGB8888 ARGB8888
interface: 'gamma_control_manager', version: 1, name: 4
interface: 'orbital_screenshooter', version: 1, name: 5
interface: 'gtk_primary_selection_device_manager', version: 1, name: 6
interface: 'org_kde_kwin_idle', version: 1, name: 7

Now we can take that screenshot! Give it a shot (heh)!

We’re getting close to the good stuff now. The next article is going to introduce the concept of surfaces, and we will use them to render our first window. If you had any trouble with this article, please reach out to me at sir@cmpwn.com or to the wlroots team at #sway-devel.

Next — Part 3: Rendering a window

Previous — Part 1: Hello wlroots

Articles from blogs I read Generated by openring

WASI support in Go

Go 1.21 adds a new port targeting the WASI preview 1 syscall API

via The Go Blog September 13, 2023

Finding Domains That Send Unactionable Reports in Mastodon

One of the things we struggle with on woof.group is un-actionable reports. For various reasons, most of the reports we handle are for posts that are either appropriately content-warned or don’t require a content warning under our content policy–things lik…

via Aphyr: Posts September 3, 2023

Summary of changes for August 2023

Hey everyone! This is the list of all the changes we've done to our projects and apps during the month of August. We'll also be reporting in our on position in the world, and on our future plans. Summary Of Changes 100r.co, added Heriot Bay, Balle…

via Hundred Rabbits September 1, 2023