跳转到内容
来自 Arch Linux 中文维基

修改键位映射的前提是了解按键如何生成符号:

  1. 键盘向计算机发送一个扫描码(scancode)
  2. Linux 内核将扫描码映射为键码(keycode);参见扫描码映射至键位码
  3. 键盘布局根据按下的修饰键将键码映射为符号,称作键符(keysym)

大部分按键应该有键码或至少有扫描码。内核无法识别没有扫描码的按键,如一些“游戏键盘”上附加的按键。

在 Xorg 中,某些键符(如 XF86AudioPlayXF86AudioRaiseVolume 等)可以映射到操作(例如启动外部应用程序),详见快捷键#Xorg

在 Linux 控制台中,某些键符(如 F1F246)可被映射到特定操作(例如切换到其他控制台或打印字符序列)。详见 Linux 控制台/键盘配置#创建自定义键盘映射

识别扫描码

使用 evtest

识别扫描码的最可靠方法是参考按键按下时生成的 MSC_SCAN evdev 事件[1]。有多种 evdev API 测试工具,但最直接的是来自 evtest 包的 evtest(1)

# evtest /dev/input/event12
...
Event: time 1434666536.001123, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70053
Event: time 1434666536.001123, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0
Event: time 1434666536.001123, -------------- EV_SYN ------------
提示:若不确定目标设备对应的事件编号,可不带参数运行 evtest,该命令会显示设备列表及其对应的事件编号并要求输入所需设备的事件编号。

MSC_SCAN 的“value”字段即为按键对应的扫描码。此示例显示 NumLock 的扫描码为70053,键码为 69。

使用 showkey

注意:手册页中指出,在现代内核上,原始扫描码模式“并不是真正的原始(is not very raw at all)”。看起来这种方法对于 USB 设备尤其容易产生错误的结果。

识别扫描码的传统方法是使用 showkey(1) 工具。showkey 等待按键按下,如果 10 秒内没有按下按键则退出。只有处于虚拟控制台而不是图形环境中,且不是通过网络连接登录时,showkey 才能正常工作。运行以下命令:

# showkey --scancodes

然后尝试按下键盘按键,应当输出对应扫描码。

使用 dmesg

注意:此方法仅可用于识别未知按键。

可以通过按下所需的按键后查看 dmesg 的输出来获取该按键的扫描码。例如,如果输出如下:

Unknown key pressed (translated set 2, code 0xa0 on isa0060/serio0

那么按下按键的扫描码就是 0xa0


识别键码

Linux 将键码定义在 /usr/include/linux/input-event-codes.h 中(参见其中以 KEY_ 开头的变量)。

在控制台中识别键码

showkey(1) 工具可用于报告虚拟控制台中按下按键的键码。showkey 等待按键按下,如果 10 秒内没有按下按键则退出。只有处于虚拟控制台而不是图形环境中,且不是通过网络连接登录时,showkey 才能正常工作。运行以下命令:

# showkey --keycodes

然后尝试按下键盘按键,应当输出对应键码。

在 Xorg 中识别“键码”

这篇文章的某些内容需要扩充。

原因:xev 同时也会报告键符。请注意,需要让“Event Tester”窗口获取到焦点。 (在 en:Talk:Keyboard Input 中讨论)
注意:Xorg 使用的“键码”比 Linux 定义的键码大 8(详见 [2]),此处中使用带双引号的“键码”指代 Xorg 使用的“键码”。


xev(1) 工具可用于报告 Xorg 中按下按键的“键码”,该工具由 xorg-xev 软件包提供。当然,要运行 xev,需要处于图形环境而不是控制台中。

使用以下命令可以启动 xev 并仅显示相关部分:

$ xev | awk -F'[ )]+' '/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", $5, $8 }'
38  a
55  v
54  c
50  Shift_L
133 Super_L
135 Menu

xev 的封装工具 xbindkeys英语xbindkeys#Identifying keycodes 同样能报告“键码”。

如果你按下某个键后终端中没有任何输出,可能意味着该键没有扫描码,或者该扫描码未映射到“键码”,又或者有其他进程在捕捉该按键事件。如果怀疑某个监听 X 服务器的进程正在捕捉按键,可以尝试在一个干净的 X 会话中运行 xev:

$ xinit /usr/bin/xterm -- :1

在 Wayland 中识别键码

虽然 xev 也能通过 XWayland 在 Wayland 上工作,但也可以使用 wev 在纯 Wayland 环境下获取“键码”。(wev 获取的“键码”也比 Linux 定义、Wayland 使用的键码大 8。)

使用以下命令可仅检索键符及其 UTF-8 等效值:

$ wev | grep 'sym'

提示与技巧

VIA 兼容键盘的配置

VIA 是一款直接将键位重映射到兼容键盘的程序。若拥有此类键盘,为了让浏览器能够识别并在线配置,需添加自定义的 udev 规则以修改通过 hidraw 驱动访问设备的权限。

注意:此方法可能存在安全风险。

创建以下 udev 规则

/etc/udev/rules.d/99-via.rules
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0666", TAG+="uaccess", TAG+="udev-acl"

随后重新加载规则使其生效。

另见

  • kbd-project⸺showkeys 工具的官方网站
  • interception-tools英语interception-tools⸺用于控制和自定义键盘输入映射行为的工具集
  • kmonad⸺高级键位重绑定与重映射守护进程
  • Hawck⸺又一个键位重绑定守护进程
  • keyd⸺简约型键位重绑定守护进程
  • Vial⸺VIA 离线配置程序
  • Keyshift⸺注重性能的 Linux 键盘分层与重映射软件