XLib:Windows 管理器在调用 XSetWMProtocols 后不发送客户端消息
XLib: Windows Manager not Sending Client Message after Calling XSetWMProtocols
网上有很多关于如何使用 XLib 处理 window 关闭的例子:
- http://cboard.cprogramming.com/linux-programming/60466-xwindows-close-window-event.html
- https://en.wikibooks.org/wiki/X_Window_Programming/XLib
- https://john.nachtimwald.com/2009/11/01/x11-intercept-window-close-event/
还有几个。也就是说,我已经尝试在代码中实现它们,如下所示。但是,当我单击 window 角落的 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;
}
}
}
}
XCheckWindowEvent() 不会returnClientMessage。它 returns none 个不可屏蔽的。解决方法:
while (XPending(display))
{
XNextEvent(display, &event);
但是 window 可以创建额外的工作来过滤事件。
BR 佩卡
如果你想阻止使用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
网上有很多关于如何使用 XLib 处理 window 关闭的例子:
- http://cboard.cprogramming.com/linux-programming/60466-xwindows-close-window-event.html
- https://en.wikibooks.org/wiki/X_Window_Programming/XLib
- https://john.nachtimwald.com/2009/11/01/x11-intercept-window-close-event/
还有几个。也就是说,我已经尝试在代码中实现它们,如下所示。但是,当我单击 window 角落的 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;
}
}
}
}
XCheckWindowEvent() 不会returnClientMessage。它 returns none 个不可屏蔽的。解决方法:
while (XPending(display))
{
XNextEvent(display, &event);
但是 window 可以创建额外的工作来过滤事件。 BR 佩卡
如果你想阻止使用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