niri 命名工作区(Named Workspaces)完全指南:静态工作区、绑定窗口与按工作区定制布局 📅 发布时间:2026/9/10 23:07:31 👁 浏览次数: niri 命名工作区Named Workspaces完全指南静态工作区、绑定窗口与按工作区定制布局【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri导读niri 是滚动式平铺scrollable-tilingWayland 合成器其工作区默认是动态的有窗口就存在窗口关完就自动消失。但在很多使用场景下你希望某些工作区常驻——比如永远有一个浏览器工作区、一个聊天工作区即使里面没有窗口也不消失。niri 的**命名工作区Named Workspaces**正是为此设计在配置文件中显式声明、可以绑定到指定输出、可以被按键和窗口规则按名字引用甚至可以为每个命名工作区单独定制一套布局参数。本文将以 docs/wiki/Configuration:-Named-Workspaces.md 为骨架结合 niri-config/src/workspace.rs、src/layout/mod.rs 等源码实现完整讲解命名工作区的声明、行为、动态改名、布局覆盖等全部能力。声明命名工作区命名工作区在配置文件的顶层声明自 niri 0.1.6 起可用。最简形式只需要一个名字workspace browser也可以带选项块指定它初始打开的显示器workspace chat { open-on-output Some Company CoolMonitor 1234 }从源码可以印证这一结构niri-config/src/workspace.rs 中Workspace结构体有三个字段name位置参数字符串、可选的open_on_output子节点字符串、可选的layout子节点布局覆盖块。配置解析由knuffel完成并且其中做了两项关键校验工作区名必须是字符串字面量否则报错 workspace names must be strings工作区名不区分大小写去重——声明两个仅大小写不同的名字如Browser与browser会触发 duplicate named workspace 错误见 niri-config/src/workspace.rs。命名工作区与普通工作区的区别命名工作区与普通动态工作区的根本区别只有一点命名工作区永远存在即使没有窗口。在 src/layout/workspace.rs 中可以看到判定依据has_windows_or_name()一个工作区只要「有窗口」或「有名字」就保留缺一不可时才会被当作空工作区清理。除此之外命名工作区与其他工作区行为完全一致可以移动、可以跨显示器拖拽、可以参与聚焦与切换只是额外多了一个可被引用的名字。这一特性最典型的用途是模拟静态工作区。niri 的 Workspaces.md 文档明确建议创建名为 one、two、three…… 的命名工作区并把按键绑定到focus-workspace one、focus-workspace two……即可得到类似传统静态桌面编号工作区的体验——工作区不会因为清空而消失编号位置稳定。按名字引用按键动作与窗口规则命名工作区的名字可以被两类机制引用按键动作和窗口规则。按键动作中按名字引用focus-workspace、move-column-to-workspace、move-window-to-workspace等动作都接受WorkspaceReference可以按名字、ID 或序号引用。在 niri-config/src/binds.rs 中可以看到相关动作的定义例如binds { ModAlt1 focus-workspace browser ModAltShift1 move-column-to-workspace browser }窗口规则指定窗口固定在某命名工作区打开更有价值的用法是配合open-on-workspace窗口规则让特定应用总在指定工作区打开// 声明一个名为 chat 的工作区初始在 DP-2 输出上打开。 workspace chat { open-on-output DP-2 } // 如果 Fractal 在 niri 启动时运行就把它的窗口放到 chat 工作区。 window-rule { match at-startuptrue app-idr#^org\.gnome\.Fractal$# open-on-workspace chat }其中match at-startuptrue表示该规则只在 niri 启动、应用自启动时生效配合命名工作区先于任何窗口存在的特性可以实现应用一启动就被安放到专属工作区的效果。open-on-output把命名工作区绑定到指定输出open-on-output用于指定命名工作区初始出现在哪块显示器上。它支持两种写法自 0.1.6 起仅支持连接器名connector name例如DP-2自 0.1.9 起还可以使用显示器的制造商、型号、序列号例如Some Company CoolMonitor 1234。从 src/layout/workspace.rs 的实现看输出匹配逻辑output_name.format_make_model_serial_or_connector()会把显示器的「制造商-型号-序列号」或连接器名格式化成可比较的字符串因此两种写法最终都走同一套匹配逻辑。在 src/layout/mod.rs 的ensure_named_workspace中如果配置的open_on_output在当前显示器集合中找不到匹配输出会回退到主显示器primary output而不是报错或丢弃该工作区。25.02 起命名工作区粘住原始输出自 25.02 起命名工作区在其上打开新窗口时不再更新/遗忘自己的原始输出普通工作区仍然会这样。也就是说命名工作区会在更多情况下粘在它原本的输出上这与其更永久的性质相符但显式把命名工作区移动到另一块显示器仍会更新其原始输出。在 src/layout/workspace.rs 可以看到只有当显式移动发生时original_output才会被更新为新输出。初始顺序与配置热重载行为命名工作区初始按配置文件中的声明顺序出现在显示器上且排在顶部。在 niri 运行期间编辑配置并重新加载时新声明的命名工作区会出现在显示器最顶端见 src/layout/mod.rs 中insert_workspace(ws, 0, false)——索引 0 即顶部插入。如果你从配置中删除某个命名工作区声明该工作区会变回普通未命名工作区此时如果它上面没有窗口就会像其他普通工作区一样被自动移除。对应实现可见 src/layout/workspace.rs 的unname()与 src/layout/mod.rs 的清理逻辑。目前没有给已存在的工作区补名字的途径。如果你需要某个已经存在的工作区变成命名工作区正确做法是新建一个空的命名工作区然后把想要的窗口移过去。动态改名set-workspace-name与unset-workspace-name自 25.01 起你可以在运行期动态修改工作区名字把永久工作区的能力从配置期扩展到运行期。binds { // 把当前聚焦的工作区改名为 project ModCtrlN set-workspace-name project // 去掉当前工作区的名字注意拼写为 UnsetWorkSpaceNameByRef ModCtrlShiftN unset-workspace-name }从源码 src/layout/mod.rs 的实现细节可以看到set_workspace_name的几个关键行为若新名字已被其他工作区占用请求会被静默忽略同名保护未指定引用时默认作用于当前聚焦的工作区改名后如果启用了empty-workspace-above-first且该工作区恰好是显示器上第一个会自动在其上方补一个空工作区如果它是最后一个也会自动在下方补一个空工作区维持两端各有空工作区的布局约定。unset_workspace_namesrc/layout/mod.rs则把工作区恢复为普通动态工作区若其上无窗口即被清理。配置绑定定义见 niri-config/src/binds.rs。测试用例 src/layout/tests.rs 中也覆盖了改名与去名的完整流程。提示set-workspace-name的动作名是SetWorkspaceName参数为字符串另有set-workspace-name-by-ref可显式指定引用对象对应unset-workspace-name与unset-workspace-name-by-ref。按工作区覆盖布局配置layout {} 块自 25.11 起命名工作区可以携带一个layout {}块为该工作区单独定制布局参数实现不同工作区不同观感workspace aesthetic { // 仅作用于这个命名工作区的布局覆盖。 layout { gaps 32 struts { left 64 right 64 bottom 64 top 64 } border { on width 4 } // ...任何其他 layout 设置。 } }它接受与顶层 Configuration:-Layout.md 中layout {}完全相同的所有选项包括但不限于gaps、center-focused-column、always-center-single-column、default-column-display、preset-column-widths、default-column-width、preset-window-heights、focus-ring、border、shadow、tab-indicator、insert-hint、struts、background-color等。两个不允许的选项根据 niri-config/src/workspace.rs 中WorkspaceLayoutPart的校验逻辑以下两个顶层layout选项不允许出现在workspace.layout中否则配置解析直接报错empty-workspace-above-first这是输出显示器级别的概念对单个工作区没有意义insert-hint目前插入提示始终在输出级别绘制按工作区定制不会生效因此被禁止。布尔开关的取消写法对于全局已开启的布尔选项想在某个工作区关闭它需要用false显式写出layout { // 全局开启单列始终居中。 always-center-single-column } workspace uncentered { layout { // 在该工作区上取消此开关。 always-center-single-column false } }配置重载时的同步命名工作区的布局覆盖在配置热重载时会同步更新src/layout/mod.rs 的update_config会遍历所有已命名工作区按名字匹配新配置中的对应声明并调用ws.update_layout_config(...)更新其布局参数。从源码看整体工作流把上面内容串起来命名工作区的完整生命周期如下声明配置解析阶段niri-config/src/workspace.rs 校验名字字符串、去重并构建Workspace配置创建niri 启动或配置重载时src/layout/mod.rs 的ensure_named_workspace为每个声明创建真实工作区——按open-on-output找到目标输出找不到回退主输出插入到该输出工作区列表顶部无输出时则放入NoOutputs容器常驻空工作区清理逻辑以has_windows_or_name()为准src/layout/workspace.rs保证命名工作区永不因空而消失引用按键动作、窗口规则通过WorkspaceReference::Name按名字定位工作区src/layout/mod.rs运行期改名set-workspace-name/unset-workspace-name动态增删名字同名请求被拒绝改名同时维护两端空工作区约定src/layout/mod.rs布局定制每个命名工作区可携带layout {}覆盖块重载配置时按名字同步src/layout/mod.rs。相关文档Configuration:-Layout.md顶层layout {}全部选项的完整参考命名工作区的layout块继承其中的所有语义Workspaces.md工作区总体行为与动态工作区说明包含用命名工作区模拟静态工作区的技巧Configuration:-Key-Bindings.mdfocus-workspace、move-column-to-workspace、set-workspace-name等动作的绑定写法Configuration:-Window-Rules.mdopen-on-workspace窗口规则及match at-startup条件Configuration:-Outputs.mdopen-on-output可用的输出标识连接器名/制造商/型号/序列号说明。【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考