weston 3: wayland协议分析
创始人
2025-05-29 11:05:09

 以下为个人工作阶段性总结,如有错误概不负责。

一,wl_display

协议部分:


1.

  接口名称:wl_display,版本:1

2.


   

    
   
        summary="callback object for the sync request"/>

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.

 
   
   
   

        summary="global registry object"/>

同上分析

最终结果为(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.


   
   

            summary="server couldn't find object"/>
            summary="method doesn't exist on the specified interface or malformed request"/>
            summary="server is out of memory"/>
            summary="implementation error in compositor"/>

枚举类型

枚举值为 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.

  接口名称: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;
}

)

被触发时函数调用顺序为如上描述

其他接口可按上述描述分析

相关内容

热门资讯

2025新版教程“欢乐五张到底... 亲,欢乐五张这款游戏可以开挂的,确实是有挂的,很多玩家在这款游戏中打牌都会发现很多用户的牌特别好,总...
2025新版教程“万博体育到底... 无需打开直接搜索微信:万博体育有挂吗本司针对手游进行,选择我们的四大理由:1、软件助手是一款功能更加...
2025新版教程“南通情怀到底... 2025新版教程“南通情怀到底是不是有挂”确实真的有挂(详细教程)是一款可以让一直输的玩家,快速成为...
2025新版教程“太仓麻将到底... 无需打开直接搜索微信:太仓麻将有挂吗本司针对手游进行,选择我们的四大理由:1、软件助手是一款功能更加...
2025新版教程“新乐游戏到底... 您好,新乐游戏这款游戏可以开挂的,确实是有挂的,通过微信【8198015 】很多玩家在这款游戏中打牌...