【问题标题】:How to get event when new application launches using XCB如何在使用 XCB 启动新应用程序时获取事件
【发布时间】:2012-10-15 22:17:25
【问题描述】:

我正在尝试制作一个非常简单的窗口管理器用于学习目的。我正在使用Cxcb 库。如果启动了新应用程序,我正在尝试引发一个事件。

现在,我创建了一个根窗口,我可以在其中接收鼠标和键盘事件。我还在窗口顶部画了一个彩色条。当我按下回车键时,xterm 将使用 fork 和 execvp 启动。这一切都很好。

当 xterm(或我认为的任何应用程序)启动时,它会被绘制在条形图的顶部(x = 0,y = 0)。我想将它移低一点(x = 0,y = 16)。我想我知道如何使用xcb_configure_window 移动窗口。但我不知道如何为新启动的应用程序获取事件。

编辑:
经过一番折腾,我得出以下结论:
如果我这样创建父窗口:

xcb_window_t window_root = screen->root;
uint32_t mask = 0;    
uint32_t values[2];
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
xcb_change_window_attributes_checked(connection, window_root, mask, values);
xcb_flush(connection);

当我生成一个新终端时,我将收到 XCB_CREATE_NOTIFY。但是,我无法在屏幕上绘制任何内容,因为我没有“订阅”XCB_EVENT_MASK_EXPOSE 事件。如果我将 values[0] 行更改为:

values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE;

我仍会收到创建事件,但不会在程序启动后立即调用公开事件,因此我的条不会被绘制。不过,一旦我启动一个新终端,它就会得到一个暴露事件,但我的初始绘图不会发生。

我创建父窗口的旧方法是:

xcb_window_t window = xcb_generate_id(connection);
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t values[2] = {screen->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY };
xcb_create_window(connection, 0, window, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values);
xcb_map_window(connection, window);

这将绘制一个白色背景并绘制我的彩色条,因为它会立即获得 XCB_EVENT_MASK_EXPOSURE 事件。但它不会得到 XCB_CREATE_NOTIFY 事件。

那么获取 XCB_CREATE_NOTIFY 事件和 XCB_EVENT_MASK_EXPOSURE 事件的正确方法是什么?

【问题讨论】:

  • @JoachimPileborg 感谢您的评论。我尝试使用 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,因为我在其他 WM 的代码中读到了类似的内容,但我在事件循环中从未收到任何 XCB_MAP_REQUEST 或 XCB_MAP_NOTIFY 事件。我用更多信息更新了我的帖子。
  • 我在今年早些时候用 Python 和 XCB 制作了一个非常非常简单的窗口管理器。除了XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,我还有XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECTXCB_EVENT_MASK_STRUCTURE_NOTIFY
  • 您刚刚将它们添加到父窗口的掩码中?我现在正在这样做,但没有任何结果。也许我需要一种不同的方式来产生一个新的终端?我有机会看到你的代码吗?
  • 我有所有这些用于根窗口。
  • @JoachimPileborg 我现在使用XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY 获得了更多成功,但我不会得到公开事件。这取决于我如何创建我的根窗口。我用一些代码更新了我的帖子。你如何创建你的根窗口?

标签: c events x11 window-managers xcb


【解决方案1】:

我傻了,我修好了!

我以为我只有在启动新终端后才会得到暴露事件。但在进入事件循环之前,我什至从未画过我的栏和背景,我只在我的XCB_EXPOSE 循环中画了它们。所以当一个新的终端启动时,expose 事件就会被调用,我的 bar 和背景就会出现。

现在我也将绘图函数放在了我的事件循环之前,一切正常。我不知道这是否是正确/最好的方法,但为了将来参考,请使用以下内容创建您的根屏幕:

xcb_window_t window_root = screen->root;
uint32_t mask = 0;    
uint32_t values[2];
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
xcb_change_window_attributes_checked(connection, window_root, mask, values);
xcb_flush(connection);

您将获得公开事件,新启动的程序将出现在XCB_CREATE_NOTIFY事件中。

【讨论】:

  • 例如捕获 EXPOSE 事件的事件循环是什么样的?
猜你喜欢
  • 2012-02-06
  • 2016-12-20
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多