简体   繁体   English

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

[英]Handle “new top level window” events in Xlib/Xt

So I'm in a situation where I need to know when a top level window gets created. 因此,我处于一种需要知道何时创建顶级窗口的情况。 I'm working at the Xlib/Xt level and on a Window Manager that doesn't support the EWMH specification. 我正在Xlib / Xt级别和不支持EWMH规范的Window Manager上工作。 My idea is to hook into the root window's SubstructureNotify events. 我的想法是挂接到根窗口的SubstructureNotify事件。 But things are not as simple as just that. 但是事情并没有那么简单。

The problem is that not every CreateNotify event corresponds to the creation of a [b]top level[/b] window. 问题在于,并非每个CreateNotify事件都对应于[b]顶层[/ b]窗口的创建。 So what I think I need to do is test the window I get from the event somehow to confirm that it is a top level window. 因此,我认为我需要做的是测试从事件中获取的窗口,以确认它是顶级窗口。 I've got close, but some spurious windows still make it through my net. 我已经接近了,但是一些伪造的窗户仍然可以穿过我的网。 For example, in a GTK application if you have a dropdown box and you click it, a new window is created that I can't figure out how to catch and ignore. 例如,在GTK应用程序中,如果有一个下拉框并单击它,则会创建一个新窗口,我无法弄清楚如何捕获和忽略它。 Such a window is troublesomely indistinguishable from a typical top level application window. 这样的窗口很难与典型的顶层应用程序窗口区分开。

Here's what I have so far: 这是我到目前为止的内容:

// 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);

// ...
}

A long shot, but does anyone have any ideas I could try? 远射,但是有人有我可以尝试的想法吗? I can't think of much else I can really do here. 我想不出我在这里能做的很多事情。

I assume you're familiar with the ICCCM and its long-winded discussion . 我认为您熟悉ICCCM及其冗长的讨论

Have you checked the WM_TRANSIENT_FOR property? 您是否检查了WM_TRANSIENT_FOR属性?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM