这里有两层,KEYCODE到KEYSYM的映射和KEYSYM到文本的映射。如果算上内核,则还有更多层,必须将AT键盘扫描码映射到XT样式的KEYCODE或将USB键盘HID代码映射到KEYCODE。KEYCODE只是一个8位无符号整数,操作系统的内核将其传递给X11服务器。在Linux和Solaris等操作系统之间,它可能有所不同。在Linux上,这些KEYCODE通常与旧XT PC键盘上使用的数字相同。带有AT,PS / 2或USB键盘的新型计算机通常只会将这些键盘映射到旧的XT代码,以使密钥保持简单。
原始键盘代码(无论是XT,AT,PS / 2还是USB)都表示键盘上的物理位置。XT键盘仅在按下或释放键时发送一个8位数字。美国/英国XT键盘上的q键发送数字16。在法语键盘上,相同的物理键标记为a,但仍发送16。这是操作系统的高层为其赋予了真正的含义。在XT键盘上释放键时,将发送相同的键码加128。对于此示例,当按q时,发送的是16,但在释放时,发送的号码是142(16 + 128)。AT键盘使用的扫描码是一系列数字,可能会很长。关键版本添加了其他代码。例如,暂停的扫描代码为E1、1D,45,E1、9D,C5。大多数操作系统,包括DOS,Windows,Linux,FreeBSD,BIOS将所有扫描码映射为更简单的XT样式的扫描码。它还使支持使用不同代码的新型键盘(例如发送HID代码的USB键盘)更加容易。在X11或应用程序看到它们之前,操作系统会将所有代码映射到相同的一致代码集。
X11不了解该过程的这一部分,它只是从内核获取KEYCODE,并应用其自己的映射将该KEYCODE转换为KEYSYM。 Xmodmap是用于控制该映射的标准工具。键盘映射的大多数行为都是可配置的,但是有几种特殊情况(例如Num Lock,模式切换和Caps Lock / Shift Lock)被硬编码到X11中。Shift等其他方面实际上是可配置的。与模式切换或数字锁定不同,任何键都可以映射为移位。
KEYCODE代表操作系统内核发送的物理密钥。每个KEYCODE可以映射到8个可能的KEYSYM。仅使用4个,有时称为1-4级。级别1指定在没有修改器处于活动状态时打印的KEYSYM。这些通常是小写字母和数字。修饰符是在修饰符处于活动状态(按下或启用时)时,其修饰其他键代码生成的KEYSYM的键代码。修饰符键代码也通过Xmodmap控制。级别2指定按下shift修饰符时要发送的KEYSYM。只要按下模式开关KEYSYM,就会激活3级。当同时按下换档键和模式开关时,将激活级别4。
生成KEYSYM后,可以直接对其进行解释,但大多数情况下将其转换为文本。并非所有的KEYSYM都变成文本,或者可能仅影响将来的KEYSYM。一个示例当然是Shift_L,它没有文本表示形式,但是也有许多KEYSYM用于组成另一个字符。在我的系统上的列表在下面/usr/share/X11/locale/en_US.UTF-8/Compose
。一个这样的示例就是dead_acute KEYSYM,当按下该键时,它将尝试将下一个KEYSYM转换为带有重音符号的字母。有一个用于将KEYSYM转换为Unicode 的标准映射。
现在已经说完了所有这些,请注意Xmodmap已过时,并由更为复杂的XKB代替。这会影响KEYCODE如何映射到KEYSYM,但不会影响内核如何生成KEYCODE,也不会影响KEYSYM如何转换为文本或组成相同的文本。可以禁用XKB来恢复Xmodmap行为。它还具有一个兼容层来支持Xmodmap,但是由于不完全兼容,因此可能会出现问题。XKB规则在下面/usr/share/X11/xkb/
并且要复杂得多。在其他地方,有一些很好的文档介绍了如何生成用于将KEYCODE映射到KEYSYM的键盘布局。
对于Linux控制台,它具有自己的键盘布局,这些布局存储在命令中/usr/share/keymaps
并随loadkeys
命令一起加载。在BIOS和较早的引导加载程序阶段(包括GRUB2)时,键盘映射是BIOS决定将键映射到的数字。