-->

如何使用Xlib的识别顶级X11窗口?(How to identify top-level X11

2019-06-27 03:13发布

我试图让在X11会话中所有顶级桌面窗口的列表。 基本上,我想那是在窗口管理器应用程序切换界面显示的所有窗口的列表(当用户按下ALT + TAB通常打开)。

我以前从来没有做过任何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()与根窗口最初被调用。

这个作品,只要它打印出约几百个窗口的信息-我需要的,是制定我可以查询,以确定哪些财产,如果给定的Window是顶级桌面应用程序窗口(不知道官方术语是),或没有。

任何人都可以阐明这一些轻? 所有我已经找到了X11编程的参考文档已经非常干燥,很难理解。 也许有人可以点是一个更好的资源?

Answer 1:

我有一个解决方案!

嗯,有点。

如果你的窗口管理器使用扩展窗口管理器提示(EWMH),您可以查询使用“根窗口_NET_CLIENT_LIST ”原子。 这returna客户端窗口的列表窗口管理器管理。 欲了解更多信息,请参见这里 。

然而,也有一些问题,与此有关。 一开始,使用的窗口管理器必须支持EWMH。 KDE和GNOME做的,我敢肯定,一些人做的一样好。 但是,我相信还有很多不知道。 另外,我注意到有KDE的几个问题。 基本上,一些非KDE应用程序没有得到包括在列表中。 例如,如果你KDE下运行xcalc它不会在这个列表中显示出来。

如果任何人都可以提供这种方法的任何改进,我会很高兴听到他们的声音。 作为参考,我正在使用的代码列表如下:

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


Answer 2:

为了扩大在以前的解决方案,如果你想要再拿到窗口名称:

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


Answer 3:

如果你没有使用的Xlib,使用GDK的gdk_screen_get_window_stack()gdk_window_get_window_type()可以帮助您为您的需求。



文章来源: How to identify top-level X11 windows using xlib?