我正在使用libxcb在c中创建一个简单的窗口管理器,我正在尝试使用标题栏,图标和最小/最大/关闭按钮来装饰窗口.
我在Xephyr测试我的wm.我可以生成一个新的xterm窗口,移动它并调整它的大小.但现在我想装饰新的xterm窗口(或任何其他应用程序),以便它有一个标题栏,图标和最小/最大/关闭按钮.
在我的Linux机器上,我刚刚安装了一个Gtk主题,如果我以Firefox为例,那么在我在我的设置中设置该主题后,窗口就会被装饰.所以在这种情况下,我认为应用窗户装饰的是Gtk.这是如何运作的?
我读到EWMH窗口属性_NET_WM_WINDOW_TYPE可用于确定如何处理窗口的装饰.所以我想我可以检查窗口类型是否为_NET_WM_WINDOW_TYPE_NORMAL,从应用程序中获取WM_NAME,然后在其上面手动绘制标题栏.
这是你应该如何正常绘制窗饰?或者我可以使用Gtk(或其他东西)吗?
解决方法:
So in that case I think it’s Gtk that applies the window decorations. How does this work?
正确. GTK应用程序告诉窗口管理器不要通过将边框宽度设置为0来装饰它们.现在我的建议是仅实现:如果窗口设置边框宽度为0,则忽略它的装饰.我一开始不打扰任何其他事情.事实上,你现在甚至可以忽略这个提示.
I read that the EWMH window property […]
现在不要打扰EWMH.只是装饰所有未设置边框的托管窗口.此外,我没有看到为什么不应该装饰其他窗口类型(如对话框)的充分理由;我不认为窗口管理器真的使用这个属性来确定,但我只能肯定地说一对.
Is this how you should draw your window decorations normally? Or can I use Gtk (or something else) for this?
虽然你没有明确要求这个,但这句话中的最后一句话告诉我你可能不完全理解装饰是如何工作的.最常见的方式,我强烈建议你这样做,称为重新定位.
重新显示意味着当您管理窗口时,您创建一个新窗口(当然您不应该像普通客户端窗口那样管理)称为框架窗口,然后将客户端窗口重新显示到框架窗口中.所以实际的*窗口是窗口管理器拥有的框架窗口;客户端窗口(用户与之交互的窗口)是它的直接子节点.
现在,您只需使框架窗口略大于客户端窗口,并在其中正确定位客户端窗口.当然,您需要跟踪客户端窗口的大小调整并对其进行操作.
那我们为什么要创建这个框架窗口呢?简单!因为您可以创建一个用于它的像素图,并在其上绘制标题栏.这比直接绘制到子窗口更好,因为您不会弄乱您实际上没有的窗口.
绘图可以使用“原始”和简单的调用来完成,例如xcb_poly_fill_rectangle,或者您可以使用更复杂的方法,例如使用像cairo这样的库(我建议).例如,i3窗口管理器使用一个简单的抽象,它支持via compile flag(libi3 / draw_util.c).
这种重新定位的方法是xwininfo或xprop等工具具有-frame选项的原因.默认情况下,这些工具实际上忽略了框架窗口并下降到客户端窗口,几乎隐藏了存在框架窗口的事实.只需在同一个窗口上尝试xprop和xprop -frame,您就会看到框架窗口附加的信息要少得多.
一旦你进行了重新定位和绘图,你可以更多地思考你不需要/想要装饰窗户的情况.鉴于此处有相当多的记录,我认为首先实现这一点会让你忙碌一段时间.我强烈建议研究其他简单窗口管理器的代码.