簡體   English   中英

如何使用xlib識別頂級X11窗口?

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

我正在嘗試獲取X11會話中所有頂級桌面窗口的列表。 基本上,我想獲取窗口管理器應用程序切換UI(通常在用戶按下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編程的所有參考文檔都非常干燥且難以理解。 也許有人會指出是更好的資源?

我有解決辦法!

好吧,有點。

如果您的窗口管理器使用擴展的窗口管理器提示(EWMH),則可以使用“ _NET_CLIENT_LIST ”原子查詢根窗口。 窗口管理器正在管理的客戶端窗口的此返回列表。 有關更多信息,請參見此處

但是,這存在一些問題。 首先,使用中的窗口管理器必須支持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);
    }

要擴展先前的解決方案,如果要獲取窗口名稱,請執行以下操作:

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