
基础知识必修1-广义上的键盘布局
键盘布局(keyboard layout)是指以按键、或键上图例来表示任何特定之机械、视觉或功能的键盘布局方式;或则是在计算机、打字机或其它字体排版键盘等之类似设备、以其键之关系含义结构在键盘上表现的布局方式。机械布局是指键盘上的位置及按键。视觉布局是指出现在键盘按键上的图例(标签、标记、图饰)的排列方式。功能布局是指键盘上所有按键由软件确定其按键含义、或键盘映射的布置。 --Wikipedia
意思是说键盘布局在使用中分三个层次
1.机械布局:按键的物理排布。
目前世界上常见的机械布局有三种,ANSI、ISO、JIS分别是图中的左上、左中、右下。其他较为少见的布局也有三种。他们的主要差别在左Shift旁边的一个按键、空格边的几个修饰键、Enter周围的几个用作符号输入的键。
101/104、102/105之类的3键差别在于两个Win键和一个菜单键(Menu),108键又比104键多了4个多媒体按键。除此之外常见的还有去除小键盘区17个按键后的87键紧凑布局、以及Apple公司生产设计的ANSI(扩展布局109键,紧凑78键)、ISO(扩展布局110键,紧凑79键)、JIS(扩展布局112键,紧凑80键)。在一些笔记本内置键盘上为了空间考虑一般Menu会和Ctrl之类的修饰键放在一起,通过Fn实现,在键盘印刷上会是和Fn一样的蓝色标识。Fn键根据不同厂商的实现有所不同,有左有右。以上这些差异都属于键盘的机械布局。
实际上,诸如“ISO和”和“ANSI”之类的机械布局标准中只提供了主要建议,事实上每个标准也都允许采用其他具体的实现方法。从这个意义上讲,键盘布局既可以指广义的分类,也可以指这些类别的细微差别。 --Wikipedia

键盘的机械布局
2.视觉布局:每个键帽上标的东西,图例、字符之类的东西。用大白话来解释就是键冒上标着什么东西。这些为了使用方便可以随意更改。
一般常见的键盘上标识的"A"、"8"、"="、"Backspace"、"Ctrl"、"F7"都属于视觉布局,刚刚提到的"Fn"和"Menu"标识的位置颜色都属于视觉布局。日本的一些键盘上还会有平假名片假名,中国台湾和中国香港、中国澳门也会使用被称为“四合一键盘”的视觉布局。
这些都是人为印刷上去的,只是为了方便使用。只要你开心,你也可以在自己的键盘上贴一些贴纸(例如Emoji😂?)来更改视觉布局(甚至刮掉原来的印刷把它变成什么都没有的白板键盘¿)。

四合一键盘

日文假名键盘

