Yar*_*tov 104 keyboard-shortcuts keyboard x11 xmodmap xkb
我正在尝试使用xmodmap重新映射Alt/Super戴尔 L100 键盘上的键,但在获取键码时遇到问题。
例如,使用xev不会给我键码Alt
FocusOut event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyGrab, detail NotifyAncestor
FocusIn event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyUngrab, detail NotifyAncestor
KeymapNotify event, serial 36, synthetic NO, window 0x0,
keys: 122 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Run Code Online (Sandbox Code Playgroud)
对于Right Super关键,xev并showkey给予不同的键码-134和126分别。
这些键码是怎么回事?
我尝试从 中获取键码showkey -k,并使用xmodmap下面的文件,但这给出了一个重新映射b键的奇怪映射:
clear Mod1
clear Control
keycode 125 = Meta_L
keycode 126 = Meta_R
keycode 58 = Control_L
keycode 56 = Control_L
keycode 100 = Control_R
add Control = Control_L Control_R
add Mod1 = Meta_L Meta_R
Run Code Online (Sandbox Code Playgroud)
dub*_*jim 71
在你的键盘和最终处理键盘事件的进程之间有很多玩家。景观的主要部分是这样一个事实,即 X 系统有自己的键盘处理层,并且 X 将不同的“键码”与键相关联,而不是您的 Linux 基本系统。该showkey命令向您显示了 Linux-base-system 行话中的键码。因为xmodmap您需要 X 键码,这xev就是显示的内容。只要您打算在 X 中工作并使用 重新绑定您的密钥xmodmap,那么,忽略showkeys并听听xev说什么。
你想在你的xev输出中寻找的是这样的块:
Run Code Online (Sandbox Code Playgroud)KeyPress event, serial 27, synthetic NO, window 0x1200001, root 0x101, subw 0x0, time 6417361, (340,373), root:(342,393), state 0x0, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 27, synthetic NO, window 0x1200001, root 0x101, subw 0x0, time 6417474, (340,373), root:(342,393), state 0x8, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
xev往往会产生大量输出,尤其是当您移动鼠标时。您可能需要向后滚动一段时间才能找到所需的输出。在前面的输出中,我们看到keysym Alt_L与 X 键码相关联64。
der*_*ert 27
奇怪的是,我的 xev 为 alt(以及 Windows 键,这里称为“超级”)提供了 KeyPress 和 KeyRelease 事件:
KeyPress event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595467354, (98,77), root:(102,443),
state 0x10, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595467453, (98,77), root:(102,443),
state 0x18, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
Run Code Online (Sandbox Code Playgroud)
和右手一个:
KeyPress event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595572876, (75,33), root:(79,399),
state 0x10, keycode 108 (keysym 0xffea, Alt_R), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595572972, (75,33), root:(79,399),
state 0x18, keycode 108 (keysym 0xffea, Alt_R), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
Run Code Online (Sandbox Code Playgroud)
我可以看到两种可能性:
xinit -- :1,它应该会得到一个只有一个 xterm 的 X 服务器——甚至不会有一个窗口管理器在运行。退出 xterm 将关闭会话)。另一种可能性:只需从 xmodmap 获取键码:
anthony@Zia:~$ xmodmap -pk | grep -i alt
64 0xffe9 (Alt_L) 0xffe7 (Meta_L) 0xffe9 (Alt_L) 0xffe7 (Meta_L)
108 0xffea (Alt_R) 0xffe8 (Meta_R) 0xffea (Alt_R) 0xffe8 (Meta_R)
204 0x0000 (NoSymbol) 0xffe9 (Alt_L) 0x0000 (NoSymbol) 0xffe9 (Alt_L)
anthony@Zia:~$ xmodmap -pk | grep -i super
133 0xffeb (Super_L) 0x0000 (NoSymbol) 0xffeb (Super_L)
134 0xffec (Super_R) 0x0000 (NoSymbol) 0xffec (Super_R)
206 0x0000 (NoSymbol) 0xffeb (Super_L) 0x0000 (NoSymbol) 0xffeb (Super_L)
Run Code Online (Sandbox Code Playgroud)
又是 64 和 108。xmodmap -pm将只显示修改器贴图,它还为您提供数字(不过,这次是十六进制)。
Rob*_*mer 23
我在你的问题中“发现”了三个问题:
xev和showkey一键报告不同的键码?xev显示Alt被正确按下?关于第一个问题:如今,X 中的键盘“驱动程序”并不真正驱动硬件,它只能将键码从内核传递到 X 内核,但事实并非如此。它在传递之前将 8 添加到键码。
第二:您的 X 会话中的某些内容正在抓取Alt事件。其他答案已经涵盖了这一点。(即xev没有得到你想看到的事件)。罪魁祸首可能与您的窗口管理器有关。尝试更裸的 X 会话。
第三:不要用xmodmap。它已经过时了十年。新人是 XKB 及其工具setxkbmap。
$ setxkbmap -query
rules: evdev
model: pc105
layout: us
variant: altgr-intl
options: caps:backspace
Run Code Online (Sandbox Code Playgroud)
对于交换Alt和Win已经存在的XKB准备的选项。只需添加它:
$ setxkbmap -option altwin:swap_alt_win
$ setxkbmap -query
rules: evdev
model: pc105
layout: us
variant: altgr-intl
options: altwin:swap_alt_win,caps:backspace
Run Code Online (Sandbox Code Playgroud)
Gre*_*reg 13
以 root 身份运行:
showkey -s
Run Code Online (Sandbox Code Playgroud)
...查看您的神秘钥匙的扫描码。我得到了这样的东西:
# showkey -s
kb mode was RAW
[ if you are trying this under X, it might not work
since the X server is also reading /dev/console ]
press any key (program terminates 10s after last keypress)...
0xc6
0x46 0xc6
0xc6
0x46 0xc6
0x46
Run Code Online (Sandbox Code Playgroud)
不知道为什么一个键会生成两个扫描码。这不是 keydown/keyup 的事情,我可以从模式中看出这一点。请注意警告,因此您可能希望在单用户模式下运行它。
我猜 0x46 是我的扫描码。
接下来,找到一个未使用的键码:
xmodmap -pke | less
Run Code Online (Sandbox Code Playgroud)
在这里您可以看到密钥代码 97 在我的系统上未使用:
keycode 94 = less greater less greater bar brokenbar
keycode 95 = F11 XF86Switch_VT_11 F11 XF86Switch_VT_11
keycode 96 = F12 XF86Switch_VT_12 F12 XF86Switch_VT_12
keycode 97 =
keycode 98 = Katakana NoSymbol Katakana
keycode 99 = Hiragana NoSymbol Hiragana
Run Code Online (Sandbox Code Playgroud)
由于“历史原因”,X 使用的键码和内核使用的键码为 OFF BY 8。所以取 97 - 8 = 89 并在 setkeycodes 命令中使用 89(再次以 root 用户身份):
# setkeycodes 46 89
Run Code Online (Sandbox Code Playgroud)
你应该被设置。使用 xev 确认您正在获得键码为 97 的 Keypress 事件。(尽管一旦我告诉 Fluxbox 键文件使用该键码,我就不再收到 KeyPress 事件——也许是因为 Fluxbox 在使用它们时吞下了它们?)
请注意,“setkeycodes”不会在重新启动后继续存在,因此您必须将其添加到您的 init 脚本中(例如,在 /etc/rc.local 中)
Kev*_*Cox 13
我试图为自己解决这个问题,我只是想通了。
主要问题是您没有收到按键事件。查看您发布的日志,原因很明显。
FocusOut event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyGrab, detail NotifyAncestor
FocusIn event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyUngrab, detail NotifyAncestor
KeymapNotify event, serial 36, synthetic NO, window 0x0,
keys: 122 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Run Code Online (Sandbox Code Playgroud)
你可以看到的Focus{In,Out}事件有一个mode的Notify{Grab,Ungrab}。这表明一个键被另一个进程处理(可能是一个快捷方式/键绑定应用程序)。
就我而言,它是 xbindkeys,但如果您使用的是桌面环境,它们可能有一个键绑定系统。为了查看这些事件是 xev,您需要停止/禁用其他程序。
如果您无法确定哪个程序正在窃取关键事件,那么最好的解决方案是在没有运行的情况下启动另一个 X 会话。运行以下命令以在 display 上启动另一个 X 会话:1,如果已经被占用,只需增加最后的数字。您当然可以将终端更改为您喜欢的或系统上已安装的任何终端。
xinit /usr/bin/xterm -- :1
Run Code Online (Sandbox Code Playgroud)
然后xev再次运行。这应该会给你结果,而不会被其他程序捕获。请注意,启动的窗口管理器是悬停焦点,因此您必须将光标放在 xev 窗口上方才能捕获键。
正如dubiousjim在这个出色的回答中所说,键码是不同的,因为 xev 和内核之间有很多层。