我最近买了一个 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
以便更改适用于所有应用程序:
udev 提供了一个 API,用于修改控制扫描码和键码之间映射的硬件数据库条目。这个 ArchiWiki 页面,其中包含说明,明确说明它适用于 X11 和控制台输入。
要点是,您创建一个自定义条目,
/etc/udev/hwdb.d/
其中包含设备匹配模式和一些扫描码到键码重新映射定义,然后运行systemd-hwdb update
以重建数据库并udevadm trigger
在无需重新启动的情况下应用它。鉴于 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
命令中,以便在必要时在重新启动时交换按键。