💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 第 19 章 图形界面 **目录** [](ch19.html#id3088822) [简介](ch19s02.html) [架构及原理](ch19s03.html) [Xserver](ch19s03.html#id3088862) [Xclient](ch19s03.html#id3088970) [Xprotocol](ch19s03.html#id3089035) [窗口管理器](ch19s04.html) [启动流程](ch19s05.html) [Startx](ch19s05.html#id3089269) [GDM会话](ch19s05.html#id3089388) [配置文件](ch19s06.html) [X服务器](ch19s06.html#xserver) [X客户端](ch19s06.html#id3089599) [字体](ch19s07.html) [freetype 渲染引擎](ch19s07.html#id3089687) [X核心字体](ch19s07.html#id3089773) [XFT字体](ch19s07.html#xft-font) ## 简介 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](ch19s03.html#ftn.id3088878)] ,向 Xserver 发送信息:       “向右移动200点,向上移动100点”(向右上移动);“按下左键”…… Xserver 作出如下响应: 1. 上一次鼠标停止的坐标为 600,500 2. 向右 200,向上 100。现在鼠标位于坐标 800,600 3. 坐标 800,600 处,为窗口 Firefox 的“关闭”按钮 4. 根据预设动作,将 “点击 Firefox 窗口的关闭按钮” 翻译为 “关闭窗口 Firefox” 5. 向X客户端 Firefox 发送一个“退出”消息 6. Xserver 通过显示子系统(显卡、显示器),全程显示鼠标的位置和移动 * 事实上,向程序发送“退出”信号,通常窗口管理器完成。为了描述方便,这里暂不区分。稍后,我们将向您介绍 [窗口管理器](ch19s04.html "窗口管理器") 的其它一些细节。 ### 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](ch19s03.html#id3088878)] 大多数的鼠标不需要专门的驱动程序,因为它们符合某一硬件规范,例如:有四个移动方向和三个键 ## 窗口管理器 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](https://box.kancloud.cn/2015-10-12_561bcb76795ae.png)](ch19s06.html#xwindowconf11) 默认分辨率为默认色深下的第一个分辨率 #### 配置文件内部结构 ``` / ├/ "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](https://box.kancloud.cn/2015-10-12_561bcb76795ae.png)](ch19s06.html#xwindowconf21) 设定X进程的启动参数。例如允许用户进程 allow-user-xsession > [![2](https://box.kancloud.cn/2015-10-12_561bcb768596e.png)](ch19s06.html#xwindowconf22) X资源文件。许多程序保留了X接口,允许X服务器管理一些视觉选项,例如窗口内的字体,配色等 > [![3](https://box.kancloud.cn/2015-10-12_561bcb94ee26f.png)](ch19s06.html#xwindowconf23) 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](ch19s07.html#ftn.id3089930)] 安装字体,只要将字体拷贝到以上任意目录, **fc-cache -fv** 刷新字体缓存即可 (选项: **-f** 强制刷新; **-v** 显示过程) 使用命令 **fc-list** 列出所有可用字体。字体的选择及显示风格,可以修改 GTK2 或者 Qt 的配置文件,建议使用图形界面配置[[34](ch19s07.html#ftn.id3089978)] * * * > [[33](ch19s07.html#id3089930)] GTK2 为 Gnome 使用的图形库,Qt 为 KDE 使用的图形库。相对来说,GTK2 图形库在程序的 GUI 设计中更加通用 > [[34](ch19s07.html#id3089978)] 一般情况下,桌面环境中附带了相关程序,例如 gnome-font-properties