协议部分:
1.
2.
wayland协议会将此interface的名称的同名结构体指针默认当做第一个参数(以后不在赘述)
(
wl_display 为同名结构体
在wayland-client.c 文件中定义
struct wl_display {
struct wl_proxy proxy;
struct wl_connection *connection;
......
pthread_cond_t reader_cond;
};
)
request:可被直接调用的函数,函数名称:sync,最终生成函数:wl_display_sync
arg 标签一般为参数加入type="new_id" 就变成了返回值,name="callback" 返回值,
interface="wl_callback" 返回类型struct wl_callback *。
最终结果为(wayland-client-protocol.h)
static inline struct wl_callback *
wl_display_sync(struct wl_display *wl_display)
{
struct wl_proxy *callback;
callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
WL_DISPLAY_SYNC, &wl_callback_interface,
wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
return (struct wl_callback *) callback;
}
3.
同上分析
最终结果为(wayland-client-protocol.h)
static inline struct wl_registry *
wl_display_get_registry(struct wl_display *wl_display)
{
struct wl_proxy *registry;
registry = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
WL_DISPLAY_GET_REGISTRY, &wl_registry_interface,
wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
return (struct wl_registry *) registry;
}
4.
event:最终被以ffi_call触发的事件,同一接口内的event,被注册成一个listener结构体,赋值到object.implementation。
(
wayland-client-protocol.h
struct wl_display_listener {
void (*error)(void *data,
struct wl_display *wl_display,
void *object_id,
uint32_t code,
const char *message);
void (*delete_id)(void *data,
struct wl_display *wl_display,
uint32_t id);
};
static const struct wl_display_listener display_listener = {
display_handle_error, // (绑定的函数)
display_handle_delete_id // (绑定的函数)
};
wl_display_connect_to_fd(wayland-client.c)函数内
display->proxy.object.implementation = (void(**)(void)) &display_listener;
)
被触发时函数调用顺序为:
客户端调用(simple-im.c等客户端)
-->wl_display_dispatch(wayland-client.c)
-->wl_display_dispatch_queue(wayland-client.c)
-->wl_display_dispatch_queue_pending(wayland-client.c)
-->dispatch_queue(wayland-client.c)
-->dispatch_event(wayland-client.c)
-->wl_closure_invoke(connection.c)
-->ffi_call(connection.c)
5.
枚举类型
枚举值为 wl_display_error+invalid_object --> wl_display_error_invalid_object
最终结果为(wayland-server-protocol.h)
enum wl_display_error {
/**
* server couldn't find object
*/
WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
/**
* method doesn't exist on the specified interface or malformed request
*/
WL_DISPLAY_ERROR_INVALID_METHOD = 1,
/**
* server is out of memory
*/
WL_DISPLAY_ERROR_NO_MEMORY = 2,
/**
* implementation error in compositor
*/
WL_DISPLAY_ERROR_IMPLEMENTATION = 3,
};
二,wl_registry
协议部分:
1.
2.
request:可被直接调用的函数,函数名称:bind,最终生成函数:wl_registry_bind
arg 标签一般为参数加入type="new_id" 就变成了返回值,name="id" 返回值。
第一个参数为 struct wl_registry *wl_registry,第二个参数为uint32_t name。
(wl_registry 接口被特殊处理,多加了两个参数)
最终结果为(wayland-client-protocol.h)
static inline void *
wl_registry_bind(struct wl_registry *wl_registry, uint32_t name, const struct wl_interface *interface, uint32_t version)
{
struct wl_proxy *id;
id = wl_proxy_marshal_flags((struct wl_proxy *) wl_registry,
WL_REGISTRY_BIND, interface, version, 0, name, interface->name, version, NULL);
return (void *) id;
}
3.
event:最终被以ffi_call触发的事件,同一接口内的event,被注册成一个listener结构体,赋值到object.implementation。
(
wayland-client-protocol.h
struct wl_registry_listener {
void (*global)(void *data,
struct wl_registry *wl_registry,
uint32_t name,
const char *interface,
uint32_t version);
void (*global_remove)(void *data,
struct wl_registry *wl_registry,
uint32_t name);
};
static const struct wl_registry_listener registry_listener = {
registry_handle_global, // (绑定的函数)
registry_handle_global_remove // (绑定的函数)
};
各个客户端测试程序中的如下代码
wl_registry_add_listener(display->registry,®istry_listener, display);
最终赋值调用到如下函数赋值给proxy->object.implementation调用如下函数
wl_registry_add_listener-->wl_proxy_add_listener
wl_proxy_add_listener(struct wl_proxy *proxy,
void (**implementation)(void), void *data)
{
if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
wl_abort("Proxy %p is a wrapper\n", proxy);
if (proxy->object.implementation || proxy->dispatcher) {
wl_log("proxy %p already has listener\n", proxy);
return -1;
}
proxy->object.implementation = implementation;
proxy->user_data = data;
return 0;
}
)
被触发时函数调用顺序为如上描述
其他接口可按上述描述分析