第 19 章 图形界面
目录
简介
Xwindow 是工作站图形系统的工业标准,它有多种不同的实现,多数 Linux 系统中使用 Xorg。
当然,Xwindow 有悠久的历史和传统,不过那不在我们讨论的范围。您要注意的有两点:
- Xwindow 和 Xbox 中的“X”意义是不同的, X 只是 W 之后的一个字母,差不多应该这样理解,Xwindow 是 Window 的接班人 (注意,Window 不是 Windows)
- 同样,也不要把 Xwindow 说成是 Xwindow
s
,那是一种亵渎!一切伟大的创造,都应得到应有的理解和尊重
架构及原理
Xwindow 使用服务器-客户端架构。无论本地图形界面,还是远程图形界面,都以同样的流程工作。这样便不需要分别进行设计和维护。
本地X客户端 ┐ ┌ 键盘
远程X客户端 ┼ X协议 ─ X服务器 ─ 驱动程序┼ 鼠标
远程X客户端 ┘ └ 显示器
Xserver
Xwindow 系统服务器端,通过驱动程序(硬件规范)来管理硬件资源。
例如:当我们移动鼠标时,通过驱动程序[32] ,向 Xserver 发送信息:
“向右移动200点,向上移动100点”(向右上移动);“按下左键”……
Xserver 作出如下响应:
- 上一次鼠标停止的坐标为 600,500
- 向右 200,向上 100。现在鼠标位于坐标 800,600
- 坐标 800,600 处,为窗口 Firefox 的“关闭”按钮
- 根据预设动作,将 “点击 Firefox 窗口的关闭按钮” 翻译为 “关闭窗口 Firefox”
- 向X客户端 Firefox 发送一个“退出”消息
Xserver 通过显示子系统(显卡、显示器),全程显示鼠标的位置和移动
事实上,向程序发送“退出”信号,通常窗口管理器完成。为了描述方便,这里暂不区分。稍后,我们将向您介绍 窗口管理器 的其它一些细节。
Xclient
Xwindow 系统客户端,通过 X协议,实现与 Xserver 的交互。例如:
- Xclient (假设 Firefox) 接收 Xserver 的消息: 输入焦点在地址栏的范围内,“linuxtoy.org”,回车
- Firefox 根据预设动作,将这些消息识别为 “打开链接 linuxtoy.org”
- Firefox 向域名服务器请求 链接 “linuxtoy.org”。域名服务器将这个请求转换为 “http://linuxtoy.org/” 和 IP地址211.148.131.7,发送回 Firefox
- Firefox 将 “http://linuxtoy.org/”显示在地址栏(向 Xserver 发送请求,在地址栏位置显示这个地址)
- Firefox 向地址 211.148.131.7 请示显示页面
- Firefox 将服务器发送回的页面显示在主窗口中
Xprotocol
Xwindow 系统协议,Xserver 和 Xclient 之间进行通信的规则
[32] 大多数的鼠标不需要专门的驱动程序,因为它们符合某一硬件规范,例如:有四个移动方向和三个键
窗口管理器
Window Manager 是一种特殊的 Xclient。
使用窗口管理器时,Xserver 并不直接与其它 Xclient 通信,而是通过 WM 中转,当一些消息被定义为 WM 指令时,它们会被拦截。例如 Alt+F4 关闭窗口、拖动标题栏……
消息“打开链接 linuxtoy.org”,具体内容如下:
输入焦点在地址栏的范围内,“linuxtoy.org”,回车
Xserver 并不能直接判断焦点,而是这样:
- Xserver 向 WM 发送位置和点击的信息,WM 根据当前的“焦点策略”确定激活(最上层)的窗口为 Firefox
- Xserver 将 Firefox 显示在最上层,高亮显示它的标题栏
- 在窗口 Firefox 内点击地址栏,或者 Ctrl+L,Xserver 将位置信息发送给 WM,WM 再发送给 Firefox
- Firefox 判断当前焦点后,显示一个闪动的文字输入光标
- Firefox 将输入光标通过 WM 发送给 Xserver,Xserver 在屏幕相应位置进行显示
那么,“窗口管理器”到底能作些什么呢?其实它所作的只有一件事──管理窗口。例如:
最上层的窗口会把其它窗口挡住
它通常是一个“已激活窗口”,根据不同的“焦点策略”,窗口管理器确定被激活的窗口。
激活窗口标题栏高亮显示,接收大部分的键盘消息和窗口内的鼠标点击消息。
为了美观和容易分辨,大多数窗口都要有标题栏和边框。
为了方便,标题栏上还要有一些按钮,比如:最小化,最大化,关闭(这些按钮是窗口管理器请求的小窗口)
一个窗口可以在另一个窗口旁边显示,而不一定完全被遮挡。为了实现这一点,就要控制窗口显示的位置
为了控制窗口的显示位置,需要将整个屏幕用座标描述,最好的办法是绘制一个填充整个屏幕的窗口,也就是根窗口。
因为根窗口是最大的,所以它可以严严实实的遮挡任何窗口,为了避免这一点,根窗口永远在最底层。这很形象的说明了为什么它叫作“根窗口” ……root
根窗口不一定只有一个,大多数的窗口管理器可以使用 “工作区” ,来切换显示多个根窗口
根窗口固定位置上通常放置一些其它 Xclient 的窗口,例如底部面板,顶部面板,侧面板,程序启动图标
面板上又可以放一些其它的 Xclient 窗口,如任务条,启动栏,菜单……
任务条可以以图标显示正在运行的任务,还可以作其它的杂活,像自动挂载 USB设备……
启动流程
我们知道 init 是 linux 的根进程,是所有进程的父进程。同样, xinit 是所有 Xwindow 进程的根进程
Startx
startx
可以在命令行下启动图形界面。执行startx 命令时,实际执行这一命令:
xinit /etc/X11/xinit/xinitrc -- /etc/X11/xinit/xserverrc
根据脚本 /etc/X11/xinit/xserverrc
启动 Xserver,同时根据脚本 /etc/X11/xinit/xinitrc
启动指定 Xclient 进程,例如窗口管理器
/etc/X11/xinit/xserverrc
以预设的参数运行程序 /usr/bin/X11/X
/etc/X11/xinit/xinitrc
脚本则指向 /etc/X11/Xsession
,依次启动 /etc/X11/Xsession.d
目录中的脚本
- 您可以在用户配置文件
~/.Xsession
中定义使用的 WM,它的优先级高于全局配置文件(对于 GDM会话 不起作用) - startx 启动时,并不会再进行身份认证。因为它启动的是 /etc/X11/Xsession.d/gnome-session ,而不是 GDM会话
GDM会话
许多 Linux 系统启动时自动进入图形界面,不需要运行 startx 命令
在某些启动级别中,包含了 gdm 的启动脚本,例如 : /etc/rc2.d/S13gdm
- 指向
/etc/gdm/gdm-cdd.conf
文件,加载预设视觉主题,启动/usr/lib/gdm/gdmgreeter
(登录屏幕) - 用户身份认证完成后,启动
/etc/X11/default-display-manager
这个文件中设定的默认窗口管理器 /usr/sbin/gdm
gdm 在启动时,会要求用户名和密码,也就是我们看到的登录屏幕(gdmgreeter)
/usr/share/xsessions
目录下为所有可用登录会话的脚本
配置文件
X服务器
X服务器的主要配置文件为 /etc/X11/xorg.conf
Section "ServerLayout" #布局
Identifier "Xorg Configured" #布局标识
Screen 0 "Default Screen" 0 0 #屏幕标识
InputDevice "Generic Keyboard" #键盘标识
InputDevice "Configured Mouse" #鼠标标识
EndSection
Section "Module" #模块
Load "ddc"
Load "dbe"
Load "dri"
Load "extmod"
Load "glx"
Load "bitmap"
Load "type1"
Load "freetype"
Load "record"
EndSection
Section "Files" #X核心字体路径
FontPath "/usr/share/X11/fonts/75dpi"
FontPath "/usr/share/X11/fonts/100dpi"
FontPath "/usr/share/X11/fonts/misc"
FontPath "/usr/share/X11/fonts/cyrillic"
FontPath "/usr/share/X11/fonts/100dpi/:unscaled"
FontPath "/usr/share/X11/fonts/75dpi/:unscaled"
FontPath "/usr/share/X11/fonts/Type1"
FontPath "/usr/share/fonts/Chinese/wqy-bitmapfont"
EndSection
Section "Screen" #屏幕
Identifier "Default Screen"
Device "Card0" #指定显卡
Monitor "Monitor0" #指定显示器
DefaultDepth 24 #默认色深为24
SubSection "Display" #可用分辨率
Depth 24 #24位色深下可用分辨率
Modes "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"
………………
EndSubSection
EndSection
Section "Device" #显卡
Identifier "Card0"
Driver "vesa" #驱动
VendorName "All"
BoardName "All"
EndSection
配置文件内部结构
/
├/ "ServerLayout" 布局
│├ "InputDevice" keyboard 键盘
│├ "InputDevice" mouse 鼠标
││
│└/ "Screen" 显示子系统
│ ├ "Monitor" 显示器
│ ├ "Device" videocard 显卡
│
│
├ "Files" 字体
└ "Module" 模块
X客户端
在 /etc/X11/Xsession
文件中可以发现下列内容
OPTIONFILE=/etc/X11/Xsession.options
SYSRESOURCES=/etc/X11/Xresources
USRRESOURCES=$HOME/.Xresources
SYSSESSIONDIR=/etc/X11/Xsession.d
USERXSESSION=$HOME/.xsession
ALTUSERXSESSION=$HOME/.Xsession
ERRFILE=$HOME/.xsession-errors
设定X进程的启动参数。例如允许用户进程 allow-user-xsession
字体
freetype 渲染引擎
作为 Xorg 服务器的一个模块,freetype 的功能包括读取 Truetype 字体信息,如大小、分辨率、编码等,并以之为依据渲染字体 - freetype2.x 相对于 freetype1.x 增加了抗锯齿等功能 - ( /etc/X11/xorg.conf
的 Module 字段中,可以选择字体渲染模块 )
freetype 只负责渲染字体。而查找字体,则可以由 X服务器、X客户端 或者 字体服务器来 完成。找到字体后,使用 freetype 引擎进行渲染
X核心字体
X服务器根据X客户端的请求(字符编码),查找字体并进行渲染,然后显示
Xft字体
X客户端自行查找字体并进行渲染,X服务器只负责显示。由于 Xft字体 的渲染在客户端完成,所以它可以动态的加载,而不需要随同X服务器一同启动
字体服务器
当客户端请求字体时,X服务器将请求转发到字体服务器,由字体服务器查找字体,并使用 freetype 引擎渲染,将结果传回X服务器,X服务器进行显示
X核心字体
/etc/X11/xorg.conf
中可以配置X核心字体的搜索路径
Section "Files"
FontPath "/usr/X11R6/lib/X11/fonts/misc/"
FontPath "/usr/X11R6/lib/X11/fonts/Type1/"
FontPath "/usr/X11R6/lib/X11/fonts/Speedo/"
FontPath "/usr/X11R6/lib/X11/fonts/100dpi/"
FontPath "/usr/X11R6/lib/X11/fonts/75dpi/"
EndSection
- 当X客户端向X服务器请求显示文字的时候,X服务器会按上面列表的先后顺序查找字体。显示中文时,如果第一个路径中的字体不包含中文,则查找下面的路径,直到发现中文字体
- 请将您偏好的字体放在靠前的位置
要使安装的字体能够作为X核心字体使用,将字体的安装路径添加到上面的列表中,使用 mkfontscale 、 mkfontdir 扫瞄文件夹中的字体,并生成索引,就可以了(建议使用 ttmkfdir 生成 fonts.scale
,将其复制为 fonts.dir
)
字体的选择及显示风格,可以修改 GTK1 的配置文件,或者在Xresources
文件中对程序单独进行定义
事实上,在我们的日常应用中,X核心字体环境并不常见,使用 GTK1 图形库的程序、某些类型的终端……
XFT字体
Xft字体相关选项在 /etc/fonts/fonts.conf
文件中配置
<dir>/usr/share/X11/fonts</dir>
<dir>/usr/share/fonts</dir>
<dir>/usr/local/share/fonts</dir>
<dir>~/.fonts</dir>
可以使用 fc-cache 命令,递归扫瞄上面目录中的字体(包括子文件夹中的字体),建立字体缓存
多数支持 GTK2 或者 Qt 图形库的X客户端能够使用 Xft字体 渲染技术[33]
安装字体,只要将字体拷贝到以上任意目录, fc-cache -fv 刷新字体缓存即可 (选项: -f 强制刷新; -v 显示过程)
使用命令 fc-list 列出所有可用字体。字体的选择及显示风格,可以修改 GTK2 或者 Qt 的配置文件,建议使用图形界面配置[34]
[33] GTK2 为 Gnome 使用的图形库,Qt 为 KDE 使用的图形库。相对来说,GTK2 图形库在程序的 GUI 设计中更加通用
[34] 一般情况下,桌面环境中附带了相关程序,例如 gnome-font-properties