大一统桌面
2002年12月,我为Linux Journal网站(www.linuxjournal.com/article/6476)撰写了一篇文章,关于Red Hat 8.0的新Bluecurve桌面,它包含了来自GNOME和KDE的程序。我收到了很多反馈,包括许多关于如何编写桌面应用程序的建议,这些应用程序可以与其他工具包编写的应用程序协同工作,并在任何桌面环境中良好运行。
一个集成的桌面是指其组件协同工作,无论它们来自哪里,并且永远不会强迫最终用户多次做同一件事。当前的默认解决方案,如GNOME和KDE,如果尝试混合使用组件,通常会存在限制。
图形客户端之间的通信,从简单的拖放操作到图标、菜单、元数据(如URL)的处理,以及一般的窗口级交互,仅适用于客户端和窗口管理器的某些子集。同样的情况也适用于集中管理且美观的字体。
那么本地化呢?有多少程序在使用非英语语言或键盘时仍然很痛苦?
KDE和GNOME是两个应用程序集合,它们似乎解决了许多这些问题。但是,以工具包为中心、全有或全无的方法是最容易维护的吗?如果有人创建了一个更好的工具包呢?来自其他工具包的应用程序或自由软件用户中如此自然的最佳实践哲学又该如何呢?
换句话说,开发适用于您最喜欢的桌面、其他人的桌面以及未来桌面的杀手级应用程序的最佳方式是什么?
重新发明轮子可能很愚蠢,但它远没有发明一个需要新道路的轮子那么愚蠢。因此,即使已经有20个Linux聊天客户端,如果感觉良好,那就再编写一个;但是,请确保它与已有的东西互操作。从常识开始,并使用正确的自由标准和协议。之后,检查您选择的任何工具包或库是否也遵守这些标准。许多顶级开发人员已经充分意识到,从长远来看,这才是制胜之道。GNOME开发人员Havoc Pennington写道:“应用程序和运行时环境之间的交互确实需要通过文档化的、独立于工具包的协议和文件格式来进行。” 让我们来看看如何在实践中做到这一点。
在办公格式领域,以及对于许多其他类型的结构化数据存储,最有趣的事情可能是Oasis Group的工作。Oasis文件格式是基于OpenOffice.org格式开发的,因此OpenOffice.org开发人员将会更容易。但是,从Emacs到KOffice到下一个文字处理程序,每个程序都可以使用它们。
沿着这些思路,没有必要创建另一种书签格式。XBEL(XML书签交换语言)是一种书签交换格式,Galeon和Konqueror已经在使用它。
交换格式的想法也适用于其他配置文件。UNIX和Linux仍然遵循工具箱方法:没有庞然大物,但有很多小部件,每个都做得很好。这样做的一个实际结果是,所有做同样事情的应用程序都需要知道并存储相同的参数集,或非常相似的参数集。
坚持聊天客户端的例子,真正愚蠢的事情是为Qt_chat_app创建一个配置文件,为GTK_chat_app创建一个,为MyToolKit_chat_app创建一个,等等。文件和创建或更新文件的方式之间存在根本区别。使用不同的编辑方法是可以的(vi、控制面板等),但从长远来看,真正重要的是拥有一个单独的~/.chatrc文件,每个现有的聊天客户端都使用它,并且如果设置从另一个聊天客户端更改,也不会抱怨。Usenet新闻阅读器已经使用标准的.newsrc文件。在您的应用程序类别的标准出现之前,一个可接受的折衷方案是让您的新程序在首次启动时加载其他类似客户端的设置,并将它们用作默认值。
从文件名猜测文件的MIME类型是查看MIME数据库执行的操作。这也可以统一,以便保证每个桌面和程序都读取相同的数据;freedesktop.org有一个关于如何做到这一点的规范草案。
许多人说X正在显示其老态龙钟,并指向雄心勃勃、影响深远的项目,如Fresco。然而,即使不追求如此高的目标,也可以做很多事情来确保任何客户端和窗口管理器的组合都能正常运行。解决这类问题的起点是freedesktop.org站点,尤其是其标准部分。
还记得我们刚才说的关于同类型应用程序共享同一组配置参数吗?我们指的是核心功能,但相同的方法可以用于所有GUI级别的设置,在桌面的所有组件中。所有程序都需要背景颜色或双击超时之类的东西,并且仍然可以由每个用户一劳永逸地配置,而无需考虑他或她需要的特定工具包组合。X资源管理器不是为交互式更改而设计的,并且将~/.Xdefaults中编写的内容与来自其他来源的数据合并,因此它不是GUI配置工具的正确后端。请改用Xsetting规范,该规范旨在解决此问题和其他问题。
让我们更进一步。在每个应用程序类别的内部配置以及它们的外观和对本地用户操作的反应之后是什么?是与其他应用程序和窗口管理器的图形交互。
至少在理论上,如果所有相关方都遵循XDND协议,那么将文本从任何窗口拖放到另一个窗口已经是可能的。目前,GTK+和Qt,以及面向脚本的工具包(如Tk和Perl/Tk)以及像FOX这样的相对局外人都支持这一点。
图1显示了XDND的工作原理。当应用程序必须向另一个应用程序发送某些内容时,它会发出适当的工具包调用。工具包通过XDND协议将所有内容发送到另一个工具包,答案以相同的方式传递回程序。
源必须向其工具包声明它支持的所有MIME类型。这些可以是多种格式的文本、图像或文件名。目标必须声明它在该列表中识别哪些格式。通过这种方式,格式化文本可以在两个文字处理器之间传递,而不会丢失字体、颜色等。同时,将段落从KOffice传递到vi将丢失格式,但保持文本完整。
当拖放操作不起作用时,问题几乎总是出在应用程序的XS内部,它没有声明所有MIME类型,仅使用了自定义类型,或者以某种类似的方式误用了工具包或协议。实际上,这意味着必须针对应用程序而不是工具包或XDND提交错误报告。
X客户端之间或客户端与窗口管理器之间的其他交互必须遵循ICCCM(客户端间通信约定手册)和扩展窗口管理器提示,简称EWMH,以前称为NetWM规范。应该注意的是,即使是古老的X剪贴板也在ICCCM中得到了充分描述。Keith Packard和Jamie Zawinski提供了关于如何处理此问题的详细解释。
第二个窗口交互标准建立在ICCCM之上。它处理所有在其前身中未指定的窗口管理功能,因为它们是在其之后才开始出现的。EWMH最初旨在替代当时的GNOME窗口管理器规范,但它的设计是正确的,因为它可以在任何桌面环境中实现和支持。GNOME 2和KDE 3都支持EWMH,因此任何符合它的应用程序都可以期望在两个环境或它们的任何组件中都能良好运行。希望更精确、快速地了解EWMH应该做什么的开发人员可能希望查看KDE的netwm.h。
我们是否涵盖了构建大一统桌面所需的一切?当然没有。考虑Red Hat 8.0。几乎每个人,包括那些讨厌GNOME/KDE混合体的人,都同意至少字体看起来比以前好得多。在您选择的发行版上复制这种特殊魔法的方法是众所周知的。
首先,改进归功于抗锯齿,它通过在适当的位置添加像素使字符更平滑。图2和图3显示了标准xterm和抗锯齿xterm中的相同文本。
其次,Red Hat 8.0是第一个尽可能多地使用UTF-8编码(稍后会详细介绍)以及由xft2和fontconfig库实现的新客户端字体管理系统的主流发行版。
基本上,fontconfig可以找出系统中可用的字体以及哪种字体最适合每个文档。一旦知道这一点,xft2就可以告诉X服务器要绘制什么。这两个库都需要与FreeType或等效的栅格化引擎交互。换句话说,字体检测和渲染已经干净地分离,但以任何客户端都可以嵌入的方式打包。这意味着
最终,应该不再需要字体服务器。
安装新字体,即使没有root密码,也容易得多。
任何使用fontconfig的应用程序都从相同的XML文件读取所有字体配置,任何前端都可以编辑这些文件。
字体管理(在任何应用程序中)现在可以以这两个库的速度进行,而不是以X本身的速度进行。
因为fontconfig不需要xft2或任何其他与X相关的元素,所以它可以嵌入到任何处理字体的东西中,包括打印驱动程序和库。libgnomeprint22正在这样做。
关于xft2/fontconfig系统的另一个好处是它不是一个全有或全无的交易。它可以与传统的字体服务器和平共处,传统字体服务器可能仍然需要协助旧的应用程序。这就是Red Hat 8.0发生的情况。而且,xft2可以与旧的和新的XFree86服务器对话。第一个接收低级绘图指令的长序列。其他服务器,使用Render扩展编译,接收更快、更复杂的命令。
当绘制漂亮的符号只是工作的一半,并且应用程序还需要高级文本布局时,首选工具是Pango,它使用fontconfig。Pango是另一个诞生于或多或少单体桌面GNOME内部的工具,但目前正在开发为可在任何其他环境中使用。
关于字体的最后一句话——更漂亮的绘图很酷,但如果它们只用于数字和英文字母,它们真的不值得付出努力,对吗?转向东欧、非洲或亚洲语言,ASCII甚至无法处理“Hello, World!”
对于开发人员来说,这意味着任何新的应用程序都必须从第一天开始就编码以处理多语言编码,并且必须至少检查所有现有程序以保证它们仍然可以工作。这不仅仅是一个建议。如果您认为您是安全的,因为您只使用ASCII并且只编写一些脚本,请再想一想。下次您升级并且您的代码被弹射到国际化的shell、终端或窗口管理器中时,它将会崩溃。我的用于随机电子邮件签名的Perl单行代码正是因为这个原因在Red Hat 8.0上停止工作,并且在将近三个月的时间里,在三个不同的列表上都没有人能提出解决方案。
正在成为Linux标准的字符编码是Unicode UTF-8[参见Reuven M. Lerner在2003年3月LJ期刊上的“Unicode”一文]。好消息是它可以表示地球上存在的所有字符,因此不需要其他编码。图4显示了Red Hat 8.0中打包的Emacs,它处理各种符号和字符。坏消息是,由于非ASCII字符占用超过8位,有时在屏幕上占用更多空间,因此许多根深蒂固的教条,从“1个字符= 1个字节”的等式开始,都消失了。除了Linux Unicode HOWTO之外,处理此问题的正确资源是“UTF-8软硬转换”迷你指南和旨在在UTF-8世界中保留X剪切和粘贴系统的UTF8_STRING机制。在更高的层次上,无论操作系统如何,为国际化编程都是Openi18n.org的目标。
为了实现漂亮的GUI还剩下什么?菜单和图标。freedesktop.org已经存在一个桌面条目标准,它描述了如何构建菜单,如何启动每个应用程序等等,而与环境无关。它确实有一些限制,即缺少一个应该放置.desktop文件的公共位置,以及菜单的硬连线,这来自于它们只是镜像这些文件在磁盘上的位置这一事实。正在编写该标准的虚拟文件夹扩展以克服这些限制。另一个具有类似范围的规范可用于标准化图标位置和主题选择。
是的,如果您分发源代码,每个人都可以编译和安装您的程序,但为什么要让其他人难以弄清楚为什么程序找不到已安装的库?为什么要硬编码一些东西,以便它们只能在一个发行版上工作?无论您计划编写什么应用程序,来自LSB组的Linux文件系统层次结构都是您的朋友。
我并不反对纯粹的KDE或纯粹的GNOME。我只是希望下一代桌面应用程序能够让每个人更容易地从任何程序组合中构建自己的环境,而不会牺牲真正的功能和性能。这里描述的方法和工具是构建此类应用程序的好方法,我感谢它们的开发人员。还要非常感谢Havoc Pennington、Keith Packard、kde-devel列表的成员以及在linuxjournal.com网站上回答问题以帮助我撰写本文的每个人。
电子邮件:m.fioretti@inwind.it
Marco Fioretti 是一位硬件系统工程师,对自由软件作为EDA平台和(作为RULE项目的现任负责人)作为高效桌面都感兴趣。Marco与家人住在意大利罗马。