wayland client surface窗口创建基本流程

本人博客已经迁移到nasdaqgodzilla.github.io

步骤

  1. client通过wl_display_connect连接到wayland server并且得到wl_display
  2. client通过wl_display_get_registry即可获取到server提供的所有基本接口(如wl_xxxx)和wayland协议接口(如xdg等协议定义的接口)。client根据自己需求来绑定这些接口,这些接口绑定后,client即可调用这些接口,以此来与server交互。
  3. 在client对server接口的绑定中,其中一些基本接口是必须绑定的,比如wl_compositor、负责接收事件的wl_seatwl_outputwl_shellzwp_linux_dmabuf等等。还有一些是可以选择性使用的与wayland协议(如xdg、remote_shell等等)相关的接口。假如需要使用xdg_shell做窗口管理,如设置标题、窗口名称等,就需要用上该接口(wayland本身不会提供,一般都是采用协议接口来实现)。
  4. 通过wl_registry_bind绑定接口、注册回调函数后,接下来就是通过wl的基本接口请求server创建surface(即窗口的内容),并且通过刚刚绑定的协议接口来进行窗口管理,如设置标题、控制最大化最小化。
  5. 创建窗口的前一步骤是准备好窗口内容的buffer。通过绑定的zwp_linux_dmabuf服务提供的接口zwp_linux_dmabuf_v1_create_params来创建buffer。也可以通过wl_shmwl_shm_pool创建wl_buffer
  6. 通过wl_compositor_create_surface创建surface,此时server端已经开始处理并显示这个窗口了。通过wl_surface_attach将buffer绑定到surface,通过wl_surface_damage刷新窗口,wl_surface_commit将双缓冲buffer提交。
  7. wl_surface只是窗口的画面,实际上还不是完整的窗口,相比普通的窗口它还缺少标题栏等ui decoration。通过wl_shell_get_shell_surface创建shell_surface,它能够为surface创建一个窗口,让它拥有标题栏。

基本接口和协议接口

基本接口诸如wl_shellwl_surface等是wayland自带的接口,client只要使用这有限的接口就能通过server显示出画面。而wayland还支持很多的协议包括处于通用级别的xdg协议。这个协议提供的接口能让你干更多窗口管理相关的内容,如设置标题栏,处理放大、缩小请求等等。因此,显示内容仅依靠基本接口即可实现,实现窗口管理还需要看server支持的协议接口,client通过对server的协议接口的绑定和调用完成窗口管理。

好的,以下是一个简单的示例代码,用于在Wayland环境下创建一个简单的桌面: ``` #include <wayland-client.h> #include <wayland-egl.h> #include <wayland-cursor.h> #include <wayland-client-protocol.h> #include <wayland-xdg-shell-client-protocol.h> static struct wl_display *display; static struct wl_registry *registry; static struct wl_compositor *compositor; static struct xdg_wm_base *wm_base; static struct wl_surface *surface; static struct xdg_surface *xdg_surface; static struct xdg_toplevel *xdg_toplevel; static void registry_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4); } else if (strcmp(interface, "xdg_wm_base") == 0) { wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); } } static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t id) { // do nothing } static const struct wl_registry_listener registry_listener = { registry_global, registry_global_remove }; int main(int argc, char *argv[]) { // connect to the Wayland display server display = wl_display_connect(NULL); if (display == NULL) { fprintf(stderr, "Failed to connect to Wayland display\n"); return -1; } // get the registry object registry = wl_display_get_registry(display); if (registry == NULL) { fprintf(stderr, "Failed to get Wayland registry\n"); wl_display_disconnect(display); return -1; } // add listener for registry events wl_registry_add_listener(registry, &registry_listener, NULL); // roundtrip to get global objects wl_display_roundtrip(display); if (compositor == NULL || wm_base == NULL) { fprintf(stderr, "Failed to get required Wayland objects\n"); wl_registry_destroy(registry); wl_display_disconnect(display); return -1; } // create a Wayland surface surface = wl_compositor_create_surface(compositor); if (surface == NULL) { fprintf(stderr, "Failed to create Wayland surface\n"); wl_registry_destroy(registry); wl_display_disconnect(display); return -1; } // create an xdg surface xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, surface); if (xdg_surface == NULL) { fprintf(stderr, "Failed to create xdg surface\n"); wl_registry_destroy(registry); wl_display_disconnect(display); return -1; } // create an xdg toplevel xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); if (xdg_toplevel == NULL) { fprintf(stderr, "Failed to create xdg toplevel\n"); wl_registry_destroy(registry); wl_display_disconnect(display); return -1; } // set the window title xdg_toplevel_set_title(xdg_toplevel, "My Wayland Desktop"); // set the window size xdg_toplevel_set_min_size(xdg_toplevel, width, height); xdg_toplevel_set_max_size(xdg_toplevel, width, height); // show the window wl_surface_commit(surface); xdg_toplevel_set_active(xdg_toplevel); // enter the Wayland event loop while (wl_display_dispatch(display) != -1) { // do nothing } // cleanup xdg_toplevel_destroy(xdg_toplevel); xdg_surface_destroy(xdg_surface); wl_surface_destroy(surface); wl_registry_destroy(registry); wl_display_disconnect(display); return 0; } ``` 这段代码使用Wayland的 Compositor 和 XDG Shell 协议来创建一个简单的窗口,并设置窗口的标题和大小,最后进入 Wayland 的事件循环。需要注意的是,这只是一个简单的示例代码,实际的桌面程序可能需要更复杂的功能和交互方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值