2 Star 0 Fork 1

凉拌茶叶 / The_X_New_Developers_Guide_zh_CN

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
02_X窗口系统的概念.md 17.42 KB
一键复制 编辑 原始数据 按行查看 历史
凉拌茶叶 提交于 2014-09-17 21:28 . 删去第二节的一个空格

X窗口系统的概念

Alan Coopersmith

本章意在向你介绍X的基本概念和你所需要掌握的术语。当你理解这些概念后,你将能够在接下来的章节中进行更深入的学习。

X是C/S(客户端/服务器)架构的

X窗口系统设计来允许多个程序共同使用一个通用的硬件设置。这些硬件设备主要包括用于输入的鼠标和键盘,还有用于输出的显示适配器和连接它们的显示器。一个单独的进程用于控制这些硬件,供多个应用程序访问。这个控制进程叫做X服务器(X server),提供客户端程序硬件访问。大体上,X server提供的服务就是使得用户能够使用键盘、鼠标和显示器进行访问。

像很多C/S系统一样,X服务器一般也同时向多个客户端服务。X服务器运行的时间比绝大部分客户端要长,并且侦听新客户端的入栈连接。

很多用户只是单机地在笔记本电脑或者台式机上使用X。在这种设置下,X客户端和X服务器运行在同一个电脑上。但是,X还是为C/S式的交流定义了一个流协议。这个协议能穿越网络来让不同机器上的服务器和客户端能够通信。不幸的是,这种模式下,客户端和服务器的角色可能会被误解。也许你面前的笔记本电脑运行着X server,显示的图像却生成于一个位于远端机房的高性能计算机的X客户端上。对于大多数其他协议来说,如供文件分享的协议(http或者类似的协议),笔记本电脑应该是客户端。所以一定要搞清楚,键盘和鼠标连接着X服务器。它也是所有客户端连接的终点(比如终端窗口,网页浏览器,文本编辑器)。

X如何工作

这一节描述了一些X的基本模块和它们具体如何工作。由于要一次性地把所用东西呈现出来,所以这节内容会有些混杂。建议先略读,回头再深入。

输入

像稍早提到过的一样,X服务器主要控制两种硬件:输入设备和输出设备。令人惊奇的是,输入控制由于其多源性、并发性、高度依赖于用户设置是两者中最难、最复杂的。

键盘输入

X服务器实现的一个任务是接受键盘的输入并且向正确的应用客户端发送对应的键盘输入事件。在一个简单的X配置下,若“输入焦点”位于某个客户端上,那么大多数键盘事件都会应用于这个客户端。取决于窗口管理器的设置,焦点可以通过点击鼠标、使用热键或是直接将鼠标移向别的窗口以及操作一个列举窗口的面板而向其他窗口转移。有焦点的客户端通常会以某种方式高亮,这样用户就能知道他们输入的信息去向何处。客户端能够使用“grabs”(将在这章后面一点的地方绍)来更改默认的键盘事件传递行为。

由于有不同语言,不同国家标准和硬件商对产品的差异化需求,世界上有很多种类的键盘类型。这种差异使得键盘事件从硬件“key codes”(键码)到文本输入的映射成为一个复杂且富有挑战的过程。当键盘上的键被按下时X服务器提供一个仅仅8bit的键码来记录按键并发射事件。X服务器也提供一个用于将Keycodes映射到“KeySyms”(KeySyms,键符号名,用于表示键盘上如“A”,“Enter”,“Shift”等的按钮的符号)上的键盘映射。键码在给定的环境外没有固定的意义,一个相同的按键也许会在不同的键盘、服务器、配置或者操作系统上形成不同的键码。KeySym则有全球统一的标准,是大多数的应用应该关心的。由于最初的协议中并没有定义如何处理额外的按键,X Keyboard(XKB)扩展提供了全面的设置和布局设置。Xlib和Toolkits也提供为高级的输入方式准备的输入方法,如组合键处理和将键盘序列映射到复杂的字符(比如亚洲语言的输入法)。

鼠标输入

X协议定义了一个输入“指针”(不是编程概念“指针”)。这个指针在屏幕上表现为光标,它通常被鼠标或者类似的输入设备所控制。应用能够控制这个光标的图像。核心协议包含一个简单的两种颜色的光标的支持。Render扩展提供Alpha混合的32位色光标支持,这个支持一般从libXcursor中获得。

