如何在 Linux 下为特定键盘重新映射按键

如何在 Linux 下为特定键盘重新映射按键

我最近买了一个 Unicomp 键盘,带有交换的右 Alt 键和 Windows 键。键盘在 lsusb 上的标识如下:

Bus 003 Device 002: ID 17f6:0822 Unicomp, Inc 

有没有办法让内核(即非基于 xmodmap 的内核)交换右 Alt 键和 Windows 键,以便每个应用程序都能在交换的位置看到它们,即使它们获得原始键盘输入(使用 xmodmap 交换内容不会这样做)?有没有办法只针对这一个键盘实现这一点?

答案1

是的,使用 XKB 是可能的。与 xmodmap 不同,XKB 可以为各个设备重新映射按键。

注意:请确保您拥有 xkbcomp > 1.2.0

首先列出您的设备:

xinput list

你会得到类似这样的结果:

⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen stylus               id=11   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger touch             id=12   [slave  pointer  (2)]
⎜   ↳ Logitech USB-PS/2 Optical Mouse           id=13   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen eraser               id=14   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger pad               id=15   [slave  pointer  (2)]
⎜   ↳ GASIA USB KB V11                          id=17   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=8    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=9    [slave  keyboard (3)]
    ↳ Logitech G19 Gaming Keyboard              id=10   [slave  keyboard (3)]
    ↳ GASIA USB KB V11                          id=16   [slave  keyboard (3)]

识别设备的字符串并编辑以下 shell 脚本,将 sed 行更改为适合您设备名称的行。然后更改您需要重新映射的键。

示例:加载xev并按下要重新映射的键。假设您发现它的键码为 84。在https://gist.github.com/zoqaeski/3880640。那里的键名是<KP5>。然后查找您想要替换的键(在同一个链接中,更远的地方)并复制括号内的内容。对所有所需的键重复此过程。

remote_id=$(
    xinput list |
    sed -n 's/.*GASIA.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$remote_id" ] || exit

# remap the following keys, only for my custom vintage atari joystick connected
# through an old USB keyboard:
#
# keypad 5 -> keypad 6
# . -> keypad 2
# [ -> keypad 8
# left shift -> left control

mkdir -p /tmp/xkb/symbols
# This is a name for the file, it could be anything you
# want. For us, we'll name it "custom". This is important
# later.
#
# The KP_* come from /usr/include/X11/keysymdef.h
# Also note the name, "remote" is there in the stanza
# definition.
cat >/tmp/xkb/symbols/custom <<\EOF

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};
EOF

# (1) We list our current definition
# (2) Modify it to have a keyboard mapping using the name
#     we used above, in this case it's the "remote" definition
#     described in the file named "custom" which we specify in
#     this world as "custom(remote)".
# (3) Now we take that as input back into our definition of the
#     keyboard. This includes the file we just made, read in last,
#     so as to override any prior definitions.  Importantly we 
#     need to include the directory of the place we placed the file
#     to be considered when reading things in.
#
# Also notice that we aren't including exactly the 
# directory we specified above. In this case, it will be looking
# for a directory structure similar to /usr/share/X11/xkb
# 
# What we provided was a "symbols" file. That's why above we put
# the file into a "symbols" directory, which is not being included
# below.
setxkbmap -device $remote_id -print \
 | sed 's/\(xkb_symbols.*\)"/\1+custom(remote)"/' \
 | xkbcomp -I/tmp/xkb -i $remote_id -synch - $DISPLAY 2>/dev/null

然后获取它(你可以将它添加到你的 .xinitrc 中)。全部完成!现在按下按键应该会生成所需的输出,仅适用于你指定的设备。

答案2

对于那些从 Google 来到这里并希望得到更符合提问者最初希望的答案的人来说,我知道两种方法可以在级别上重新映射事件,evdev以便更改适用于所有应用程序:

  1. udev 提供了一个 API,用于修改控制扫描码和键码之间映射的硬件数据库条目。这个 ArchiWiki 页面,其中包含说明,明确说明它适用于 X11 和控制台输入。

    要点是,您创建一个自定义条目,/etc/udev/hwdb.d/其中包含设备匹配模式和一些扫描码到键码重新映射定义,然后运行systemd-hwdb update以重建数据库并udevadm trigger在无需重新启动的情况下应用它。

  2. 鉴于 Wayland 不使用 X11 的键盘子系统,并且主要的 Wayland 合成器(如 GNOME Shell 和 Weston)没有实现 UI 来配置 libinput 的相关方面,有人编写了一个名为evdevremapkeys它以与 Logitech G15 游戏键盘的 G15Daemon 用户空间驱动程序类似的方式解决了该问题。

    (它吞下它想要重新映射的事件,因此设备上的其他任何监听器都看不到它们,然后通过 API 发出更正后的事件,uinput以从用户空间创建内核级输入设备。)

答案3

对于那些使用@Watcom 选项没有成功的人,只需放入新的映射文件,如下所示:

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};

以 root 身份(ubuntu,可能因发行版而异)访问 /usr/share/X11/xkb/symbols/,将文件命名为“custom”。使用 询问您当前的布局字符串setxkbmap -device <device id> -print | grep xkb_symbols并添加+custom到其中。使用 和修改后的布局字符串设置带有重新映射键的新布局:

setxkbmap -device <device id> -layout "us+ru:2+us:3+inet(evdev)+capslock(grouplock)+custom"

效果不是永久的,不幸的是,当连接其他键盘时会重置,目前还不知道如何修复它。您可以将上面的命令添加到您的.bashrc命令中,以便在必要时在重新启动时交换按键。

相关内容