X Window System 的一个特点:窗口无处不在

每个窗口系统(Window System)都有窗口这个实体。通常我们认为,窗口和类似窗口的东西;应用程序窗口、那些总是在错误的时间打断你的极其恼人的弹出式模式对话框,甚至是弹出式菜单。在原始状态下,X 的窗口数量远不止这些。它之所以能做到这一点,部分原因在于 X 允许窗口在窗口树中相互嵌套,现在你仍然可以使用 "xwininfo -root -tree "查看窗口树。

X 具有大量嵌套窗口的原因之一是,X 在设计时考虑到了编写 X 程序的特定模式,而这种模式将所有东西都变成了(嵌套)窗口。说真的,所有东西都是。在老式的 X 应用程序中,窗口无处不在。按钮是窗口(如果是单选按钮或类似按钮,则是多个窗口),文本区域是窗口,菜单条目是菜单窗口中的每个窗口,可见的容器是窗口(窗口中嵌套了更多窗口),等等。

对窗口的大量使用使得服务器端可以做很多事情,因为各种事情(如鼠标指针)都是按窗口定义的,而且还可以通过服务器设置边框等方式创建窗口。因此,X 服务器可以渲染子窗口边框,为按钮添加轮廓,并在鼠标移入或移出子窗口时自动更改光标,而客户端无需做任何事情。通常,鼠标点击或按键等输入事件都会与某个子窗口特别绑定,这样你的程序就不必在 widget 几何图形中查找点击了什么。还有更多的技巧;例如,当鼠标进入或离开一个(子)窗口时,你可以获得 “进入 “和 “离开 “事件,程序可以利用这些事件来突出光标下的当前事物(即子窗口),而无需每次都不断跟踪鼠标移动并找出光标下的部件。

XtAthena widget set (Xaw) 等古老而经典的 X 工具包大量使用了这种 “嵌套窗口树 “方法,当你将 "xwininfo "应用于有大量可见按钮的旧应用程序时,仍然可以看到大型窗口树;"xfontsel "就是一个例子。即使是古老的 xterm,通常也包含一个嵌套窗口(用于滚动条,我相信部分原因是当鼠标移动到滚动条上时,它会自动改变 X 光标)。不过,这种情况似乎并不普遍;当我查看我手头一个基于 Xaw 的应用程序时,尽管它有一个可点击的列表部件,但似乎并没有使用子窗口。也许在 Xaw 和 Xt 中,这取决于你使用的是哪种窗口小部件,有些窗口小部件使用子窗口,有些则不使用。另一个使用 Tk 编写的程序确实为其按钮使用了子窗口(在 "xwininfo -tree "中清晰可见)。

这种方法因各种原因而失宠,但其中一个重要原因是它与 X 的服务器端渲染紧密相关。由于这些子窗口 “位于 “父(子)窗口的 “顶部”,因此必须对它们进行单独渲染;否则,它们将覆盖渲染到父窗口中的内容(当然,它们也会将渲染到它们的内容剪切到其可见边界)。如果您向服务器发送渲染命令,这只是一个窗口和绘制坐标的问题,但如果您在客户端进行渲染,您就必须发送大量的小缓冲区(每个子窗口一个),而不是整个窗口的一个大缓冲区,事实上,您可能还要发送额外的数据(所有父窗口中被子窗口覆盖的部分)。

因此,在现代工具包中,顶层窗口及其中的所有内容通常只有一个 X 窗口,没有嵌套的子窗口,所有按钮和其他用户界面元素都由客户端直接绘制到该窗口中(通常使用客户端绘制)。客户端本身会跟踪鼠标指针,并在指针进出应具有不同鼠标指针的用户界面元素时向服务器发送 “将光标更改为 <X>”请求,而在收到事件时,客户端会搜索自己的 widget 层次结构,以决定应如何处理这些事件(可能包括客户端窗口装饰(CSD))。

(我认为工具包可能会出于事件处理的原因创建一些不可见的子窗口。例如,Gnome-terminal 和其他 Gnome 应用程序似乎会创建一个 1×1 的子窗口)。

顺便提一句,在一些老式的 X 窗口管理器(如 fvwm)中,你还能找到这种多窗口风格。当 fvwm 在窗口周围放置一个框架时(例如在我桌面上的窗口中可以看到的框架),框架中的特定元素(标题栏、标题栏中的任何按钮、边角拖动调整区域等)都是独立的 X 子窗口。我认为它的作用之一是当鼠标位于正确位置时自动显示相应的鼠标光标。例如,如果你的鼠标位于右侧的 “抓取向右调整大小 “边框中,鼠标光标就会发生变化,显示出这一点。

(现代桌面的窗口管理器(如 Cinnamon)不会这样处理窗口管理器的装饰;它们会将所有内容都画成装饰,并在内部处理标题栏按钮等的 “小部件 “性质)。

本文文字及图片出自 A peculiarity of the X Window System: Windows all the way down

阅读余下内容
 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注


京ICP备12002735号