简体   繁体   English

如何使用xlib识别顶级X11窗口?

[英]How to identify top-level X11 windows using xlib?

I'm trying to get a list of all top level desktop windows in an X11 session. 我正在尝试获取X11会话中所有顶级桌面窗口的列表。 Basically, I want to get a list of all windows that are shown in the window managers application-switching UI (commonly opened when the user presses ALT+TAB). 基本上,我想获取窗口管理器应用程序切换UI(通常在用户按下ALT + TAB时打开)中显示的所有窗口的列表。

I've never done any X11 programming before, but so far I've managed to enumerate through the entire window list, with code that looks something like this: 我以前从未做过任何X11编程,但是到目前为止,我已经设法枚举了整个窗口列表,其代码如下所示:

void CSoftwareInfoLinux::enumerateWindows(Display *display, Window rootWindow)
{
    Window parent;
    Window *children;
    Window *child;
    quint32 nNumChildren;

    XTextProperty wmName;
    XTextProperty wmCommand;

    int status = XGetWMName(display, rootWindow, &wmName);
    if (status && wmName.value && wmName.nitems)
    {
        int i;
        char **list;
        status = XmbTextPropertyToTextList(display, &wmName, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "Found window with name:" << (char*) *list;
        }

        status = XGetCommand(display, rootWindow, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "... and Command:" << i << (char*) *list;
        }

        Window tf;
        status = XGetTransientForHint(display, rootWindow, &tf);
        if (status >= Success && tf)
        {
            qDebug() << "TF set!";
        }

        XWMHints *pHints = XGetWMHints(display, rootWindow);
        if (pHints)
        {
            qDebug() << "Flags:" << pHints->flags
                    << "Window group:" << pHints->window_group;
        }
    }

    status = XQueryTree(display, rootWindow, &rootWindow, &parent, &children, &nNumChildren);
    if (status == 0)
    {
        // Could not query window tree further, aborting
        return;
    }

    if (nNumChildren == 0)
    {
        // No more children found. Aborting
        return;
    }

    for (int i = 0; i < nNumChildren; i++)
    {
        enumerateWindows(display, children[i]);
    }

    XFree((char*) children);
}

enumerateWindows() is called initially with the root window. enumerateWindows()最初是用根窗口调用的。

This works, in so far as it prints out information about hundreds of windows - what I need, is to work out which property I can interrogate to determine if a given Window is a top-level Desktop application window (not sure what the official terminology is), or not. 就可以打印出数百个窗口的信息而言,这是可行的-我需要的是确定我可以查询的属性,以确定给定的Window是否是顶级桌面应用程序窗口(不确定官方术语是什么)是),还是没有。

Can anyone shed some light on this? 谁能对此有所启发? All the reference documentation I've found for X11 programming has been terribly dry and hard to understand. 我发现的有关X11编程的所有参考文档都非常干燥且难以理解。 Perhaps someone could point be to a better resource? 也许有人会指出是更好的资源?

I have a solution! 我有解决办法!

Well, sort of. 好吧,有点。

If your window manager uses the extended window manager hints (EWMH), you can query the root window using the " _NET_CLIENT_LIST " atom. 如果您的窗口管理器使用扩展的窗口管理器提示(EWMH),则可以使用“ _NET_CLIENT_LIST ”原子查询根窗口。 This returna list of client windows the window manager is managing. 窗口管理器正在管理的客户端窗口的此返回列表。 For more information, see here . 有关更多信息,请参见此处

However, there are some issues with this. 但是,这存在一些问题。 For a start, the window manager in use must support the EWMH. 首先,使用中的窗口管理器必须支持EWMH。 KDE and GNOME do, and I'm sure some others do as well. KDE和GNOME可以做到,而且我敢肯定其他人也可以。 However, I'm sure there are many that don't. 但是,我敢肯定有很多没有的。 Also, I've noticed a few issues with KDE. 另外,我注意到KDE的一些问题。 Basically, some non-KDE applications don't get included in the list. 基本上,某些非KDE应用程序不会包含在列表中。 For example, if you run xcalc under KDE it won't show up in this list. 例如,如果在KDE下运行xcalc,它将不会显示在此列表中。

If anyone can provide any improvements on this method, I'd be glad to hear them. 如果任何人都可以对此方法进行任何改进,我很高兴听到他们的声音。 For reference, the code I'm using is listed below: 作为参考,下面列出了我正在使用的代码:

    Atom a = XInternAtom(m_pDisplay, "_NET_CLIENT_LIST" , true);
    Atom actualType;
    int format;
    unsigned long numItems, bytesAfter;
    unsigned char *data =0;
    int status = XGetWindowProperty(m_pDisplay,
                                rootWindow,
                                a,
                                0L,
                                (~0L),
                                false,
                                AnyPropertyType,
                                &actualType,
                                &format,
                                &numItems,
                                &bytesAfter,
                                &data);

    if (status >= Success && numItems)
    {
        // success - we have data: Format should always be 32:
        Q_ASSERT(format == 32);
        // cast to proper format, and iterate through values:
        quint32 *array = (quint32*) data;
        for (quint32 k = 0; k < numItems; k++)
        {
            // get window Id:
            Window w = (Window) array[k];

            qDebug() << "Scanned client window:" << w;
        }
        XFree(data);
    }

To expand on the previous solution, if you want to then get the window names: 要扩展先前的解决方案,如果要获取窗口名称,请执行以下操作:

// get window Id:
Window w = (Window) array[k];

char* name = '\0';
status = XFetchName(display, w, &name);
if (status >= Success)
{
    if (name == NULL)
        printf("Found: %ul  NULL\n", w);
    else
        printf("Found: %ul  %s\n", w, name);
}
XFree(name);

如果您不必使用Xlib,则使用GDK的gdk_screen_get_window_stack()gdk_window_get_window_type()可能会帮助您满足需要。

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

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