ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

niri 图层规则(Layer Rules)完全指南:精确掌控 layer-shell 表面的外观与行为

2026/9/10 22:48:51 拓冰建站 浏览量
niri 图层规则(Layer Rules)完全指南:精确掌控 layer-shell 表面的外观与行为 niri 图层规则Layer Rules完全指南精确掌控 layer-shell 表面的外观与行为【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri图层规则Layer Rules是 niri 可滚动平铺 Wayland 合成器提供的一套针对 layer-shell 表面的动态配置机制让你可以按命名空间namespace、启动时机与所在图层为 Waybar、mako、fuzzel、swaybg 等栏、通知、启动器和壁纸工具逐表面定制不透明度、阴影、圆角、背景特效与截屏屏蔽等行为。读完本文你将掌握 layer rules 的全部匹配器与属性语法理解它们与窗口规则window rules的异同并能结合源码了解规则是如何被解析、合并与实时应用到底层渲染管线的。图层规则自 niri 25.01 起提供核心定义位于 niri-config/src/layer_rule.rs规则的实际解析与合并逻辑在 src/layer/mod.rs渲染阶段的应用则在 src/layer/mapped.rs。概述图层规则与窗口规则的关系图层规则允许你针对单个 layer-shell 表面调整行为。它拥有match和exclude指令用来控制规则应作用于哪些 layer-shell 表面以及一系列可以设置的属性properties。从实现上看LayerRule与窗口规则结构高度同构但匹配器和属性不同// niri-config/src/layer_rule.rs #[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)] pub struct LayerRule { #[knuffel(children(name match))] pub matches: VecMatch, #[knuffel(children(name exclude))] pub excludes: VecMatch, #[knuffel(child, unwrap(argument))] pub opacity: Optionf32, #[knuffel(child, unwrap(argument))] pub block_out_from: OptionBlockOutFrom, #[knuffel(child, default)] pub shadow: ShadowRule, #[knuffel(child)] pub geometry_corner_radius: OptionCornerRadius, #[knuffel(child, unwrap(argument))] pub place_within_backdrop: Optionbool, #[knuffel(child, unwrap(argument))] pub baba_is_float: Optionbool, #[knuffel(child, default)] pub background_effect: BackgroundEffectRule, #[knuffel(child, default)] pub popups: PopupsRule, }规则的匹配逻辑与窗口规则的处理方式非常相似——如果你还不熟悉匹配matching如何工作建议先阅读 窗口规则 wiki 页面。从源码可以确认两者的解析都通过 knuffel 配置解析器完成并采用同样的match/exclude语义。下面是图层规则可以使用的全部匹配器与属性一览layer-rule { match namespacewaybar match at-startuptrue match layertop // Properties that apply continuously. opacity 0.5 block-out-from screencast // block-out-from screen-capture shadow { on // off softness 40 spread 5 offset x0 y5 draw-behind-window true color #00000064 // inactive-color #00000064 } geometry-corner-radius 12 place-within-backdrop true baba-is-float true background-effect { xray true blur true noise 0.05 saturation 3 } popups { opacity 0.5 geometry-corner-radius 6 background-effect { xray true blur true noise 0.05 saturation 3 } } }Layer Surface 匹配Matchingmatch与exclude内部的字段统称匹配器。在 src/layer/mod.rs 的ResolvedLayerRules::compute中规则按顺序处理当matches为空或其中任意一个匹配器命中、且所有excludes都未命中时该规则才被应用。属性按规则书写顺序逐个合并后写的规则可以覆盖或叠加先写的值。namespace这是一个正则表达式只要能在表面命名空间surface namespace的任意位置匹配上即可。支持的语法与 Rust 的regexcrate 一致。// 匹配 namespace 中包含 waybar 的表面 layer-rule { match namespacewaybar }要查看所有已打开 layer-shell 表面的命名空间运行niri msg layers该命令会列出所有 layer-shell 表面及其 namespace方便你为某个具体的栏、通知或启动器编写精确的规则。at-startup可以取true或false。当取值为true时只在niri 启动后的前 60 秒内匹配取false则相反只在启动阶段之外匹配。在源码中这个判断由is_at_startup标志驱动见src/layer/mod.rs中的matches闭包与窗口规则的at-startup语义一致。// 让所有 layer-shell 表面在 niri 启动时以 0.5 不透明度显示之后恢复正常 layer-rule { match at-startuptrue opacity 0.5 }layer自版本 26.04 起可用匹配位于某个 layer-shell 图层layer上的表面。可选值为background、bottom、top或overlay。源码中的对应关系为// src/layer/mod.rs Layer::Background niri_ipc::Layer::Background, Layer::Bottom niri_ipc::Layer::Bottom, Layer::Top niri_ipc::Layer::Top, Layer::Overlay niri_ipc::Layer::Overlay,// 让所有 overlay 图层的表面 FLOAT 起来 layer-rule { match layeroverlay baba-is-float true }由于一个layer-rule块内可以书写多个match而命中规则是“任一匹配器命中即可”因此你可以用多个match layer...一次性覆盖多个图层例如后面background-effect一节的示例。动态属性Dynamic Properties以下属性持续作用于已经打开的 layer-shell 表面而不是仅在表面创建时生效一次。当规则匹配条件随时间变化例如at-startup窗口结束或配置被重新加载时recompute_layer_rules会重新计算解析结果并触发重绘见 src/layer/mapped.rs 的recompute_layer_rules与ResolvedLayerRules::compute。block-out-from你可以把某些表面从 xdg-desktop-portal 的 screencast屏幕录制或所有屏幕捕获中屏蔽掉被屏蔽的表面会在录制画面中替换为纯黑色矩形。这对通知等敏感内容尤其有用。与窗口规则中的block-out-from有相同的注意事项和配置方法详见 窗口规则中的block-out-from一节。// 将 mako 通知从 screencast 中屏蔽 layer-rule { match namespace^notifications$ block-out-from screencast }取值有两种screencast仅屏蔽 xdg-desktop-portal 的录制/投屏与screen-capture屏蔽所有屏幕捕获。从源码看二者对应BlockOutFrom枚举的两个变体// niri-config/src/appearance.rs #[derive(knuffel::DecodeScalar, Debug, Clone, Copy, PartialEq, Eq)] pub enum BlockOutFrom { Screencast, ScreenCapture, }在渲染阶段src/layer/mapped.rs的render_normal当ctx.target.should_block_out(self.rules.block_out_from)为真时niri 会改用一个纯黑[0., 0., 0., 1.]的SolidColorBuffer来绘制该表面从而实现屏蔽效果。opacity设置表面的不透明度。0.0为完全透明1.0为完全不透明。该值会叠加在表面自身的不透明度之上因此半透明表面会变得比原来更透明。透明度会逐个应用到 layer-shell 表面的每一个子表面child上所以子表面subsurface和弹出菜单背后的窗口内容依然可见不会因为整体 alpha 而出现黑色描边或“挖洞”问题。// 让 fuzzel 半透明 layer-rule { match namespace^launcher$ opacity 0.95 }从渲染实现看src/layer/mapped.rsopacity会被clamp(0., 1.)后作为 alpha 传入push_elements_from_surface_tree因此超出范围的数值会被自动收敛。shadow自版本 25.02 起可用覆盖该表面的阴影选项。这些选项与 布局layout配置中的shadow完全一致。与窗口阴影不同layer 表面的阴影必须通过图层规则显式开启——在 layout 配置节中启用阴影并不会自动为 layer 表面生效。这一点从ShadowRule的默认值可以印证默认on: false见niri-config/src/appearance.rs中Shadow的Default实现只有通过规则的on或shadow { on }才会真正开启。[!NOTE] Layer 表面无法告诉 niri 它们的视觉几何形状visual geometry。 例如如果某个 layer 表面包含不可见的外边距像 mako 那样niri 无从得知就会把阴影画在整个表面背后包括那些不可见的外边距。因此要使用 niri 阴影你需要配置 layer-shell 客户端让它们移除自身的边距或阴影。// 为 fuzzel 添加阴影 layer-rule { match namespace^launcher$ shadow { on } // fuzzel 默认有 10 px 的圆角 geometry-corner-radius 10 }shadow块支持的完整选项与默认值取自niri-config/src/appearance.rs选项默认值说明on/off关显式开启/关闭阴影softness30阴影柔和度范围 0–1024spread5阴影扩散范围范围 -1024–1024offset x... y...x0 y5阴影偏移draw-behind-windowfalse是否绘制在窗口背后color#00000077阴影颜色支持 CSS 颜色语法inactive-color无非激活状态的阴影颜色geometry-corner-radius自版本 25.02 起可用设置表面的圆角半径。该设置只影响阴影——它会把阴影的圆角调整为与几何圆角一致。layer-rule { match namespace^launcher$ geometry-corner-radius 12 }在配置解析层面CornerRadius支持单个参数四角统一或四个参数分别指定 top-left、top-right、bottom-right、bottom-left且半径必须不小于 0见niri-config/src/appearance.rs中CornerRadius的Decode实现。place-within-backdrop自版本 25.05 起可用设置为true可将表面放入 Overview 总览 以及工作区切换过渡中可见的backdrop背景层中。该属性只对忽略独占区域exclusive zones的background图层表面生效典型如壁纸工具落入 backdrop 内的图层将忽略所有输入事件。这一限制在源码中有明确体现src/layer/mapped.rs的place_within_backdrop表面必须处于Layer::Background且exclusive_zone ExclusiveZone::DontCare才会真正生效。// 把 swaybg 放进 overview 的 backdrop 中 layer-rule { match namespace^wallpaper$ place-within-backdrop true }baba-is-float自版本 25.05 起可用让你的 layer 表面**上下漂浮FLOAT**起来。这是 2025 年愚人节推出的 窗口规则baba-is-float特性的自然延伸——窗口版让窗口在屏幕上漂浮图层版让图层表面以同样的正弦/弹性运动上下浮动。// 让 fuzzel FLOAT 起来 layer-rule { match namespace^launcher$ baba-is-float true }从源码看baba_is_float_offset见src/utils相关实现会根据合成器的内部时钟self.clock.now()与表面高度计算一个周期性的垂直偏移并在渲染时叠加到表面位置与 xray 位置上src/layer/mapped.rs的bob_offset。同时are_animations_ongoing会因baba_is_float返回true保证浮动动画持续被调度渲染。background-effect自版本 26.04 起可用覆盖该表面的背景特效选项xray设为true开启 xray 透视效果设为false关闭。blur设为true开启该表面背后的模糊设为false强制关闭。noise添加到背景上的像素噪点数量有助于缓解模糊带来的色带/条纹color banding。saturation背景的色彩饱和度0为去饱和1为正常2为 200% 饱和度。背景特效的整体介绍见 窗口特效页面。在niri-config/src/appearance.rs中BackgroundEffectRule的四个字段全部可选解析后的BackgroundEffect语义为xray/blur的None表示“按需/跟随客户端请求”例如客户端通过 ext-background-effect 协议请求Some(false)强制禁用Some(true)强制启用。// 让 top 与 overlay 图层使用常规 blur如果已启用 // 而 bottom 与 background 图层继续使用高效的 xray blur layer-rule { match layertop match layeroverlay background-effect { xray false } }popups自版本 26.04 起可用覆盖该 layer 表面**弹出菜单pop-ups**的属性例如点击 Waybar 中的某个条目后弹出的菜单。其属性与对应 layer-rule 属性工作方式相同区别在于它们作用于 layer 表面的弹出菜单而非表面本身opacity会叠加在 layer 表面自身的不透明度规则之上因此同时设置两者会让弹出菜单比表面更透明其他属性geometry-corner-radius、background-effect则独立应用。从源码结构看popups块复用了窗口规则中的PopupsRule结构见 niri-config/src/window_rule.rs包含opacity、geometry_corner_radius与background_effect三个可覆盖项。[!NOTE] 此块只影响应用通过 Wayland 的 xdg-popup 协议创建的弹出菜单大多数应用都属于此类。某些桌面 shell 会通过在普通 layer 表面内部绘制一个看起来像弹出菜单的东西来模拟弹窗。对 niri 而言那只是 layer 表面而非弹出菜单此块不会作用于它们。此外输入法弹出菜单如 Fcitx也不受此块影响。// 模糊 Waybar 弹出菜单背后的背景 layer-rule { match namespace^waybar$ popups { // 匹配 GTK 3 默认的弹出圆角半径 geometry-corner-radius 6 opacity 0.85 background-effect { blur true } } }请记住只有当弹出菜单是圆角矩形形状、且 layer 表面正确设置其 Wayland geometry 以排除自身阴影时背景特效才会看起来正确。自定义形状的弹出菜单需要应用自行实现 ext-background-effect 协议 才能获得理想效果。实践建议与常见组合综合以上内容几个开箱即用的典型配置组合1. 透明且带阴影的 fuzzel 启动器layer-rule { match namespace^launcher$ opacity 0.95 geometry-corner-radius 10 shadow { on } }2. 屏蔽通知、并让 top 栏背景模糊layer-rule { match namespace^notifications$ block-out-from screencast } layer-rule { match layertop background-effect { xray false blur true } }3. 启动瞬间隐藏所有 overlay 表面避免启动闪烁layer-rule { match layeroverlay match at-startuptrue opacity 0 }小结图层规则把窗口规则的理念带到了 layer-shell 表面世界通过namespace正则、at-startup启动 60 秒窗口与layerbackground/bottom/top/overlay三种匹配器精确定位目标再用opacity、shadow、geometry-corner-radius、place-within-backdrop、baba-is-float、background-effect、block-out-from与popups等属性持续调整外观与安全行为。结合 niri-config/src/layer_rule.rs 的结构定义与 src/layer/mod.rs 的合并逻辑你可以放心地为自己的状态栏、通知、启动器和壁纸工具编写既美观又安全的规则并把它们写进 niri 的 KDL 配置文件中随配置热重载即时生效。【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考