Frage

Ich versuche, eine Liste aller Top-Level-Desktop-Fenster in einer X11-Sitzung zu erhalten. Grundsätzlich mag ich eine Liste aller Fenster erhalten, die Benutzeroberfläche in dem Window-Manager-Anwendung vermittelnde gezeigt werden (üblicherweise geöffnet, wenn der Benutzer drückt ALT + TAB).

Ich habe noch nie eine beliebige X11 Programmierung getan, aber bisher habe ich es geschafft, durch die gesamte Fensterliste aufzuzählen, mit Code, der etwa wie folgt aussieht:

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() wird zunächst mit dem Root-Fenster genannt.

Das funktioniert, soweit es Informationen ausdruckt über Hunderte von Fenstern -, was ich brauche, ist herauszufinden, welche Eigenschaft ich, ob ein gegebenes Window ein Top-Level Desktop-Anwendungsfenster ist zu bestimmen, abfragen kann (nicht sicher, was die offizielle Terminologie ist) oder nicht.

Kann jemand etwas Licht in diese? Alle Referenzdokumentation ich für X11 Programmierung gefunden habe war furchtbar trocken und schwer zu verstehen. Vielleicht hat jemand deuten auf eine bessere Ressourcen sein könnte?

War es hilfreich?

Lösung

Ich habe eine Lösung!

Nun, irgendwie.

Wenn die Fenster-Manager der erweiterten Fenstermanager Hinweise (EWMH) verwendet, können Sie die Root-Fenster abfragen, um das „_NET_CLIENT_LIST“ Atom verwendet wird. Diese returna Liste der Client-Fenster ist der Fenstermanager verwaltet. Weitere Informationen finden Sie unter hier .

Es gibt jedoch einige Probleme mit diesem. Für den Anfang muss der Window-Manager im Einsatz die EWMH unterstützen. KDE und GNOME tun, und ich bin sicher, dass einige andere auch tun. Aber ich bin sicher, es gibt viele, die dies nicht tun. Außerdem habe ich ein paar Probleme mit KDE bemerkt. Grundsätzlich einige Nicht-KDE-Anwendungen nicht in die Liste aufgenommen bekommen. Zum Beispiel, wenn Sie xcalc unter KDE laufen wird es zeigen, die nicht in dieser Liste nach oben.

Wenn jemand irgendwelche Verbesserungen dieser Methode zur Verfügung stellen kann, würde ich mich freuen, sie zu hören. Als Referenz bin mit dem Code I wird im Folgenden aufgeführt:

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

Andere Tipps

Um auf der vorherige Lösung zu erweitern, wenn Sie wollen, um dann die Fensternamen zu bekommen:

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

Wenn Sie zu Xlib nicht verwenden, mit GDK des gdk_screen_get_window_stack() und gdk_window_get_window_type() können Sie für Ihre Bedürfnisse helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top