Como faço para obter e sincronizar uma lista completa de todas as janelas do X11?

Eu quero monitorar todas as janelas abertas no X11. Atualmente, estou fazendo isso da seguinte maneira:

Inicialmente percorrendo toda a árvore chamando recursivamente o XQueryTree da janela raizOuvindo as alterações da subestrutura em toda a área de trabalho:XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )Manipulando todos os eventos MapNotify, UnmapNotify e DestroyNotify, atualizando minha própria lista de janelas no processo

Estou preocupado principalmente com o ponto 1. Durante a recursão, o XQueryTree será chamado várias vezes. Existe alguma maneira de garantir que a árvore não mude enquanto isso? Em outras palavras, para obter um "instantâneo" da árvore inteira em um ponto no tempo?

Além disso, notei que, em alguns sistemas X11, nem todos os eventos chegam corretamente. Por exemplo, ao abrir uma nova janela na área de trabalho, o MapNotify para essa janela pode nunca chegar ao meu aplicativo de monitoramento. Como isso pode ser? É possível que seja jogado fora antes de chegar?

Atualizar:

Eu escrevi um pequeno programa que irá monitorar eventos X na janela raiz (veja abaixo). Agora, quando eu executo este programa e inicio e saio do xcalc, recebo a seguinte saída:

<code>Reparented: 0x4a0005b to 0x1001e40
Mapped    : 0x1001e40
Destroyed : 0x1001e40
</code>

É isso aí.Eu nunca sou notificado da janela real (0x4a0005b) sendo destruída. Nem mesmo de ser mapeado! Alguém pode me dizer por que não? O SubStructureNotifyMask só causa eventos dedireto subjanelas a serem enviadas em vez de toda a subárvore?

By the way, isso aparentemente não acontece quando o Compiz está sendo executado. Então, nenhuma reparação é feita:

<code>Mapped    : 0x4a0005b
Mapped    : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
</code>

Fonte do programa de monitoramento:

<code>#include <X11/Xlib.h>
#include <cstdio>

int main()
{
    Display *display;
    Window rootwin;

    display = XOpenDisplay( NULL );
    rootwin = DefaultRootWindow( display );
    XSelectInput( display, rootwin, SubstructureNotifyMask );

    XEvent event;

    while ( 1 ) {
        XNextEvent( display, &event );
        if ( event.type == MapNotify ) {
            XMapEvent *mapevent = (XMapEvent *)&event;
            printf( "Mapped    : 0x%x\n", (unsigned int)(mapevent->window) );
        }
        if ( event.type == DestroyNotify ) {
            XDestroyWindowEvent *destroywindowevent = (XDestroyWindowEvent *)&event;
            printf( "Destroyed : 0x%x\n", (unsigned int)(destroywindowevent->window) );
        }
        if ( event.type == ReparentNotify ) {
            XReparentEvent *reparentevent = (XReparentEvent *)&event;
            printf( "Reparented: 0x%x to 0x%x\n", (unsigned int)(reparentevent->window), (unsigned int)(reparentevent->parent) );
        }
    }

    return 0;
}
</code>

questionAnswers(3)

yourAnswerToTheQuestion