niri 深度解析:这款滚动平铺 Wayland 合成器,让新窗口再也不会挤动旧窗口
2026/9/4 12:44:55 网站建设 项目流程

niri 深度解析:这款滚动平铺 Wayland 合成器,让新窗口再也不会挤动旧窗口

【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri

niri 是一款用 Rust 编写的滚动平铺(scrollable-tiling)Wayland 合成器。它的核心机制一句话就能说清:窗口按列排布在一条无限向右延伸的横带上,打开新窗口时,已有窗口一律不改尺寸。下面不急着装环境,先把"它是什么、凭什么值得了解、适合谁"讲明白。

它解决了什么真实痛点

传统平铺窗口管理器有一个长期存在的副作用:每开一个新窗口,整列窗口都要重新计算高度并互相挤压。你在终端里写代码,随手开一个浏览器查文档,原来所有窗口的大小和位置都变了——焦点窗口甚至会自己"动"一下。多窗口重度用户对此的抱怨可以归成一句话:我的窗口为什么自己会动?

niri 的回答是:横向上不再挤压。新窗口作为新的一列出现在带子上,向左右滚动即可看到;需要并排对照的窗口,手动合并进同一列,此时才等分高度。窗口大小只在"你主动决定合并/拆分"时变化,其余时间纹丝不动。

这种思路不是凭空来的:GNOME 扩展 PaperWM、KDE 的 karousel、i3/sway 上的 papersway 都实现过类似工作流,但 niri 是少数从第一天起就把滚动平铺当作核心设计的合成器,而不是在现成桌面环境上打补丁。

心智模型:横带 + 纵向动态工作区

理解 niri,只需要记住两个轴向。

横向是一条无限滚动带:每个显示器拥有独立的窗口带,窗口永远不会"溢出"到隔壁显示器——这是作者写 niri 的直接动机之一,因为作为 GNOME 扩展的 PaperWM 受限于 Shell 的全局坐标空间,很难真正隔离多显示器。

纵向是工作区,但它是动态的,而非传统的"预设 9 个编号桌面":

  • 每个显示器独立拥有一组工作区,垂直排列;
  • 每列工作区的最下方永远留着一个空工作区,窗口开满也不会"无处安放";
  • 中间的空工作区在你切走后自动消失;
  • 断开外接显示器时,它的工作区会迁往其他屏幕,重新接入后又自动迁回。

这套模型带来一个很实际的好处:得益于横向滚动已经能容纳大量窗口,多数人需要的工作区数量比静态桌面少得多。作者自己的习惯是浏览器常驻最上层,每个项目一个工作区,再配合"把工作区上下挪动"把最常用的项贴近焦点。想要更稳定的锚点时,可用命名工作区(named workspace)给工作区起名,之后按名字跳转,且不会因变空而消失。详见 docs/wiki/Workspaces.md。

设计原则:为什么"眼不见为净"是特性而不是偷懒

niri 的 docs/wiki/Development:-Design-Principles.md 把几条硬性原则写在明面上,值得逐条体会:

  1. 打开新窗口不得影响任何已有窗口的尺寸。这是滚动平铺的立身之本。
  2. 焦点窗口不得自行移动。消除"窗口自己会跳"这一平铺管理器的经典槽点。
  3. 所有操作即时生效。不做"延迟确认"式的交互,按键即结果。
  4. 视觉特效关闭时不得拖累性能,开启时也不得过度渲染。动画、模糊、渐变边框都可以整体关掉,桌面回到纯工具状态。

代码层面,布局与窗口的核心逻辑集中在 src/layout/(工作区、列、窗口、滚动、浮动窗口的状态机),配置解析独立成 niri-config/ 子 crate,渲染效果在 src/render_helpers/ 里以着色器方式实现。这种分层让"布局引擎""配置层""渲染层"各自可测,仓库里的快照测试(src/tests/snapshots/)就大量覆盖窗口打开时的全屏/最大化边界组合。

配置哲学:KDL + 热重载 + 一切皆规则

niri 的配置文件~/.config/niri/config.kdl使用 KDL 语法,且保存即生效:键位、输出设置、窗口规则、动画参数全部实时热加载,不需要重启会话。想检查语法,niri validate可以提前解析报错。

