我想截取张贴到我正在编写的应用程序的特定窗口的WM_DELETE_WINDOW
消息(AllTray),以便我可以对它进行操作,而不是接收它的应用程序。我目前正在尝试在GDK级别via gdk_display_add_client_message_filter
上尝试这种方法,但是如果有的话,我会对Xlib解决方案感到满意。似乎有可能,但我似乎并不了解如何成功地做到这一点。
当前,我有两个程序(用C编写)试图用来弄清楚这个问题,the first one除了创建一个窗口并注册知道WM_DELETE_WINDOW
的内容外什么也不做,而the second one尝试捕获该消息,但似乎失败了在这样做;它似乎无能为力。我是否理解此文档是错误的,还是我需要做其他事情(或者是否需要避免完全使用GDK)?
背景是这样的:在我重写AllTray之前,它做事的方式似乎是尝试拦截X按钮本身上的鼠标单击。对于某些窗口管理器而言,此操作正常进行,对于其他窗口管理器则根本不起作用,对于其他窗口管理器,用户必须手动对其进行配置,并指示AllTray关闭窗口的按钮在何处。我正在寻找的解决方案不涉及LD_LIBRARY_PRELOAD
,并且适用于符合当前标准并在关闭窗口时发送WM_DELETE_WINDOW
ClientMessage的任何窗口管理器/应用程序组合。
更新:我仍在寻找答案。我目前采取的方法是尝试重新设置窗口并自己管理它,但我只是无法使其正常工作。重新定居后,我似乎无法以任何方式找回它。我可能错过了一些非常基本的内容,但是我无法弄清楚如何使它真正再次出现在我自己的窗口中,以使其重新出现在屏幕上。
更新2 :好的,所以我碰到了另一堵墙。 X服务器文档说要在窗口的事件掩码上设置StructureNotifyMask以同时接收MapNotify和ReparentNotify事件。我有兴趣接收其中之一。我目前的想法是创建一个窗口,将其用作事件接收器,然后在我收到有关有趣事件的事件时,通过创建和重新 parent 对其进行操作。但是,这似乎根本不起作用。我实际收到的唯一事件是PropertyNotify事件。因此,这条路线似乎也做得不好。
最佳答案
我不知道X11,但我使用"Intercept WM_DELETE_WINDOW
X11"作为关键字在Google上进行了搜索。找到17k - MarkMail和Mplayer-commits r154 - trunk/libvo。在这两种情况下,他们都在做同一件事。
/* This is used to intercept window closing requests. */
static Atom wm_delete_window;
在
static void x11_init()
中,XMapWindow(display, win);
wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, win, &wm_delete_window, 1);
然后,在
static int x11_check_events()
中,XEvent Event;
while (XPending(display)) {
XNextEvent(display, &Event);
if (Event.type == ClientMessage) {
if ((Atom)Event.xclient.data.l[0] == wm_delete_window) {
/* your code here */
}
}
}
参见XInternAtom,XSetWMProtocols和XNextEvent。
在写完上面的内容之后,我发现Handling window close in an X11 app:
// example.cpp
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
int main()
{
Display* display = XOpenDisplay(NULL);
Window window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0,
500, 400,
0,
0, 0);
// register interest in the delete window message
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1);
std::cout << "Starting up..." << std::endl;
XMapWindow(display, window);
while (true) {
XEvent event;
XNextEvent(display, &event);
if (event.type == ClientMessage &&
event.xclient.data.l[0] == wmDeleteMessage) {
std::cout << "Shutting down now!!!" << std::endl;
break;
}
}
XCloseDisplay(display);
return 0;
}
关于c - 在X11上拦截WM_DELETE_WINDOW?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1157364/