---
# System prepended metadata

title: Wayland Library - How message is called by Client
tags: [Chromium-Graphics, elkurin-daily-note]

---

# Wayland Library - How message is called by Client

Chromium uses wayland protocol to communicate between Client (Lacros) and Server (Ash).  
We often expand wayland protocol to support ChromeOS features and implement the inner behvior, but how are they managed?  
This note goes through how wayland message called from client dispatch the message implementation on server side.

## Overview of Wayland message called by Client
The protocol called by client is implemented and called as bellow:
```cpp=
// Server side impl //components/exo/wayland/*
void aura_popup_set_menu(
  wl_client* client,
  wl_resource* resouce,
  ...Args) {
  GetUserDataAs<AuraPopup>(resource)->SetMenu();
}

// Client side caller // ui/ozone/platform/wayland/host/*
zaura_popup_set_menu(aura_popup_.get());
```

There is a concept called "object". This is an entity known to both the client and server and changes to which are negotiated over the wire.  

On calling `zaura_popup_set_menu` from client, it updates the state via wayland and dispatches `aura_popup_set_menu`.

## Client Implementation
On client side, [`wl_proxy`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-client.c;l=63;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) is an interface to refer to object.  

For example, in the example above, [`aura_popup_`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h;l=71;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) is wl::Object<zaura_popup> where `zaur_popup` is `wl_proxy`.  

Here's `zaura_popup_set_menu` impl auto-generated by xml file (auto-generation will be described maybe next time).  
```cpp=
static inline void
zaura_popup_set_menu(struct zaura_popup *zaura_popup)
{
  wl_proxy_marshal_flags(
    (struct wl_proxy *) zaura_popup,
    ZAURA_POPUP_SET_MENU, NULL,
    wl_proxy_get_version((struct wl_proxy *) zaura_popup), 0);
}
```
[`wl_proxy_marshal_flags`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-client.c;l=779;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) is in charge of negotiating object state with client.  

On starting communicating with server, it locks a mutex by `pthread_mutex_lock(&disp->mutex)`.  
The message to send is specified by `opcode`.
In above case, it is [`ZAURA_POPUP_SET_MENU`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:out/Debug/gen/components/exo/wayland/protocol/aura-shell-client-protocol.h;l=2594;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) and the message is found by `message = &proxy->object.interface->methods[opcode];`.  
[`wl_closure_marshal`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=745;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) generate `wl_closure` which represents a message and this is set via [`wl_closure_send`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=1357;drc=f80633b34538615fcb73515ad8c4bc56a748abfe).  
[`wl_closure_send`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=1357;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) will communicate with server via fd. This uses `proxy->display->connection`.  
It calls [`wl_connection_write`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=524;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) and add connection to queue by [`wl_connection_queue`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=536;drc=f80633b34538615fcb73515ad8c4bc56a748abfe).  
After adding connection to the queue, it explicitly flush the connection by [`wl_connection_flush`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=542;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) and then [`displatch_event`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-client.c;l=1560;drc=f80633b34538615fcb73515ad8c4bc56a748abfe).  
This calls [`wl_closure_invoke`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=1145;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) and finds the correct message to send from [`implementation`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=1167;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) and runs it.  

When closure is done, it returns result of connection.  
After this, it unlocks mutex and gives back `new_proxy` with new `interface`.
The mutex lock is alive during updateing wl_proxy.

In the above example, `ineterface` is set to NULL so `new_proxy` stays NULL. This is because set_popup message won't update object state and there is no need to update wl_proxy.  

The example which uses `new_proxy` is for example [`xdg_surface_get_popup`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:out/Debug/gen/third_party/wayland-protocols/src/stable/xdg-shell/xdg-shell-client-protocol.h;l=1129;drc=f80633b34538615fcb73515ad8c4bc56a748abfe). It specifies `&xdg_popup_interface` as an interface to use.  

## Server Implementaion
On server side [`wl_resource`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-server.c;l=127;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) is an abstract struct of objects. It's owned by a single client.  
[`wl_resource`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-server.c;l=127;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) consists of several prameters such as [`data`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-server.c;l=137;drc=f80633b34538615fcb73515ad8c4bc56a748abfe). This is a pointer to wl::Object inside client.  

[`GetUserDataAs(wl_resource* resource)`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:components/exo/wayland/server_util.h;l=27;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) casts `resource->data` into type `T`, in this example AuraPopup.  


Such message implementation is added by `SetImplementation` as below:
```cpp=
const struct zaura_popup_interface aura_popup_implementation = {
  ...,
  zura_popup_set_menu,
  ...,
}

void aura_shell_get_aura_popup(wl_client* client,
                               wl_resource* resource,
                               uint32_t id,
                               wl_resource* surface_resource) {
  wl_resource* aura_popup_resource = wl_resource_create(
      client, &zaura_popup_interface, wl_resource_get_version(resource), id);

  ShellSurfaceBase* shell_surface =
      GetShellSurfaceFromPopupResource(surface_resource);

  SetImplementation(aura_popup_resource, &aura_popup_implementation,
                    std::make_unique<AuraPopup>(shell_surface));
}
```
They are added on creating `aura_popup_resource` wl_resouce.  
[`wl_resource_set_implementation`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/wayland-server.c;l=1842;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) adds the implementation to `resource->object`.  

This impl will be refered from client by [`wl_closure_invoke`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/wayland/src/src/connection.c;l=1145;drc=f80633b34538615fcb73515ad8c4bc56a748abfe) as mentioned above.