1 概述
GUI体系结构
2 驱动程序
2.1 FrameBuffer
Linux抽象一个显示的帧缓冲区,往/dev/fb0地址读写文件就能对显示设备直接进行操作。Linux启动时顶端的两只小企鹅就是通过FrameBuffer渲染上去的。
2.2 NV与ATI
Linux内核还直接自带有最小化通用的NV与ATI驱动程序,这代表上一层的应用程序可以用过这些驱动程序做一个更有效率的渲染操作。
3 显示服务层
显示服务层有两个作用:
- 处理图元,驱动程序只认像素点,不认文字,图形,图像,系统组件等抽象性的显示图元。显示服务层可以作为中间层,处理这些图元,输出像素点给驱动程序。
- 协调多窗体的显示,由于在图形显示界面上,绝大部分都不只一个窗体在工作,如何协调多个窗体之间的显示合并,事件派发就是一个问题。显示服务层可以作为中间层,处理这个问题。
3.1 X11
XWindow显示服务层,是在本地建立一个XServer,然后其他程序作为XClient连接XServer来渲染属于自己区域的UI。XWindow不仅需要将各个XClient的显示合并为一张图像,然后输出到更低一层的FrameBuffer。而且XWindow还需要负责将鼠标事件,键盘事件转发到对应到XClient上。总而言之,XWindow是一个Client/Server架构的显示服务层。
XWindow包含三个方面
- 协议,定义XServer与XClient之间通讯的方式,以及通讯的内容具体是什么
- 服务器,作为XWindow的统领程序,具体的实现有XFREE86、Xorg。只要满足XWindow协议的服务器都称为XServer。mac上有自己的X11协议实现,XQuartz。
- 客户端,客户端一般使用Xlib库来与XServer通讯,而非直接自己写XWindow协议来通讯。客户端有很多,包含各个GUI程序,桌面,窗口管理器等等。
XWindow的架构非常灵活,它的宗旨是只提供机制,不提供标准。所以,XWindow的协议到1989年就已经定下来了,就是XWindow的v11版本,简称X11。而直到现在,这个X11依然是现代GNOME和KDE等桌面系统的显示服务层。另外,值得注意的是,XWindow的很多功能都是通过XClient来实现的,例如Compositor,keyborad,而非由XServer来实现的,这使得它的架构本身非常灵活。
3.2 Wayland
Wayland是现代的显示服务层,它的整体结构跟X11其实相差不大。它的唯一区别在于,它精简了XServer的插件架构,自身承担了Compositor,Keyboard和Mouse的功能,至于渲染系统组件的事情则交由XClient自身来实现。这使得Wayland相比X11更加简单,效率也较高。当然,灵活性比起X11就弱多了。
3.3 DirectFB
DirectFB是一个为嵌入式开发的显示服务层,它不需要像X11和Wayland管理多个窗体的输入和输出的问题,它只需要去处理文字,图形和图像的基本输出问题。所以,它的效率最高,功能也是最受限制的。
由于DirectFB仅仅需要处理一个窗体的问题,所以它不需要像X11和Wayland一样采用Server/Client结构,它采用是函数库的结构。使用者仅仅需要include这个库,然后就可以直接使用了,DirectFB会将它的显示结果直接输出到本地的/dev/fb0上。
4 图形管理层
在一个窗体中,如何处理图元,布局,动画,可访问性就是一个问题,这一层都是以外部库的方式提供的。
4.1 GTK/GTK+
一套使用C/C++开发的GUI框架,其支持xlib,directfb等显示服务器后端。最开始是用c语言写的GTK,后来使用C++封装了一下,成为了GTK+。主要特定是性能好,速度快,但是使用起来太麻烦,复杂度高。
当然,GTK也支持跳过显示服务层,直接写入到FrameBuffer中,而这个库就是GtkFB。
4.2 Qt
一套使用C++开发的跨平台框架,其支持xlib,directfb等linux显示服务后端,甚至支持window的GDI,mac的CoreGraphics等等。而且,除了GUI外,Qt还实现了跨平台的多媒体,网络组件。它简直就是一个操作系统。而且,Qt自身扩展了C++的语法,加入了signal和slot的模型,大大方便了GUI的开发。
另外,Qt自身也支持跳过显示服务层,直接写入到FrameBuffer中,这个库就是Qt/Embedded。
4.3 wxWidgets
这个库就弱很多了,wxWidgets自身更像是一个壳,而不是图形管理层,在linux环境下,它调用的是GTK,在window环境下,它调用的是GDI。它将多个平台的api封装成统一的接口,让程序员可以用一套写法写出不同平台外观的GUI。
4.4 DirectUI
DirectUI是一种图形管理的技术,常见的有duilib,soui。他们底层都需要依赖一个特定的绘图引擎,例如是GDI,GDI+,Direct2D,OpenGL,skia等等。总的来说,directui是面向控件的,用户使用它的控件(按钮,文本框,标签,列表等等)就能绘制出界面。但绘图引擎是面向图形的,用户使用它的图形(边框,矩形,圆形,背景,前色等等)来绘制出界面。
对于一些复杂的控件,它无法通过组合现有控件来完成时,就需要自己通过绘图引擎来实现自定义的控件了。例如,画图编辑器,富文本编辑器,UI排版编辑器,幻灯片编辑器,辅助设计编辑器(CAD)等等,它往往是一个特定业务下的控件容器,就需要实现自己来绘图了。
提高绘图效率,最终离不开三个方法:
- 只绘制视觉区域,一个列表可能很大,但我们只绘制视觉部分的区域,这样每次变动时需要重绘的区域就会很少。
- 只绘制变动区域,控件变化时往往都是只有一小部分是变动的,其他部分都是未改动过的,我们可以只会知变化的区域,其他区域不用绘制。
- 擅用贴图缓存加快绘制速度,在一些动画和编辑器的业务上,每次都需要整个页面刷新的,例如鼠标拖动控件时,变化的是整个页面。但是,我们可以将背景缓存为一个bitmap,被拖动的控件也是一个bitmap。那么拖动的过程就是,不断将两个bitmap合并后输出的过程。虽然绘制的区域很大,但是两个bitmap合并的工作量很少,所以速度依然很快。
4.5 Cocoa
使用obj-c的面向对象技术实现的Cocoa框架,是开发mac和ios平台下的利器。
5 桌面
有了图形管理层后,再上一层就是桌面程序。用户启动了显示服务器以后,他希望看到一个用户登录界面,菜单栏,桌面图标,通知栏,以及一系列的资源管理工具(文件,网络,系统管理等等)。
与此同时,桌面自身也要提供api,让上层的其他客户端都能使用它的接口来实现桌面上的功能。例如是复制黏贴,输入法,通知消息等等。一般来说,桌面的api都是通过dbus来实现进程间通信的。例如,想要向gnome发送桌面通知,我们可以通过dbus向这个地址/org/freedesktop/Notifications发送数据就可以了。
5.1 GNOME
使用GTK作为后端的桌面系统。
5.2 KDE
使用Qt作为后端的桌面系统,功能非常完善,而且稳定。
5.3 DDE
由国人开发的桌面系统,画面非常绚丽,是历史上最好看的桌面系统,使用Qt作为后端。
5.4 XFCE
XFCE是一个非常精简的桌面系统,使用GTK+作为后端。
5.5 LXDE
LXDE也是一个非常精简的桌面系统,使用GTK作为后端。
6 总结
GUI体系结构的入门介绍
参考资料
- 本文作者: fishedee
- 版权声明: 本博客所有文章均采用 CC BY-NC-SA 3.0 CN 许可协议,转载必须注明出处!