代码之家  ›  专栏  ›  技术社区  ›  Daniel Jennings

处理Xlib/Xt中的“新顶层窗口”事件

  •  4
  • Daniel Jennings  · 技术社区  · 17 年前

    问题是并不是每个CreateNotify事件都对应于一个[b]顶级[/b]窗口的创建。所以我想我需要做的是测试我从事件中得到的窗口,以确认它是顶层窗口。我靠得很近,但仍有一些假窗户穿过我的网。例如,在GTK应用程序中,如果您有一个下拉框并单击它,则会创建一个新窗口,我不知道如何捕获和忽略它。这样的窗口很难与典型的顶级应用程序窗口区分开来。

    以下是我目前掌握的情况:

    // I am omiting (tons of) cleanup code and where I set the display and toplevel variables.
    
    Display* display;
    Widget toplevel;
    
    bool has_name(Window window)
    {
        XTextProperty data = XTextProperty ();
        return (!XGetWMName (display, window, &data));
    }
    
    bool has_client_leader(Window window)
    {
        unsigned long nitems = 0;
        unsigned char* data = 0;
        Atom actual_type;
        int actual_format;
        unsigned long bytes;
        // WM_CLIENT_LEADER is an interned Atom for the WM_CLIENT_LEADER property
        int status = XGetWindowProperty (display, window, WM_CLIENT_LEADER, 0L, (~0L), False,
            AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes, &data);
        if (status != Success || acutal_type == None) return false;
        Window* leader = reinterpret_cast<Window*> (data);
        return (*leader != 0);
    }
    
    bool has_class(Window window)
    {
        XClassHint data = XClassHint ();
        return (!GetClassHint (display, window, &data));
    }
    
    void handle_event(Widget widget, XtPointer, XEvent* event, Boolean*)
    {
        if (event->type != CreateNotify) return;
    
        Window w = event->xcreatewindow.window;
    
        // confirm window has a name
        if (!has_name (w)) return;
    
        // confirm window is a client window
        Window client = XmuClientWindow (display, w);
        if (!client || client != w) return;
    
        // confirm window has a client leader that is not 0x0
        if (!has_client_leader (client)) return;
    
        // confirm window has a class
        if (!has_class (client)) return;
    
        // The window has passed all our checks!
        // Go on to do stuff with the window ...
    }
    
    int main(int argc, char* argv[])
    {
        // ...
    
        // Setting up the event handler for SubstructureNotify on root window
        Window root_window = XDefaultRootWindow (display);
        Widget dummy = XtCreateWidget ("dummy", coreWidgetClass, toplevel, 0, 0);
        XtRegisterDrawable (display, root_window, dummy);
        XSelectInput (display, root_window, SubstructureNotifyMask);
        XtAddRawEventHandler (dummy, SubstructureNotifyMask, False, handle_event, 0);
    
    // ...
    }
    

    不可能,但有人有什么想法我可以试试吗?我想不出我还能做什么了。

    1 回复  |  直到 17 年前
        1
  •  2
  •   Kim Reece    17 年前

    ICCCM long-winded discussion

    你检查过房间了吗 WM_TRANSIENT_FOR 财产?