所以在这种情况下,我认为是 Gtk 应用了窗口装饰。这是如何工作的?
正确。 GTK 应用程序告诉窗口管理器不要通过将边框宽度设置为 0 来装饰它们。现在我的建议是只实现:如果窗口将边框宽度设置为 0,则忽略它的装饰。一开始我不会打扰其他任何事情。事实上,你现在甚至可以忽略这个提示。
我读到 EWMH 窗口属性 […]
暂时不要打扰 EWMH。只需装饰所有未将边框设置为 0 的托管窗口。此外,我看不出为什么不应该装饰其他窗口类型(如对话框)的充分理由;我认为窗口管理器并没有真正使用这个属性来确定这一点,但我只能肯定地说几个。
这就是你正常绘制窗户装饰的方式吗?或者我可以为此使用 Gtk(或其他东西)吗?
虽然您没有明确要求这样做,但此引文中的最后一句话告诉我您可能并不完全了解装饰的工作原理。最常见的方法,我强烈建议您这样做,称为 reparenting。
Reparenting 意味着当您管理一个窗口时,您会创建一个称为 frame 窗口的新窗口(当然,您应该不像普通客户端窗口一样管理它)和然后将客户端窗口重新设置为您的框架窗口。所以实际的顶层窗口是窗口管理器拥有的框架窗口;客户端窗口(用户与之交互的窗口)是它的直接子窗口。
现在您只需使框架窗口略大于客户端窗口,并将客户端窗口正确定位在其中。当然,您需要跟踪客户端窗口的大小调整并对其采取行动。
那么我们为什么要创建这个框架窗口呢?简单的!因为您可以创建一个用于它并在其上绘制标题栏的像素图。这比直接在子窗口上绘图要好,因为您不会弄乱您实际上并不拥有的窗口。
可以使用“原始”和简单的调用(例如 xcb_poly_fill_rectangle)来完成绘图,或者您可以使用更复杂的方法,例如使用 cairo 之类的库(我会推荐)。例如,i3 窗口管理器使用一个简单的抽象,通过编译标志 (libi3/draw_util.c) 支持两者。
这种重设方法是xwininfo 或xprop 等工具具有-frame 选项的原因。默认情况下,这些工具实际上忽略了框架窗口并下降到客户端窗口,几乎隐藏了存在框架窗口的事实。只需在同一个窗口上尝试xprop 和xprop -frame,您就会发现框架窗口附加的信息要少得多。
一旦您完成了重新设置和绘图,您就可以更多地考虑您不需要/不想装饰窗户的情况。鉴于这里有很多事情要跟踪,我认为一开始实施这个会让你忙一段时间。我强烈建议研究其他简单的窗口管理器的代码。