在 Wayland 生态系统中,平铺式窗口管理器通常采用传统的网格或栈式布局,而 Niri 作为一款新兴的可滚动平铺(scrollable-tiling)Wayland compositor,以其独特的设计理念脱颖而出。本文基于 Niri 26.04 版本,深入解析其架构设计与渲染管线实现细节。
核心设计理念:无限水平滚动条
Niri 的核心创新在于将每个显示器的窗口排列在一条无限向右延伸的水平条带上。传统平铺管理器在新窗口打开时会触发现有窗口的重新调整大小,而 Niri 彻底避免了这一行为 —— 新窗口的加入永远不会改变现存窗口的尺寸。这种设计模拟了一条传送带:每个窗口占据固定宽度的列,用户通过横向滚动浏览整个窗口序列。
每个显示器拥有独立的窗口条带,窗口永远不会 “溢出” 到相邻显示器上。动态工作区按垂直方向排列,每个显示器维护独立的工作区集合,且最下方始终保留一个空工作区。这种设计确保了多显示器环境下各屏幕的完全独立性,同时支持在显示器断开连接时将其工作区迁移到其他屏幕,重连后又能自动回归原显示器。
技术栈选型:Rust 与 Smithay
Niri 采用 Rust 语言从零构建,这一选择带来了内存安全保证和现代并发原语支持。在 Wayland 协议层面,Niri 深度依赖 Smithay 生态系统 —— 这是 Rust 语言中最重要的 Wayland compositor 库。Smithay 提供了与图形栈交互的基础抽象,使 Niri 能够专注于其独特的布局算法实现。
渲染层面,Niri 同时支持硬件加速的 OpenGL 渲染路径和基于 Pixman 的软件渲染路径。底层使用 DRM/GBM 进行缓冲区管理,通过 EGL 创建渲染上下文。这种双路径支持使得 Niri 能够在从现代游戏主机到老旧上网本的各种硬件上运行。开发者曾在 2008 年的 Eee PC 900 上成功运行 Niri,足以证明其轻量级特性。
渲染管线深度解析
Niri 的渲染管线遵循经典的帧驱动模型。当 GPU 完成上一帧的显示后,系统触发下一帧的渲染流程。具体步骤如下:首先由 VBlank(垂直同步中断)或定时器触发帧更新,此时动画系统计算当前帧的变换参数;随后进入渲染通道,执行表面合成与效果应用;最后将完成的帧提交给 DRM 进行页面翻转。
损坏跟踪(Damage Tracking) 是渲染管线中的关键优化环节。Niri 在表面级别维护损坏区域信息,结合坐标变换和裁剪操作,精确计算需要重绘的区域。这种精细化的损坏跟踪显著降低了每帧的渲染工作量。此外,Niri 尽可能使用 DRM planes 直接扫描输出,绕过合成过程以获得更低的延迟。
在动画系统方面,Niri 支持丰富的视觉效果,包括窗口背景模糊、渐变边框(支持 Oklab 和 Oklch 色域)以及自定义着色器动画。动画更新在每次渲染通道执行前进行,确保状态变更能够及时反映到视觉输出。
多显示器与工作区管理
Niri 从设计之初就将多显示器支持作为核心功能。每个显示器拥有独立的工作区栈和窗口条带,这解决了传统窗口管理器在多屏环境下的坐标空间混乱问题。工作区排列在垂直方向滚动,用户可以通过键盘快捷键或触摸板手势在不同工作区之间切换。
触摸板手势支持是 Niri 的一大特色,用户可以通过自然的手势操作在工作区之间导航或触发概览模式。概览模式能够将所有工作区和窗口缩小显示,方便用户快速定位目标窗口。截屏功能集成在 compositor 内部,支持通过 xdg-desktop-portal-gnome 进行屏幕录制,并能排除敏感窗口的显示。
配置与扩展
Niri 采用声明式配置文件,支持热重载 —— 修改配置后无需重启即可生效。布局参数包括窗口间距、边框样式、支柱(struts)尺寸等,均可通过配置调整。窗口规则系统允许用户针对特定应用程序设置自定义行为,如强制浮动、忽略平铺等。
Xwayland 支持通过 xwayland-satellite 实现,允许运行未针对 Wayland 优化的 X11 应用程序。Niri 还集成了屏幕阅读器无障碍支持,确保视力障碍用户也能正常使用。
性能考量与实践建议
对于计划采用 Niri 的用户,以下几点值得注意:虽然 Niri 设计时考虑了轻量化,但开启大量视觉效果(如模糊、复杂动画)会显著增加 GPU 负载;损坏跟踪虽然能优化渲染,但在极端情况下(如全屏视频播放)可能需要手动调整策略;多显示器环境下,建议为每个显示器独立配置缩放因子,以获得最佳的视觉体验。
Niri 的架构设计体现了对传统平铺窗口管理器的深刻反思 —— 通过将窗口布局从 “空间填充” 思维转向 “无限画布” 思维,为用户提供了一种全新的窗口组织方式。对于追求高效工作流和清晰视觉组织的用户,Niri 提供了一个值得探索的选项。
资料来源:Niri 官方 GitHub 仓库(https://github.com/niri-wm/niri)