IBM/Windows键盘(美式布局)
3.功能布局:按下一个或多个按键产生的效果,由软件定义。
严格来讲,“Qwerty布局”、“Dvorak布局”、“Colemak布局”布局是由操作系统定义的功能布局。它们由不同的软件把你的输入变成对应的符号或修饰命令(Shift、Ctrl之类的)。称它们为布局只是一个通用的约定叫法,它们其实更应该被叫做“Qwerty键盘映射”、“Dvorak键盘映射”之类的名字。
还有非常常见的复制粘贴功能:Windows风格的Ctrl-c复制,Ctrl-v粘贴,Emacs编辑器中Meta-w复制,Ctrl-y粘贴,这些都是由软件提供定义的。包括Adobe全家桶中的各种快捷键,都是功能布局。各个软件的功能布局有的可以定制,有的不能定制,由软件自身决定。
基础知识必修2-键盘按键的处理过程
概述,一个键从按下到得到最终的效果需要经过三次处理:KEYBOARD --> scancode --> keycode --> keysymbol ①键盘电路 ②内核处理 ③软件设置
①键盘硬件把你的按键行为转换成计算机能识别的 scancode
②系统内核把scancode转换成TTY或X11需要使用的 keycode
③TTY或X11的设置把keycode转换成具体的按键目的 keysymbol
硬件层KEYBOARD --> scancode不管是什么样的键盘,你常见的普通QWERTY键盘也好,其他国家的小语种键盘也好。键盘上的按键,在触发或弹起时都会产生一个叫扫描码(scancode)的16进制数,并通过线缆或者无线信号传给计算机。扫描码由键盘的电路产生,由通用协议定义,在不拆开键盘修改键盘电路板和键盘固件的情况下无法更改。这个协议描述了键盘上位于特定物理位置的键会产生什么样的扫描码,生产厂家生产键盘时都要遵循这些标准。古老的AT键盘,中古时代的PS2键盘,现代的USB键盘都有各自的协议,不同协议中,这个值的位数和具体数值都可能不同。这些定义由于是针对全球的,所以不同机械布局的键盘也都遵守。
内核层(驱动层)scancode --> keycode(kernel) 注¹系统内核,或者更准确的说,硬件驱动接收到这个扫描码。根据一个内置的,缺省的映射表(scancode-to-keycode mapping)来产生一个叫键码(keycode)的16进制数。keycode的值代表一个键盘上某个特定且唯一的键被按下或释放的事件,不代表具体的键入符号。可以和scancode一一对应。
应用软件层keycode(kernel) --> keycode(App) --> keysymbol 注²最后一步,内核把这个键码传递到一个转译软件里,转译软件根据Qwerty、Dvorak、Colemak或者其他等不同键盘映射所定义的“键盘映射表”和其他一些选项来把键码转译到键符号(keysymbol)。就是通常可以看到的各种按键行为(Action):输入一个字符、切换大写锁定、按Ctrl+C复制、TTY下Ctrl+C中断指令的执行……转译软件是应用软件,装系统的时候让你选择键盘布局就是选择转译选项,但绝大多数情况下默认提供,少数情况下需要自行安装。例如Win10就不提供Colemak键盘映射的选项,需要到Colemak官网自行下载安装。注¹²:转译软件会自己定义一套keycode,具体值由内核传出的keycode而定。我们为了方便区分,把内核传出的keycode叫keycode(kernel),把转译软件定义的keycode叫keycode(App)。TTY和X11的转译软件相互独立,所以它们的keycode(App)是互相独立的,并不通用,一般来说:TTY内部定义的keycode(App_TTY) = keycode(kernel)X11内部定义的keycode(App_X11) = keycode(kernel) + 8
补充:查看键码到键符号映射的方法:
X11图形环境:在图形环境的虚拟终端执行命令 xmodmap -pke | less
TTY:在TTY中执行 dumpkeys -f | less
总结:通过多层次的键盘处理可以让不同机械布局、不同视觉布局的实体键盘可以映射到任意的键盘映射。增强了通用性,不至于让你在欧洲或者日本买到的那些根据ISO或JIS标准设计、印着假名或者各类小语种字符的键盘变成摆设。
现代计算机键盘被设计为在按下某个键时将扫描代码发送到操作系统,而不是将刻在该键上的特定字符发送给它。操作系统使用称为键盘映射表的“扫描码转换为字符”转换表将扫描码转换为特定的二进制字符码。这意味着物理键盘可以动态映射到任何
布局注³,而无需切换硬件组件,而只需更改解释按键的软件即可。 --Wikipedia 注³:准确的说应该是任何的键盘映射,甚至包括你自定义的键盘映射。
Linux键盘映射的设置分两个地方,一个是X11的图形环境,一个是虚拟控制台TTY。但是如果你的发行版使用Systemd来作为系统和服务管理器。那么可以使用它提供的localectl来统一管理。具体使用方法见man Page https://jlk.fjfi.cvut.cz/arch/manpages/man/community/man-pages-zh_cn/localectl.1.zh_CN
https://jlk.fjfi.cvut.cz/arch/manpages/man/community/man-pages-zh_cn/localectl.1.zh_CN
X11环境的设置
关于其中的LAYOUT、MODULE、VARIANT、OPTIONS
LAYOUT就指你键盘上默认的机械布局,目前中国可以买到的绝大多数键盘设为us就可以了。
MODULE指对一部分特殊硬件做的适配,多数为笔记本电脑,例如Thinkpad、Surface、Latitude、Macbook之类的。如果你没有找到你使用的型号,用pc104就可以。
VARIANT指你要设置的键盘映射,例如Dvorak、Colemak、Workman等等。如果你没有使用这些键盘映射的需求,那么缺省不填或使用qwerty都可。
OPTIONS指你需要使用的一些选项,例如交换Esc和CapsLock、交换Win和Ctrl之类的。但是非常不建议使用。
这些可用选项见man Page https://jlk.fjfi.cvut.cz/arch/manpages/man/extra/xkeyboard-config/xkeyboard-config.7.en
https://jlk.fjfi.cvut.cz/arch/manpages/man/extra/xkeyboard-config/xkeyboard-config.7.en
TTY的下的设置
TTY下也可以使用set-keymap来设置键盘映射,可用的所有映射在/usr/share/kbd/keymaps/目录下分类存放,后缀名为.map.gz或.map的是可用的键盘映射,后缀名为.inc的是一些可用的按键具体行为的选项,因为大多数键盘映射的这些行为都相同,所以提取出来实现代码复用。
如果你对TTY下的键盘映射有自己的需求,可以自己进行修改。
例如我使用Dvorak键盘映射,但是TTY下自带的Dvorak映射会把右边的Alt设为AltGr,以用来输入一些特殊的字符比如á ð ú等等(事实上因为TTY的自体限制,这些字符一般也没法显示)。我用不到,我需要用Meta-f和Meta-b来在TTY下快速移动光标而非AltGr。
我的做法是把/usr/share/kbd/keymaps/i386/dvorak/dvorak.map.gz做一个拷贝,并解压到/usr/share/kbd/keymaps/person-dvorak.map(之所以不放在原来的目录下是为了方便管理)。
然后把其中的include "linux-with-alt-and-altgr.inc"选项改为include "linux-with-two-alt-keys.inc"并保存。此时使用localectl set-keymaps person-dvorak就可以设置我自己定义的布局了。如果你像我一样希望使用自己定义的映射,那么需要使用--no-convert选项,否则会默认使用相同的映射,而忽略你自己定义的映射文件。
!!!极其不建议修改原有的映射文件
正确做法:拷贝原有映射文件,并在此基础上修改内容和文件名。