开发日志
Wayland 协议基础:不是 X11 的替代品,是完全不同的模型
很多人把 Wayland 理解成”更快的 X11”,这个理解会让后面所有细节都变得费解。 Wayland 不是 X11 的性能优化版,是彻底不同的架构:谁负责画像素,这件事换了人。
X11 的模型:服务器画一切
X11 里,X server 是一个真正的”服务器”——它管理一块共享的屏幕缓冲区,客户端发
绘图指令(画线、画矩形、贴图)过去,服务器负责实际画到屏幕上。窗口管理器、
合成器都是跑在服务器”上面”的普通客户端,通过一堆扩展协议(XComposite、
XDamage、XRandR……)互相打配合。这套东西三十多年积累下来极其灵活,但也极其
复杂——很多现代效果(毛玻璃、精确的帧率控制)都是在这套本不是为它们设计的架构上
“叠”出来的。
Wayland 的模型:客户端自己画,合成器只管拼
Wayland 把”画像素”这件事直接交还给客户端:每个应用自己用 EGL/Vulkan 把内容渲染
到一块缓冲区(wl_buffer),然后把这块缓冲区”提交”给合成器。合成器不再解释绘图
指令,它只做一件事——把所有客户端提交的缓冲区按正确的顺序、位置合成到屏幕上。
这个模型下,合成器 = 窗口管理器 = 显示服务器,是同一个进程。这也是为什么 Wayland 下没有独立的”X server”概念,Hyprland、Sway、GNOME Mutter、KDE KWin……这些既是合成器也是桌面环境的核心。
核心协议对象
Wayland 协议本身是一套基于 XML 定义、wayland-scanner 生成 C 代码的 RPC 系统。
最基础的几个对象:
wl_display — 客户端与合成器连接的入口wl_registry — 全局对象注册表,客户端通过它发现合成器支持哪些协议wl_compositor — 创建 wl_surface 的工厂wl_surface — 一块"表面",客户端往上面贴 wl_bufferwl_seat — 输入设备的抽象(键盘/鼠标/触摸)一个最小的客户端连接骨架大概是这样:
struct wl_display *display = wl_display_connect(NULL);struct wl_registry *registry = wl_display_get_registry(display);
struct wl_compositor *compositor = NULL;struct wl_registry_listener listener = { .global = registry_handle_global, // 回调里按 interface 名字匹配感兴趣的全局对象};wl_registry_add_listener(registry, &listener, &compositor);wl_display_roundtrip(display); // 阻塞直到拿到所有 global 通告
// 到这里 compositor 应该已经在回调里被赋值了struct wl_surface *surface = wl_compositor_create_surface(compositor);注意这里的异步风格:wl_registry 通告全局对象是靠事件回调,不是同步返回值——
Wayland 协议整体是请求(client → compositor)和事件(compositor → client)
双向异步的模型,这也是为什么几乎没人手写裸协议客户端,都是用 libwayland 或者更
高层的工具包(GTK、Qt、wlroots)。
光有 wl_surface 还画不出一个”窗口”
这是初学者常见的困惑点:wl_surface 只是一块能贴缓冲区的表面,连”这是不是一个
应用窗口”、“标题栏""最大化/最小化”这些概念核心协议里根本没有定义。这些是靠
扩展协议(extension protocol)加上去的,最重要的是 xdg-shell:
xdg_wm_base — 工厂对象xdg_surface — 包一层 wl_surface,赋予"这是一个桌面用途的表面"的语义xdg_toplevel — 具体到"这是一个可以被最大化/移动/关闭的顶层窗口"也就是说,一个真正意义上的”应用窗口”,在协议层面是
wl_surface + xdg_surface + xdg_toplevel 三层对象组合出来的,任何一层不对
都拿不到期望的窗口行为。这种”核心协议极简 + 能力靠扩展协议叠加”的设计,也是
Wayland 相对 X11 更容易演进的原因——加新能力不需要改核心协议,加一个新的扩展
XML 定义就行。
为什么切换成本这么高
理解了这个模型就能理解为什么从 X11 迁移到 Wayland 花了十几年:那些依赖”服务器 能看到/能改所有客户端像素”的功能(全局按键抓取、任意窗口截图、某些远程桌面方案、 老式的输入法框架)在 Wayland 下都必须重新设计——不是实现细节的调整,是因为这个 模型下合成器故意不给客户端这种越界的能力,这是安全设计上的收益,也是兼容性上的 代价。