【问题标题】:How to draw titlebar with XCB如何使用 XCB 绘制标题栏
【发布时间】:2016-09-26 21:16:48
【问题描述】:

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

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

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

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

这就是你正常绘制窗户装饰的方式吗?或者我可以为此使用 Gtk(或其他东西)吗?

【问题讨论】:

    标签: c linux xcb ewmh


    【解决方案1】:

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

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

    我读到 EWMH 窗口属性 […]

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

    这就是你正常绘制窗户装饰的方式吗?或者我可以为此使用 Gtk(或其他东西)吗?

    虽然您没有明确要求这样做,但此引文中的最后一句话告诉我您可能并不完全了解装饰的工作原理。最常见的方法,我强烈建议您这样做,称为 reparenting

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

    现在您只需使框架窗口略大于客户端窗口,并将客户端窗口正确定位在其中。当然,您需要跟踪客户端窗口的大小调整并对其采取行动。

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

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

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

    一旦您完成了重新设置和绘图,您就可以更多地考虑您不需要/不想装饰窗户的情况。鉴于这里有很多事情要跟踪,我认为一开始实施这个会让你忙一段时间。我强烈建议研究其他简单的窗口管理器的代码。

    【讨论】:

    • 啊,我不知道重新养育子女,谢谢。我将使用它来绘制自己的标题栏。但我不明白如何让 GTK 主题出现在 GTK 应用程序中。如果应用将边框宽度设置为 0,我是否需要做任何事情(除了不绘制自己的装饰品)?
    • 不,GTK 只是客户端使用的库。窗口管理器不参与渲染客户端窗口本身,这取决于客户端,在这种情况下,客户端使用 GTK 使事情变得更容易。没有什么可担心的。
    • 最常见的方法是重复。还有什么其他的方法来绘制标题栏?
    • @oel_runs_the_world 从技术上讲,窗口管理器可以渲染到客户端窗口(甚至根窗口)旁边的窗口。客户寡妇不需要为此重新父母。虽然没有多大意义,反而会导致很多问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多