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


18

我最近购买了Unicomp键盘,该键盘带有互换的右键和Windows键。键盘在lsusb上标识如下:

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

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


我怀疑您可以通过udev做到这一点,方法是匹配键盘的序列号,然后调用执行重新映射的脚本。您可能需要在detach上调用类似的脚本,以便设备将其放回原处。
果酱

1
@jam会重新映射所有连接的键盘吗?我无法想象Linux如此灵活,以至于它只能为所有连接的(USB)键盘管理一个映射表。
2014年

@jam此外,如果您可以描述如何进行实际交换,那么您将真的对我有帮助。我没有找到任何有用的东西,只有xmodmap东西(我不想使用)。
2014年

如果您不想使用xmodmap,那么您所要求的内容似乎太具体了,以至于我无法帮助您。我建议的方法是,在连接特定键盘的期间内,使用xmodmap交换所有设备的这些键的键代码,然后放回去。您是否希望同时使用多个键盘?
2014年

@jam如果使用Xmodmap,则X程序仍会看到错误的键码,因为X服务器还将未翻译的键码发送到客户端。例如,这对于视频游戏很重要。内核中应该有一个解决方案,不会因读取扫描代码的应用程序而使我的生活变得更加复杂。
2014年

Answers:


27

是的,可以使用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中查找84 。的键名是<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中)。全做完了!现在,按键应该只为您指定的设备生成所需的输出。

编辑:最近,我注意到由于某种原因,新配置没有立即应用。您必须首先按另一个键盘上的一个键,然后在修改后的键盘上测试配置的键。我不知道为什么会发生这种情况,也许是某种缓存。


回到星期一使用键盘的计算机上,让我尝试一下。
FUZxxl 2015年

1
a) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' c)是,您绝对应该先用$remote_idid编号进行测试。请注意,这里有两个引用$remote_id,您都更改了吗?
Watcom

1
哦,在测试硬编码时$remote_id,请确保将行注释掉([ "$remote_id" ] || exit如果尚未注释),否则它将退出紧急状态。
Watcom

1
@ stats-hb $9无法正常工作,是9什么意思?
Watcom


6

对于从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的G15Daemon用户空间驱动程序G15游戏键盘。

    (它吞下了打算重新映射的事件,因此,在设备上进行监听的其他任何人都无法看到它们,然后通过uinputAPI 发出更正后的事件,以从用户空间创建内核级输入设备。)


要从

0

对于那些无法使用@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 ]        };
};

到/ usr / share / X11 / xkb / symbols /(可能是root)(ubuntu,对于您的发行版可能有所不同),将文件称为“ 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,以便在必要时重新启动时交换密钥。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.