Overview === Wayland is a library with some helper programs. The library is linked to by both the client (which typically e.g. wants to draw a window) and the server (aka compositor). In essence, it is an event exchange mechanism. Additionally, wayland can help creating shared memory buffers to exchange bulk data (ie. screen drawings). All events (they are actually called "messages" in wayland, so we'll stick to that terminology) are sent by either the server to the client (this is what wayland calls an "event"), or by the client to the server (a "request" type message). A message is always bound to a wayland "object", which is an opaque wayland concept - for all uses and purposes, you can view it as an ID which you are free to associate to whatever objects your client/server works with. That means that the wayland protocol can be described as an object-oriented event passing library (although that's not entirely accurate, and probably not very helpful either). Other documentation: - [Official wayland docs](http://wayland.freedesktop.org/docs/html/) - [Pekka Paalanen's object lifespan blog post](http://ppaalanen.blogspot.com/2014/07/wayland-protocol-design-object-lifespan.html) - [Jason Ekstrand's wayland language bindings guide](http://www.jlekstrand.net/jason/projects/wayland/language-bindings-guide/) Terminology === - Event: something that's sent from the server to the client - Request: something that's sent from the client to the server - Message: either an event or a request. Always associated to an object (so either a proxy or a resource) - Object: either a wl\_object (no longer used except internally - we won't discuss it further but you may encounter it), or a wl\_proxy (client-side) or a wl\_resource (server-side) - there is a correspondence between wl\_proxy and wl\_resource, for they are both handles to the wayland objects that we don't otherwise have access to. All objects have a type, namely an interface. - Interface: either the protocol specification of an object (for example, there are the interfaces wl\_display, wl\_surface, wl\_keyboard, wl\_seat) (see the XML files) or a callback receiving mechanism on the server side (but luckily, in conversation, this name is not used to refer to those callbacks - they are called implementations) - Protocol: wayland's API consists of a relatively small set of semi-fixed utility functions (wayland-client.h, wayland-server.h, wayland-util.h, wayland-egl.h, wayland-version.h), and a list of interfaces that one can interact with, specified by XML files. E.g., wayland would define a "wl\_pointer" interface with a "motion" event with a "time" argument, and "surface\_x" and "surface\_y" coordinate arguments. - Proxy: the client-side representation of a wayland object - Resource: the server-side representation of a wayland object, but also used to refer to the object that both sides have handles to (ie. as a synonym for "wayland object") - Implementation: the server-side callback mechanism for receiving messages. In particular, a specific instance of callback specifications. - Enum: a list of constants. Used to give semantics to integer message arguments. Sometimes actually an enumeration, sometimes a bitfield, sometimes neither. - Argument: messages can have several bits of data associated with them, which are called arguments. - Listener: either a client-side callback mechanism, or a server-side wl\_listener (which is "primarily" used to receive a signal that objects are destroyed - apparently functionality that you don't really need) - List: a wl\_list or a wl\_array - Event queue: primarily used internally; can't be arsed to understand these. apparently some kind of client-side per-object store of messages that are pending processing - Event loop: either the code you write for a client that loops to process events (using wayland\_display\_dispatch), or a wl\_event\_loop on the server side, which implements the event loop for you (although this loop actually processes _requests_ rather than events, since the incoming messages into the server are _request_ type messages! but "request loop" would be a rather unhelpful name.) - Display: any of the following: the actual physical display, or a wl\_display, which has three strictly distinct flavors: a server side resource, a client side proxy, or a client side C struct which has a display proxy as its first member and is therefore usable as a proxy (the third option being the one that is returned by wl\_display\_connect) - Scanner: A piece of code that generates an API (wayland-server-protocol.h, wayland-client-protocol.h) from the protocol files (wayland.xml). These haskell bindings contain a scanner to generate a haskell API that binds to the C api generated by the wayland scanner. - Callback: either a normal callback into your code (as used in the receiving of messages on either end) or a wl\_callback, which I haven't figured out yet. - ... From here on, "object" refers to a wayland object in the sense of wl\_proxy or wl\_resource. Object creation === To send or receive messages, you have to first construct (on the server side) or request (on the client side) the object for which you want to send or receive messages, since all messages are associated to an object (additionally, on the server side, every object is associated to a client). But on the client side, the way you request objects is by sending the right request messages. So that leaves us with a dependency problem: as a client, how do you request your first object? This is what the Display (wl\_display) object is for: it is an singleton object which you get when you connect to a server (and whereas programs can connect as clients to several servers, yielding several wl\_display objects, creating several servers in the same program is a bit more subtle, and I don't want to get into that). Once you have a wl\_display, you can proceed to request the wl\_registry, which has a "bind" request that can construct all objects which are blessed to be "global" by the "global" event. The arguments to bind define the type of the return value, which is why we bind to it manually. Additionally, it is only known at runtime which objects can be constructed using bind (because they are advertised as such by the "global" event). The reason behind this is: 1. Different compositors implement different protocols, so having a connection does not guarantee that you can create the objects you want; 2. Some objects are associated to others (e.g. surfaces are associated to compositors), and as such may not be created without specifying their associated parent. So the purpose of a "global" event is twofold: the server tells you that it can create such an object, and in addition, that it doesn't require any further arguments (e.g. a parent object). In these bindings, we assume that if there is a way to request an object from another one, then you cannot use wl\_registry.bind, and that if you want to use wl\_registry.bind, you should first wait for the right globals to be available. wl\_display and wl\_registry are the only two protocol interfaces that have a sort of elevated status above the other interfaces: wl\_display is created via a process called "connecting to a server", and a wl\_registry is a sort of superinterface to create all kinds of other objects. I haven't yet figured out what the server side does here exactly. You can create objects using wl\_resource\_create, but to request objects internally, I think you just call your own code (which makes sense), rather than going via wayland. Additionally, presumably to do a wl\_resource\_create, you will need some kind of wl\_proxy to bind it to. IOW I *THINK* that servers are not free to construct wl\_resource instances as they please. As long as the client follows the protocol (ie. only construct objects which the server allowed it to construct), object creation is guaranteed to work. Object destruction === The client and server can both destroy objects: the client using wl\_proxy\_destroy, and the server using wl\_resource\_destroy. Additionally, some interfaces expose a "destroy" request, which, if available, must be used. HOWEVER, servers are not free to destroy whatever they please, for there is no standard way to inform the client that objects no longer exist. Hence, utmost care should be taken when you wish to destroy an object from the server side. Consider refactoring your protocol. Receiving messages === Messages are received on both sides using callbacks. On the client side, these are called when you call wayland\_display\_dispatch: so wayland continuously receives messages in the background, but only passes them to your callbacks when you ask it to. You specify these callbacks using the Listener stuff. Note that you can only set listeners once for every proxy! On the server side, there's a corresponding "interface" api, but the interfaces are also called "implementations" (as in: you specify the callbacks by setting the interface aka implementation), to differentiate from the client-side usage of the word "interface" (as in: a protocol consists of several interfaces). To dispatch your callbacks (ie actually process incoming requests), you call wl\_display\_run, or do some magic with wl\_event\_loops which I haven't figured out yet. Sending messages === Every message has a list of arguments. Every argument has a name and a type. The following types are available: - int, uint, fixed (integer, unsigned integer, float) - object, new\_id - array (which we don't bind to atm) - fd (just an integer) Most types speak for themselves, but the "object" and "new\_id" types need some discussion. Most arguments are sent in the direction of the message itself. However, the new\_id type is used to create or request objects: so a client can get access to an object by sending a request message which has a new_id type argument. Now, note that all objects "exist" at the server side - the wayland protocol simply provides an interface to them for the client. You can get and set its attributes using the various requests and events. When a new\_id argument is present, the request instructs the server to create an object with a given identification. Such creations are guaranteed to work as long as protocol is followed. So this gives the client a handle to an object on the server. Hence, in some sense, this argument flows in the other direction, but only in a semantic way: technically the client just sends a command to create an object to the server, and assumes it worked, but it kind of looks like the client "gets" an object from the server. These bindings can bind messages with a new\_id argument only if they are typed (ie. the type of the returned object is known at compile time). The only known exception is wl\_registry.bind, which has a special purpose anyway, and we'll bind manually. Various quotes from #wayland IRC === Requests are from the client to the server. Events are from the server to the client. there are all kinds of magic interfaces with special status, and stuff that you could have made symmetric between server and client, but didn't the magic interfaces are just wl_display and wl_registry that's it am i right in saying that the only signal emitted by wayland code is the destroy signal, which it emits when any wl_resource is destroyed? tulcod: I think so tulcod: wl_listener is for putting in a wl_signal (which we use for lots of stuff inside weston) whereas the interface has a bunch of different callbacks with different signatures each for a different event (client-side) or request (server-side) does that mean that except for the "destroy" stuff, the entire wl_signal and wl_listener API is a convenience for the user, and nohting to do with wayland? whereas interfaces (aka implementations?) are just the server-side way to receive events from a client? ie the wl_signal and wl_listener stuff is intended to exchange events /within the server/, instead of between the server and client? pretty much libwayland may use signals internally for some things too (I don't remember) but you can implement a wayland server without ever using one. so if i want to bind to wayland, do i bind to wl_listener at all? would a minimal API include it? tulcod: No, it's not needed. You may find it useful, but you can get along without it just fine. It's a convenience to know when a resource is destroyed. If you are wrapping the library, you know when a resource is destroyed, because somebody called the destroy function. "As all requests and events are always part of some interface (like a member of a class), this creates an interface hierarchy. For example, wl_compositor objects are created from wl_registry, and wl_surface objects are created from wl_compositor." so what if i use wl_registry.bind to create a wl_surface? tulcod: i'm not sure what will happen exactly but it won't work, as there is no wl_surface global. probably you'll get a protocol error oh, non sequitur, by the way giucam: but "Object creation never fails." tulcod: i don't think that applies to globals binding a global can fail, and the server will create a dummy wl_resource, send an error and destroy it ah, so it can fail, it's just that it tells you afterwards ie it tells you if it failed, or doesn't tell you anything if it succeeded but i'm not sure what wl_registry.bind returns if it fails i.e if it is a valid proxy, and what happens if you call a request on it probably fails in a non-destructive way tulcod, all requests always "succeed" - if they don't, you violated the protocol. tulcod, did you already notice that there are at least three different wl_display structs? server-side wl_display (opaque), client-side wl_display (opaque), and the wl_proxy cast to wl_display IIRC the first member of client wl_display is a wl_proxy so it's interchangeable tulcod, btw. another thing you should be wary with is wl_buffer. tulcod, again, the client-side wl_buffer is a wl_proxy. The server-side is the tricky one. pq: ah, but the server-side one is deprecated :) I wonder if wl_resource_destroy_func_t is needed for set_implementation calls which interface already contains destroy function yes, they serve different purposes The one on the interface lets you know that the client has sent the destroy request The wl_resource_destroy_func_t lets you know that the object has been destroyed and lets you clean stuff up. This happens to all the resources when the client disconnects. Cloudef: you mean "interfaces which have a 'destroy' request" ? tulcod: yes ok yes, then i agree with jekstrand jekstrand: on which function I should actually free the resource? weston seems to do this on the interface one (and on the other one too) (fwiw, it's no problem to free twice) Cloudef: You need to call wl_resource_destroy in the interface one. wl_resource_destroy calls th wl_resource_destroy_func_t one. Cloudef: If you're familiar with C++, wl_resource_destroy is like "delete res" whereas the wl_resource_destroy_func_t is like MyThing::~MyThing() why those two are separate is because wl_resource_destroy may end up called also at other times, namely when cleaning up state after a client disconnection. the interface one is just a request, that's all. there's no implicit destruction of resources. ..except on the client side, so the server side cannot really not do it, too since server and client must agree on what objects exist yup when we say that an object is a singleton, we usually mean the real object, not the protocol object jekstrand: uhm, so let's suppose the client has a wl_shell_surface jekstrand: and the server, for whatever reason, destroys it what am i missing? can't the client keep the handle to that non-existent object? the server can't just up and destroy it that's a broken server. Clients shouldn't handle that case. jekstrand: okay, so compositors can't freely destroy stuff? nope If compositors were allowed to add-hock destroy client's objects, that would result in insanity RE: Object destruction: A better way to think about the object lifecycle is that the client manages (creates/destroys) objects. The special cases of server-destroyed objects isn't so much the server destroying things as objects getting "automatically" destroyed because it's clear that they're no longer needed (such as when a wl_callback is finished.) The server simply storres them.