Quiero controlar todas las ventanas abiertas bajo X11. Actualmente, estoy haciendo esto de la siguiente manera:¿Cómo obtengo y sincronizo una lista completa de todas las ventanas X11?
- Inicialmente caminar todo el árbol mediante la llamada recursiva XQueryTree de la ventana raíz
- Para escuchar a la subestructura cambios en todo el escritorio:
XSelectInput(display, root_window, SubstructureNotifyMask | PropertyChangeMask)
- el manejo de todo MapNotify, UnmapNotify y eventos DestroyNotify, actualizando mi propia lista de ventanas en el proceso
Me preocupa principalmente 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 punto en el tiempo?
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 puede que nunca llegue a mi aplicación de monitoreo. ¿Cómo puede ser esto? ¿Es posible que se tire antes de llegar?
Actualización:
He escrito un pequeño programa que va a supervisar los eventos de X en la ventana raíz (véase más adelante). Ahora, cuando ejecuto este programa y comienzo y salgo de xcalc, obtengo la siguiente salida:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40
Eso es todo. Nunca me notifican que se está destruyendo la ventana real (0x4a0005b). ¡Ni siquiera de ser mapeado! ¿Alguien puede decirme por qué no? ¿SubStructureNotifyMask solo causa que se envíen eventos de las subventanas directas en lugar de todo el subárbol?
Por cierto, esto aparentemente no ocurre cuando se ejecuta Compiz. Entonces no se realiza reparentalización:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
Monitoreo fuente del programa:
#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;
}
Gracias! Eché un vistazo al código fuente de xwininfo y parece hacer el recorrido del árbol de la misma manera que lo hago: sin proteger las construcciones a su alrededor. Entonces, si existe la posibilidad de que el árbol cambie entre las llamadas a XQueryTree, xwininfo también se verá afectado y no dará los resultados correctos, supongo ... – Marten
@Marten, sí. xwininfo es una instantánea, pero te dará la jerarquía. Luego puede abrir varias ventanas y usarlas para ejecutar xprop -spy para buscar actualizaciones. Hay bastantes de estas herramientas. Eche un vistazo a la lista de la página man en http://www.x.org/archive/X11R6.9.0/doc/html/manindex1.html –