跳转至内容

键盘输入

来自 ArchWiki
(重定向自Keycode)

修改按键映射的前提是知道按键如何产生符号。

  1. 键盘向计算机发送一个 扫描码
  2. Linux 内核将扫描码映射到 **键码**;请参阅 Map scancodes to keycodes
  3. 根据是否按下 修饰键键盘布局会将键码映射到符号或 **键名** (keysym)。

您的绝大多数按键应该已经有了一个 *键码*,或者至少有一个 *扫描码*。没有 *扫描码* 的按键不会被内核识别;这可能包括“游戏”键盘上的额外按键等。

在 Xorg 中,一些 *键名*(例如 XF86AudioPlay, XF86AudioRaiseVolume 等)可以映射到操作(即启动外部应用程序)。详情请参阅 Keyboard shortcuts#Xorg

在 Linux 控制台中,一些 *键名*(例如 F1F246)可以映射到特定操作(例如切换到其他控制台或打印一系列字符)。详情请参阅 Console keyboard configuration#Creating a custom keymap

识别扫描码

使用 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

注意 手册页指出,在现代内核上,原始扫描码模式“一点也不原始”。特别是对于 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 也报告键名。提及您需要聚焦“事件测试器”窗口。(在 Talk:Keyboard input 中讨论)
注意 Xorg 的 *键码* 比 Linux 的 *键码* 大 8。[2]

Xorg 使用的 *键码* 由一个名为 xev(1) 的实用程序报告,该实用程序由 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

Xbindkeys 是 *xev* 的另一个包装器,它报告 *键码*。

如果您按下某个按键但终端没有任何显示,则意味着该按键要么没有 *扫描码*,要么 *扫描码* 未映射到 *键码*,或者有其他进程正在捕获该按键。如果您怀疑某个监听 X 服务器的进程正在捕获该按键,您可以尝试从一个干净的 X 会话运行 *xev*。

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

在 Wayland 中识别键码

尽管 *xev* 可以通过 Xwayland 工作,您也可以使用 wev 来访问纯 Wayland 下的键码。

例如,此命令可让您仅检索按键名称及其 UTF-8 等效字符:

$ wev | grep 'sym'

技巧与提示

配置 VIA 兼容键盘

VIA 是一个直接重映射兼容键盘的程序。如果您拥有其中一款键盘,为了让浏览器能够识别并在线配置它,您需要添加一个自定义 udev 规则,更改通过 *hidraw* 驱动器访问的设备的权限。

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

创建以下 udev 规则

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

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

参见

  • kbd-project - showkeys 工具的官方网站
  • interception-tools - 一组用于控制和自定义键盘输入映射行为的实用程序
  • kmonad - 一个高级按键重绑定和重映射守护进程
  • Hawck - 另一个按键重绑定守护进程
  • keyd - 简化的按键重绑定守护进程
  • Vial - VIA 独立的程序
  • Keyshift - 面向性能的 Linux 键盘分层和重映射软件