【问题标题】:XCB: detect change of a window's name / titleXCB:检测窗口名称/标题的变化
【发布时间】:2021-01-22 12:44:27
【问题描述】:

XCB 允许我们...

  • 通过WM_NAME_NET_WM_NAME 属性读取窗口的名称(标题)
  • 通过XCB_EVENT_MASK_PROPERTY_CHANGE监控窗口属性的变化

我成功地做到了这两点。具体来说,这是我如何监视所有窗口的_NET_WM_NAME 属性的变化(通过订阅根窗口上的事件):

/* ... */

const uint32_t list[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xcb_change_window_attributes(conn, root_window, XCB_CW_EVENT_MASK, &list);
xcb_flush(conn);

xcb_generic_event_t *evt;
while ((evt = xcb_wait_for_event(conn)))
{
    if (evt->response_type == XCB_PROPERTY_NOTIFY)
    {
        xcb_property_notify_event_t *e = (void *) evt;
        /* ... print the window name ... */
    }
    free(evt);
}

/* ... */

这在大多数情况下似乎工作正常,但我注意到当我在浏览器中更改选项卡时没有收到事件,即使这确实改变了浏览器窗口的标题。

是我做错了还是 XCB 不可能做到这一点?


以上代码的功劳大多归于this answer on a related question

【问题讨论】:

    标签: c linux events window xcb


    【解决方案1】:

    具体来说,这是我如何监视所有窗口的 _NET_WM_NAME 属性的变化(通过订阅根窗口上的事件):

    您显示的代码不会监视所有窗口的属性更改。它只监视根窗口上的属性变化。

    如果您想监听所有窗口上的属性变化...嗯,这很复杂。您可以选择SubstructureNotify。每当创建新的子窗口时,这应该会为您提供 CreateNotify 事件。对于该窗口,您将再次选择 SubstructureNotify 等以递归方式获取所有窗口。

    对于您找到的每个窗口,您还希望发送QueryTree 请求以获取其子级。您还必须为程序启动之前已经存在的子窗口选择事件。

    当然,您在请求SubstructureNotify 时也应该选择PropertyNotifyMask。这样,每当任何窗口更改任何属性 (*) 时,您都应该得到通知。

    (*): 嗯,当然可以创建一个窗口并立即更改一个属性。很可能,此属性将在您有机会请求PropertyNotify 之前设置。因此,如果您真的想查看所有属性,您还需要在请求更改属性后在 windows 上发出ListProperties 请求...

    【讨论】:

    • 啊,你的第一句话澄清了我哪里出错了。首先,我想知道为什么每次更改活动窗口时都会收到一个事件——即使您说我没有监视所有窗口的更改。但现在我明白了:因为根窗口的 _NET_ACTIVE_WINDOW 属性在聚焦另一个窗口时会发生变化 - 但在 same 窗口中切换选项卡时它不会改变。现在一切都说得通了。
    猜你喜欢
    • 2023-04-08
    • 2023-04-05
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 2013-03-21
    • 2011-05-15
    • 1970-01-01
    • 2012-05-29
    相关资源
    最近更新 更多