几个典型的"规则驱动"能力:

  • layout {}控制间距(gaps)、边框、阴影、焦点环、预设列宽,还可以用struts在屏幕边缘留出固定边距:

  • window-rule {}按应用 ID、标题等条件给单个窗口下指令:初始工作区、默认列宽、全屏、甚至把敏感窗口从屏幕录制中屏蔽;
  • 边框支持 Oklab/Oklch 色彩空间的渐变,窗口与层壳表面支持背景模糊:

  • 全屏与最大化是两种独立状态:最大化让整列占满工作区(同列多窗口共存),全屏则独占整个工作区视图:

进阶玩家还可以关注 docs/wiki/IPC.md:niri 通过 Unix socket 提供 IPC 与事件流(event stream),第三方工具可以订阅"焦点窗口变化""工作区变化"等事件,做状态栏和指示器时不用轮询,这是它作为可编程合成器的重要一环。

三个真实使用场景

场景一:长时间多项目并行开发。编辑器、终端、文档浏览器各占一列,向左右滚动切换;需要并排 diff 时把两个终端合并进同一列。全程窗口不再互相挤动,注意力成本显著降低。

场景二:动态工作区 + 总览视图。按项目切分工作区,用move-workspace-up/down把当前工作区挪到焦点下方,一次按键来回。配合 Overview(可四指上滑或热角落唤起),所有工作区缩成缩略图,直接拖拽窗口跨工作区移动——全程鼠标也能完成。

场景三:窗口标签化。同一列窗口可以切换为标签(tab)显示,多个窗口共享同一尺寸、只占一块空间,适合"多个同类窗口、很少同时看"的情况,比如开着一堆后台下载或聊天窗口。列内还能多标签全屏。

同类工具横向对比

平铺世界里 niri 的定位可以这样概括:

  • sway / i3:经典的静态工作区 + BSP 式平铺,规则严谨、生态成熟,但开新窗即全局重排,且没有滚动布局这一维度(i3 系的 papersway 是社区补丁实现)。
  • Hyprland:高度可定制、动效丰富,内置了滚动布局选项,但滚动平铺不是其默认心智模型,需要额外配置才能接近 niri 的体验。
  • GNOME + PaperWM:在不离开 GNOME 的前提下获得滚动平铺,适合 GNOME 重度用户;缺点是受 Shell 全局坐标空间束缚,多显示器隔离不彻底——这正是 niri 想要正面解决的问题。
  • niri:更激进——从底层把"无限横带 + 动态工作区 + 多显示器完全隔离"作为第一性原理,并原生支持触控板/鼠标手势、Overview、标签列、动态工作区迁移。代价是它不是完整桌面环境,需要搭配状态栏、启动器等组件。

上手建议与进阶方向

入门路径其实很轻:主流发行版已有包(Fedora COPR、Arch 等),装完在登录管理器选 niri 会话即可;没有显示管理器时,在 TTY 里运行niri-session。若从源码构建,仓库地址为 https://gitcode.com/GitHub_Trending/ni/niri ,cargo build --release之后产物在target/release/。注意 niri 本身不带动效完整的桌面壳,社区常见搭配是 Quickshell 类桌面(如 README 提到的 DankMaterialShell、Noctalia)或 LXQt。

完整文档在 docs/wiki/,建议顺序是:Getting-Started → Configuration: Introduction → Configuration: Layout。

进阶方向有三条值得走:一是用命名工作区 +window-rule把常用应用的落点固化下来;二是研究 IPC 事件流,给自己的状态栏或脚本接上实时状态;三是关注动画与自定义着色器(src/render_helpers/shaders/下的开源/关闭/缩放特效链),这是少数把"视觉特效可编程"做到合成器内核层的平铺项目。

结语

niri 值得了解的核心理由,是它对平铺窗口管理器一个老问题的正面回应:窗口不该自己乱动。用"无限横带 + 动态纵向工作区"这套心智模型,它把开窗、切窗、找窗的路径都压短了,同时把多显示器隔离、手势、总览、标签这些体验做进了内核而非补丁。如果你受够了"一开窗口全桌抖",或者一直在 GNOME 之外寻找更顺手的平铺方案,这个项目值得花一个下午认真体验。

【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询