VT 下的键盘映射设置
最近遇到在 X11 下切换到 TTY 可以用 Ctrl+LeftAlt+Fn 或 Ctrl+RightAlt+Fn,但从 TTY 切换回 X11 只能使用 Ctrl+LeftAlt+Fn 的问题。 为了手感比较一致今晚解决了这个问题并记录在这里,希望能帮助遇到同样问题的人。
具体原因是 X11 下的键盘映射由 xkbmap 来管理,它默认提供了比较复杂的配置;但 VT 直接运行在内核上没有经过 X11 它的配置更直接和简单。
这两份配置的不同导致了在 VT 下 RightAlt 不能正确映射。
这里我们关心的是 keycode 到 keysym 的映射关系,
更过关于 scancode, keycode, keysym 的概念解释可以先参考
ArchLinux 键盘映射 的第一小节。
这个 keycode 到 keysym 的映射关系就是我们常说的 keymap,
就是装各种系统时要选的键盘布局。
所有的 keymap 都存在 /usr/share/dbd/keymaps
中:
find /usr/share/kbd/keymaps/ -type f
关键在于 X11 和 VT 中如何选择这些文件,其中每个 .map.gz 文件解压后得到的 .map 文件即为键盘布局文件。文件中的数字表示 keycode,Alt、Control 这样的词即为 keysym。
查看 X11 下的键盘映射
X11 的键盘映射可以通过 setxbdmap
打印出来,可以看到它合并了很多个 keymap 文件:
> setxkbmap -print -verbose 10
...
xkb_keymap {
xkb_keycodes { include "evdev+aliases(qwerty)" };
xkb_types { include "complete" };
xkb_compat { include "complete" };
xkb_symbols { include "pc+us+inet(evdev)+terminate(ctrl_alt_bksp)" };
xkb_geometry { include "pc(pc104)" };
};
在 X11 下可以通过 xev
来看每个键对应的 keycode 和 keysym。
配置 X11 下的键盘映射
设置 X11 键盘映射可以使用 setxbdmap
, localectl
,也可以配置在 xorg.conf 里。比如 /etc/X11/xorg.conf.d/00-keyboard.conf
文件中:
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "cz,us"
Option "XkbModel" "pc104"
Option "XkbVariant" ",dvorak"
Option "XkbOptions" "grp:alt_shift_toggle"
EndSection
这里的 XkbLayout 的值即对应 /usr/share/kbd/keymaps/
下的映射文件。
可以查阅 ArchWiki 有更详细的教程。
查看 VT 下的键盘映射
VT(Virtual Terminal)就是 Linux 内核提供的虚拟终端,通常使用 Ctrl+Alt+Fn 来切换,X11 通常运行在 Ctrl+Alt+F7 上面。 可以通过 Ctrl + Alt + F2 切到第二个 VT 上。 本文的上下文中 VT 和 TTY 是指同一个东西,叫做 TTY 是因为它的设备名叫做 ttyN。 比如在任何一个 VT 或 Terminal Emulator(比如 Termite、Konsole、Urxvt)中执行:
echo hello > /dev/tty2
你可以在第二个 VT 上看到 "hello"
字样输出。还分不清 VT、Shell、Terminal 概念的请看这篇扫盲文章:
Shell 的相关概念和配置方法。
VT 下的键盘映射可以通过 dumpkeys
来查看:
> dumpkeys | less
...
keycode 56 = Alt
keycode 100 = AltGr
keycode 59 = F1 F13 Console_13
control alt keycode 59 = Console_1
keycode 60 = F2 F14 Console_14
control alt keycode 60 = Console_2
...
VT 下可以通过 showkey
可以看到左右 Alt 对应的 keycode:
> showkey
keycode 56 press # 按下 Left Alt
keycode 56 release
keycode 100 press # 按下 Right Alt
keycode 100 release
因此 Alt(56)是指 Left Alt,AltGr(100)是指 Right Alt。
dumpkeys
显示 control alt F1 映射到 Console_1,但 control altgr F1 没有映射,
因此 Control+RightAlt+F1 无法切换 VT。原因已经明确接下来我们想办法把 AltGr 的映射也加进去。
设置 VT 下的键盘映射
VT 下的 keymap 由 /etc/vconsole.conf
中的 KEYMAP
字段来配置(可以 man vconsole.conf
来查看这个配置文件的语法)。
如果你的文件中也没有这项配置,那么你跟 Harttle 一样用的默认布局 us
,
即这个文件:/usr/share/kbd/keymaps/i386/qwerty/us.map.gz
。
我们解压后看这个 us.map 文件内容:
> cp /usr/share/kbd/keymaps/i386/qwerty/us.map.gz keymap.map.gz
> gunzip keymap.map.gz && cat keymap.map
...
keycode 56 = Alt
接下来我们在解压后的 keymap.map 中添加如下内容并另存为 /home/harttle/.config/keymap.map
。
control altgr keycode 59 = Console_1
control altgr keycode 60 = Console_2
control altgr keycode 61 = Console_3
control altgr keycode 62 = Console_4
control altgr keycode 63 = Console_5
control altgr keycode 64 = Console_6
control altgr keycode 65 = Console_7
control altgr keycode 66 = Console_8
control altgr keycode 67 = Console_9
control altgr keycode 68 = Console_10
control altgr keycode 87 = Console_11
control altgr keycode 88 = Console_12
然后在 /etc/vconsole.conf
中把 KEYMAP 配置到我们的新文件:
KEYMAP=/home/harttle/.config/keymap.map
重启后在 VT 中左右 Alt 都可以正常切换 TTY 了。也可以在 VT 中先用 loadkeys
(这就是启动时 systemd 执行的命令)验证:
loadkeys /home/harttle/.config/keymap.map
本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2019/12/07/virtual-console-keymap.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。