niri 按键绑定配置完全指南:binds 段语法、动作系统与热键覆盖层定制

📅 发布时间:2026/9/10 20:15:07
niri 按键绑定配置完全指南:binds 段语法、动作系统与热键覆盖层定制
niri 按键绑定配置完全指南binds 段语法、动作系统与热键覆盖层定制【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri导读本文是 niri一个滚动平铺式 Wayland 合成器配置文件binds {}段的完整实战指南覆盖热键声明语法、修饰符解析规则、滚动与鼠标点击绑定、冷却与重复机制、hotkey-overlay-title热键覆盖层定制以及spawn/spawn-sh/quit/do-screen-transition/screenshot等核心动作的详细用法。读完本文你将能独立编写一套贴合自身工作流、可在 TTY 与嵌套窗口间平滑切换的完整按键配置并理解每个配置项背后的源码实现逻辑。Overviewbinds 段的基本结构按键绑定Key Bindings声明在配置文件的binds {}段中。每一条绑定由一个热键hotkey和一个用花括号包裹的动作action组成binds { ModLeft { focus-column-left; } SuperAltL { spawn swaylock; } }[!NOTE]binds是少数几个不会在你省略时自动填入默认值的段。因此务必从默认配置中复制该段位于 resources/default-config.kdl 的binds {}段再在其基础上增删改。热键由以号分隔的修饰符序列与末尾的 XKB 键名组成。niri 的默认配置本身就是一份极佳的速查表包含了方向键ModLeft/ModRight、H/J/K/L类 Vim 风格键位、工作区切换ModPage_Down等、以及媒体键XF86AudioRaiseVolume等的完整映射见 resources/default-config.kdl。有效修饰符修饰符说明Ctrl或Control控制键Shift移位键Alt交替键Super或Win系统键Windows/Command 键ISO_Level3_Shift或Mod5某些布局上的 AltGr 键ISO_Level5_Shift可与 xkb lv5 选项如lv5:caps_switch配合使用Mod特殊修饰符见下文从源码看这些别名在 niri-config/src/binds.rs 的Key::from_str中逐一解析大小写不敏感地匹配mod、ctrl/control、shift、alt、super/win、iso_level3_shift/mod5、iso_level5_shift/mod3解析结果存入Modifiersbitflags其中Mod对应专门的COMPOSITOR位。注意源码中Mod3被解析为ISO_LEVEL5_SHIFT而Mod5才是 AltGrISO_LEVEL3_SHIFT这与 XKB 的命名习惯一致。Mod特殊修饰符Mod是一个特殊的修饰符在 TTY 上运行 niri 时Mod等于Super以嵌套 winit 窗口方式运行 niri 时Mod等于Alt。这样一来你可以直接在宿主合成器窗口里测试 niri而不会与宿主合成器的按键绑定产生大量冲突。出于这个原因绝大多数默认按键都使用Mod修饰符。Since: 25.05你可以在 配置文件的 input 段 中自定义Mod键例如将mod-key Alt、mod-key-nested Super对调。查找 XKB 键名使用 wev要确定某个按键的 XKB 名称可以使用wev之类的程序。从终端打开它按下想要检测的按键终端中会出现类似输出[14: wl_keyboard] key: serial: 757775; time: 44940343; key: 113; state: 1 (pressed) sym: Left (65361), utf8: [14: wl_keyboard] key: serial: 757776; time: 44940432; key: 113; state: 0 (released) sym: Left (65361), utf8: [14: wl_keyboard] key: serial: 757777; time: 44940753; key: 114; state: 1 (pressed) sym: Right (65363), utf8: [14: wl_keyboard] key: serial: 757778; time: 44940846; key: 114; state: 0 (released) sym: Right (65363), utf8: 这里看sym: Left和sym: Right就是键名——上例中按下的是左右方向键。绑定带 Shift 的键需要按你的 XKB 布局写全Shift加上该键未按 Shift 时的名称。例如在美式 QWERTY 布局下位于Shift,因此要写成类似ModShiftComma。再如法式 BÉPO 布局中位于AltGr«而AltGr就是ISO_Level3_Shift等价于Mod5所以要写成类似ModMod5guillemotleft。解析拉丁键时niri 会搜索第一个配置了该拉丁键的 XKB 布局。例如同时配置了美式 QWERTY 和俄语布局时拉丁键绑定会使用美式 QWERTY。[!TIP] 从源码看键名解析最终通过 libxkbcommon 的keysym_from_name完成niri-config/src/binds.rs。代码中还处理了一个边界情况XF86ScreenSaver与XF86Screensaver之间没有定义大小写映射因此会先尝试大小写不敏感匹配再回退到大小写敏感匹配保证两种写法都能被绑定这一点有单元测试parse_xf86_screensaver覆盖niri-config/src/binds.rs。按键重复repeatSince: 0.1.8绑定默认会重复触发即按住绑定键会反复触发动作。可以为特定绑定设置repeatfalse来禁用binds { ModT repeatfalse { spawn alacritty; } }从源码看重复触发由 src/input/mod.rs 的start_key_repeat实现它会以repeat_delay作为初始延迟然后以repeat_rate每秒次数换算出的时长周期性地重新触发动作。默认配置中ModO { toggle-overview; }、ModQ { close-window; }都刻意使用了repeatfalse避免按住时反复开关概览或反复关窗。绑定冷却cooldown绑定还可以设置冷却时间对绑定做速率限制防止其触发过快binds { ModT cooldown-ms500 { spawn alacritty; } }这对滚动类绑定尤其有用。实现上src/input/mod.rs 会为每个绑定键维护一个冷却计时器表bind_cooldown_timers处于冷却期内的按键事件会被直接丢弃。默认配置中ModWheelScrollDown cooldown-ms150 { focus-workspace-down; }正是靠它防止滚轮快速翻过多个工作区。滚动绑定Scroll Bindings可以使用以下语法绑定鼠标滚轮的滚动 tickbinds { ModWheelScrollDown cooldown-ms150 { focus-workspace-down; } ModWheelScrollUp cooldown-ms150 { focus-workspace-up; } ModWheelScrollRight { focus-column-right; } ModWheelScrollLeft { focus-column-left; } }这些绑定会随natural-scroll设置改变方向。同样地也可以绑定触摸板滚动的“tick”。触摸板滚动是连续的因此这些绑定会按移动距离被切分为离散的区间binds { ModTouchpadScrollDown { spawn wpctl set-volume DEFAULT_AUDIO_SINK 0.02; } ModTouchpadScrollUp { spawn wpctl set-volume DEFAULT_AUDIO_SINK 0.02-; } }这些绑定同样受触摸板natural-scroll影响所以上面这组示例是“反转”的——因为 niri 默认对触摸板启用了natural-scroll见 resources/default-config.kdl。[!IMPORTANT] 鼠标滚轮和触摸板滚动绑定在其修饰符被按住时都会阻止应用接收任何滚动事件。例如你定义了ModWheelScrollDown绑定那么按住Mod期间所有鼠标滚轮滚动都会被 niri 吞掉。默认配置利用这一点还额外提供了ModShiftWheelScrollDown/Up绑定来模拟应用内“Shift滚轮 横向滚动”的常见行为resources/default-config.kdl。鼠标点击绑定Mouse Click BindingsSince: 25.01可以使用以下语法绑定鼠标点击binds { ModMouseLeft { close-window; } ModMouseRight { close-window; } ModMouseMiddle { close-window; } ModMouseForward { close-window; } ModMouseBack { close-window; } }鼠标点击作用于点击发生时正处于焦点的窗口而不是你正在点击的那个窗口。[!NOTE] 绑定ModMouseLeft或ModMouseRight会覆盖对应的鼠标手势移动或调整窗口大小。因此如果你在默认配置之外又绑定了ModMouseLeft原本的“Mod左键拖动移动窗口”行为将不再可用。从源码看除键盘键名外MouseLeft/MouseRight/MouseMiddle/MouseBack/MouseForward、WheelScroll*、TouchpadScroll*乃至数位笔按键TabletStylusButton1/2/3都在Trigger枚举中并列解析niri-config/src/binds.rs说明 niri 把键盘、鼠标、滚轮、触摸板和数位笔统一进了同一套热键声明体系。自定义热键覆盖层标题Custom Hotkey Overlay TitlesSince: 25.02热键覆盖层即“Important Hotkeys”对话框默认展示一列硬编码的绑定。你可以用hotkey-overlay-title属性定制这份列表。给绑定设置该属性即可将其加入热键覆盖层并显示指定标题binds { ModShiftS hotkey-overlay-titleToggle Dark/Light Style { spawn some-script.sh; } }带有自定义标题的绑定会排在硬编码绑定之后、未自定义的 Spawn 绑定之前。要把某个硬编码绑定从覆盖层中移除将该属性设为nullbinds { ModQ hotkey-overlay-titlenull { close-window; } }[!TIP] 当多个键位组合绑定到同一动作时只要其中任何一个绑定带有自定义热键覆盖层标题niri 就显示该绑定否则只要任何一个绑定带有null标题niri 就隐藏该绑定否则niri 显示第一个键位组合。从源码看这些逻辑在 src/ui/hotkey_overlay.rs 与 src/ui/hotkey_overlay.rs 中实现遍历全部绑定按“自定义标题 null 标题 首个键位”的优先级决定每项动作的展示与隐藏。自定义标题支持 Pango 标记markupbinds { ModShiftS hotkey-overlay-titlebToggle/b span foregroundredDark/span/Light Style { spawn some-script.sh; } }覆盖层渲染时通过pango::parse_markup解析标题src/ui/hotkey_overlay.rs解析失败时会打印警告并退化为纯文本src/ui/hotkey_overlay.rs因此即使标记写错也不会导致崩溃。动作Actions每一个可绑定动作都可以通过niri msg action以编程方式调用。运行niri msg action可以获取全部动作及其简短描述。下面详细讲解几个值得展开的动作。spawn直接运行程序spawn的第一个参数是程序二进制路径随后是传给程序的参数。例如binds { // Run alacritty. ModT { spawn alacritty; } // Run wpctl set-volume DEFAULT_AUDIO_SINK 0.1. XF86AudioRaiseVolume { spawn wpctl set-volume DEFAULT_AUDIO_SINK 0.1; } }[!TIP]Since: 0.1.5Spawn 绑定有一个特殊的allow-when-lockedtrue属性可以让它在会话锁定时依然生效binds { // This mute bind will work even when the session is locked. XF86AudioMute allow-when-lockedtrue { spawn wpctl set-mute DEFAULT_AUDIO_SINK toggle; } }spawn不使用 shell 运行命令这意味着你必须手动分隔参数binds { // Correct: every argument is in its own quotes. ModT { spawn alacritty -e /usr/bin/fish; } // Wrong: will interpret the whole alacritty -e /usr/bin/fish string as the binary path. ModD { spawn alacritty -e /usr/bin/fish; } // Wrong: will pass -e /usr/bin/fish as one argument, which alacritty wont understand. ModQ { spawn alacritty -e /usr/bin/fish; } }这也意味着无法展开环境变量或~。如有需要可以手动通过 shell 执行命令binds { // Wrong: no shell expansion here. These strings will be passed literally to the program. ModT { spawn grim -o $MAIN_OUTPUT ~/screenshot.png; } // Correct: run this through a shell manually so that it can expand the arguments. // Note that the entire command is passed as a SINGLE argument, // because shell will do its own argument splitting by whitespace. ModD { spawn sh -c grim -o $MAIN_OUTPUT ~/screenshot.png; } // You can also use a shell to run multiple commands, // use pipes, process substitution, and so on. ModQ { spawn sh -c notify-send clipboard \$(wl-paste)\; } }作为一个特例niri 只会在程序名的最开头展开~到主目录binds { // This will work: one ~ at the very beginning. ModT { spawn ~/scripts/do-something.sh; } }[!NOTE] 从源码看spawn的参数直接以VecString形式解析Spawn(#[knuffel(arguments)] VecString)见 niri-config/src/binds.rs这正是“无 shell、逐参数传递”的根源。另外allow-when-locked属性仅允许设置在 spawn 类绑定上如果把它用在其它动作上配置解析会直接报错niri-config/src/binds.rs。spawn-sh通过 shell 运行命令Since: 25.08spawn-sh通过 shell 运行命令。参数是单个字符串会被原样传给sh因此可以使用 shell 变量、管道、~展开等一切 shell 特性binds { // Works with spawn-sh: all arguments in the same string. ModD { spawn-sh alacritty -e /usr/bin/fish; } // Works with spawn-sh: shell variable ($MAIN_OUTPUT), ~ expansion. ModT { spawn-sh grim -o $MAIN_OUTPUT ~/screenshot.png; } // Works with spawn-sh: process substitution. ModQ { spawn-sh notify-send clipboard \$(wl-paste)\; } // Works with spawn-sh: multiple commands. SuperAltS { spawn-sh pkill orca || exec orca; } }spawn-sh some command等价于spawn sh -c some command只是更不易混淆的简写。需要注意的是经过 shell 会带来极小的性能开销相比直接spawn一个二进制略慢。使用sh是硬编码的这与其它合成器保持一致。如果你想用别的 shell就用spawn明确写出例如spawn fish -c some fish command。[!NOTE] 默认配置中大量媒体键示例都采用了spawn-shXF86AudioRaiseVolume、XF86AudioMute、XF86AudioPlayplayerctl、XF86MonBrightnessUpbrightnessctl等全部带有allow-when-lockedtrue保证锁屏后音量、亮度、媒体控制依然可用resources/default-config.kdl。这组配置可以直接复制到你的binds {}段中按需启用。quit退出 niri显示确认对话框后退出 niri以避免误触binds { ModShiftE { quit; } }跳过确认对话框binds { ModShiftE { quit skip-confirmationtrue; } }默认配置中CtrlAltDelete { quit; }也绑定了该动作resources/default-config.kdl。do-screen-transition屏幕过渡动画Since: 0.1.6短暂冻结屏幕然后交叉淡入到新内容binds { ModReturn { do-screen-transition; } }该动作主要用于从脚本中切换系统主题或样式例如深色/浅色时触发让各窗口逐个改变样式的过渡看起来平滑而同步。例如配合 GNOME 配色方案设置niri msg action do-screen-transition dconf write /org/gnome/desktop/interface/color-scheme \prefer-dark\默认冻结屏幕 250 ms 以给窗口重绘时间之后才开始交叉淡入。可以这样调整延迟binds { ModReturn { do-screen-transition delay-ms100; } }或在脚本中niri msg action do-screen-transition --delay-ms 100toggle-window-rule-opacity切换窗口透明度规则Since: 25.02切换当前焦点窗口的 opacity 窗口规则。只有当窗口的 opacity 窗口规则已被设为半透明时该动作才有效binds { ModO { toggle-window-rule-opacity; } }screenshot、screenshot-screen、screenshot-window截屏动作screenshot打开内置的交互式截屏界面screenshot-screen、screenshot-window分别截取当前屏幕或窗口。截图会同时存入剪贴板并保存到磁盘保存路径遵循 screenshot-path 选项。Since: 25.02可以为特定绑定用write-to-diskfalse禁用写入磁盘binds { CtrlPrint { screenshot-screen write-to-diskfalse; } AltPrint { screenshot-window write-to-diskfalse; } }在交互式截屏界面中按CtrlC会将截图复制到剪贴板而不写入磁盘。Since: 25.05可以用show-pointerfalse在截图中隐藏鼠标指针binds { // The pointer will be hidden by default // (you can still show it by pressing P). Print { screenshot show-pointerfalse; } // The pointer will be hidden on the screenshot. CtrlPrint { screenshot-screen show-pointerfalse; } }Since: 26.04可以用show-pointertrue在窗口截图中显示鼠标指针。只有当窗口当前正在接收指针输入通常意味着指针位于窗口之上时指针才会被包含进截图binds { // The pointer will be visible on the screenshot // if its on top of the window. AltPrint { screenshot-window show-pointertrue; } }从源码看各截屏动作的默认值分别为screenshot与screenshot-screen的show-pointer默认truescreenshot-window的show-pointer默认false而screenshot-screen/screenshot-window的write-to-disk默认trueniri-config/src/binds.rs。默认配置中Print { screenshot; }、CtrlPrint { screenshot-screen; }、AltPrint { screenshot-window; }三条可直接使用resources/default-config.kdl。toggle-keyboard-shortcuts-inhibit键盘快捷键抑制开关Since: 25.02远程桌面客户端、软件 KVM 切换器等应用可能请求 niri 停止处理其键盘快捷键以便将按键原样转发到远程机器。toggle-keyboard-shortcuts-inhibit就是切换该抑制器的“逃生舱”。建议务必绑定它以免某个有问题的应用把你的会话“绑架”binds { ModEscape { toggle-keyboard-shortcuts-inhibit; } }你也可以用allow-inhibitingfalse让某些绑定无视抑制始终由 niri 处理、绝不透传给窗口binds { // This bind will always work, even when using a virtual machine. SuperAltL allow-inhibitingfalse { spawn swaylock; } }[!NOTE] 从源码看抑制逻辑在 src/input/mod.rs 处判断当抑制生效且绑定允许被抑制is_inhibiting_shortcuts bind.allow_inhibiting时绑定事件会被让给应用。另外有两个值得注意的强制保证niri-config/src/binds.rsToggleKeyboardShortcutsInhibit动作本身永远不可被抑制allow_inhibiting被强制置为false否则它将永远无法被触发默认配置中的ModEscape allow-inhibitingfalse { toggle-keyboard-shortcuts-inhibit; }正是利用了这一特性resources/default-config.kdl。附一份可落地的完整 binds 示例结合默认配置resources/default-config.kdl与本文讲解下面给出一个兼顾平铺操作、工作区、媒体键与安全逃逸的骨架配置可直接复制进你的配置文件按需裁剪binds { // 焦点与布局Vim 风格 ModLeft { focus-column-left; } ModRight { focus-column-right; } ModDown { focus-window-down; } ModUp { focus-window-up; } ModH { focus-column-left; } ModJ { focus-window-down; } ModK { focus-window-up; } ModL { focus-column-right; } ModCtrlLeft { move-column-left; } ModCtrlRight { move-column-right; } ModCtrlDown { move-window-down; } ModCtrlUp { move-window-up; } // 工作区 ModPage_Down { focus-workspace-down; } ModPage_Up { focus-workspace-up; } ModCtrlPage_Down { move-column-to-workspace-down; } ModCtrlPage_Up { move-column-to-workspace-up; } // 常用程序带热键覆盖层标题 ModT hotkey-overlay-titleOpen a Terminal: alacritty { spawn alacritty; } ModD hotkey-overlay-titleRun an Application: fuzzel { spawn fuzzel; } SuperAltL hotkey-overlay-titleLock the Screen: swaylock { spawn swaylock; } // 媒体键锁屏时依然可用 XF86AudioRaiseVolume allow-when-lockedtrue { spawn-sh wpctl set-volume DEFAULT_AUDIO_SINK 0.1 -l 1.0; } XF86AudioLowerVolume allow-when-lockedtrue { spawn-sh wpctl set-volume DEFAULT_AUDIO_SINK 0.1-; } XF86AudioMute allow-when-lockedtrue { spawn-sh wpctl set-mute DEFAULT_AUDIO_SINK toggle; } // 滚动绑定带冷却防止翻过快 ModWheelScrollDown cooldown-ms150 { focus-workspace-down; } ModWheelScrollUp cooldown-ms150 { focus-workspace-up; } ModWheelScrollRight { focus-column-right; } ModWheelScrollLeft { focus-column-left; } // 截屏 Print { screenshot; } CtrlPrint { screenshot-screen; } AltPrint { screenshot-window; } // 抑制逃生舱与退出 ModEscape allow-inhibitingfalse { toggle-keyboard-shortcuts-inhibit; } ModShiftE { quit; } }进一步阅读想了解Mod键的底层定义与mod-key/mod-key-nested自定义方法参见 input 段配置文档截屏保存路径等杂项选项见 Miscellaneous 配置文档绑定与动作的完整解析源码见 niri-config/src/binds.rs运行时触发与冷却、重复、抑制逻辑见 src/input/mod.rs热键覆盖层渲染见 src/ui/hotkey_overlay.rs默认按键布局与完整动作示例始终以 resources/default-config.kdl 为准——它是你开始自定义按键的最佳起点。【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考