3. Wayland架构解析

Wayland 并不是一个“新的图形服务器”,而是一套显示服务器协议加上其参考实现。理解 Wayland 的关键,是把它看成“客户端与合成器之间的一份通信契约”:客户端不再直接操作显卡和输入设备,而是通过协议请求合成器代为完成窗口合成、输入分发与缓冲区上屏。本节围绕协议、合成器、客户端-服务器模型、与 X11 的根本区别,以及 Surface、Seat、Output、Buffer 四个核心概念展开。

一、核心原理:协议 + 合成器 + 客户端-服务器模型

Wayland 架构由三部分组成:Wayland 协议定义对象、请求(request)和事件(event);合成器(Compositor)是服务器端,负责管理输出、输入、窗口与缓冲区合成;客户端是应用程序,通过 Unix 域套接字连接合成器,创建 Surface、提交 Buffer、接收输入事件。

与 X11 的“客户端-服务器 + 窗口管理器”分层不同,Wayland 把窗口管理、合成、输入分发统一收进合成器。合成器既是显示服务器,也是窗口管理器,还是合成引擎。这种“三合一”设计减少了中间层,使每一帧的路径更短,但也意味着合成器承担了更多职责。

一句话理解:X11 是“客户端画到服务器,窗口管理器再管窗口”;Wayland 是“客户端把 Buffer 交给合成器,合成器直接合成上屏”。

二、Wayland 协议与通信模型

Wayland 协议基于对象模型:客户端连接后获得 wl_display 对象,通过它获取 wl_registry,再绑定 wl_compositor、wl_shm、wl_seat、wl_output 等全局对象。每个对象都有接口、请求和事件。客户端发送请求,合成器回送事件,形成双向异步通信。

# 查看当前 Wayland 会话信息
echo $XDG_SESSION_TYPE        # wayland
echo $WAYLAND_DISPLAY         # wayland-0
ls -l $XDG_RUNTIME_DIR/wayland-0

# 查看合成器暴露的全局对象(需安装 wayland-utils)
wayland-info | head -40

协议本身不规定合成策略,只规定“怎么问、怎么答”。因此 Weston、Mutter、KWin、Sway、Hyprland 等合成器可以有不同的窗口管理行为,但都遵循同一套协议。这也是 Wayland 生态“协议统一、实现多样”的根源。

三、与 X11 的根本区别

X11 的架构中,X Server 负责显示和输入,窗口管理器(如 Mutter、KWin)作为独立客户端运行,合成器(Compositor)又是另一个可选组件。Wayland 把这三者合并,带来几个根本差异:

  • 渲染路径:X11 客户端通过 X 协议绘制到 X Server;Wayland 客户端直接渲染到 Buffer,再交给合成器合成。
  • 输入处理:X11 由 X Server 分发到窗口;Wayland 由合成器根据焦点和 Surface 层级分发。
  • 窗口管理:X11 依赖外部 WM;Wayland 由合成器内置窗口管理逻辑。
  • 安全模型:X11 客户端可截屏、注入输入;Wayland 默认隔离,需通过 portal 授权。
  • 同步机制:X11 依赖 XSync 等机制;Wayland 使用 frame callback 与 buffer release 事件。
对比维度X11Wayland
服务器角色X Server 负责显示与输入合成器负责显示、输入与合成
窗口管理独立 WM 客户端合成器内置
渲染方式X 协议绘制命令客户端渲染 Buffer 提交
输入分发X Server 按窗口分发合成器按焦点与 Surface 分发
安全隔离弱,客户端可全局访问强,默认隔离,需 portal
同步机制XSync / 事件队列frame callback / buffer release

四、核心概念:Surface、Seat、Output、Buffer

这四个概念是理解 Wayland 的“最小词汇表”:

  • Surface:一块可绘制的矩形区域,是窗口、子窗口、光标、弹窗的抽象。客户端在 Surface 上提交 Buffer,合成器决定它显示在屏幕的哪个位置。
  • Seat:一组输入设备的集合,代表“用户输入能力”。一个 Seat 可包含键盘、指针、触摸。客户端通过 wl_seat 获取输入事件。
  • Output:一个显示输出,如 HDMI 显示器、笔记本内屏。客户端通过 wl_output 获知分辨率、刷新率、缩放比例和物理尺寸。
  • Buffer:客户端渲染好的像素数据,通常通过 wl_shm(共享内存)或 DMA-BUF 提交。合成器读取 Buffer 并合成到最终画面。
记忆技巧:Surface 是“画布”,Buffer 是“画布上的像素”,Seat 是“输入手”,Output 是“显示器”。客户端画好 Buffer,贴到 Surface,合成器把它放到 Output 上,Seat 把输入事件送回客户端。

五、案例场景:一个窗口从创建到上屏

假设一个 Wayland 客户端要显示一个 800×600 的窗口,典型流程如下:

  1. 连接 wl_display,获取 wl_registry,绑定 wl_compositor、wl_shm、wl_seat、wl_output。
  2. 通过 wl_compositor.create_surface() 创建 Surface。
  3. 通过 wl_shm.create_pool() 创建共享内存池,分配 Buffer。
  4. 将 Buffer 附加到 Surface,调用 commit() 提交。
  5. 合成器收到提交,进行合成,并在下一帧通过 frame callback 通知客户端。
  6. 客户端收到 frame callback 后,渲染下一帧,再次提交 Buffer。
  7. Seat 将键盘、鼠标事件发送给客户端,客户端更新界面并重新提交。

这个流程中,客户端不直接访问显卡,也不直接读取输入设备,所有交互都通过协议完成。合成器负责决定窗口位置、层级、缩放和最终合成。

六、误区与复盘

常见误区:“Wayland 就是 Weston。” 实际上 Weston 只是参考合成器,Mutter、KWin、Sway、Hyprland 都是 Wayland 合成器。协议是统一的,实现是多样的。

另一个误区是“Wayland 不需要窗口管理器”。实际上窗口管理逻辑被内置到合成器中,只是不再以独立进程存在。还有开发者认为“Wayland 不能截屏”,实际上通过 xdg-desktop-portal 和 PipeWire,Wayland 可以实现安全的屏幕共享与截屏。

复盘来看,Wayland 架构的核心变化是职责合并与安全隔离:合成器统一管理显示、输入与合成,客户端只负责渲染自己的 Buffer。理解 Surface、Seat、Output、Buffer 四个概念,就能读懂大多数 Wayland 客户端与合成器的交互代码。

Wayland 架构:协议、合成器与核心概念 Wayland 协议 对象 · 请求 request · 事件 event 合成器 Compositor(服务器) 窗口管理 输入分发 合成上屏 Buffer 管理 Weston / Mutter / KWin / Sway / Hyprland 客户端 Client(应用程序) 渲染 Buffer 创建 Surface 提交 commit 处理输入事件 GTK / Qt / SDL / 自研客户端 请求 事件 四个核心概念 Surface 可绘制矩形区域 窗口 / 子窗口 / 光标 弹窗 / 菜单 Seat 输入设备集合 键盘 / 指针 / 触摸 焦点与事件分发 Output 显示输出 分辨率 / 刷新率 缩放 / 物理尺寸 Buffer 像素数据 wl_shm / DMA-BUF 提交与释放 客户端渲染 Buffer → 附加到 Surface → 提交给合成器 → 合成到 Output;Seat 负责输入事件回传