如何获取 xmodmap 的键码?

如何获取 xmodmap 的键码?

我正在尝试使用Dell L100 键盘上的xmodmap重新映射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密钥,xev并分别showkey给出不同的密钥代码 -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

答案1

在你的键盘和最终处理键盘事件的进程之间有很多参与者。其中最重要的部分是 X 系统有自己的键盘处理层,并且 X 将不同的“键码”与按键相关联,这与 Linux 基本系统不同。该showkey命令向您显示 Linux 基础系统术语中的键码。因为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 keycode 关联64

答案2

xev应该可以工作

奇怪的是,我的 xev 为 alt 提供了 KeyPress 和 KeyRelease 事件(对于 Windows 键,这里称为“超级”):

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只会显示修改器映射,它还会为您提供数字(不过,这次是十六进制)。

答案3

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

  1. 为什么对一个键要报告不同的键码xevshowkey
  2. 为什么xev没有显示Alt被正确按下?
  3. Alt和怎样交换Win

关于第一个问题:如今,X 中的键盘“驱动程序”并不真正驱动硬件,它可能只是将键码从内核传递到 X 核心,但事实并非如此。它在传递密钥代码之前会添加 8。

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

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

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

对于交换AltWinXKB 中已经准备了一个选项。只需添加它:

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

答案4

我试图自己解决这个问题,然后我就弄清楚了。

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

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}mode一个Notify{Grab,Ungrab}。这表明某个键已由另一个进程(可能是快捷方式/键绑定应用程序)处理。

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

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

xinit /usr/bin/xterm -- :1

然后再跑xev。这应该会给你结果,而不会被其他程序捕获。请注意,启动的窗口管理器是悬停焦点,因此您必须将光标放在 xev 窗口上方才能捕获按键。


正如中所说dubiousjim 的精彩回答,键码不同,因为 xev 和内核之间有很多层。

相关内容