5
Dans ce chapitre nous allons dtailler tous les vnements concernant la souris et le clavier.
Nous avons vu dans le chapitre prcdent que pour recevoir un vnement il fallait en avoir fait la demande auprs du serveur en slectionnant cet vnement sur une fentre. En ralit cette condition n'est pas suffisante pour les vnements sur les dispositifs dÕentre. Comme nous l'avons dj nonc dans le chapitre prcdent, une seule fentre, un instant donn, recevra les vnements concernant le clavier, et une seule fentre (pas ncessairement la mme), recevra les vnements de mouvements et boutons de souris.
En effet, les dispositifs d'entre sont partags par toutes les applications tournant l'cran mais ne concernent un instant donn qu'une seule fentre. Par exemple, lÕenfoncement dÕune touche du clavier opr par lÕutilisateur ne concerne un instant donn quÕune seule application.
Le problme de la destination des actions de l'utilisateur sur le clavier et la souris est rsolu lÕaide dÕun certain nombre de rgles. La propagation des vnements (gouverne par les attributs event_mask et do_not_propagate_mask des fentres) est l'une de ces rgles, mais il y a d'autres notions qui interviennent, que nous allons dtailler dans ce chapitre. Dans cette premire section, nous allons d'abord dcrire le comportement par dfaut du systme, tout en introduisant deux notions fondamentales permettant de comprendre l'attribution des dispositifs d'entre.
La fentre
recevant les entres des touches du clavier est dite avoir le focus du clavier[1]. La convention par dfaut du systme est
que c'est la fentre racine qui a le focus. Une fentre qui a le focus en fait
bnficier ses descendantes et il s'ensuit que c'est la fentre situe sous le
curseur de souris qui bnficie par dfaut du focus du clavier.
Concernant le focus, les window manager mettent en Ļuvre deux conventions : la convention par dfaut, selon laquelle la fentre ayant le focus est la fentre situe sous le pointeur de souris, et une deuxime convention, selon laquelle c'est l'utilisateur qui dtermine le focus en cliquant pralablement sur la fentre concerne ou sur sa bannire. Pour implanter cette deuxime convention, les window manager utilisent la fonction XSetInputFocus qui permet dÕattribuer le focus du clavier une fentre autre que la racine.
XSetInputFocus (dpy, focus_win, revert_to, time)
Display* dpy ;
Window focus_win, revert_to ;
Time time ;
XSetInputFocus attribue le focus la fentre focus_win. Il sÕensuit que seule cette fentre et ses descendantes pourront ensuite recevoir les vnements KeyPress et KeyRelease. La fentre qui reoit le focus doit tre visible, sinon une erreur de type BadMatch est gnre au moment de l'excution de la requte.
On peut passer pour focus_win un identificateur de fentre ou les constantes PointerRoot (pour dsigner la racine contenant le pointeur ce moment) ou None pour annihiler tout vnement sur le clavier jusqu'au prochain changement de focus. L'argument revert_to indique vers quelle fentre rediriger le focus si la fentre accaparante devenait invisible. On peut indiquer l'une des constantes RevertToParent, RevertToPointerRoot ou RevertToNone. Cet argument n'est consult que si l'on a pass un vritable identificateur de fentre (sinon, on aura pass PointerRoot ou None, et dans les deux cas, un changement de focus ne pourra se produire que par un nouvel appel XSetInputFocus). Quant l'attribut time, il prcise quand le changement de focus doit prendre effet. On peut passer une estampille du temps en millisecondes ou la constante CurrentTime.
Un appel XSetInputFocus gnre lÕenvoi dÕvnements de type FocusIn et FocusOut aux fentres acqurant et perdant respectivement le focus.
La fentre recevant les vnements souris est par dfaut la fentre situe sous le pointeur de souris, sauf en cas de saisie du pointeur.
On appelle saisie (grab en anglais) la monopolisation d'un dispositif d'entre par une fentre. En cas de saisie, les vnements concernant le dispositif sont uniquement achemins vers la fentre accaparante. Autrement dit, les autres fentres ne peuvent plus recevoir d'vnement concernant ce dispositif, et c'est pourquoi l'on dit que le dispositif a t saisi. Contrairement ce que l'on pourrait croire, les cas de saisie sont frquents car le systme dclenche automatiquement une saisie du pointeur sur l'occurrence d'un vnement de type ButtonPress. Entre deux vnements de type ButtonPress et ButtonRelease les vnements souris sont achemins uniquement pour la fentre ayant slectionn lÕenfoncement de bouton, et ce, jusquÕ ce que tous les boutons de la souris soient relchs. On parle dans ce cas de saisie automatique du pointeur.
En cas de
saisie, la fentre recevant les vnements souris nÕest plus ncessairement
celle dans laquelle se trouve le pointeur. En effet, c'est la fentre qui a
reu l'vnement ButtonPress qui
reoit alors les vnements souris, mme si le pointeur sort de cette fentre.
En outre, aucune autre fentre ne reoit plus dÕvnement souris, mme si la
fentre accaparante n'en a pas slectionn d'autre.
Les rgles que nous venons d'noncer dcrivent le comportement par dfaut du systme. En ralit, tout client peut sortir de ces conventions et demander au serveur la saisie d'un dispositif d'entre ou la modification des paramtres de la saisie dclenche automatiquement par le systme sur lÕvnement ButtonPress. Mais avant de dtailler les phnomnes de saisie, nous allons prsenter les vnements souris et donner un exemple simple de programmation.
ButtonPress ButtonRelease |
Ces vnements sont envoys si un bouton de la souris est enfonc ou relch. On les slectionne avec les masques ButtonPressMask et ButtonReleaseMask. Ces vnements sont envoys la fentre dans laquelle se trouvait la souris au moment de l'enfoncement du bouton, sauf en cas d'appropriation de la souris. Un vnement de type XButtonEvent contient un champ button permettant de connatre le numro du bouton qui est enfonc ou relch. |
Comme nous l'avons dj indiqu, l'enfoncement d'un bouton de souris dclenche automatiquement une saisie de la souris par la fentre ayant slectionn cet vnement. Cette fentre reoit ensuite les vnements souris qu'elle a slectionns, quelque soit la position de la souris et jusqu' ce que tous les boutons soient relchs. Durant toute cette priode, les autres fentres ne reoivent plus d'vnement souris. Pour prvenir l'utilisateur, le curseur de souris garde la forme qui lui tait attribu dans la fentre accaparante, mme s'il se trouve l'extrieur.
Les avantages de la saisie automatique sont nombreux. Sans ce mcanisme, il serait impossible de faire glisser un objet sur l'cran en l'entranant avec la souris, car cet objet cesserait de recevoir les vnements ds que la souris sortirait de la fentre. Il y a cependant des cas o ce comportement n'est pas avantageux pour l'application.
On peut supprimer cette redirection des vnements vers la fentre accaparante au niveau de l'application en ajoutant le masque OwnerGrabButtonMask[2] au masque de slection de l'vnement bouton. Dans ce cas, les vnements souris sont envoys aux fentres de l'application se trouvant sous le curseur jusqu' ce que la saisie prenne fin.
La saisie du pointeur reste cependant active dans les fentres des autres clients, et ces derniers ne reoivent plus d'vnement souris. L'intrt de ce mcanisme est que l'application qui a slectionn un vnement de type ButtonPress est toujours assure de pouvoir rcuprer l'vnement ButtonRelease correspondant, mme s'il se produit dans la fentre dÕun autre client. CÕest pourquoi, la saisie nÕest pas entirement dsactive par le masque OwnerGrabButtonMask et elle continue d'affecter les fentres des autres clients.
Dtaillons pour ces premiers vnements, les champs accessibles dans la structure XButtonEvent associe[3]. Une structure d'vnement contient quel que soit son type les cinq champs de la structure XAnyEvent que nous avons dj comments dans le chapitre prcdent. On aura donc accs ici (comme pour n'importe quel type d'vnement) aux champs type, window, serial, display et send_event. Les autres champs disponibles sont les suivants :
Window root Ce champ indique la racine sur laquelle s'est produit l'vnement.
Window subwindow Ce champ indique la sous-fentre dans laquelle s'est produit l'vnement quand elle diffre de la fentre qui l'a reu (champ window).
Time time Le champ time indique l'heure de l'vnement en millisecondes. Le type Time correspond en ralit au type unsigned long. Ce champ devient par consquent faux quand sa valeur dpasse 32 bits, ce qui se produit environ tous les 49,7 jours[4].
int x,y Les champs x et y fournissent les coordonnes du pointeur au moment de l'vnement, relativement la fentre ayant reu l'vnement (champ window).
int x_root, y_root Ces champs fournissent les coordonnes du pointeur au moment de l'vnement relativement la racine sur laquelle l'vnement s'est produit (champ root).
unsigned int state L'entier state est un masque qui fournit l'tat des modifieurs[5] et des boutons juste avant l'vnement. On pourra tester le champ state grce aux entiers symboliques numrs figure 5.1.
Mod1Mask Button1Mask
ShiftMask Mod2Mask Button2Mask
LockMask Mod3Mask Button3Mask
ControlMask Mod4Mask Button4Mask
Mod5Mask Button5Mask
fig.
5.1. Les masques d'tat des boutons et modifieurs
unsigned int button Dtail indiquant le numro du bouton qui a t enfonc ou relch. Les valeurs possibles sont Button1, Button2, etc. ( ne pas confondre avec les masques de la figure 5.1).
Bool same_screen Le boolen same_screen indique si le pointeur est toujours sur le mme cran. Ce champ sert dans les cas de saisie du pointeur quand la souris peut changer dÕcran.
La plupart de ces champs sont galement disponibles dans les vnements de mouvement de souris que nous allons dcrire maintenant.
MotionNotify |
La souris a boug. Ce type d'vnement est envoy pour tous les mouvements de souris ; mais les mouvements de souris tant trs nombreux, on peut restreindre le nombre des vnements envoys en indiquant des contraintes par des masques de slection spcifiques. |
Les masques permettant de slectionner des mouvements souris sont PointerMotionMask, ButtonMotionMask et Button<n>MotionMask, o n est un entier compris entre 1 et 5. Les mouvements ne seront tous envoys que s'ils ont t slectionns avec PointerMotionMask. ButtonMotionMask limite l'envoi des vnements aux mouvements se produisant lorsqu'un bouton de souris est enfonc. On peut mme restreindre encore l'envoi des vnements ceux se produisant lorsquÕun bouton particulier de la souris est enfonc, commele deuxime bouton avec Button2MotionMask. Ces masques de slection peuvent tre combins entre eux.
La structure associe un vnement de type MotionNotify est de type XMotionEvent et on y accde via le membre xmotion de lÕunion XEvent. Elle contient les cinq champs de la structure XAnyEvent et les neufs champs que nous avons dj comments pour les vnements ButtonPress et ButtonRelease. Ces neufs champs supplmentaires sont en ralit communs tous les vnements sur les entres (i.e. aux vnements de type ButtonPress, ButtonRelease, KeyPress, KeyRelease, MotionNotify, EnterWindow et LeaveWindow) et ont t regroups figure 5.2.
Window root; /* racine sur laquelle l'ev. s'est produit */
Window subwindow; /* fentre fille o s'est produit l'ev.*/
Time time; /* horaire en millisecondes */
int x, y; /* coordonns relatives window */
int x_root, y_root; /* coordonns relatives root */
unsigned int state; /* tat des boutons et modifieurs (masque) */
Bool same_screen; /* si le pointeur est sur le mme cran*/
fig.
5.2. Neuf champs communs aux vnements dÕentre
(en
sus de ceux communs tous les vnements)
En outre, un champ supplmentaire is_hint (de type char) indique si l'vnement MotionNotify a t envoy normalement ou selon un mode spcial, prconis par l'emploi du masque PointerMotionHintMask.
Le masque PointerMotionHintMask, (de lÕanglais Hint, indication, trace ou piste) permet de rduire l'envoi des vnements de mouvement et de mieux synchroniser leur traitement par l'application. Ce masque ne slectionne pas en lui‑mme de mouvement mais peut tre utilis en association avec les masques de slection (restreint ou non) numrs dans la section prcdente. Le masque PointerMotionHintMask demande en ralit l'envoi dÕun seul vnement de mouvement — un autre mouvement de souris n'tant envoy lÕapplication que si le client en ritre explicitement la demande[6] via un appel XQueryPointer ou XGetMotionEvents.
Ce mcanisme permet dÕignorer les mouvements qui se produisent pendant que lÕapplication traite les vnements de mouvement quÕelle reoit. Sur rception d'un premier mouvement de souris, lÕapplication peut traiter cet vnement et appeler alors XQueryPointer. Cette fonction lui permet la fois de rcuprer la position actuelle de la souris et de reslectionner lÕenvoi dÕun nouvel vnement. La position du pointeur de souris qui est rcupre par XQueryPointer est plus rcente que celle fournie par l'vnement reu et donc mieux synchronise avec lÕutilisateur. En outre, lÕapplication demandant les vnements un un se trouve elle-mme mieux synchronise avec le serveur car on vite d'accumuler du retard en ayant trop d'vnements de mouvement traiter. On utilisera cette technique pour optimiser le suivi de la souris chaque fois que les positions intermdiaires de la souris peuvent tre ignores[7]. LÕexemple dvelopp dans la section suivante utilise cette technique.
La fonction XQueryPointer prend les arguments suivants :
Bool XQueryPointer ( dpy, win, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &state)
Display* dpy ;
Window win,
root_return, child_return;
int root_x_return, root_y_return ,win_x_return, win_y_return ;
unsigned int state ;
Grossirement, cette fonction permet de rcuprer la position de la souris relativement une fentre quelconque. L'argument win est une fentre choisie par le programmeur, et qui servira d'origine pour rapporter la position actuelle de la souris (dans win_x et win_y), sous rserve que la souris se trouve encore sur le mme cran. Dans ce cas, la fonction retourne True. Sinon, la fonction retourne False mais permet (dans tous les cas) de rcuprer la racine sur laquelle se trouve la souris (dans root_return) et la position de la souris relativement la racine (dans root_x et root_y). L'argument child_return rapporte l'identificateur de la fentre dans laquelle se trouve la souris et le masque state rapporte l'tat des boutons et des modifieurs.
Dans cette section nous allons dtailler la programmation d'une barre de dfilement. La figure 5.3. donne quelques indications sur les noms des variables que lÕon va utiliser. Pour matrialiser la barre de dfilement, on va crer une fentre rectangulaire assez longue appele barre. Pour matrialiser l'ascenseur nous utiliserons une seconde fentre plus petite que nous appellerons tirette. La seconde fentre tant toujours incluse dans la premire, nous pourrons la crer fille de la premire.
fig.
5.3. La programmation dÕune barre de dfilement
Les contraintes matrielles sont que les deux fentres aient toujours mme hauteur et que la position en x de la tirette reste comprise entre 0 et LONGUEUR moins LARGEUR pour que la tirette ne sorte pas de la barre.
Les vnements slectionner dpendent du fonctionnement de la barre de dfilement. Supposons ici que :
„ quand on clique dans la barre, le centre de la tirette est amen l'endroit o l'on vient de cliquer.
„ quand on clique et que lÕon tire la souris en maintenant le bouton enfonc, la tirette (c'est--dire son centre) suit le mouvement de la souris sur l'axe de la barre.
„ si on modifie la taille de la barre, la hauteur de la tirette s'adapte celle de la barre mais sa largeur initiale reste constante.
Il rsulte de cette description que l'on doit slectionner les vnements ButtonPress sur la barre pour capter l'enfoncement du bouton, et slectionner les mouvements de souris avec le masque ButtonMotionMask pour capter les mouvements qui se produisent quand un bouton de la souris est enfonc. On doit galement slectionner les vnements ConfigureNotify ( l'aide du masque StructureNotifyMask) sur la barre pour capter les changements de taille de la barre et rajuster la hauteur de la tirette en consquence. On aurait pu slectionner aussi les vnements souris sur la tirette, mais cela n'est gure ncessaire ici du fait de la propagation des vnements. Un vnement qui se produit sur la tirette sera de toute faon propag la barre[8].
Pour raliser un suivi rapide de la souris, on va demander ne recevoir qu'une trace des mouvements de souris. On utilisera donc le masque PointerMotionHintMask en combinaison avec ButtonMotionMask pour slectionner les mouvements. On fera ensuite appel XQueryPointer chaque fois qu'on recevra un vnement de mouvement pour rcuprer la position actuelle de la souris et demander l'envoi du prochain mouvement au serveur. Dans notre exemple, on peut considrer que notre dispositif d'affichage n'a qu'un cran et rcuprer les coordonnes du pointeur relativement la barre avec XQueryPointer sans en tester la valeur de retour.
Avant de nous lancer dans la programmation, reste encore se poser la question suivante[9] : Doit-on lever ou non la saisie de la souris dclenche par lÕvnement ButtonPress ? (Si oui, il suffit de rajouter le masque OwnerGrabButtonMask lors de la slection de l'enfoncement du bouton. )
Ici, la rponse est non. Au contraire, on se trouve dans un bon cas vis--vis du comportement par dfaut. Il est souhaitable en effet que les vnements souris soient toujours achemins vers la barre, mme si la souris sort de la fentre. Sinon, on ne recevra plus d'vnement quand la souris quitterait un peu la barre, et cela pourrait gner l'utilisateur si la barre est troite. Par contre, il faut faire bien attention bloquer la tirette l'intrieur de la barre.
Voici finalement une programmation possible de cette barre de dfilement, o l'on note l'abscisse de la tirette relativement la barre dans la variable tire_x, et l'abscisse de la souris relativement la barre dans pt_x :
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/bitmaps/gray3> /* Pour le fond de la tirette */
#define LONGUEUR 600 /* Les dimensions initiales de la barre */
#define LARGEUR 50
char* nom_de_station = NULL;
unsigned long pixel_blanc, pixel_noir;
Display* dpy;
Window root,
barre, /* la barre de defilement, ici fenetre principale */
tirette; /* l'ascenseur proprement dit */
int screen_n;
/*
* une procdure de sortie qui imprime un message d'erreur
*/
void erreur (message_format, a1, a2, a3)
char* message_format;
{
printf (message_format, a1, a2, a3);
exit (1);
}
/*
* La boucle d'vnements
*/
events () {
XEvent ev;
int tire_x, /* position courante de la tirette */
pt_x, /* position de la souris */
i_bidon; /* entier bidon */
int width, /* les dimensions */
height; /* de la barre */
Window w_bidon; /* fentre bidon */
XWindowAttributes xwa;
tire_x = 0; /* position courante de la tirette relativement la barre */
/*
* La largeur et la hauteur de la barre peuvent avoir t modifies par l'intervention
* du window manager et de l'utilisateur. Il faut rcuprer ces donnes avant de
* procder au traitement des vnements.
*/
XGetWindowAttributes (dpy, barre, &xwa);
width = xwa.width;
height = xwa.height;
for (;;) {
XNextEvent (dpy, &ev);
switch (ev.type) {
case ButtonPress:
/*
* Si on est dans la barre il faut dplacer la tirette la o on a cliqu
*/
if (ev.xbutton.subwindow != tirette) {
/*
* on doit tenir compte de la position limite droite
*/
if (ev.xbutton.x > width - LARGEUR/2)
tire_x = width - LARGEUR;
else
tire_x = ev.xbutton.x - LARGEUR/2;
if (tire_x < 0)
tire_x = 0;
XMoveWindow (dpy, tirette, tire_x, 0);
}
break;
case MotionNotify:
/*
* Rcuprer la position actuelle de la souris relativement la barre
*/
XQueryPointer (dpy, barre, &w_bidon, &w_bidon, &i_bidon, &i_bidon, &pt_x, &i_bidon, &i_bidon);
/*
* Un effet de bord de cette fonction (avec PointerMotionHintMask)
* est de slectionner l'envoi du prochain mouvement de souris
*
* Dplacer le centre de la tirette l'emplacement point en tenant
* compte des positions limites
*/
tire_x = pt_x - LARGEUR/2;
if (tire_x < 0)
tire_x = 0;
if (tire_x > width - LARGEUR)
tire_x = width - LARGEUR;
XMoveWindow (dpy, tirette, tire_x, 0);
break;
case ConfigureNotify:
/*
* La barre a chang de taille, il faut modifier la hauteur de la tirette
*/
height = ev.xconfigure.height;
XResizeWindow (dpy, tirette, LARGEUR, height);
break;
}
}
}
main (argc, argv) char **argv;
{
Pixmap fond_gris;
XSetWindowAttributes xsw;
/*
* Ouvrir la connexion
*/
dpy = XOpenDisplay (nom_de_station);
if (dpy == NULL)
erreur ("%s: ne peut ouvrir la connexion a %s\n", argv[0],
XDisplayName(nom_de_station));
/*
* Initialisations globales
*/
screen_n = DefaultScreen (dpy);
root = RootWindow (dpy, screen_n);
pixel_blanc = WhitePixel (dpy, screen_n);
pixel_noir = BlackPixel (dpy, screen_n);
/*
* Crer la barre de dfilement
*/
barre = XCreateSimpleWindow (dpy, root, 200, 200, LONGUEUR,
LARGEUR, 2, pixel_blanc, pixel_noir);
/*
* Slectionner ButtonPress et ConfigureNotify sur la barre et les mouvements
* souris restreints aux mouvements se produisant bouton enfonc, plus le masque
* PointerMotionHintMask pour nÕavoir trace que dÕun vnement la fois
*/
XSelectInput (dpy, barre, ButtonPressMask | ButtonMotionMask |
PointerMotionHintMask | StructureNotifyMask);
/*
* Crer le fond de la tirette
*/
fond_gris = XCreateBitmapFromData (dpy, root, gray3_bits, gray3_width,
gray3_height);
xsw.background_pixmap = fond_gris;
/*
* Puis crer la tirette gauche dans la barre
*/
tirette = XCreateWindow (dpy, barre, 0, 0, LARGEUR, LARGEUR, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWBackPixmap, &xsw);
/*
* Afficher les fentres avant de rcuprer les vnements
*/
XMapSubwindows (dpy, barre);
XMapWindow (dpy, barre);
events ();
}
De manire gnrale, on peut s'approprier la souris, le clavier, un bouton, ou une combinaison de touches du clavier et mme le serveur[10]. Des conventions rgissent lÕusage des fonctions dÕappropriation mais en dernire instance, ce sera le premier client en ayant exprim la demande qui sera rendu matre du dispositif.
On a vu dans la section 5.1. que le terme de saisie dsignait l'appropriation des vnements relatifs un dispositif par une fentre appele alors fentre accaparante (ou grab-window). Les vnements concernant le dispositif saisi ne suivent plus alors le mcanisme standard de propagation et sont systmatiquement envoys la fentre accaparante quelle que soit la position de la souris[11].
La fonction permettant dÕaccaparer la souris est la fonction XGrabPointer.
int XGrabPointer(dpy, grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor, time)
Window grab_window ;
Bool owner_events ;
unsigned int event_mask ;
int pointer_mode ;
int keyboard_mode ;
Window confine_to ;
Cursor cursor ;
Time time ;
LÕargument grab_window spcifie la fentre accaparante, le boolen owner_events prcise si les vnements doivent tre achemins normalement pour les fentres de lÕapplication. (S'il est positionn True, le monopole dclench est analogue au monopole automatiquement dclench aprs slection de l'vnement ButtonPress par ButtonPressMask | OwnerGrabButtonMask.) Le masque event_mask permet de spcifier les vnements slectionns durant le processus de saisie, annulant ceux prcdemment slectionns par la fentre ; pointer_mode indique si les vnements doivent tre envoys de manire synchrone ou asynchrone (GrabModeSync ou GrabModeAsync) ; confine_to spcifie si le pointeur doit rester bloquer dans une fentre particulire durant la saisie (passer None sinon) ; cursor indique la forme du pointeur pendant la dure de la saisie et time spcifie quand doit tre dclench le processus de saisie. On peut passer la constante CurrentTime. La constante de retour de cette fonction peut valoir GrabSuccess, GrabNotViewable, AlreadyGrabbed, GrabFrozen ou GrabInvalidTime. Cette requte gnre des vnements EnterNotify et LeaveNotify .
Le dclenchement de la saisie automatique sur l'vnement ButtonPress est en fait quivalent un appel XGrabPointer en mode asynchrone, avec le masque de slection d'vnements event_mask de la fentre. La prsence o lÕabsence du masque OwnerGrabButtonMask dans ce masque de slection revient dclencher la requte avec le masque owner_events True ou False.
Signalons galement propos de la souris, la fonction XWarpPointer[12] qui permet de placer la souris n'importe o et de rcuprer le focus.
Pour sÕapproprier le clavier on utilisera la fonction XGrabKeyboard.
int XGrabKeyboard(dpy, grab_window, owner_events, pointer_mode,
keyboard_mode, time)
Cette fonction gnre elle aussi lÕenvoi dÕvnements FocusIn et FocusOut aux applications intresses, le champ mode indiquant quÕil s'agit dÕune saisie . Les arguments sont similaires ceux de XGrabPointer. Selon la valeur de owner_events, on peut ici encore limiter la saisie et garder un acheminement normal des vnements l'intrieur de l'application.
De manire gnrale, une saisie peut tre active par :
„ L'enfoncement d'un bouton de souris. C'est le comportement par dfaut du systme (automatic grab).
„ Un appel XGrabPointer ou XGrabKeyboard. C'est une saisie brutale et les applications ne doivent pas en abuser.
„
La ralisation dÕactions dfinies lors d'une appropriation passive. Une telle appropriation conditionnelle aura t
prcdemment demande par un appel XGrabButton
ou
XGrabKey.
Les saisies passives sont des demandes de saisies qui ne sont pas immdiatement dclenches. On parle alors de saisies passives, par opposition aux saisies actives, o la saisie est directement active par la requte[13].
Les fonctions suivantes permettent de demander une saisie qui ne sera active que si certains vnements particuliers se produisent :
XGrabButton(dpy, button, modifiers, grab_window, owner_events, event_mask,
pointer_mode, keyboard_mode, confine_to, cursor)
XGrabKey (dpy, keycode, modifiers, grab_window, owner_events, pointer_mode,
keyboard_mode)
unsigned int button, keycode ;
unsigned int modifiers ;
Window grab_window ;
Bool owner_events ;
unsigned int event_mask ;
int pointer_mode,
keyboard_mode ;
Window confine_to ;
Cursor cursor ;
Ainsi, certains programmes autorisent lÕutilisateur choisir une combinaison de touches pour faire apparatre un menu n'importe o. En ralit, le clavier est alors lÕobjet dÕune saisie passive effectue avec XGrabKey, saisie qui n'est active que par lÕenfoncement de cette combinaison de touches. Une saisie passive a alors gain de cause sur la saisie active dclenche par un simple enfoncement du bouton (sans la combinaison de touches).
Des fonctions symtriques permettent d'interrompre ces processus d'appropriation :
XUngrabPointer(dpy, time)
XUngrabKeyboard(dpy, time)
XUngrabKey(dpy, keycode, modifiers, grab_window)
XUngrabButton(dpy, button,
modifiers, grab_window)
Il existe en outre une fonction qui permet de modifier les paramtres dÕune saisie active de la souris :
XChangeActivePointerGrab(dpy, event_mask, cursor, time)
Les vnements d'entre et sortie des fentres sont de type EnterNotify et LeaveNotify. Ces vnements concernent la souris, mais traduisent en ralit autant une proprit des fentres franchies qu'un vnement souris. En voici une brve description.
EnterNotify LeaveNotify |
La souris est entre ou sortie d'une fentre. On slectionne ces vnements avec les masques EnterWindowMask et LeaveWindowMask. Ces vnements se produisent lorsqu'on dplace la souris d'une fentre l'autre ou lorsqu'on affiche (ou retire) une fentre sous la souris. |
En effet, ces vnements traduisent tous les changements de position du pointeur relativement aux empilements des fentres. Ils peuvent donc se produire non seulement quand la souris bouge et franchit une frontire, mais galement quand les fentres se trouvent dplaces par une requte dans la pile. Le but est d'avertir les applications de la position de leurs fentres vis--vis de la rception des vnements concernant les entres.
La structure associe ce type d'vnement dans l'union XEvent a le type XCrossingEvent et est accessible par le membre xcrossing de l'union. Cette structure partage de nombreux champs avec les vnements souris tudis prcdemment. On retrouve en effet les neufs champs dcrits pour les vnements boutons (cf. fig. 5.2.). En outre elle partage un certain nombre de champs avec les structures de type XFocusEvent correspondant aux vnements de type FocusIn et FocuOut. Les champs supplmentaires sont les suivants : focus, detail et mode.
Bool focus Ce boolen indique si la fentre concerne a le focus du clavier.
La fentre qui reoit EnterNotify est normalement avertie quÕelle va recevoir ensuite les vnements souris. Normalement, elle reoit aussi le focus du clavier, sauf en cas dÕappropriation du focus. Pour savoir si la fentre dans laquelle entre la souris a le focus, il faut consulter le champs focus. Il est True si cette fentre a le focus (ou compte la fentre ayant le focus parmi ses anctres), et False sinon.
Nous recommandons au lecteur de sauter cette section s'il n'a pas immdiatement besoin d'informations prcises sur les vnements EnterNotify et LeaveNotify.
int detail Cet entier peut prendre les valeurs NotifyAncestor, NotifyVirtual, NotifyInferior, NotifyNonlinear ou NotifyNonlinearVirtual. Il indique la position de la fentre qui reoit l'vnement relativement au mouvement du pointeur.
Dans les cas simples o les deux fentres sont dans une relation de parent directe, le champ detail indique la destination du mouvement pour un vnement de sortie et son origine pour une entre. Par exemple, si lÕon passe de F1 F2 (F2 tant fille de F1) selon le mouvement indiqu par la flche A sur la figure 5.4. (page 108), F1 recevra un vnement LeaveNotify de dtail NotifyInferior (avec un champ subwindow F2). Symtriquement, F2 recevra un EnterNotify de dtail NotifyAncestor. Le mouvement inverse de F2 F1 donnerait un LeaveNotify de dtail NotifyAncestor et un EnterNotify de detail NotifyInferior.
La situation se complique un peu quand on passe d'une fentre une autre, sans que les deux fentres soient dans un rapport de parent directe. En effet, des vnements EnterNotify et LeaveNotify sont galement envoys aux fentres qui se trouvent sur le chemin entre la fentre d'origine et la fentre destination dans la hirarchie. On dit alors que ces fentres intermdiaires sont traverses virtuellement.
fig.
5.4. Les mouvements d'entre/sortie de fentres
Dans le cas o l'origine et la destination sont situes sur une mme branche (cas de parent verticale), le champ detail de la structure event.xcrossing contiendra la valeur NotifyVirtual pour les fentres intermdiaires, l'origine et la destination recevant comme prcdemment un champ detail NotifyAncestor ou NotifyInferiror selon le sens du mouvement.
Par contre, si l'origine et la destination du mouvement sont dans un rapport de parent non vertical, elles recevront seulement une indication de dtail NotifyNonlinear et les fentres intermdiaires situes sur le chemin joignant l'une l'autre (l'anctre commun exclu) recevront un dtail NotifyNonlinearVirtual. La situation est la mme si l'on change d'cran : les fentres intermdiaires (jusqu'aux deux racines) recevront un dtail NotifyNonlinearVirtual et l'origine et la destination, un dtail NotifyNonlinear.
Par exemple, un passage de F2 G2 illustr par le mouvement de flche B sur la figure 5.4. provoquera un LeaveNotify sur F2 de dtail NotifyNonlinear, un LeaveNotify sur F1 de dtail NotifyNonlinearVirtual, un EnterNotify sur G1 de dtail NotifyNonlinearVitual avec subwindow G2 et un EnterNotify sur G2 de dtail NotifyNonlinear.
int mode Cet entier peut prendre les valeurs NotifyNormal, NotifyGrab ou NotifyUngrab. Il permet de savoir si l'vnement provient d'un mouvement normal ou s'il rsulte du dbut ou de la fin d'un processus de saisie.
Des vnements de type EnterNotify et LeaveNotify sont en effet envoys quand la souris est saisie et que le pointeur ne se trouvait pas dj dans la fentre accaparante. Symtriquement, des vnements seront envoys aux applications pour avertir de la fin du processus de saisie (par exemple, sur le relchement d'un bouton). CÕest le champs mode qui permet de savoir sÕil sÕagit dÕun cas simple (NotifyNormal) ou sÕil sÕagit dÕune notification de dbut ou de fin de saisie (NotifyGrab, ou NotifyUngrab).
Par exemple, dans le cas o l'on passe de F2 F1, mais aprs enfoncement de bouton dans F2, on recevra les vnements suivants : un LeaveNotify sur F2 de dtail NotifyAncestor, mode NotifyNormal, pour annoncer la sortie de fentre. Ensuite, ce n'est qu'aprs le relchement du bouton que l'on recevra les vnements souris sur F1 (car dans l'intervalle, la saisie est automatiquement active sur F2). Quand le bouton sera relch sur F1, on recevra un LeaveNotify sur F2, de mode NotifyUngrab et dtail NotifyAncestor pour annoncer la fin de la saisie, et un EnterNotify sur F1, de mode NotifyUngrab avec detail NotifyInferior pour annoncer l'entre dans la fentre F1 due la fin du processus de saisie. Les composantes du pointeur ce moment seront celles qu'il avait au moment o le bouton a t relch dans F1 (et non pas celles qu'il avait au moment du franchissement du bord). Ce n'est en effet qu' partir de ce moment l que la souris est considre comme tant dans F1 du point de vue de l'envoi des vnements souris. Auparavant, c'est F2 qui recevait les vnements.
Une fin de saisie peut ainsi provoquer une cascade d'vnements EnterNotify et LeaveNotify, en particulier quand on aura positionn le masque OwnerGrabButtonMask. En effet, ce masque, qui permet aux fentres de recevoir les vnements souris, ne supprime pas pour autant le phnomne de saisie, et il y a quand mme mission d'vnements avertissant les fentres de la saisie.
Ainsi , un passage de F2 G2, avec saisie (enfoncement de bouton dans F2, relcher dans G2) et slection du masque OwnerGrabButtonMask[14], dclenchera l'envoi des vnements suivants :
LeaveNotify sur F2
mode NotifyNormal, detail NotifyNonlinear
LeaveNotify sur F1
mode NotifyNormal, detail NotifyNonlinearVirtual
EnterNotify sur G1, subwindow G2
mode NotifyNormal, detail NotifyNonlinearVirtual
EnterNotify sur G2
mode NotifyNormal, detail NotifyNonlinear
ButtonRelease sur G2
LeaveNotify sur F2
mode NotifyUngrab, detail NotifyNonlinear
LeaveNotify sur F1
mode NotifyUngrab, detail NotifyNonlinearVirtual
EnterNotify sur G1, subwindow G2
mode NotifyUngrab, detail NotifyNonlinearVirtual
EnterNotify sur G2
mode NotifyUngrab, detail NotifyNonlinear
On a vu que le modle dvelopp par la librairie Xlib comporte la notion de fentre ayant le focus du clavier. Par dfaut, c'est la fentre racine qui a le focus, ce qui a pour effet de transmettre le focus toute fentre dans laquelle se trouve la souris. Ainsi, les vnements EnterNotify et LeaveNotify qui indiquent lÕapplication que la souris entre ou sort d'une fentre lui indiqueront aussi normalement si elle peut recevoir les entres du clavier. Cependant, on l'a vu, la rception d'un vnement de type EnterNotify ne garantit pas toujours que la fentre qui le reoit ait le focus du clavier, cause des divers mcanismes de saisie. En particulier, pour connatre lÕtat du focus du clavier au moment o la souris entre dans une fentre, il faut consulter le champs focus de l'vnement.
En effet, plusieurs fonctions du systme peuvent perturber la convention par dfaut. Par exemple, la fonction XSetInputFocus permet dÕattribuer le focus une fentre pourvu quÕelle soit affiche. Les vnements FocusIn et FocusOut sont l pour avertir les applications des changements de focus survenant ainsi, suite lÕappel dÕun client XSetInputFocus ou une fonction accaparant le clavier comme XGrabKeyboard ou XGrabKey.
FocusIn, FocusOut Ces vnements sont slectionnables par FocusChangeMask. Le champ dÕaccs de la structure dans une union XEvent est le membre xfocus. L'vnement FocusIn informe l'application qu'une de ses fentres bnficie du focus du clavier et FocusOut qu'elle vient de le perdre.
Ces vnements sont assez analogues aux vnements d'entre/sortie des fentres. Ils traduisent en quelque sorte un mouvement du focus (les vnements d'entre/sortie traduisant un mouvement du pointeur) et permettent de dterminer si l'application peut ou non recevoir des entres.
Pour rsumer ces diverses considrations sur le focus du clavier et son accessibilit, voici une boucle de programme indiquant par un boolen nomm Clavier_accessible, si lÕapplication peut ou non recevoir les entres du clavier :
Bool Clavier_accessible,
Focus_saisi = False;
for (;;) {
XNextEvent (dpy, &ev);
switch (ev.type) {
case FocusIn:
/* On est sr dÕavoir le focus du clavier */
Focus_saisi = True;
Clavier_accessible = True;
break;
case FocusOut:
/* On est sr dÕavoir perdu le focus */
Clavier_accessible = False;
Focus_saisi = False;
break;
case EnterNotify:
/*
Il faut tester le champ focus de lÕev. */
if (ev.xcrossing.focus)
then Clavier_accessible = True ;
else Clavier_accessible = False;
break;
case LeaveNotify:
/* Normalement, on nÕa pas le focus,
* sauf si on a saisi le clavier
*/
if (Focus_saisi)
then Clavier_accessible = True ;
else Clavier_accessible = False;
break;
}
}
Nous invitons ici encore le lecteur sauter la fin de cette section s'il n'a pas rellement besoin de dtail sur les vnements de changement de focus.
Outre les cinq champs communs tous les types d'vnements, les vnements de changement de focus contiennent deux autres champs : un champ mode et un champ detail. (Il n'y a pas de champ focus car le type de l'vnement indique en lui-mme si la fentre peut recevoir des entres).
int mode Le champ mode est tout--fait analogue celui des vnements de type EnterNotify. Il indique si l'avertissement provient d'un simple changement de focus (i.e. d'un appel XSetInputFocus ) ou s'il rsulte d'un mcanisme de saisie (par exemple, un appel XGrabKeyboard). Il peut prendre les valeurs NotifyNormal, NotifyGrab, ou NotifyUngrab.
int detail Le champ detail des vnements de type FocusIn et FocusOut peut prendre les valeurs suivantes :
NotifyAncestor, NotifyVirtual, NotifyInferior, NotifyNonLinear, NotifyNonLinearVirtual, NotifyPointer, NotifyPointerRoot, NotifyDetailNone.
Son sens est trs voisin de celui des vnements d'entre/sortie de fentres, ceci prs qu'il s'agit d'un mouvement du focus au lieu d'un mouvement de souris. Comme dans le cas de EnterNotify et LeaveNotify, de nombreuses fentres sont susceptibles de recevoir ces vnements. La valeur du champ detail est base sur les distinctions suivantes : fentre d'origine (ancien focus), fentre de destination (nouveau focus) et fentre du pointeur contenant la souris au moment du changement de focus.
Dans les cas simples o l'origine et la destination sont dans un rapport de parent vertical, le champ detail prendra la valeur NotifyAncestor et NotifyInferior pour les extrmes, et NotifyVirtual pour les fentres intermdiaires. Dans les cas o l'origine et la destination ne sont pas anctres l'une de l'autre, il prendra les valeurs NotifyNonlinear pour les extrmits et NotifyNonlinearVirtual pour les fentres situes entres les deux, l'anctre commun tant exclu. Ce sera galement le cas pour les changements de focus survenant sur des racines diffrentes.
La prsence de la fentre contenant le pointeur complique un peu la situation. En effet, cette fois, des vnements de changement de focus seront envoys non seulement toutes les fentres situes entre la source et la destination dans la hirarchie, mais galement toutes les fentres situes entre la fentre contenant le pointeur et la destination, si cette dernire n'est pas une des extrmits. Ainsi, la fentre contenant le pointeur et toutes les ascendantes concernes par ce changement de focus recevront galement des vnements de type FocusIn (ou FocusOut, selon les cas) avec un champ detail NotifyPointer.
De plus, si une requte de saisie indique une attribution de focus PointerRoot ou None, toutes les fentres des racines concernes par l'acquisition recevront des vnements FocusIn (et toutes les fentres concernes par la perte des vnements de type FocusOut) avec detail NotifyPointerRoot ou NotifyDetailNone. Dans ce cas, les fentres origine et destination auront un champ detail NotifyNonlinear, NotifyPointerRoot ou NotifyDetailNone, selon la valeur passe en argument la requte de saisie.
Si une fentre donne perd le focus, le champ detail sera NotifyNonlinearVirtual pour toutes les fentres intermdiaires entre cette fentre et sa racine. En outre toutes les fentres (de toutes les racines) recevront un vnement de dtail NotifyPointerRoot ou NotifyDetailNone indiquant l'acquisition (ou la perte) gnrale de focus. On voit bien dans ce cas qu'une mme fentre peut recevoir plusieurs vnements de type FocusIn et FocusOut correspondant un mme changement de focus. Une fentre peut en effet tre avertie la fois de la perte de focus relative la perte de focus d'une fentre, et de l'acquisition de focus, relative l'acquisition gnrale, par passage de PointerRoot la requte de saisie.
Dans cette section, nous allons commenter les diffrents vnements qui concernent le clavier et donner un aperu de la saisie de texte au clavier (par des programmes ignorant la notion de localit ou antrieurs la Release 5[15]).
LÕvnement de type KeymapNotify permet de connatre lÕtat du clavier avant dÕen recevoir les entres.
KeymapNotify Cet vnement est mis juste aprs un EnterNotify ou un FocusIn car ces deux types dÕvnements sont susceptibles dÕindiquer lÕapplication quÕelle va recevoir des entres. Il donne l'tat du clavier et sera utilis par les applications qui souhaitent savoir dans quel tat se trouvait le clavier avant d'interprter des entres.
En fait l'vnement KeymapNotify est rarement utilis, car l'tat des modifieurs est dj fourni par les vnements EnterNotify et FocusIn, qui sont mis juste avant. Le type de cet vnement est XKeymapEvent. On pourra le slectionner avec le masque KeymapStateMask et on accdera la structure associe dans une union XEvent via le champs xkeymap. Son principal champ est le champ key_vector qui donne un vecteur dÕtat des touches sous la forme dÕun masque de 32 caractres (256 bits). Le keycode dÕune touche donne est le rang du bit signifiant dans le vecteur des touches. La fonction
XQueryKeymap(dpy, tableau)
Display* dpy ;
char tableau [32] ;
permet galement de lire lÕtat du clavier. Cependant, elle est plus coteuse, (comme toutes les fonctions en XQuery), quÕun appel XNextEvent - d'o l'intrt de cet vnement.
On rcupre les entres tapes au clavier au moyen des vnements KeyPress et KeyRelease.
KeyPress KeyRelease |
Ces vnements traduisent le fait quÕune touche du clavier a t enfonce ou relche. Ces vnements sont de type XKeyEvent et on y accde dans lÕunion XEvent par le membre xkey. |
La structure associe contient principalement le code mis par la touche (champ keycode). Pour recevoir ces vnements, il faut bnficier du focus du clavier et avoir slectionn ces vnements par KeyPressMask (ou KeyReleaseMask). Les autres champs de la structure de type XKeyEvent sont les mmes que ceux que nous avons dj dtaills pour les vnements souris (cf. figure 5.2). On pourra donc accder aux champs window, root, subwindow, x, y, x_root, y_root, time, state, same_screen, etc.
Remarques :
1. LÕvnement KeyRelease nÕexiste pas sur certaines machines bas de gamme. On vitera donc d'en faire usage si lÕon veut que l'application soit portable sur ces machines.
2. Il ne peut y avoir de saisie du clavier entre un vnement de type KeyPress et un vnement de type KeyRelease.
Le champ keycode peut tre assimil un code physique directement mis par le clavier de par la position de la touche. On ne peut pas modifier les liens entre les touches et les keycode. Cependant, les claviers tant loin d'tre standardiss, le systme X a prvu un second niveau de codage permettant d'associer au code mis par la touche, et compte tenu de l'tat du clavier, un code symbolique ou keysym. C'est ce code symbolique qui va tre rcupr et interprt par les applications grce la fonction XLookupString.
On nÕinterprte jamais directement le code mis par une touche partir du keycode. CÕest un code symbolique keysym, rcupr par une fonction en XLookupString[17] qui permet vritablement dÕinterprter le code mis par une touche.
Le code symbolique keysym est un entier dcrit par des constantes dfinies dans le fichier <X11/keysym.h>. Les constantes symboliques prsentent l'avantage de permettre d'interprter directement des associations de touches physiques avec des modifieurs. Par exemple, le code symbolique de la touche "a" enfonce simultanment avec le modifieur Shift gauche sur le clavier fournit le code symbolique XK_Shift_A. Pour ces associations, le serveur utilise des tables de codes symboliques associs un keycode donn en association avec des modifieurs[18].
L'vnement de type KeyPress rcupr par une application ne comporte que le champ keycode. On rcupre le code symbolique keysym qui lui est associ et sa traduction (si elle existe) sous forme de chane de caractres ASCII grce la fonction[19] XLookupString.
int XLookupString ( &ev, buffer, n_buf, &keysym_return, &status_in_out )
XEvent ev ; /* doit tre de type XKeyEvent */
char buffer [] ;
int n_buf ;
KeySym keysym_return ;
XComposeStatus status_in_out ;
Pour utiliser XLookupString, il faut inclure le fichier <X11/Xutil.h>. Cette fonction permet de rcuprer, dans un tableau de caractres buffer (allou par lÕapplication qui en fournit lÕadresse et la taille dans n_buf), la traduction du code mis par la touche sous la forme d'une chane de caractres ASCII, ainsi que la valeur du code symbolique keysym associ, compte tenu de l'tat des modifieurs Shift, Lock, Control et Meta (le code mis par la touche tant rcupr par le serveur grce au champ keycode de lÕvnement). L'vnement dont on aura pass lÕadresse est suppos tre de type XKeyEvent. XLookupString retourne le nombre de caractres ASCII placs dans le buffer. On ne rcupre gnralement qu'un seul caractre la fois, mais il arrive qu'une touche ait t rassocie une chane de plusieurs caractres, suite un appel XRebindKeysym.
On peut en effet modifier les chanes de caractres ASCII associes par XLookupString (dans le buffer) au code symbolique keysym grce la fonction XRebindKeysym. Cette redfinition est locale au client. Elle ne modifie que les rponses aux futurs appels XLookupString mis par le client (cf. figure 5.5.).
fig. 5.5. Le codage des touches du clavier
retourn par XLookupString
On peut aussi dans certaines implantations modifier les liens entre les keycode et les keysym. Mais cela n'est gure recommand, car, cette fois, la modification ne sera plus locale au client. Si on modifie ces liens, les autres clients recevront des vnements de type MappingNotify.
MappingNotify Cet vnement informe qu'un changement d'association a t effectu par un autre client sur les ressources concernant le clavier ou la souris. Ce type dÕvnement nÕa pas besoin dÕtre slectionn pour tre reu.
Un vnement de type MappingNotify annoncera par exemple :
„ un appel XChangeKeyboardMapping (qui modifie les liens entre touches physiques et touches symboliques),
„ un appel XSetModifierMapping (qui modifie les liens entre touches modifieurs et modifieurs logiques),
„ ou encore un appel XSetPointerMapping (qui modifie les liens entre les boutons physiques et les bouton logiques de la souris).
La raction normale un changement sur les touches est un appel XRefreshKeyboardMapping (tester le champ request de l'vnement) pour remettre jour les tables locales.
Les
fonctions importantes
Bool XQueryPointer ( dpy, win, &root_return, &child_return,
&root_x, &root_y, &win_x, &win_y, &state)
int XLookupString ( &ev, buffer, n_buf, &keysym_return,
&status_in_out )
Des vnements importants sont traits dans ce chapitre : ButtonPress, ButtonRelease, MotionNotify, KeyPress, EnterNotify, LeaveNotify, FocusIn et FocusOut.
La notion de saisie d'un dispositif d'entre est une notion importante puisqu'une saisie du pointeur est automatiquement dclenche par la rception d'un vnement de type ButtonPress. On retiendra l'importance des masques de slection d'vnements souris OwnerGrabButtonMask et PointerMotionHintMask, et l'exemple de programmation de la section 5.3. On s'attardera galement sur les sections 5.5. 5.7. pour savoir quand et comment saisir les entres du clavier.
Les corrigs de ces exercices figurent pages 292 et suivantes.
Exercice 8: (Rception des caractres lus dans une fentre X)
Imprimer (sur la console de lancement du programme), les caractres frapps au clavier dans une fentre X, par exemple avec la commande fprintf(stderr, ...).
Exercice 9 : (Etude des vnements EnterNotify et LeaveNotify)
Crer deux fentres ayant chacune une sous-fentre et les placer l'aide du window manager selon la disposition de la figure 5.5. Faire varier les masques de slection des vnements boutons pour avoir (ou non) saisie de la souris ; afficher les champs mode et dtail des vnements d'entre/sortie des fentres.
[1] Cette fentre pourra tre dsigne comme argument de certaines fonctions par la constante InputFocus.
[2] Ce masque s'appelle OwnerGrabButtonMask, de Owner, propritaire et Grab, saisie, pour indiquer que le serveur ne libre la souris que pour les fentres de l'application propritaire de la saisie.
[3] Ici via le membre xbutton de l'union XEvent. Par exemple, on crira
if (ev.xbutton.subwindow == FenetreMenu) etc...
[4] Cela signifie que l'on a intrt relancer priodiquement le serveur si l'on veut faire usage de cette information.
[5] Les modifieurs sont les touches qui produisent une modification de l'interprtation des autres touches enfonces simultanment avec elles. Par exemple Shift, Alternate, Meta, etc.
[6] Il y a deux exceptions : si le bouton change d'tat ou si la souris sort de la fentre. Mais dans ces deux cas, il faudra qu'un nouveau mouvement se produise et que l'application soit encore en mesure de recevoir cet vnement pour qu'elle le rcupre.
[7] Si l'on souhaite rcuprer tous les vnements, on pourra faire appel sur certaines machines une mmoire appele motion history buffer, permettant de rcuprer simultanment tous les vnements de mouvements qui ont suivi lÕunique mouvement envoy spontanment par le serveur. Pour savoir si le serveur possde une telle capacit, on testera la valeur de retour de la fonction
int XDisplayMotionBufferSize(dpy)
qui doit tre strictement positive. On procde alors une slection de mouvements module par PointerMotionHintMask mais on appelle cette fois XGetMotionEvents lÕintrieur de la boucle dÕvnements.
[8] Sous rserve que la tirette n'ait pas slectionn ni bloqu l'vnement. Rcuprer les vnements sur la mre n'entraine d'ailleurs aucune perte d'information car on peut tester si l'vnement provient de la tirette ou de la barre grce au champ subwindow.
[9] Question qui se pose chaque fois que l'on slectionne un vnement de type ButtonPress.
[10] Dans certains cas, il peut sembler ncessaire de monopoliser le serveur lui-mme, pour empcher, par exemple, qu'un dessin extrieur ne vienne modifier l'tat de l'cran entre deux requtes. Dans ces cas trs particuliers, (que les conventions entre clients recommandent par ailleurs d'exclure), les programmes feront appel la fonction XGrabServer.
[11] En outre, si la fentre accaparante n'a pas slectionn ces vnements souris, ces derniers sont perdus.
[12] Cependant, les conventions entre clients recommandent de ne pas utiliser cette fonction.
[13] Les requtes prcdentes peuvent dclencher des saisies actives ou passives selon la valeur de l'argument time .
[14] Qui empche la saisie d'tre active pour les fentres de l'application mais ne supprime pas la saisie.
[15] A partir de la Release 5, on dispose d'un outil trs puissant, les mthodes de lecture d'entre, qui permet de s'adapter la langue de l'utilisateur. Ces mthodes de lecture utilisent ventuellement de larges dictionnaires et des algorithmes complexes pour interprter les chanes de caractres tapes au clavier. Elles ont t dfinies dans le but de permettre l'internationalisation des programmes c'est--dire la portabilit des programmes indpendamment des langues utilises (cf. chapitre 8).
[16] A partir de la Release 5, on dispose d'un outil trs puissant, les mthodes de lecture d'entre, qui permet de s'adapter la langue de l'utilisateur. Ces mthodes de lecture utilisent ventuellement de larges dictionnaires et des algorithmes complexes pour interprter les chanes de caractres tapes au clavier. Elles ont t dfinies dans le but de permettre l'internationalisation des programmes c'est--dire la portabilit des programmes indpendamment des langues utilises (cf. chapitre 8).
[17] Dans la Release 5 on pourra utiliser les fonctions XwcLookupString ou XmbLookupString qui interprtent les chanes relativement la localit courante avec une mthode d'entre spcifique.
[18] En fait seulement quatre symboles keysym peuvent tre associs dans la Release 4 un keycode donn (les rgles dÕassociation standards nÕutilisant que les deux premiers groupes). Le premier groupe est utilis quand les modifieurs sont tous relchs et le deuxime groupe, quand les modifieurs sont actifs. Si cette question intresse le lecteur, quÕil se reporte dans la documentation aux fonctions XGetKeyboardMapping ou XChangeKeyboardMapping. Cependant, ces fonctions ne sont pas disponibles dans toutes les implantations. Dans la Release 5, c'est la mthode d'entres qui grera les associations de touches et modifieurs.
[19] XwcLookupString et XmbLookupString dans la Release 5.