linux xcb_poll_for_event未检测到关闭窗口的XCB_CLIENT_MESSAGE事件

daolsyd0  于 2023-04-29  发布在  Linux
关注(0)|答案(1)|浏览(199)

我正在将我的应用程序移植到Linux上,并且我正在使用XCB库来处理窗口。我需要检测窗口何时关闭,以便应用程序可以退出。然而,由于系统的设计方式,系统不能阻塞主窗口回路。这在Windows中很容易,因为你只需要使用PeekMessage。但是,当我尝试使用xcb_poll_for_event检测XCB_CLIENT_MESSAGE时,xcb似乎不起作用。当我尝试注入WM_DELETE_WINDOW协议时,窗口上的关闭按钮实际上没有任何功能。
窗口设置:

// initialize XCB
this->connection = xcb_connect(NULL, NULL);
this->screen = xcb_setup_roots_iterator(xcb_get_setup(this->connection)).data;;

// create window
u32 mask = 0;
u32 values[1];
this->window = xcb_generate_id(this->connection);
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(this->connection, 0, this->window, this->screen->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, this->screen->root_visual, mask, values);

// setup close handler event
xcb_intern_atom_cookie_t protocolCookie = xcb_intern_atom_unchecked(this->connection, 1, 12, "WM_PROTOCOLS");
xcb_intern_atom_reply_t* protocolReply = xcb_intern_atom_reply(this->connection, protocolCookie, 0);
xcb_intern_atom_cookie_t closeCookie = xcb_intern_atom_unchecked(this->connection, 0, 16, "WM_DELETE_WINDOW");
this->m_closeReply = xcb_intern_atom_reply(this->connection, closeCookie, 0);
xcb_change_property(this->connection, XCB_PROP_MODE_REPLACE, this->window, protocolReply->atom, 4, 32, 1, &(this->m_closeReply->atom));
free(protocolReply);

// map and flush
xcb_map_window(this->connection, this->window);
xcb_flush(this->connection);

消息循环:

// handle all incoming messages
xcb_generic_event_t* e;
while(e = xcb_poll_for_event(connection))
{
    // take action from message
    switch(e->response_type & ~0x80)
    {
        case XCB_EXPOSE:
            // invalidated
            xcb_flush(connection);
            break;
        case XCB_CLIENT_MESSAGE:
            // close window
            if(((xcb_client_message_event_t*)e)->data.data32[0] == (*this->m_closeReply).atom)
                return false;
            break;
    }

    // cleanup
    free(e);
}

当我将xcb_poll_for_event替换为xcb_wait_for_event时,窗口关闭工作得很完美,但随后窗口循环在等待消息时被阻塞。我只需要知道我做错了什么,在使用xcb_poll_for_event时,事件永远不会被检测到。

vjrehmav

vjrehmav1#

来自XCB教程
注意:程序员经常会在程序中添加代码来处理新的事件类型,而在创建窗口时却忘记为这些事件添加掩码。这样的程序员应该坐下来调试他的程序,想知道“为什么我的程序没有注意到我释放了按钮?””,才发现它们注册了按钮按下事件,但没有注册按钮释放事件。
在你的代码里

mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(
  this->connection,
  0,
  this->window,
  this->screen->root,
  0, 0,
  width, height,
  0,
  XCB_WINDOW_CLASS_INPUT_OUTPUT,
  this->screen->root_visual,
  mask, values  // <--
);

您已经告诉X服务器只向您发送某些事件,而忽略了包含XCB_EVENT_MASK_STRUCTURE_NOTIFY

- values[0] = XCB_EVENT_MASK_EXPOSURE;
+ values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;

相关问题