7.1.7 绘制装饰窗口

在7.1.6节中,winman创建了各个装饰窗口,但是并没有为各装饰窗口绘制内容。事实上,即使winman想去绘制,也是有心无力。基于X的原理,X服务器并不保存窗口的内容,在窗口可见时,X服务器会向应用报告Expose事件,应用收到这个事件后,开始绘制。否则即使应用在创建窗口时自说自话地进行了绘制,也会被丢掉。

因此,在函数wm_new_client中,在构建了窗口装饰后,调用了窗口对象中函数指针show指向的函数,请求X服务器进行显示。对于标准窗口来说,请求X服务器显示窗口是normal_client_show,代码如下:

7.1.7 绘制装饰窗口 - 图1

在接受了winman的显示请求后,X服务器将向winman发送Expose事件。收到Expose事件后,winman将绘制窗口装饰。标准窗口的处理Expose事件的函数如下:

7.1.7 绘制装饰窗口 - 图2

该函数执行的主要操作如下:

1)为标题栏绘制边框,使标题栏看上去更富立体感。

2)为标题栏上的关闭等各个按钮绘制图标,并为它们也绘制边框。

3)为窗口绘制边框。

事实上,所谓的绘制边框就是在窗口边上绘制线条,但是不同的线条使用不同的颜色,依据色差来产生立体感。函数draw_raised和draw_lowered就是做这件事的。

对于标题栏上关闭等按钮的图标,winman使用了类似掩码的方法来绘制。以函数XFillRectangle为例,在默认情况下,将使用图形上下文(GC)中指定的前景色填充矩形。但是,如果设置了GC中的clip_mask,那么clip_mask中凡是值为“1”的位,依然使用前景色填充,但是值为“0”的位则不会进行填充,如图7-10所示。

7.1.7 绘制装饰窗口 - 图3

图 7-10 clip_mask使用示意图