【译】从零开始的 Wayland 合成器 —— 2. 装配服务器
原文链接:Writing a Wayland Compositor, Part 2: Rigging up the server
译者注:这个系列文章中使用的为早期 wlroots 版本,大约在 0.3 到 0.4.1 之间,请注意安装的版本
这是关于使用 wlroots 从头开始编写 Wayland 合成器的系列文章中的第二篇。如果你还没有看过第一篇文章,可以看看。上一次,我们最终得到了一个应用程序,它启动了 wlroots 后端,枚举了输出设备,并在屏幕上绘制了一些漂亮的颜色。今天,我们将开始接受 Wayland 客户端的连接,尽管我们还不打算对它们做什么。
本文剖析的提交是b45c651。
关于这些博客文章的性质,我想说的是:我们将需要大量的文章来充实我们的合成器。我将会比平时更频繁地发布这些文章,大概每周1-2篇,并继续以通常的速度发布我的文章。好吗?很好。
所以我们已经启动了后端,并且正在渲染一些有趣的东西,但是我们仍然没有运行Wayland服务器–Wayland客户端没有连接到我们的应用程序。添加这个其实很容易:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @@ -113,12 +113,18 @@ int main(int argc, char **argv) { server.new_output.notify = new_output_notify; wl_signal_add(&server.backend->events.new_output, &server.new_output); + const char *socket = wl_display_add_socket_auto(server.wl_display); + assert(socket); + if (!wlr_backend_start(server.backend)) { fprintf(stderr, "Failed to start backend\n"); wl_display_destroy(server.wl_display); return 1; } + printf("Running compositor on wayland display '%s'\n", socket); + setenv("WAYLAND_DISPLAY", socket, true); + wl_display_run(server.wl_display); wl_display_destroy(server.wl_display); return 0;
|
这就是了! 如果你再次运行 McWayface,它将打印出这样的东西:
1
| Running compositor on wayland display 'wayland-1'
|
Weston 是 Wayland 的参考合成器,包括一些简单的参考客户端。我们可以使用 weston-info
连接到我们的服务器并列出全局变量:
1 2
| $ WAYLAND_DISPLAY=wayland-1 weston-info interface: 'wl_drm', version: 2, name: 1
|
如果你还记得我的《Wayland 简介》,Wayland 服务器通过 Wayland 注册表向客户端输出了一个全局变量列表。这些全局变量提供了客户端可以用来与服务器互动的接口。我们通过 wlroots 获得了 wl_drm,但我们实际上还没有连接上任何有用的东西。wlroots提供了许多 “类型”,其中大部分是像这样的 Wayland 全局接口的实现。
一些 wlroots 的实现需要你进行一些操纵,但其中有几个是自动搞定的。装配这些东西很容易:
1 2 3 4 5 6 7 8 9 10 11
| printf("Running compositor on wayland display '%s'\n", socket); setenv("WAYLAND_DISPLAY", socket, true); + + wl_display_init_shm(server.wl_display); + wlr_gamma_control_manager_create(server.wl_display); + wlr_screenshooter_create(server.wl_display); + wlr_primary_selection_device_manager_create(server.wl_display); + wlr_idle_create(server.wl_display); wl_display_run(server.wl_display); wl_display_destroy(server.wl_display);
|
请注意,这些接口中的一些并不一定是你通常想要暴露给所有 Wayland 客户端的接口–例如,screenshooter 是应该被保护起来的东西。我们将在后面的文章中讨论安全问题。现在,如果我们再次运行 weston-info,我们会看到更多的全局变量已经出现:
1 2 3 4 5 6 7 8
| $ WAYLAND_DISPLAY=wayland-1 weston-info interface: 'wl_shm', version: 1, name: 3 formats: XRGB8888 ARGB8888 interface: 'wl_drm', version: 2, name: 1 interface: 'gamma_control_manager', version: 1, name: 2 interface: 'orbital_screenshooter', version: 1, name: 3 interface: 'gtk_primary_selection_device_manager', version: 1, name: 4 interface: 'org_kde_kwin_idle', version: 1, name: 5
|
你会发现 wlroots 实现了各种不同来源的协议–在这里我们看到 Orbital、GTK 和 KDE的 协议。wlroots 包括一个 Orbital 屏幕截图的客户端实例–我们现在可以用它来给我们的合成器截个图:
1 2
| $ WAYLAND_DISPLAY=wayland-1 ./examples/screenshot cannot set buffer size
|
啊,这是个问题–你可能已经注意到,我们没有任何 wl_output 的全局变量,屏幕截图客户端依靠它来计算屏幕截图缓冲区的分辨率。我们也可以添加这些:
1 2 3 4 5 6 7
| @@ -95,6 +99,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); + + wlr_output_create_global(wlr_output); }
|
再次运行 weston-info 会给我们提供一些关于我们现在的 output 的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $ WAYLAND_DISPLAY=wayland-1 weston-info interface: 'wl_drm', version: 2, name: 1 interface: 'wl_output', version: 3, name: 2 x: 0, y: 0, scale: 1, physical_width: 0 mm, physical_height: 0 mm, make: 'wayland', model: 'wayland', subpixel_orientation: unknown, output_transform: normal, mode: width: 952 px, height: 521 px, refresh: 0.000 Hz, flags: current interface: 'wl_shm', version: 1, name: 3 formats: XRGB8888 ARGB8888 interface: 'gamma_control_manager', version: 1, name: 4 interface: 'orbital_screenshooter', version: 1, name: 5 interface: 'gtk_primary_selection_device_manager', version: 1, name: 6 interface: 'org_kde_kwin_idle', version: 1, name: 7
|
现在我们可以拍下那张截图了! 给它一个机会(wwwwww)!
我们现在已经接近完成了。下一篇文章将介绍 Surface 的概念,我们将用它们来渲染我们的第一个窗口。如果你在这篇文章中遇到任何问题,请联系我,[email protected],或者联系 wlroots 团队,#sway-devel。
本文及原文使用 CC-BY-SA 协议开放。