Question

J'essaie d'obtenir une liste de toutes les fenêtres de bureau de niveau supérieur dans une session X11. En gros, je souhaite obtenir une liste de toutes les fenêtres affichées dans l'interface utilisateur de commutation d'applications du gestionnaire de fenêtres (généralement ouverte lorsque l'utilisateur appuie sur ALT + TAB).

Je n'ai jamais programmé X11 auparavant, mais j'ai réussi jusqu'à présent à énumérer toute la liste des fenêtres, avec un code qui ressemble à ceci:

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 () est appelé initialement avec la fenêtre racine.

Cela fonctionne, dans la mesure où il imprime des informations sur des centaines de fenêtres - ce dont j'ai besoin, c'est de déterminer quelle propriété je peux interroger pour déterminer si un Window donné est un niveau supérieur Fenêtre de l'application de bureau (ne sachant pas quelle est la terminologie officielle), ou non.

Quelqu'un peut-il nous éclairer? Toute la documentation de référence que j'ai trouvée pour la programmation X11 a été terriblement sèche et difficile à comprendre. Peut-être que quelqu'un pourrait indiquer une meilleure ressource?

Était-ce utile?

La solution

j'ai une solution!

Eh bien, en quelque sorte.

Si votre gestionnaire de fenêtres utilise les indications du gestionnaire de fenêtres étendu (EWMH), vous pouvez interroger la fenêtre racine à l'aide de l'option " _NET_CLIENT_LIST ". atome. Cette liste retourne les fenêtres clientes gérées par le gestionnaire de fenêtres. Pour plus d'informations, consultez ici .

Cependant, cela pose quelques problèmes. Pour commencer, le gestionnaire de fenêtres utilisé doit prendre en charge EWMH. KDE et GNOME le font, et je suis sûr que d’autres le font aussi. Cependant, je suis sûr que beaucoup ne le font pas. De plus, j'ai remarqué quelques problèmes avec KDE. Fondamentalement, certaines applications non-KDE ne sont pas incluses dans la liste. Par exemple, si vous exécutez xcalc sous KDE, il n'apparaîtra pas dans cette liste.

Si quelqu'un peut apporter des améliorations à cette méthode, je serais heureux de les entendre. Pour référence, le code que j'utilise est listé ci-dessous:

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

Autres conseils

Pour développer la solution précédente, si vous souhaitez obtenir ensuite les noms de fenêtre:

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

Si vous n’êtes pas obligé d’utiliser Xlib, utilisez le gdk_screen_get_window_stack () et le gdk_window_get_window_type de GDK pour vous aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top