Domanda

Sto cercando di ottenere un elenco di tutte le finestre desktop di livello superiore in una sessione X11. Fondamentalmente, voglio ottenere un elenco di tutte le finestre mostrate nell'interfaccia utente di commutazione delle applicazioni dei gestori di finestre (normalmente aperta quando l'utente preme ALT + TAB).

Non ho mai fatto alcuna programmazione X11 prima, ma finora sono riuscito a enumerare l'intero elenco di finestre, con un codice simile a questo:

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 () viene chiamato inizialmente con la finestra principale.

Funziona, nella misura in cui stampa informazioni su centinaia di finestre - ciò di cui ho bisogno, è capire quale proprietà posso interrogare per determinare se un dato Window è di livello superiore Finestra dell'applicazione desktop (non so quale sia la terminologia ufficiale) oppure no.

Qualcuno può far luce su questo? Tutta la documentazione di riferimento che ho trovato per la programmazione X11 è stata terribilmente secca e difficile da capire. Forse qualcuno potrebbe indicare una risorsa migliore?

È stato utile?

Soluzione

Ho una soluzione!

Beh, una specie di.

Se il tuo gestore di finestre utilizza i suggerimenti per il gestore di finestre estesi (EWMH), puoi eseguire una query sulla finestra di root utilizzando " _NET_CLIENT_LIST " atomo. Questo elenco returna di finestre client che gestisce il gestore delle finestre. Per ulteriori informazioni, vedere qui .

Tuttavia, ci sono alcuni problemi con questo. Per cominciare, il gestore delle finestre in uso deve supportare l'EWMH. KDE e GNOME lo fanno, e sono sicuro che anche altri lo fanno. Tuttavia, sono sicuro che ce ne sono molti che non lo fanno. Inoltre, ho notato alcuni problemi con KDE. Fondamentalmente, alcune applicazioni non KDE non vengono incluse nell'elenco. Ad esempio, se esegui xcalc in KDE non verrà visualizzato in questo elenco.

Se qualcuno può fornire miglioramenti su questo metodo, sarei felice di ascoltarli. Per riferimento, il codice che sto usando è elencato di seguito:

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

Altri suggerimenti

Per espandere la soluzione precedente, se si desidera ottenere i nomi delle finestre:

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

Se non devi usare Xlib, usare GDK gdk_screen_get_window_stack () e gdk_window_get_window_type () può aiutarti per le tue esigenze.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top