指针设备报告移动事件和按键事件并把事件发射到客户端。默认配置的Xorg服务器有一个单一的指针。这个指针将所有所有链接到服务器的指针类设备的移动事件和按键事件总和到一起:比如笔记本电脑的触摸板和USB外接鼠标。用户可以在Xinput 2.0扩展中用MultiPointer X(MPX)功能实现多个光标并将设备分配给每个光标。使用MPX时,每个指针有自己的焦点。每个指针和键盘一一绑定来让指针焦点所处的客户端接受输入。

触摸板输入

就基础输入而言,对于客户端来说触摸板只是另一种移动指针和发生点击事件的设备。想要使用超过模拟鼠标功能的客户端可以使用Xinput 2.2扩展(随Xorg 1.12发布)或更高版本,以开启多点触控支持。

触摸屏输入

[XXX write me --po8] 谁来写一下这一节?

高级输入设备和技术

[Make whot write this? or steal from http://who-t.blogspot.com? --alanc] 哪个来写一下这儿嘛?要不然从http://who-t.blogspot.com 偷过来?

GetImage: 从显示中直接读取信息

X服务器并不保它在显示输出中绘制了什么图像的记录。一旦二进制数据被渲染交给帧缓存(Frame Buffer),X服务器的使命就结束了。如果数据需要被再次渲染(比如,它们被暂时隐藏了),X服务器会让一个客户端——一般要么是一个合成管理器,要么是原本绘制这个数据的应用——来再次绘制它们。

某些情况下,最有代表性的就是当你使用“screenshots(截图)”功能时,某个客户端需要直接从Frame Buffer中取回内容。X协议提供一个GetImage请求来应对这种状况。

GetImage有很多缺点,建议不必要时应该尽量避免使用。现代图像技术中,因为硬件和软件被优化成输出像素和渲染像素的代价相同,使得GetImage成为了缓慢方式的典范。GetImage也很难被正确地使用。在这里,不同于X协议中的其他所有地方,底层硬件直接暴露在客户端面前。请求的帧缓存内容将和该帧缓存的所有队列、填充、字节顺序一起被发送给客户端。Xlib和XCB两个库中提供一些代码来将收到的帧缓存翻译成的有用信息。即使这样,使用这些代码还是会让处理变得更慢。

输出

渲染和光栅化(Rendering/Rasterization)

X协议原生定义了一些核心的渲染操作,比方划线,多边形填充和复制图像缓存。但他们不随着图形硬件的发展和现代应用的需求而进化,所以现在只有很老的应用才使用它们。

现代应用在客户端一侧采用种类繁多的渲染库,如渲染2D图像的Cairo或者渲染3D图像的OpenGL。它们也许把图像交给X服务器来显示,或者为了使用GPU在图形加速上的优势和其他硬件特性,通过DRI绕过X服务器直接和本地视频硬件进行交互。

多边形渲染模型(Polygon Rendering Model)

显示与屏幕(Displays and Screens)

X将一台机器上的资源分为显示(Displays)和屏幕(Screens)。Display通常是一个X服务器上连接的所有设备,并且为单一用户显示单一会话。系统也许会有多个Display,比如多座位的机器,甚至是系统控制台中的多个虚拟终端。每个显示都有一套输入设备以及一个或多个Screens与之关联。Screens下属于Displays,窗口可以在其上显示或移动,但是窗口不能跨越过多个屏幕显示或是在不同屏幕间移动。输入设备可以与一个X Server的所有屏幕交互,比如把鼠标从一个屏幕移动到另一个。开始时,每个屏幕都与单个显卡和显示器相连接,不过现代技术允许多设备共同组成逻辑上的屏幕或单个显卡同时服务多个屏幕。

当一个客户端连接到X服务器上时,你必须指定你要连接到的Display,要么设置$DISPLAY环境变量,要么通过应用的命令行参数,比如-display或者--display。DISPLAY变量的所有语法都能在man的X(7)页面中找到,但此处还是给出典型的语法: hostname:display.screen。“hostname”在本地连接中也许会被省略,而在使用默认Screen时“.screen”也会被省略,剩下最小规格的display定义“:display”,比如“:0”是普通机器上X Server的默认设置。

图形上下文(Graphics contexts)

Graphics contexts(GC)是一个为X的绘图操作存储共享状态和普通变量的数据结构。必要时客户端可以分配额外的Graphics contexts,并给通过设定不同的值来为每个操作设置合适的GC。

Colors (really?) and Visuals

X太老了,以至于它被设计出来时,大多数用户都还在使用黑白显示器,那时硬件厂商甚至没有在黑色白色哪个是0哪个是1上达成一致。花上额外数千美元的人能拥有4或8位的颜色,使得像素能最多有256种颜色。但现在都2012年了,要是哪个人没有一个支持32位色深的屏幕,他肯定是个老古董。但是,这里仍然有许多复杂的地方需要某人来解释一番……

译者(凉拌茶叶)注:感觉这里也没写完呢。

同步和刷新的联系(Syncing and Flushing connections)

就像通信一章中描述那样,X尽量通过异步操作来减少通信延时。这让调用渲染函数的新手们很奇怪:为什么他们既没有看到所期望的画面也没有看到错误输出。这是由于绘图操作并不要求X Server的响应,而只是被放置在客户端的输出缓冲区中,除非有什么东西使得这个缓冲区被刷新了,否则数据是不会被发送到X Server的。这个缓冲区在被填满后会自动刷新,但要填满Xlib的32Kb缓冲区需要很多的命令。Xlib和XCB在调用需要服务器响应的函数时会刷新缓冲区(虽然这些功能在Xlib和XCB这两种设计模式中是有区别的——详见Xlib和XCB章节)。客户端也可以显式地调用Xlib中的XFlush()或者XCB中的xcbflush()来向服务器发送缓存队列中的所有请求。为了在刷新缓存的同时等待X服务器处理完这些请求,客户端能够使用Xlib中的XSync()或者XCB中的xcbaux_sync()。

窗口系统对象(Window SYstem Objects)

X中使用了种类繁多的对象。

窗口(Windows)

在X中,窗口只是屏幕上可以进行绘图操作的区域。窗口被存放在一个树状结构中,其中根窗口由服务器所创建,覆盖着整个屏幕,存在于整个服务器的生命周期中。其他所有窗口都是根窗或者别的窗口的子窗口。用户界面元素“窗口”其实只是窗口层级结构中的一级。

在每一级结构中,窗口都有一个栈顺序,用来控制同级窗口相互堆叠时如何显示。客户端可以注册Visibility notifications来在窗口可视性发生改变时得到一个事件,这可用于优化实现只绘制窗口的可见部分。

在传统X环境下运行的客户端会在其部分从不可视变得可视时接收到Expose事件,这是由于X Server并不知道那里有什么内容。当合成扩展(Composite Extension)被启用时,客户端通常不会收到Expose事件,因为合成功能把每个窗口的内容分开存放在不同的、没有重叠关系的缓存中,最后才将每个窗口的可见部分混合起来显示在屏幕上。无论是传统环境还是使用合成扩展的环境,客户端都不能按照他们什么时候将会显示来进行控制,它们都需要准备应对Expose事件。

像素映射(Pixmaps)

像素映射,就像窗口一样,是一个能进行绘图操作的区域。但与窗口不同,像素映射不是窗口树结构中的一部分,也不直接显示在屏幕上。像素映射的内容可能被复制到窗口上来进行显示,要么直接通过CopyArea这样的请求,要么通过设置窗口的背景来输出像素映射。像素映射可以被储存在系统内存、显存或者X服务器和客户端的共享内存中。某个像素映射可以在需要的时候在系统内存和显存之间移动,这可以使得访问频繁的像素映射保持在访问速度更快的显存之中。使用MIT-SHM扩展可以让客户端通过写共享内存来让刷新图像的速度加快,这时客户端直接在与服务器的共享内存中操作,而不是通过套接字协议拷贝内容并传送给服务器,但这也将阻止服务器将像素映射移动到显存而使得在屏幕上显示窗口的速度变慢。

窗口小部件(Widgets)

应用需要窗口和像素映射外的方法来提供用户接口——用户希望在窗口中看到菜单,按键,文本框,等等。在大多数地方,这些用户界面元素被笼统地称为“窗口小部件”(Widgets)。X其实并不在核心协议或者库中提供任何窗口小部件功能,只提供用于构建它们的基本功能,如渲染方法和输入事件等。QT和GTK+这样的工具包提供一整套通用的Widgets来帮助你构建,而且有非常丰富的功能来为用户需要的各种各样的功能提供支持,比如多语言支持和通用辅助功能。一些工具包通过使用X提供的有关窗口堆叠和位置控制的所有功能来使得每个Widget作为单独的窗口存在,但现代的工具包通常在客户端完成这种管理,而非将这个工作留给服务器。

XIDs

许多被服务器管理的资源都被分配有32位的ID,在整个服务器的名字空间中叫做XID。每个客户端在第一次连接服务器时会被分配一段XID范围,每当它请求建立窗口、像素映射、光标或者其他应被XID标记的资源请求时,客户端(通常在Xlib或者XCB库中是透明的)从它拥有的那段XID中选择一个没有使用过的XID,并把它包含在给服务器的请求中以标志这个新建立的对象。这种办法使得客户端向服务器请求创建新资源时不必等待服务器完成资源的创建并返回所分配的XID。因为XID的命名空间在服务器上是全局的,在一些情况下客户端可以从别的客户端处引用XID,比如把其他客户端的窗口。

原子(Atoms)

为了减少公共串的重复转换,X引入了一个简单的查找表。表中的条目称为原子(Atom),由一个用于X协议大多数操作的整型键和一个能够被检索的串构成。InternAtom操作查找对应于给定字符串的Atom id,如果找不到,便将这个串添加到表中并返回新原子的id。GetAtomName操作返回与给定Atom id匹配的字符串。原子被广泛地应用到各种请求和事件当中,但有一个在给定X服务器上独立于所有运算和客户端的命名空间。

Properties(属性)

X使用属性(Property)机制作为一种通用的设计模式来提供可扩展的元数据(metadata)。属性是键值对结构的,其中键是一个字符串,代表一个X Atom,值的类型不定,可能是Atom、整数或其他数据类型。核心协议提供窗口和字体的属性。Xinput扩展加入了输入设备的属性,Xrandr扩展加入了输出设备的属性。

X自身并不对窗口属性赋予任何意义或目的。但是还是约定了许多处理窗口属性的惯例,提供对管理窗口和会话十分管用的元数据。最开始,在ICCCM(the X Inter-Client Communication Conventions Manual)规定了一系列属性,你可以在 http://www.x.org/releases/current/doc/ 中找到。这个初稿后来被freedesktop.org上一个致力于开发现代桌面环境的通用功能的团队所扩展,称作EWMH(Extended Window Manager Hints)规范,可以在 http://www.freedesktop.org/wiki/Specifications/wm-spec 中找到。

Grabs(强占)

强占在X中提供锁定和保留功能。“Active Grabs”会立刻独占其给定的目标资源的使用权,并且将其他所有客户端锁在外面,直到Grab被释放。“Passive Grabs”预约某个资源,当某事件发生时(比如按键事件)触发一个“Active Grabs”。可以用于实现用热键忽略当前的输入焦点来控制某个给定的应用。

Server Grab用于强占服务器并将其他客户端锁在外面,在Server Grab释放前防止别的应用更新显示或者与用户交互。这种Grab应该尽快释放,因为用户会因为不能切换到其他应用而感到困扰,这也会造成很多安全问题,因为使用屏幕锁的只是一个客户端,却把剩下的客户端都锁住了。(?)

其它主强占(Primary Grab)主要关心的是输入设备和事件。客户端可以主动强占鼠标和键盘来强制接收这个设备所有的输入,即使指针移动到了这个应用窗口的外面。“Passive Grabs”可以预约某个特定的输入事件,比如一个特定的键盘事件或者鼠标点击事件,事件发生时将为客户端自动产生一个Primary Grab。

更多信息请查看http://who-t.blogspot.com/2010/11/high-level-overview-of-grabs.html

Selections, Cut-Copy-Paste

[copy-and-paste from http://keithp.com/~keithp/talks/selection.ps and other docs on http://www.x.org/wiki/CutAndPaste ? ]

1
https://gitee.com/leo_song/The_X_New_Developers_Guide_zh_CN.git
git@gitee.com:leo_song/The_X_New_Developers_Guide_zh_CN.git
leo_song
The_X_New_Developers_Guide_zh_CN
The_X_New_Developers_Guide_zh_CN
master

搜索帮助