如何使用XCB绘制标题栏

时间:2016-05-28 17:38:58

标签: c linux xcb ewmh

我正在使用libxcb在c中创建一个简单的窗口管理器,我正在尝试使用标题栏,图标和最小/最大/关闭按钮来装饰窗口。

我在Xephyr中测试我的wm。我可以生成一个新的xterm窗口,移动它并调整它的大小。但现在我想装饰新的xterm窗口(或任何其他应用程序),以便它有一个标题栏,图标和最小/最大/关闭按钮。

在我的Linux机器上我刚刚安装了一个Gtk主题,如果我以Firefox为例,那么在我在我的设置中设置该主题后,窗口就会被装饰。所以在这种情况下,我认为应用窗户装饰的是Gtk。这是如何工作的?

我读到EWMH窗口属性_NET_WM_WINDOW_TYPE可用于确定如何处理装饰窗口。所以我想我可以检查窗口类型是否为_NET_WM_WINDOW_TYPE_NORMAL,从应用程序中获取WM_NAME,然后在其上面手动绘制标题栏。

这是你应该如何正常绘制窗饰?或者我可以使用Gtk(或其他东西)吗?

1 个答案:

答案 0 :(得分:5)

  

所以在这种情况下,我认为应用窗户装饰的是Gtk。这是如何工作的?

正确。 GTK应用程序告诉窗口管理器不要通过将边框宽度设置为0来装饰它们。现在我的建议是仅实现:如果窗口设置边框宽度为0,则忽略它的装饰。我一开始不打扰任何其他事情。事实上,你现在甚至可以忽略这个提示。

  

我读到了EWMH窗口属性[...]

现在不要打扰EWMH。只是装饰所有未设置边框的托管窗口。此外,我没有看到为什么不应该装饰其他窗口类型(如对话框)的充分理由;我不认为窗口管理器真的使用这个属性来确定,但我只能肯定地说一对。

  

这是你应该如何正常绘制窗饰?或者我可以使用Gtk(或其他东西)吗?

虽然你没有明确要求这个,但这句话中的最后一句话告诉我你可能不完全明白装饰是如何工作的。最常见的方式,我强烈建议您这样做,称为重新显示

重新显示意味着当您管理窗口时,您创建一个新窗口(当然您应该像普通客户端窗口一样管理),称为 frame 窗口,然后将客户端窗口重新显示到框架窗口中。所以实际的顶级窗口是窗口管理器拥有的框架窗口;客户端窗口(用户与之交互的窗口)是它的直接子项。

现在,您只需使框架窗口略大于客户端窗口,并将客户端窗口正确放置在其中。当然,您需要跟踪客户端窗口的大小调整并对其进行操作。

那我们为什么要创建这个框架窗口呢?简单!因为您可以创建一个用于它的像素图,并在其上绘制标题栏。这比直接绘制到子窗口更好,因为你不会弄乱你实际上没有的窗口。

可以使用“原始”和简单调用(例如xcb_poly_fill_rectangle)完成绘图,也可以使用更复杂的方法,例如使用像cairo这样的库(我建议使用)。例如,i3窗口管理器使用一个简单的抽象,它通过编译标志(libi3 / draw_util.c)支持。

这种重新定位的方法是xwininfoxprop这样的工具具有-frame选项的原因。默认情况下,这些工具实际上忽略了框架窗口并下降到客户端窗口,几乎隐藏了存在框架窗口的事实。只需在同一窗口中尝试xpropxprop -frame,您就会看到框架窗口附加的信息少得多。

一旦你进行了重新定位和绘图,你就可以更多地思考你不需要/想要装饰窗户的情况。鉴于此处有相当多的记录,我认为首先实现这一点会让你忙碌一段时间。我强烈建议研究其他简单窗口管理器的代码。