在电脑中,X窗口系统(常称作 X11、X)是一种以位图显示的网络透明化窗口系统。本条目详述 X11 的协议及其技术架构。
X C/S模型和网络透明性
X 基于C/S模型。运作在电脑上的X 服务器程序以图形显示,并以各种客户端程序进行通信。X 服务器接受图形输出(窗口画面)方面的请求,并回传使用者的输入(键盘、鼠标)。
在 X窗口系统 中,服务器可以在使用者的电脑上运行,而在其他的机器上运行客户端。也可以反过来,客户端在使用者的电脑上运行,而服务端在远程电脑上运行。X窗口系统 使用的术语是以程序为基准,而不是使用者或硬件。远程的程序连接到本地的 X 服务器,那些远程的程序就视为客户端;本地的 X 接受所传入的消息,这部分就视为服务端。
主从间通信协议的网络透明:服务器和客户端可以运行在同一机器或不同机器上,那些机器更可以是不同的硬件架构或操作系统。主从之间的通信安全,可以加密连接的方式加强。
设计原则
Bob Scheifler 和 Jim Gettys 陈述的早期 X 的基本原则如下(Scheifler/Gettys 于 1996 所列):
- 不要加入新的功能,除非没有它就不能完成实际所需的应用程序。
- 决定一个系统不是什么和决定系统是什么同样重要。不要满足全部的需求;而是使系统具有可扩充性,额外的需求可以向上兼容的方式来满足。
- 只有完全没实例,才会比只有一个实例来的更糟。
- 如果没把问题弄清楚,不解决它也许会是最好的。
- 如果预期要用 90% 的努力去完成 10% 的工作,就用更简单的方法解决。(参见更糟就是更好。)
- 尽量避免复杂性。
- 提供机制而不是提供方针,用户界面的方针由实际应用者自主。
后来在设计 X11 时,将第一项原则修改为:“不要加入新的功能,除非你知道某些实际的应用程序会需要它”。X 基本上一直遵循这些原则,参考实现的扩充及改进也是以此原则来着手,也因为奉行上述原则,使至今的最新版 X 仍能与最初(1987年)发布的协议标准几乎完全兼容。
X窗口系统 核心协议
服务器和客户端之间的通信,是由网络通道上的交换数据包所完成。由客户端创建连接,并发送第一个数据包。服务器以回传数据包来答复,数据包中陈述接受或拒绝连接,或要求进一步的验证。如果接受连接,接受数据包内会包含客户端接下来和服务器交互所需的数据。
创建连接之后,在客户端和服务器的通道上,会有四种交换数据包的类型:
- 请求:客户端请求服务器的信息,或者请求服务器进行一个动作。
- 回应:服务器回应请求。并非所有的请求都会产生回复。
- 事件:服务器发送事件给客户端,例如,键盘或鼠标的输入,或移动、调整、显示窗口。
- 错误:如果请求无效时,服务器会发送一个错误数据包。因为请求是以排队方式处理,所以经由请求所产生的错误数据包,并不会立即发送。
X 服务器提供一系统基本的服务。客户端程序可以和服务器交互,以实现更复杂的功能。
窗口
在 X窗口系统以及各种图形化使用者界面中,窗口即为一个顶层窗口。窗口也用来指窗口内部的窗口,这类窗口是父窗口的子窗口。图形化组件,如按钮、菜单、图标等等,都是使用窗口来实现的。
任何窗口都只能是父窗口之下的子窗口,使窗口以树状的层次结构结构组织起来,层次结构结构最根部的窗口便称为根窗口,而根窗口是由服务器自动创建的。顶层窗口即直接隶属于根窗口的子窗口。根窗口即整个屏幕画面,且其他窗口都在根窗口之下。
识别子
所有关于窗口的数据、字体等等,皆存放在服务器上。客户端知道那些对象的识别子,和服务器交互时,对象以整数为名称。例如,当客户端希望创建一个窗口时,便指定一个识别子,并请求服务器创建一个窗口。服务器会创建一个窗口,并与指定的识别子关系。稍后客户端可使用这个识别子进行请求,例如在窗口上画上一个字符串。
识别子在服务器上是独一无二的,在多个客户端之间也不例外。例如,即使是由两个不同客户端所创建的窗口,也不会同时具有相同的识别子。即使某个对象不是由自己的客户端所创建的,只要指定相对应的识别子,就可访问另一个客户端所创建的对象。
属性
每一个窗口都有一组预先定义的属性值(Attributes)和属性(Properties),并存放在服务器上,客户端可以适当的请求方式取存。属性值是有关窗口方面的数据,如大小、位置、背景色等等。属性则是附属于窗口上的数据片断。与属性值相反,属性在 X窗口系统 核心协议的层次中并没有其他含意。客户端可在窗口的属性中存放属性值数据。
属性以名称、类型和值来描述,属性相当于指令式编程语言的变量,应用程序可以指定名称、类型和值来创建新的属性。属性和窗口连系:两个相同名称的属性可存在于两个不同的窗口,且可具有不同的类型和值。
属性大多用于客户端之间的通信。例如,名称为 WM_NAME
的属性,用来存放窗口的名称;窗口管理器通常会读取这个属性,并在窗口顶部显示名称。
窗口的属性可以 xprop
程序显示。xprop
-root
更可显示根窗口的属性,包括 X资源(程序参数)。
事件
事件是由服务器发送到客户端用以通信的数据包,发送一些客户端可能感兴趣的事物。客户端可以请求服务器发送事件给另一个客户端;这部分用于客户端之间的通信。例如,当客户端请求目前所选取的文字,就会发送事件给客户端,以处理目前所持有的选取内容。
在某些情况下,窗口的内容可能会被销毁(例如当窗口隐蔽时)。当再度观看被销毁的区域时,服务器会产生一个 Expose
(显露)事件,用以通知客户端重绘窗口已消失的部分。
其他事件是用来通知键盘或鼠标输入的客户端、创建新窗口等等。
某些类型的事件会不断发送给客户端,但大多数的事件只在客户端预先表示关心时才会发送。因为客户端可能只需要关心某类型的事件。例如,客户端可能会关心关于键盘的事件,但却不关心关于鼠标的事件。
色彩模式
对于 X窗口系统处理色彩的方式,有时使用者会感到迷惑,且 X窗口系统 支持有史以来各种不同的模式。现今大多数的应用程序皆使用真实色(TrueColor)(24 比特色彩,红、绿、蓝各有 8 比特),不过比较旧或特殊的应用程序,可能会要求使用其他的色彩模式。许多商业用的专业应用程序使用伪彩色(PseudoColor)。
目前的 X11 协议在大多数的图形运算中,是使用一个 32 比特无负号整数来表示一个颜色,称为像素值。当转移到原色的饱和度时,对每一个色彩元素使用 16 比特整数。便有如下的色彩表示,但实际设备未必能全部支持。
- 直接色(DirectColor):像素值分为红、绿、蓝子域,每一个子域索引一份独立的色彩映射,可改变色彩映射的内容。
- 真实色(TrueColor):与直接色大致相同,但色彩映射的内容是由硬件预先定义,不可改变。通常每个红、绿、蓝色彩映射提供一个(接近)线性斜度的饱和度。
- 灰阶(GrayScale):像素值索引一份色彩映射,且无色彩饱和度(黑白)。可改变色彩映射的内容。
- 静态灰阶(StaticGray):与灰阶大致相同,但色彩映射的内容是由硬件预先定义,不可改变。
- 伪彩色(PseudoColor)(en:Chunky):像素值索引一份色彩饱和度方面的色彩映射。可改变色彩映射的内容。
- 静态色(StaticColor):与伪彩色大致相同,但色彩映射的内容是由硬件预先定义,不可改变。
Xlib 和其他的客户端程序库
大部分的客户端程序借由 Xlib 客户端程序库与服务器交流。特别是客户端大多使用 Xaw、Motif、GTK+、Qt 之类使用到 Xlib 的程序库,以便与服务器交互。
客户端之间的通信
X窗口系统 核心协议提供了客户端之间通信的机制:窗口属性和事件,特别是客户端对客户端的消息事件。不过这部分并未指明任何协议,协议部分由客户端之间的通信协议单独管理。
客户端之间的通信协议手册指明借由选取和应用程序的窗口管理器交互,以交换数据。但这个规格被认为过于困难和混乱;应用程序的质量和通信的一贯性,通常是由指定的桌面环境所提供。
客户端之间的交换协议(ICE)指定了用以创建客户端间互相通信的框架,因此,特定的协议可创建在其上。特别是 X 期间管理器协议(XSMP)便是建基于 ICE 的协议,以期间管理器托管应用程序间的交互。这个程序是在交互期间退出时,用来维护存放的桌面状态,并在同一使用者再次开始另一个期间时恢复。
较新的协议包含在 freedesktop 规范,包括拖曳协议 Xdnd,用以选取要转移的数据,然后拖曳到另一个窗口上。还有嵌入式应用程序协议 Xembed,详述应用程序如何在另一个应用程序的子窗口之中运行。
选取、剪切缓冲器和拖曳
选取、剪切缓冲器和拖曳机制在 X窗口系统中,是给使用者从某个窗口传递数据给另一个窗口。选取、剪切缓冲器通常用于,使用者在窗口中选取文字和其他数据,并在另一个窗口中粘贴。拖曳用于,使用者在窗口中选取某些东西,然后对选取区按住按钮,并拖曳到另一个窗口。
由于两个窗口可能由两个不同的应用程序所持有,数据传递需要两个不同的客户端连接相同的 X 服务器才能交互。X窗口系统 核心协议包含明确选择交换的请求和事件类型,不过传递的完成,主要是由一般的客户端对客户端事件发送,和未指明选择发送的窗口属性。
客户端之间发送的数据可以是不同的类型:通常是文字,不过也可以是图形、数字、对象的列表等等。
选取和拖曳是主动机制:在窗口中选取文字以后,客户端所处理的窗口必须主动支持相关的协议,才能发送数据到需要它的应用程序。相反的,剪切缓冲器则是被动机制:当使用者选取文字时,其内容会发送到剪切缓冲器,即使应用程序所处理的窗口已退出并销毁窗口,缓冲器的内容仍会保留下来。
窗口管理器
窗口管理器是用来控管窗口整体的外观,以及其他图形化使用者界面的要素。在不同的安装中,X窗口系统会有不同的外观,主要是因为使用不同的窗口管理器,或是不同的窗口管理器配置。
窗口管理器维护窗口的位置、周围加上装饰性的边框、处理图标、处理鼠标对窗口外表的点击(在“幕后”)、处理按键(例如按下 ALT-F4 时,将窗口缩小成图标)等等。
从 X 服务器的角度来看,窗口管理器和其他的客户端并没有什么不同。起始位置和窗口周围的装饰性边框,是由窗口管理器使用如下请求处理的:
- 应用程序可以请求服务器不要满足特定窗口的子窗口映射(显示)要求,并把事件发送过来。
- 应用程序可以请求改变窗口的亲属关系。
窗口管理器使用第一个请求,拦截所有映射顶层窗口(根窗口的子窗口)的请求。每当另一个应用程序请求映射顶层窗口,服务器不会去做,反而发送事件给窗口管理器。大部分的窗口管理器会改变窗口的亲属关系:创建更大的顶层窗口(称作框架窗口),并改变原窗口的亲属关系为自己的子窗口;相当于在框架窗口内部放置原窗口。框架窗口(而不是在原窗口上)多出来的空间,是用来装饰窗口周围的框架(“边框”和“标题栏”)。
窗口管理器管理鼠标在框架窗口上的点击。例如,当使用者在边框或标题栏上点击并按住时,便允许改变大小或移动窗口。
窗口管理器也负责处理图标和图形组件的显示关系。图标并不存在于 X窗口系统 核心协议的层次上,那些是由窗口管理器实作的。例如,当窗口“图标化”时,窗口管理器 FVWM 取消映射那个窗口,使其不可见,并创建一个图标名称的窗口,且图标的图像可能和那个窗口有关。图标的意义和处理完全由窗口管理器来决定:某些窗口管理器,如 wm2,根本不实现图标功能。
期间管理器
概略地说,在一个特定时间中,期间的状态就是“桌面的状态”:一组窗口及其当下的内容。更精确地说,就是一系列应用程序管理的这些窗口和信息,其允许应用程序在需要时还原所管理窗口的情况。X 期间管理器便是一个保存并还原期间状态的程序。
使用期间管理器最明显的作用,便是从一个交互期间注销,当再次登录时,有可能在相同的状态下恰好发现相同的窗口。关于这部分的运作,在注销时,期间管理器程序存储运行中应用程序的名称,并在登录时再次启动它们。并按照应用程序状态的次序来还原(需要还原窗口的内容),应用程序必须能够保存这些运行状态,并在再次启动时,能够根据期间管理器的请求来读回这些状态。
X窗口系统含有一个默认的期间管理器,称作 xsm
。特定的桌面系统中也已开发了其他的期间管理器:例如,ksmserver
是 KDE 默认的期间管理器。
X 显示管理器
X显示管理器在 X窗口系统中,是一个用来显示图形化登录提示的程序。更广泛的说,显示管理器在本机电脑上运行一个或多个 X 服务器,并接受来自远程电脑上运行的 X 服务器的新连接。本机服务器借由显示管理器来启动,然后显示管理器连接到服务器,以呈现出使用者登录画面。远程服务器从显示管理器独立启动并且与之连接。在这个情况下,显示管理器的运作就如同图形化的 telnet 服务器:X 服务器可连接到显示管理器,并启动一个期间;期间之中的程序运行在显示管理器的同一部电脑上,不过在电脑上的输出和输入是由 X 服务器运行(使用者面前的那部电脑)。
XDM 是 X窗口系统所提供最基本的显示管理器。其他的显示管理器还有 GDM(GNOME)、KDM(KDE)、WDM(使用 Window Maker 的 WING 组件集),以及 entrance(使用 Enlightenment v.17 的架构)。
使用者界面组件
X 早期的组件工具包有 Xaw(雅典娜工程组件集)、OLIT(OPEN LOOK 内部工具包)、XView、Motif、Tk。OLIT 和 XView 为 AT&T 和升阳的 OPEN LOOK GUI 起基础工具包的作用。
Motif 为 Common Desktop Environment(CDE)提供基础工具包,即用于商业化 Unix 系统的标准桌面环境,如 Solaris 和 HP-UX。(GNOME 也用于 Solaris 9,且即将成为未来版本的标准。)
更多最新的工具包还包括 Qt(用于 KDE)、GTK+(用于 GNOME)、wxWidgets、FLTK、FOX。
扩充
X 服务器被设计成简单而可扩充。如此一来,许多功能就存在于扩充协议之中。
在协议层次上,每个扩充都可以指定新的请求/事件/错误的数据包类型。客户端应用程序使用客户端程序库,以促进访问由扩充所提供的功能。据说为目前的 X 服务器编写扩充是相当困难的,这归咎于 X 服务器缺乏模块化的设计。XCB 项目是一个长期的目标,朝向根据 XML 协议描述,自动化产生客户端和服务端的扩充。
以下是一部分已开发的扩充列表,以引入的时间排列:
扩充 | 描述和注解 |
---|---|
AIGLX | 支持间接 GLX 绘图。 |
Composite | 整个窗口层次结构之外的幕外绘制,允许应用程序和组件管理器能在任何情况下作用。某些情况需要此功能,如用于窗口和阴影的 Alpha 半透明。 |
Damage | 追踪窗口的修改范围,并在维持必要的显示下,将带宽消耗降到最低。 |
XFixes | 若干协议的修改。 |
Extended-Visual-Information (EvIE) | |
Distributed Multihead (DMX) | |
XvMC | 支持卸载视频对 GPU 的动态补偿。 |
GLX | 支持窗口内部的 OpenGL 绘图。 |
XRender | 硬件加速的 Alpha 图像混合。 |
Resize and Rotate (RANDR) | 实时调整桌面的大小,以及侧向旋转或上下翻转。 |
Xinerama | 将桌面拆解,以对应多屏幕。 |
Display Power Management Signaling (DPMS) | 允许控制屏幕的电源节能模式。 |
XPRINT | |
X keyboard extension | 改善键盘布局的处理。 |
DOUBLE-BUFFER | |
RECORD | |
MIT-SHM | 增进共享存储器的使用性能。 |
SYNC | |
XTEST | |
XInputExtension | 支持绘图板之类的输入设备。 |
BIG-REQUESTS | |
XC-MISC | |
X video extension | 支持硬件视频重叠,以及播放时的硬件视频缩放。亦称 Xv(不要和 xv 程序混淆)。 |
Shape | 支持非矩形和部分透明(二进制,非 alpha 半透明)的窗口。 |
DEC-XTRAP | |
MIT-SCREEN-SAVER | |
MIT-SUNDRY-NONSTANDARD | |
SECURITY | |
TOG-CUP | |
X-Resource | |
XC-APPGROUP | |
XFree86-Bigfont | |
XFree86-DGA | |
XFree86-Misc | |
XFree86-VidModeExtension |
废弃的扩充
扩充 | 描述和注解 |
---|---|
Low Bandwidth Extension (LBX) | 以安全壳层连接的 X tunneled 取代,且证明比 LBX 快速。 |
PEX | “PHIGS 扩充到 X 上”,以支持 PHIGS 3D 场景图形 API。已被运用 OpenGL 的 GLX 所取代。 |
XImage Extension | 以 MIT-SHM 取代。 |