Je veux surveiller toutes les fenêtres ouvertes sous X11. À l'heure actuelle, je fais cela comme suit:Comment obtenir et synchroniser une liste complète de toutes les fenêtres X11?
- marchant Dans un premier temps l'arbre tout en appelant récursive XQueryTree de la fenêtre racine
- l'écoute des changements de sous-structure sur l'ensemble de bureau:
XSelectInput(display, root_window, SubstructureNotifyMask | PropertyChangeMask)
- manutention Tous les MapNotify, UnmapNotify et DestroyNotify événements, mise à jour de ma propre liste de fenêtres dans le processus
Je suis principalement préoccupé par le point 1. Pendant la récursivité, XQueryTree sera appelé plusieurs fois. Y a-t-il un moyen de s'assurer que l'arbre ne change pas entre-temps? En d'autres termes, obtenir un «instantané» de l'ensemble de l'arbre à un moment donné?
En outre, j'ai remarqué que sous certains systèmes X11, tous les événements n'arrivent pas correctement. Par exemple, lors de l'ouverture d'une nouvelle fenêtre sur le bureau, MapNotify pour cette fenêtre peut ne jamais arriver à mon application de surveillance. Comment se peut-il? Est-il possible qu'il soit jeté avant d'arriver?
Mise à jour:
J'ai écrit un petit programme qui contrôlera les événements X sur la fenêtre racine (voir ci-dessous). Maintenant, quand je cours ce programme et commence et quitte xcalc, j'obtiens la sortie suivante:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40
C'est tout. Je ne suis jamais averti que la fenêtre réelle (0x4a0005b) est détruite. Pas même d'être cartographié! Quelqu'un peut-il me dire pourquoi pas? Est-ce que SubStructureNotifyMask ne cause que les événements directs sous-fenêtres à envoyer à la place du sous-arbre entier? D'ailleurs, cela ne se produit apparemment pas lorsque Compiz est en cours d'exécution. Alors pas reparentage est fait:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
source de programme de surveillance:
#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;
}
Merci! J'ai regardé le code source pour xwininfo et il semble faire la traversée de l'arbre de la même manière que je le fais: sans protéger les constructions autour. Donc, s'il y a la possibilité que l'arbre change entre les appels XQueryTree, xwininfo sera également affecté et ne donnera pas les bons résultats je suppose ... – Marten
@Marten, oui. xwininfo est un instantané, mais il vous donnera la hiérarchie. Ensuite, vous pouvez ouvrir plusieurs fenêtres et les utiliser pour lancer xprop -spy pour vérifier les mises à jour. Il y a quelques uns de ces outils. Jetez un oeil à la liste des pages de man http://www.x.org/archive/X11R6.9.0/doc/html/manindex1.html –