如何使用XCB绘制标题栏

我在一个简单的窗口pipe理器与libxcb ,我试图装饰一个标题栏,图标和最小/最大/closuresbutton的窗口。

我在Xephyrtesting我的WM。 我可以产生一个新的xterm窗口,移动它并调整它。 但现在我想装饰新的xterm窗口(或任何其他应用程序),以便它有一个标题栏,图标和最小/最大/closuresbutton。

在我的Linux机器上,我刚刚安装了一个Gtk主题,例如,如果我启动Firefox,窗口会在我的设置中设置主题后进行修饰。 所以在这种情况下,我认为这是应用窗口装饰的Gtk。 这个怎么用?

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

这是你应该如何绘制你的窗口装饰通常? 或者我可以使用Gtk(或其他)?

所以在这种情况下,我认为这是应用窗口装饰的Gtk。 这个怎么用?

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

我读了EWMH窗口属性[…]

现在不要打扰EWMH。 只是装饰所有管理的窗口,不将边框设置为0.此外,我不明白为什么其他窗口类型,如对话框不应该被装饰, 我不认为窗口经理真的使用这个属性来确定,但我只能说一对夫妇。

这是你应该如何绘制你的窗口装饰通常? 或者我可以使用Gtk(或其他)?

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

重新构建意味着当你管理一个窗口时,你创建了一个新的窗口(当然你不应该像普通的客户窗口那样管理)调用框架窗口,然后把客户窗口重新设置到框架窗口中。 所以实际的顶层窗口是窗口管理器拥有的窗口窗口; 客户窗口(用户与之交互的窗口)是它的直接子窗口。

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

那么为什么我们要创建这个框架窗口? 简单! 因为你可以创建一个你用来绘制标题栏的像素图。 这比直接绘制到子窗口上要好,因为你不会瞎搞你实际上并不拥有的窗口。

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

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

一旦您完成了重新设计和绘图,您可以更多地考虑不需要/不想装饰窗户的情况。 考虑到这里有很多需要跟踪的地方,我认为首先实施这一点会让你忙一阵子。 我强烈建议学习其他简单的窗口管理器的代码,这些窗口管理器是reparent。