如何获取xmodmap的密钥代码?


76

我试图用来xmodmap重新映射Dell L100键盘上的Alt/ Super键,并且在获取键码时遇到问题。

例如,使用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   

对于Right Super关键,xevshowkey给予不同的键码- 134126分别。

这些键码是怎么回事?

我尝试从中获取密钥代码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

我在XUbuntu 14.04上有一个不触发Alt_L的问题(但是Alt_R很好)。您正在使用什么系统?
Paul Price

Answers:


54

键盘和最终处理键盘事件的过程之间有许多参与者。X环境具有自己的键盘处理层,并且X与Linux基本系统相比,X将不同的“键码”与键相关联,这是整个格局的主要组成部分。该showkey命令向您显示Linux-base-system术语中的键代码。因为xmodmap您需要显示的X键码xev。只要您打算使用X并使用进行键重新绑定xmodmap,那么就忽略showkeys并仅听其内容xev

您想要在xev输出中寻找的是这样的块:

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


3
问题是我没有在Windows键上收到KeyPress事件。我尝试了3种不同的键盘,结果相同。从xev只能得到FocusOut,FocusIn和KeymapNotify,如上所示。但是,我可以通过Gnome管理器来设置快捷方式,它会将Windows密钥视为“ Mod4”
Yaroslav Bulatov 2012年

右Windows键报告为Mod4,左Windows键报告为Alt ...这令人困惑,因为我的xmodmap中甚至没有“ Alt”类别。
Yaroslav Bulatov

尝试使用Mod1替代Alt。
dubiousjim 2012年

2
@YaroslavBulatov听起来像你的桌面环境是吃的关键(可能以显示其主菜单?)
derobert

3
您可以过滤xev给您的事件。在这种情况下xev -event keyboard,足以消除大多数噪音。
Fredrik Wendt

24

xev应该工作

奇怪的是,我的xev为alt(以及Windows键,在这里称为“ super”)给出了一个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

右手:

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

我可以看到两种可能性:

  1. 其他事情是完全吃掉了按键,或者在按下alt时使窗口散焦。尝试在原本为空的X服务器中运行xev(例如,只需运行xinit -- :1,这将使您只有一个xterm的X服务器-甚至没有窗口管理器在运行。退出xterm将关闭会话)。
  2. 您只是错过了xev发出的两个事件。

一种简单的方法,如果您知道密钥名

另一种可能:只需从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)

再有64和108。xmodmap -pm只会向您显示修饰符映射,该映射也为您提供数字(尽管这次是十六进制)。


15

我“发现”您的问题中的三个问题:

  1. 为什么xevshowkey一键报告不同的键码?
  2. 为什么xev显示Alt不正确?
  3. 如何互换AltWin

关于第一个问题:近来,X中的键盘“驱动程序”并没有真正驱动硬件,它只能将键码从内核传递到X内核,但事实并非如此。在传递密码之前,它会在键码上加8。

第二:您的X会话中正在抓取Alt事件。其他答案已经涵盖了这一点。(即xev没有您想要看到的事件)。罪魁祸首可能与您的窗口管理器有关。尝试更赤裸的X会话。

第三:不要使用xmodmap。它已经过时了十年。新手是XKB及其工具setxkbmap

$ setxkbmap -query
rules:      evdev
model:      pc105
layout:     us
variant:    altgr-intl
options:    caps:backspace

对于交换AltWin已经存在的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

您如何使setxkbmap更改永久生效?
Steve Kehlet17年

将更改添加到~/.xinitrc
Matthias Braun

11

以超级用户身份运行:

showkey -s

...以查看神秘密码的扫描码是什么。我得到这样的东西:

# 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 

不知道为什么一个键会生成两个扫描代码。从我从模式中可以看出,这不是按键/按键操作。请注意警告,因此您可能需要在单用户模式下运行此警告。

我猜是0x46是我的扫描代码。

接下来,使用以下命令查找未使用的键码:

xmodmap -pke | less

在这里,您可以看到在我的系统上未使用键码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

由于“历史原因”,X使用的密钥代码和内核使用的密钥代码均为OFF BY 8。因此,将97-8 = 89并与setkeycodes命令一起使用89(再次以root用户身份):

# setkeycodes 46 89

而你应该被设置。用xev确认您收到的键代码为97的Keypress事件。(尽管一旦我告诉Fluxbox密钥文件使用该键代码,我就再也没有KeyPress事件了-也许是因为Fluxbox在使用它们时会吞下它们吗?)

请注意,“ setkeycodes”在重启后将无法生存,因此您必须将其添加到初始化脚本中(例如,在/etc/rc.local中)


1
您是否有关于“由于历史原因而减少8分”的指标?
罗伯特·西默

我用您的答案将大写锁定映射到功能键上(特别是F9)。这使我可以将F9用作tmux中的前缀键。谢谢。
雷蒙德·克鲁克

@RobertSiemer tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html “通常X数比Linux数多8。” 我用“历史的”一词一定是来自另一本手册。
格雷格·贝尔

11

我试图自己解决这个问题,但我只是想出了办法。

主要问题是您没有为按键事件。查看您发布的日志,原因很明显。

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   

你可以看到的Focus{In,Out}事件有一个modeNotify{Grab,Ungrab}。这表明密钥是由另一个进程(可能是快捷方式/密钥绑定应用程序)处理的。

就我而言,它是xbindkeys,但是如果您使用的是桌面环境,则它们可能具有键绑定系统。为了看到这些事件是xev,您将需要停止/禁用其他程序。

如果您无法确定哪个程序在窃取关键事件,最好的解决方案是在不运行该程序的情况下启动另一个X会话。运行以下命令以启动显示器上的另一个X会话:1(如果已执行),只需增加最后的数字即可。当然,您可以将终端更改为您喜欢的终端或系统上已安装的终端。

xinit /usr/bin/xterm -- :1

然后xev再次运行。那应该给您结果而不会被其他程序捕获。请注意,开始的窗口管理器是悬停焦点,因此必须将光标置于xev窗口上方才能捕获键。


就像dubiousjim这个很好的回答中所说的那样,键码是不同的,因为xev和内核之间有很多层。


4

Alt_L在XUbuntu 14.04中消失时遇到了同样的问题(Alt_R很好)。经过大量的演奏,我观察到showkey记录了击键,但是xev并没有---它一定是窗口系统中的东西。我搜寻了所有的“窗口管理器”和“窗口管理器调整”设置,但没有找到任何东西。最终,我在“设置编辑器” Alt_L的键盘快捷键(xfce4-keyboard-shortcuts)列表中发现了一个流浪汉。我将其“重置”,并且我得到了Alt_L支持!Alt_L除“设置编辑器” 中外,杂散快捷方式未在其他任何地方显示。

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.