We’re developing our own Wayland Compositor, and we noticed most projects just use libwayland-server. However, we want more control over the on-the-write protocol I/O and better integration with our C++ codebase.
If you’ve written a Wayland Compositor you know that the protocol is defined in XML format. So, we decided to create our compiler for the Wayland protocols.
In these protocol definitions there are interfaces with requests and events defined. These are the most important abstractions for communication between a Wayland Compositor and its clients.
You can see this example from wayland.xml from 1.0 version:
As you can see, a request called
get_registry is defined with only one
single argument of type
get_registry is one of the most important requests a client
makes right in the beginning, to be able to get the
which the client can listen on events to get other global objects and
which it can use to bind client objects to the compositor.
Since the protocol doesn’t define return values from requests, the way
to create objects is to have the client define ids for them in
getters. That’s what the type
The client calls
get_registry and passes a id, usually 0, to be set
as the id of the registry that it is supposedly getting.
Now the client knows that the registry id is 0, since it got it with that argument.
get_registry request also triggers the global event for each
global object the wayland compositor has and needs to publish to the
The VWM Wayland Compositor has a compiler that reads multiple XML wayland protocol and creates a single class that handles requests and translates events to the on-the-write binary protocol of the wayland.
The protocol is quite simple and is implemented in our compiled result as simple POD copies over the write and special handling for strings and file descriptor arguments.
For example, the result of the
get_registry request is compiled as:
1 represents the index of the request in the interface
server_protocol class has one member function that
interprets the message to a request or event and calls the appropriate
function by using CRTP, aka Curiously Recurring Template Parameter, to
customize the Wayland Compositor behavior. Which is where the
wl_display_get_registry is defined.
As we can see in
wl_display_get_registry is implemented:
As you can see, taking control of the protocol and handling is
possible and a small part of the work needed to write a Wayland
Compositor. It is also a rewarding task that allows extending the
Wayland protocol to other mediums beside UNIX sockets. The biggest
challenge is supporting
shm_buffer over slower mediums.
This also allows implementing faster and more scalable protocol handling code.