Sélection/masque et propagation des événements
Sélection des événements
C'est à votre application de définir fenêtre par fenêtre quels événements elle veut pouvoir traiter.
Il s'agit en fait d'un attribut de fenêtre:event_mask que l'on peut modifier. Il est à noter que par défaut, l'attribut event_mask d'une fenêtre est positionné à NoEventMask donc que la fenêtre ne reçoit aucun événement.
Pour le modifier, vous utiliserez la fonction XSelectInput ()
int XSelectInput(Display *display, Window w, long event_mask);
En entrée:
display comme d'habitude, il s'agit du display...soit la connexion à
un serveur X
w est l'identifiant de la fenêtre pour laquelle l'on veut recevoir les
événements dont la liste va suivre
event_mask la liste des événements que l'on veut recevoir
En sortie:
une valeur indiquant éventuellement qu'il y a un problème de fenêtre inexistante.
event_mask contient la liste des événements à traiter. En fait, il s'agit de masques binaires que l'on concatène en utilisant | pour faire un ou logique. Méthode que l'on retrouve souvant:suivant le type d'événement, celui-ci se retrouve avec une valeur de masque qui indique une position binaire. A cette position, 0 indique non sélectionné, 1 indique sélectionné. L'utilisation des Mask permet donc de positionner à 1 la position binaire correspondant à l'événement.
Par exemple, pour traiter les événements clic de la souris, le type d'événement est ButtonPress, le masque est ButtonPressMask
J'en
profite tout de suite pour signaler un risque d'erreur: Ne pas confondre le
type d'événement et le masque correspondant au type d'événement:
Il faudra bien utiliser ButtonPressMask dans XSelectInput() et surtout
pas ButtonPress. Cela ne provoquera pas d'erreur à la compilation
d'utiliser ButtonPress, mais les résultats seront surprenant ! Une valeur
est en effet associée à ButtonPress, cette valeur pouvant représenter
plusieurs positions binaires et donc plusieurs types d'événements
(et pas forcement celle que l'on veut !!!)...
Pour connaître le déplacement du pointeur de la souris, on utilisera PointerMotionMask.
Pour recevoir l'ensemble des événements, il faudra coder : XSelectInput (diplay, w, ButtonPressMask | PointerMotionMask);
Il est
aussi possible de modifier l'attribut event_mask d'une fenêtre via XCreateWindow()
ou XChangeWindowAttributes(). Je reviendrai dessus plus tard.
Propagation des événements
Le principe de propagation des événements est le suivant:
Le serveur X détermine qui doit être destinataire d'un évènement (par exemple un clic de souris). Cependant, lorsqu'une fenêtre ne traite pas ce type d'événement, le serveur X va remonter dans l'arborescence des fenêtres afin de voir si la fenêtre mère peut traiter ou non ce type d'événement. L'événement remonte ainsi jusqu'à ce qu'une fenêtre mêre soit en mesure de traiter l'événement, c'est la propagation.
Lorsque la fenêtre mère est trouvée, le serveur X met dans la file des événements le type d'événement, en précisant la fenêtre cible initiale grâce au champ subwindow de l'événement.
Vous pouvez avoir un exemple de code utilisant le champ subwindow afin de déterminer si l'événement concerne la fenêtre principale ou sa fille (il s'agit en fait de l'exemple final):
Bon, c'est un peu tôt, car nous n'avons pas encore vu la phase de lecture de la file d'événements...mais pour les intrépides.
Eviter la propagation des événements
Il est possible de bloquer la propagation d'un événement en modifiant l'attribut de la fenêtre do_not_propagate_mask via XCreateWindow() ou en utilisant XChangeWindowAttributes(). Je reviendrai dessus plus tard.
Ainsi si une fenêtre fille ne traite pas un événement, et bloque la propagation, la fenêtre mère ne traitera pas cet événement, même si elle accepte de traiter celui-ci.
Remplacer la liste des événements d'une fenêtre
Il est possible de remplacer la liste des événements traités par une fenêtre durant son existance, càd supprimer ou déclarer les événements que l'on veut traiter.
Nous utiliserons pour cela la fonction XChangeWindowAttributes
XChangeWindowAttributes (Display *display, Window w, CWEventMask, XSetWindowAttributes *xattrib);
En entréee:
display et w, vous devez connaître maintenant...
CWEventMask Pour indiquer que l'on veut changer les attributs "événement" de la fenêtre
xattrib avec xattrib.event_mask renseigné avec la liste des événements que l'on veut traiter dans la fenêtre (séparé par un |). Exemple: xattrib.event_mask= ButtonPressMask | PointerMotionMask;