我想截取张贴到我正在编写的应用程序的特定窗口的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 - MarkMailMplayer-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 */
        }
    }
}

参见XInternAtomXSetWMProtocolsXNextEvent

在写完上面的内容之后,我发现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/

10-12 04:47