Answers:
有几种不同的方案。我将介绍最常见的那些。连续的宏观事件是:
a
。a
上显示的顺序。Unix系统的事实上的标准图形用户界面是X Window System,通常称为X11,因为它稳定在应用程序和显示服务器之间的核心协议的第11版中。名为X服务器的程序位于操作系统内核和应用程序之间;它提供的服务包括在屏幕上显示窗口以及将按键传送到具有焦点的窗口。
+----------+ +-------------+ +-----+
| keyboard |------------->| motherboard |-------->| CPU |
+----------+ +-------------+ +-----+
USB, PS/2, … PCI, …
key down/up
首先,有关按键和释放键的信息从键盘传输到计算机以及计算机内部。详细信息取决于硬件类型。在这一部分中,我不会再赘述,因为在整个链的这一部分中,信息都是相同的:按下或释放某个键。
+--------+ +----------+ +-------------+
-------->| kernel |------->| X server |--------->| application |
+--------+ +----------+ +-------------+
interrupt scancode keysym
=keycode +modifiers
发生硬件事件时,CPU会触发一个中断,从而导致内核中的某些代码执行。此代码检测到硬件事件是来自键盘的按键按下或释放,并记录了标识该键的扫描代码。
X服务器通过设备文件读取输入事件,例如/dev/input/eventNNN
在Linux(其中NNN是数字)上。每当发生事件时,内核都会发出信号,表明有数据要从该设备读取。设备文件使用扫描代码传输上/下键事件,该事件可能与硬件传输的值相同或不同(内核可以将扫描代码从与键盘相关的值转换为公共值,而Linux 不会)不会重新传输它不知道的扫描代码)。
X调用它读取密钥代码的扫描代码。X服务器维护转换键码到表键符(以下简称“重点符号”)。键码是数字的,而键符的名字,如A
,aacute
,F1
,KP_Add
,Control_L
,...的键符可以根据在其上按下修改键(不同Shift,Ctrl...)。
有两种机制可以配置从键码到键符的映射:
应用程序连接到X服务器并在该应用程序的窗口具有焦点的情况下按下键时收到通知。该通知表明已按下或释放了某个键,以及当前按下了哪些修饰符。您可以通过xev
从终端运行程序来查看键盘符号。应用程序如何处理信息就可以了;一些应用程序具有可配置的键绑定。
在典型的配置中,当您按下A没有修饰符的键时,这会将键盘符发送a
到应用程序;如果应用程序处于您输入文本的模式,则会插入字符a
。
键盘布局和xmodmap的关系在键盘输入上有更详细的说明。鼠标事件在Linux中如何工作?概述了较低级别的鼠标输入。
+-------------+ +----------+ +-----+ +---------+
| application |------->| X server |---····-->| GPU |-------->| monitor |
+-------------+ +----------+ +-----+ +---------+
text or varies VGA, DVI,
image HDMI, …
有两种显示字符的方法。
请参阅不同类型的XWindows字体的用途是什么?在X11下讨论客户端和服务器端文本呈现。
X服务器与图形处理单元(视频卡上的处理器)之间发生的情况与硬件有关。简单的系统将X服务器绘制在称为framebuffer的内存区域中,GPU会拾取该内存以进行显示。诸如21世纪PC或智能手机上的高级系统都可以使GPU直接执行某些操作,以提高性能。最终,GPU每隔几分之一秒将屏幕内容逐像素传输到监视器。
如果您的文本编辑器是在终端中运行的文本模式应用程序,则对于以上部分而言,终端是该应用程序。在本节中,我将解释文本模式应用程序和终端之间的接口。首先,我描述了在X11下运行终端仿真器的情况。“终端”,“外壳”,“ tty”和“控制台”之间的确切区别是什么?在这里可能是有用的背景。阅读本文之后,您可能想阅读更详细的内容,每个伪终端(PTY)组件(软件,主控端,从属端)的职责是什么?
+-------------------+ +-------------+
----->| terminal emulator |-------------->| application |
+-------------------+ +-------------+
keysym character or
escape sequence
终端仿真器接收到诸如“ Left
按下时Shift
被按下”之类的事件。终端仿真器和文本模式应用程序之间的接口是伪终端(pty),即一种传输字节的字符设备。当终端仿真器收到按键事件时,它将事件转换为一个或多个字节,应用程序将从pty设备读取该字节。
ASCII范围以外的可打印字符将根据一个字符或一个以上字节进行传输,具体取决于字符和编码。例如,在Unicode字符集的UTF-8编码中,ASCII范围内的字符被编码为单个字节,而该范围之外的字符被编码为多个字节。
对应于一个功能键或用改性剂,例如可打印的字符按键Ctrl或Alt作为一个发送转义序列。转义序列通常由字符转义(字节值27 = 0x1B = \033
,有时表示为^[
或\e
)组成,后跟一个或多个可打印字符。在基于ASCII的编码中,一些键或组合键具有与之相对应的控制字符(当今几乎所有这些键或键都在使用中,包括Unicode):Ctrl+ letter产生的字符值为1–26,Esc是转义字符看出上述和也一样Ctrl+ [,Tab是一样的Ctrl+ I,Return与Ctrl+ M等相同
对于给定的键或键组合,不同的终端发送不同的转义序列。幸运的是,事实并非如此:给定一个序列,实际上最多只能编码一个组合键。一个例外是字符127 = 0x7f = \0177
,该字符经常出现,Backspace但有时会出现Delete。
在终端中,如果键入Ctrl+ V后跟一个组合键,则会从字面上直接插入组合键中转义序列的第一个字节。由于转义序列通常仅在第一个字符之后包含可打印字符,因此这会按字面意义插入整个转义序列。看到键绑定表?在这种情况下讨论zsh。
终端可以为某些修饰符组合传输相同的转义序列(例如,许多终端都为+ Space和Shift+ 传递空格字符Space;xterm具有区分修饰符组合的模式,但基于流行的vte库的终端则没有)。一些键根本不会传输,例如修饰键或触发终端仿真器绑定的键(例如,复制或粘贴命令)。
如果需要,应由应用程序将转义序列转换为符号键名称。
+-------------+ +-------------------+
| application |-------------->| terminal emulator |--->
+-------------+ +-------------------+
character or
escape sequence
输出比输入要简单得多。如果应用程序将字符输出到pty设备文件,则终端仿真器将其显示在当前光标位置。(终端仿真器保持光标位置,并滚动如果光标将落在屏幕底部下方。)应用程序还可以输出转义序列(主要以^[
或开头^]
),以告知终端执行诸如移动光标,更改文本属性(颜色,粗体等)或删除屏幕的一部分。
termcap或terminfo数据库中描述了终端仿真器支持的转义序列。如今,大多数终端仿真器都与xterm紧密结合。请参阅有关LESS_TERMCAP_ *变量的文档?有关终端功能信息数据库的详细讨论,以及如何停止光标闪烁,是否可以将本地计算机的终端颜色设置为使用ssh进入的计算机的终端颜色?对于一些用法示例。
如果应用程序直接在文本控制台中运行,即由内核而不是由终端仿真器应用程序提供的终端,则适用相同的原理。终端与应用程序之间的接口仍然是一个字节流,用于传输字符,并带有特殊键和编码为转义序列的命令。
如果您在远程计算机上(例如,通过SSH)运行程序,则网络通信协议将以pty级别中继数据。
+-------------+ +------+ +-----+ +----------+
| application |<--------->| sshd |<--------->| ssh |<--------->| terminal |
+-------------+ +------+ +-----+ +----------+
byte stream byte stream byte stream
(char/seq) over TCP/… (char/seq)
这几乎是透明的,只是有时远程终端数据库可能不知道本地终端的所有功能。
服务器与应用程序之间的通信协议本身就是字节流,可以通过诸如SSH之类的网络协议发送字节流。
+-------------+ +------+ +-----+ +----------+
| application |<---------->| sshd |<------>| ssh |<---------->| X server |
+-------------+ +------+ +-----+ +----------+
X11 protocol X11 over X11 protocol
TCP/…
这几乎是透明的,除了某些加速功能(如电影解码和3D渲染)无法在应用程序和显示器之间进行直接通信之外,这是不可用的。
PgUp
并且Ctrl+PgUp
无法区分。可以配置keysym->控制序列映射吗?
man 5 keymaps
的内容翻译keycodes
为的内容scancodes
。如前所述,它基本上是一组完全不同的工具/程序,这可能值得更多的见解。其次,答案是+1,因为嵌入的相关问题非常好。