XLib:Windows Manager在调用XSetWMProtocols之后未发送客户端消息

问题描述 投票:2回答:2

有很多关于如何使用XLib处理窗口关闭的示例,可以在互联网上找到:

还有几个。这就是说我试图在代码中实现它们,如下所示。但是,当我点击窗口一角的X时,我没有收到任何事件发送到我的消息循环。这是因为XChcekWindowEvent忽略或不处理客户端消息?如果不是这种情况,我应该寻找什么其他东西来使用SetWMProtocols从XLib集中获取消息?

m_impl->m_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
if (!XSetWMProtocols(display, window, &m_impl->m_delete_window, 1)) {
  std::cout << "Set Window Protocols Failed" << std::endl;
}

...

while (!terminate) {
  while (::XCheckWindowEvent(display, window, events::mask, &x_event)) {
    if (x_event.type == ClientMessage) {
      std::cout << "Client Message" << std::endl;   
      if ((Atom)x_event.xclient.data.l[0] == m_impl->m_delete_window) {
        terminate = true;
      }
    }
  }
}
c++ xlib
2个回答
2
投票

XCheckWindowEvent()不会返回ClientMessage。它不返回任何不可屏蔽的。解决方法:

while (XPending(display))
{
    XNextEvent(display, &event);

但是可以通过窗口创建额外的工作来过滤事件。 BR Pekka


0
投票

如果要防止使用XNextEvent(不在实时事件循环中应用),可以使用以下基于XCheckTypedWindowEvent的代码:

// Globals

Atom wm_protocols;
Atom wm_delete_window;

// Functions

void PreventClose(Display* disp, Window& win)
{
  wm_protocols = XInternAtom(disp, "WM_PROTOCOLS", false);
  wm_delete_window = XInternAtom(disp, "WM_DELETE_WINDOW", false);
  XSetWMProtocols(disp, win, &wm_delete_window, 1);
}

bool IsClosed(Display* disp, Window& win)
{
  XEvent e;
  if (XCheckTypedWindowEvent(disp, win, ClientMessage, &e))
    if (e.xclient.message_type == wm_protocols &&
        e.xclient.data.l[0]    == wm_delete_window_)
      return true;
  return false;
}

// Usage

int main()
{
   ...
   PreventClose(disp, win);
   do {
     if (IsClosed(disp, win))
       // break, some actions, etc...
     ...
   } while(true);
   return 0;
}

有关更多信息,请参阅man 3 XCheckTypedWindowEvent

© www.soinside.com 2019 - 2024. All rights reserved.