The wayland-client library

The easiest way to implement a Wayland client is to use the official wayland-client library. Basically, it abstracts away the wire format.

To use it, include the header:

#include <wayland-client.h>

and link in the library by passing -l wayland-client to the compiler:

$ gcc main.c -l wayland-client

To keep track of objects, wayland-client stores some metadata about them in appropriately named opaque structures. You always use the structure instances via pointers and never care what's inside. You interact with a structure instance as if it was the Wayland object it represents.

In particular, making request is just a matter of calling a function, passing the object pointer and the request arguments as the function arguments:

struct wl_shell_surface *shell_surface = ...;
wl_shell_surface_set_title(shell_surface, "Hello World!");

Here we make the wl_shell_surface.set_title request on a wl_shell_surface object. The request has only one argument, namely the new title as a UTF-8 encoded string.

In order to react to events issued by the server, we need to set up event handlers. The API is quite straightforward:

void surface_enter_handler(void *data, struct wl_surface *surface, struct wl_output *output)
{
    printf("enter\n");
}
void surface_leave_handler(void *data, struct wl_surface *surface, struct wl_output *output)
{
    printf("leave\n");
}

...
struct wl_surface *surface = ...;
struct wl_surface_listener listener = {
    .enter = surface_enter_handler,
    .leave = surface_leave_handler
};
wl_surface_add_listener(surface, &listener, NULL);

Here we establish handlers for the events that may be issued on a wl_surface object. There are two: enter and leave. Both have one argument of type wl_output. We need to create a "listener" structure containing pointers to event handlers, and pass it by pointer to the "add listener" function (note that the pointer must be valid for as long as the object is alive). The third argument that we pass to it (just NULL here) ends up as the first argument of the handler (void *data). The second argument of the handler is the object the event was issued on; this allows you to set the same set of handlers for multiple objects. The rest are just the event arguments.

When making a request that has a new_id (i.e. the ID of an object created by this request) as one of its arguments, the corresponding function returns a pointer to the structure instance representing the new object. For example:

struct wl_shm *shm = ...;
struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size);

Here, we construct a new wl_shm_pool object using the wl_shm.create_pool request that has new_id, fd and size arguments. Instead of passing the new_id, we get a new object pointer as a return value.

results matching ""

    No results matching ""