wayland核心协议为wayland/protocol/wayland.xml,其中部分代码如下所示:
<interface name="wl_display" version="1">
<description summary="core global object">
The core global object. This is a special singleton object. It
is used for internal Wayland protocol features.
</description>
<request name="sync">
<description summary="asynchronous roundtrip">
The sync request asks the server to emit the 'done' event
on the returned wl_callback object. Since requests are
handled in-order and events are delivered in-order, this can
be used as a barrier to ensure all previous requests and the
resulting events have been handled.
The object returned by this request will be destroyed by the
compositor after the callback is fired and as such the client must not
attempt to use it after that point.
The callback_data passed in the callback is the event serial.
</description>
<arg name="callback" type="new_id" interface="wl_callback"
summary="callback object for the sync request"/>
</request>
<request name="get_registry">
<description summary="get global registry object">
This request creates a registry object that allows the client
to list and bind the global objects available from the
compositor.
It should be noted that the server side resources consumed in
response to a get_registry request can only be released when the
client disconnects, not when the client side proxy is destroyed.
Therefore, clients should invoke get_registry as infrequently as
possible to avoid wasting memory.
</description>
<arg name="registry" type="new_id" interface="wl_registry"
summary="global registry object"/>
</request>
<event name="error">
<description summary="fatal error event">
The error event is sent out when a fatal (non-recoverable)
error has occurred. The object_id argument is the object
where the error occurred, most often in response to a request
to that object. The code identifies the error and is defined
by the object interface. As such, each interface defines its
own set of error codes. The message is a brief description
of the error, for (debugging) convenience.
</description>
<arg name="object_id" type="object" summary="object where the error occurred"/>
<arg name="code" type="uint" summary="error code"/>
<arg name="message" type="string" summary="error description"/>
</event>
<enum name="error">
<description summary="global error values">
These errors are global and can be emitted in response to any
server request.
</description>
<entry name="invalid_object" value="0"
summary="server couldn't find object"/>
<entry name="invalid_method" value="1"
summary="method doesn't exist on the specified interface"/>
<entry name="no_memory" value="2"
summary="server is out of memory"/>
</enum>
<event name="delete_id">
<description summary="acknowledge object ID deletion">
This event is used internally by the object ID management
logic. When a client deletes an object, the server will send
this event to acknowledge that it has seen the delete request.
When the client receives this event, it will know that it can
safely reuse the object ID.
</description>
<arg name="id" type="uint" summary="deleted object ID"/>
</event>
</interface>
通过wayland自带工具wayland-scanner可以生成wayland-client-protocol.h,wayland-protocol.c,wayland-server-protocol.h三个文件,该工具的具体实现为wayland/src/scanner.c,下面对其实现进行具体分析。
代码中定义了以下几个主要类型:
struct protocol {
char *name;
char *uppercase_name;
struct wl_list interface_list;
int type_index;
int null_run_length;
char *copyright;
struct description *description;
bool core_headers;
};
struct interface {
struct location loc;
char *name;
char *uppercase_name;
int version;
int since;
struct wl_list request_list;
struct wl_list event_list;
struct wl_list enumeration_list;
struct wl_list link;
struct description *description;
};
struct message {
struct location loc;
char *name;
char *uppercase_name;
struct wl_list arg_list;
struct wl_list link;
int arg_count;
int new_id_count;
int type_index;
int all_null;
int destructor;
int since;
struct description *description;
};
enum arg_type {
NEW_ID,
INT,
UNSIGNED,
FIXED,
STRING,
OBJECT,
ARRAY,
FD
};
struct parse_context {
struct location loc;
XML_Parser parser;
struct protocol *protocol;
struct interface *interface;
struct message *message;
struct enumeration *enumeration;
struct description *description;
char character_data[8192];
unsigned int character_data_length;
};
包括协议,接口,消息,参数类型,解析上下文,着重看下接口的定义,其中包含三个wl_list,分别为xml文件中定义的request,event,enum。request为wayland中client端向server端发送的请求,event为wayland中server端向client端发送的事件,event和request都被定义为一种message,enum为协议中定义的enum值。
生成两个头文件的函数为emit_header,其中
printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
printf("#ifndef %s_%s_PROTOCOL_H\n"
"#define %s_%s_PROTOCOL_H\n"
"\n"
"#include <stdint.h>\n"
"#include <stddef.h>\n"
"#include \"%s\"\n\n"
"#ifdef __cplusplus\n"
"extern \"C\" {\n"
"#endif\n\n",
protocol->uppercase_name, s,
protocol->uppercase_name, s,
g