如何改变scancode->keycode映射

如何改变scancode->keycode映射

我已将大写锁定键重新映射为退格键。

/etc/默认/键盘

XKBLAYOUT="us"
XKBVARIANT="altgr-intl"
BACKSPACE="guess"
XKBOPTIONS="caps:backspace"

这个功能很好用,只是对某些特定工具不起作用。我以前经常会xev发现这是怎么回事。

按下退格键

KeyPress event, serial 38, synthetic NO, window 0x2400001,
    root 0x159, subw 0x0, time 1028211, (335,635), root:(452,749),
    state 0x10, keycode 22 (keysym 0xff08, BackSpace), same_screen YES,
    XLookupString gives 1 bytes: (08) "
    XmbLookupString gives 1 bytes: (08) "
    XFilterEvent returns: False

KeyRelease event, serial 38, synthetic NO, window 0x2400001,
    root 0x159, subw 0x0, time 1028272, (335,635), root:(452,749),
    state 0x10, keycode 22 (keysym 0xff08, BackSpace), same_screen YES,
    XLookupString gives 1 bytes: (08) "
    XFilterEvent returns: False

按下 Caps Lock 键

KeyPress event, serial 38, synthetic NO, window 0x2400001,
    root 0x159, subw 0x0, time 859789, (391,558), root:(508,672),
    state 0x10, keycode 66 (keysym 0xff08, BackSpace), same_screen YES,
    XKeysymToKeycode returns keycode: 22
    XLookupString gives 1 bytes: (08) "
    XmbLookupString gives 1 bytes: (08) "
    XFilterEvent returns: False

KeyRelease event, serial 38, synthetic NO, window 0x2400001,
    root 0x159, subw 0x0, time 859875, (391,558), root:(508,672),
    state 0x10, keycode 66 (keysym 0xff08, BackSpace), same_screen YES,
    XKeysymToKeycode returns keycode: 22
    XLookupString gives 1 bytes: (08) "
    XFilterEvent returns: False

我也在浏览器中尝试使用

addEventListener('keyup', event => {
  console.log(event.keyCode, event.key, event.code)
})

当我按下退格键和大写锁定键时,会记录以下内容

8 "Backspace" "Backspace"
8 "Backspace" "CapsLock"

因此,基本上我的大写锁定键被重新映射到退格键,但只有当工具和网站使用适当的检查时,它才有效。我不想为我曾经使用过的每个错误实现此功能的工具或网站提交错误报告。

是否可以以某种方式映射大写锁定,使其完全模拟退格键,而不是像重新映射的大写锁定键那样?

答案1

首先,让我们看看按键是如何处理的(取自这个答案):

/键盘/ → scancode→ /输入驱动程序/ → keycode→ /X 服务器 XKB/ →keysym

scancode与特定键绑定的设备特定代码,在不同的供应商/产品之间可能有所不同。keycodekeysym传播到应用程序。keycode充当抽象层,因为它与设备和语言环境无关。 相同的keycode可以产生不同的keysym,具体取决于语言环境和修饰键的状态。 这就是为什么某些应用程序只查找 的原因keycode,尤其是在处理键盘快捷键时。

因此,我们的目标是将scancodeCapsLock 键的 映射到keycodeBackSpace 键的 。这样,无论您按下的是 BackSpace 还是 CapsLock,应用程序都会看到相同keycode的。keysym

此映射由udev使用H阿尔德d艾塔base 文件(hwdb.bin)是从和中的 .hwdb 文件编译而来/lib/udev/hwdb.d//etc/udev/hwdb.d/


如何改变scancode->keycode映射

收集所需信息

首先,您必须确定输入设备(键盘)的bustypevendor和,product以及您要重新映射的键的 和您要将其映射到的 。versionscancodekey code identifier

运行evtest(您可能必须先安装它)并在设备列表中识别您的键盘。在带有附加键(如播放/暂停、WWW 等)的键盘上,这些键通常显示为不同的输入设备。如果按下某个键时没有得到任何输出,请按Control+C并尝试使用其他设备。识别键盘后,记住第一列(/dev/input/eventX)并按下要重新映射的键。后面的值(MSC_SCAN)scancode。在我的键盘上:

$ evtest
Available devices:
/dev/input/event0:  Power Button
/dev/input/event1:  Power Button
/dev/input/event2:  G19 Gaming Keyboard
/dev/input/event3:  G19 Gaming Keyboard
...
Select the device event number [0-18]:2
...
Event: time 1522111203.117945, -------------- SYN_REPORT ------------
Event: time 1522111220.778787, type 4 (EV_MSC), code 4 (MSC_SCAN),value 70039
Event: time 1522111220.778787, type 1 (EV_KEY), code 14 (KEY_BACKSPACE), value 1

...scancode70039

现在运行以下命令,其中eventX是您之前选择的命令:

$ grep "" /sys/class/input/eventX/device/id/*

我的键盘的输出是

/sys/class/input/event2/device/id/bustype:0003
/sys/class/input/event2/device/id/product:c228
/sys/class/input/event2/device/id/vendor:046d
/sys/class/input/event2/device/id/version:0110

要获取key code identifier,请使用的输出evtest或查看按键和按钮部分中/usr/include/linux/input-event-codes.h的完整列表。标识符是KEY_转换为小写后的部分,例如KEY_BACKSPACE变为退格键

配置 udev

看一下/lib/udev/hwdb.d/。我们将在中创建一个文本文件/etc/udev/hwdb.d/文件名以大于我们设备类型对应的文件的数字开头。对于键盘,这个数字可以是大于 60 的任何数字,而对于指点杆,这个数字应该大于 70。例如65-keyboard-custom.hwdb。使用您最喜欢的文本编辑器,但请记住,您必须以 的形式启动它root,例如

$ sudo gedit /etc/udev/hwdb.d/65-keyboard-custom.hwdb

添加以下内容

evdev:input:b[bustype]v[vendor]p[product]e[version]*
 KEYBOARD_KEY_[scancode]=[key code identifier]

...在哪里

  • [bustype]、[vendor]、[product] 和 [version] 恰好有 4 个字符(如果需要,用零填充),并且字母需要大写
  • [scancode] 不需要填充,但字母必须小写
  • evdev:...生产线没有前导空格
  • KEYBOARD_KEY...生产线恰好一个前导空格

在我的示例中,该文件如下所示:

evdev:input:b0003v046DpC228e0110*
 KEYBOARD_KEY_70039=backspace   # map CapsLock to BackSpace

第一行将与您的设备匹配。您可以指定其他evdev:行,也可以使用多个通配符 ( *) 来匹配其他设备,但请记住,扫描码是特定于设备的。您还可以添加多个扫描码映射。请查看/lib/udev/hwdb.d/60-keyboard.hwdb以获取灵感。该文件的更详细和最新版本可以在在线存储库

应用新配置

将新配置编译到硬件数据库:

$ sudo systemd-hwdb update

如果要立即应用更改,请通知 udev:

$ sudo udevadm trigger

请注意,配置值只能在系统运行时添加或更改。如果删除配置(例如扫描码映射),则必须重新启动才能使更改生效。

请记住还要恢复您之前执行的重新映射(使用/etc/default/keyboard),因为它仍将应用于所有键盘。

相关内容