¿Cómo obtengo y sincronizo una lista completa de todas las ventanas X11?

Quiero monitorear todas las ventanas abiertas bajo X11. Actualmente, estoy haciendo esto de la siguiente manera:

Inicialmente, caminar todo el árbol llamando recursivamente a XQueryTree desde la ventana raízEscuchando cambios de subestructura en todo el escritorio:XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )Manejo de todos los eventos de MapNotify, UnmapNotify y DestroyNotify, actualizando mi propia lista de ventanas en el proceso

Principalmente me preocupa el punto 1. Durante la recursión, se llamará a XQueryTree varias veces. ¿Hay alguna manera de asegurar que el árbol no cambie mientras tanto? En otras palabras, ¿para obtener una 'instantánea' de todo el árbol en un momento dado?

Además, he notado que en algunos sistemas X11, no todos los eventos llegan correctamente. Por ejemplo, al abrir una nueva ventana en el escritorio, MapNotify para esa ventana nunca llegará a mi aplicación de monitoreo. ¿Cómo puede ser esto? ¿Es posible que se deseche antes de llegar?

Actualizar:

He escrito un pequeño programa que monitoreará los eventos X en la ventana raíz (ver más abajo). Ahora, cuando ejecuto este programa y comienzo y salgo de xcalc, obtengo el siguiente resultado:

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

Eso es.Nunca se me notifica que la ventana real (0x4a0005b) está siendo destruida. ¡Ni siquiera de que sea mapeado! ¿Alguien puede decirme por qué no? ¿SubStructureNotifyMask solo causa eventos dedirecto ¿Subwindows para enviar en lugar de todo el subárbol?

Por cierto, esto aparentemente no sucede cuando se está ejecutando Compiz. Entonces no se hace ninguna reparación:

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

Fuente del programa de monitoreo:

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

Respuestas a la pregunta(3)

Su respuesta a la pregunta