第 19 章 图形界面

目录

简介

架构及原理

Xserver

Xclient

Xprotocol

窗口管理器

启动流程

Startx

GDM会话

配置文件

X服务器

X客户端

字体

freetype 渲染引擎

X核心字体

XFT字体

简介

Xwindow 是工作站图形系统的工业标准,它有多种不同的实现,多数 Linux 系统中使用 Xorg。

当然,Xwindow 有悠久的历史和传统,不过那不在我们讨论的范围。您要注意的有两点:

  • Xwindow 和 Xbox 中的“X”意义是不同的, X 只是 W 之后的一个字母,差不多应该这样理解,Xwindow 是 Window 的接班人 (注意,Window 不是 Windows)
  • 同样,也不要把 Xwindow 说成是 Xwindows,那是一种亵渎!一切伟大的创造,都应得到应有的理解和尊重

架构及原理

Xwindow 使用服务器-客户端架构。无论本地图形界面,还是远程图形界面,都以同样的流程工作。这样便不需要分别进行设计和维护。

本地X客户端 ┐                        ┌ 键盘
远程X客户端 ┼ X协议 ─ X服务器 ─ 驱动程序┼ 鼠标
远程X客户端 ┘                        └ 显示器

Xserver

Xwindow 系统服务器端,通过驱动程序(硬件规范)来管理硬件资源。

例如:当我们移动鼠标时,通过驱动程序[32] ,向 Xserver 发送信息:

  “向右移动200点,向上移动100点”(向右上移动);“按下左键”……

Xserver 作出如下响应:

  1. 上一次鼠标停止的坐标为 600,500
  2. 向右 200,向上 100。现在鼠标位于坐标 800,600
  3. 坐标 800,600 处,为窗口 Firefox 的“关闭”按钮
  4. 根据预设动作,将 “点击 Firefox 窗口的关闭按钮” 翻译为 “关闭窗口 Firefox”
  5. 向X客户端 Firefox 发送一个“退出”消息
  6. Xserver 通过显示子系统(显卡、显示器),全程显示鼠标的位置和移动

  7. 事实上,向程序发送“退出”信号,通常窗口管理器完成。为了描述方便,这里暂不区分。稍后,我们将向您介绍 窗口管理器 的其它一些细节。

Xclient

Xwindow 系统客户端,通过 X协议,实现与 Xserver 的交互。例如:

  1. Xclient (假设 Firefox) 接收 Xserver 的消息: 输入焦点在地址栏的范围内,“linuxtoy.org”,回车
  2. Firefox 根据预设动作,将这些消息识别为 “打开链接 linuxtoy.org”
  3. Firefox 向域名服务器请求 链接 “linuxtoy.org”。域名服务器将这个请求转换为 “http://linuxtoy.org/” 和 IP地址211.148.131.7,发送回 Firefox
  4. Firefox 将 “http://linuxtoy.org/”显示在地址栏(向 Xserver 发送请求,在地址栏位置显示这个地址)
  5. Firefox 向地址 211.148.131.7 请示显示页面
  6. Firefox 将服务器发送回的页面显示在主窗口中

Xprotocol

Xwindow 系统协议,Xserver 和 Xclient 之间进行通信的规则


[32] 大多数的鼠标不需要专门的驱动程序,因为它们符合某一硬件规范,例如:有四个移动方向和三个键

窗口管理器

Window Manager 是一种特殊的 Xclient。

使用窗口管理器时,Xserver 并不直接与其它 Xclient 通信,而是通过 WM 中转,当一些消息被定义为 WM 指令时,它们会被拦截。例如 Alt+F4 关闭窗口、拖动标题栏……

消息“打开链接 linuxtoy.org”,具体内容如下:

输入焦点在地址栏的范围内,“linuxtoy.org”,回车

Xserver 并不能直接判断焦点,而是这样:

  1. Xserver 向 WM 发送位置和点击的信息,WM 根据当前的“焦点策略”确定激活(最上层)的窗口为 Firefox
  2. Xserver 将 Firefox 显示在最上层,高亮显示它的标题栏
  3. 在窗口 Firefox 内点击地址栏,或者 Ctrl+L,Xserver 将位置信息发送给 WM,WM 再发送给 Firefox
  4. Firefox 判断当前焦点后,显示一个闪动的文字输入光标
  5. 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

  1. 指向 /etc/gdm/gdm-cdd.conf 文件,加载预设视觉主题,启动 /usr/lib/gdm/gdmgreeter(登录屏幕)
  2. 用户身份认证完成后,启动 /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

1 默认分辨率为默认色深下的第一个分辨率

配置文件内部结构

/
├/ "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

1 设定X进程的启动参数。例如允许用户进程 allow-user-xsession

2 X资源文件。许多程序保留了X接口,允许X服务器管理一些视觉选项,例如窗口内的字体,配色等

3 X进程。可以设置一些启动时自动运行的程序,也可以用来设定自己的窗口管理器(窗口管理器和桌面环境或者登录管理器是无关的)

字体

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