C. Recanati
Option C avancé, avec X-Window
Licence 3, 2007-2008

Examen Partiel du 6 nov 2007
9h00-12h00
salle C102

I. Connexion et création de fenêtres
Question 1.	Que fait la fonction XOpenDisplay lorsqu’elle est appelée avec la chaîne vide ?  
		Display * dpy;
		dpy = XOpenDisplay(NULL);

Question 2.	 Quel type de fenêtre est créée avec
Window XCreateSimpleWindow(display, parent, x, y, width, height, border_width, border, background)
      Display *display;
      Window parent;
      int x, y;
      unsigned int width, height;
      unsigned int border_width;
      unsigned long border;
      unsigned long background;
Commentez les arguments de cette requête, ainsi que ceux de
Window XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes)
      int depth;
      unsigned int class;
      Visual *visual;
      unsigned long valuemask;
      XSetWindowAttributes *attributes;
Commentez en particulier les valeurs possibles du champ class.
 
Question 3.	 On veut disposer trois fenêtres dans une fenêtre simple, en bas et approximativement au centre de cette fenêtre, comme sur la figure ci-dessous :

On fait les déclarations suivantes :
#define LARGEUR   700
#define HAUTEUR   300
Display * dpy ;
unsigned long blanc, noir;	// pixels blanc et noir
Window root, win,
	subwin1, subwin2, subwin3 ;
On supposera que les variables dpy, root, blanc et noir, ont été correctement initialisées en début de programme. 
Ecrire les définitions (#define ESPACE ...) et les lignes de codes permettant de créer les quatre fenêtres win, subwin1, subwin2 et subwin3 de sorte que ces fenêtres soient disposées comme sur la figure précédente et aient les mêmes couleurs de fond. Attention à bien paramétrer les dimensions de ces fenêtres en fonction de vos définitions, sinon vous n’aurez pas tous les points de cette question.

Question 4.	 Que faut-il ajouter au code précédent (déclarations et instructions) pour que les sous-fenêtres restent placées au centre et en bas de la mère quand celle-ci est agrandie ?
 Indication : vous pourrez utiliser la fonction
XChangeWindowAttributes(display, w, valuemask, attributes)
      Display *display;
      Window w;
      unsigned long valuemask;
      XSetWindowAttributes *attributes;
si vous le souhaitez. Le détail de la structure d’attributs est donnée ici (et les masques associés sont à la fin du sujet) :
typedef struct {
	Pixmap background_pixmap;		
unsigned long background_pixel;	
	Pixmap border_pixmap;		
	unsigned long border_pixel;	
	int bit_gravity;		
	int win_gravity;		
	int backing_store;		
	unsigned long backing_planes;
	unsigned long backing_pixel;		
Bool save_under;		
	long event_mask;		
	long do_not_propagate_mask;	
	Bool override_redirect;		
	Colormap colormap;		
	Cursor cursor;			
} XSetWindowAttributes;

Question 5.	 A quoi sert l’attribut cursor?

Question 6.	 Quels attributs de fenêtre (figurant dans la structure SetWindowAttributes) n’existent pas dans les fenêtres de classe InputOnly ?

II. Gestion des événements

Question 7.	 Comment s’appelle la requête permettant de sélectionner des événements sur une fenêtre ? Donnez son prototype (c’est-à-dire le type de sa valeur de retour et celui de chacun de ses arguments) ?

Question 8.	 Quel lien existe-t-il entre la requête précédente (requête de sélection des événements) et l’attribut event_mask d’une fenêtre ?

Question 9.	 Commentez l’attribut do_not_propagate_mask d’une fenêtre. (Expliquez brièvement ce qu’est la propagation des événements).

Question 10.	A quoi sert l’attribut override_redirect ?
(Expliquez brièvement le mécanisme de redirection). 
Pour réaliser l’affichage demandé question 3, doit-on mettre l’attribut override_redirect des sous-fenêtres à True ?

Question 11.	Quel type d’événement est sélectionné par le masque ExposureMask ? Que contient le champs count de la structure associée à ce type d’événement ? A quoi sert cette information ?

Question 12.	Quel est le nom du masque qui permet de sélectionner un clic de souris (enfoncement d’un bouton) ? Quel est le nom du type associé à cet événement ?

Question 13.	Complétez le programme des questions 3 et 4 :
- en sélectionnant le clic de souris sur la première sous-fenêtre noire (subwin1). 
- Affichez ensuite toutes les fenêtres puis appellez une procédure events () de traitement des événements. 
- Traitez un clic de souris dans la première sous-fenêtre en quittant le programme.
Pour présenter votre solution, vous pouvez indiquer en commentaires
 /* connexion et initialisations diverses */, puis
/* créations des fenêtres (cf. questions 3-4) */
 et enchaîner la suite.

Question 14.	Quel type d’événement est sélectionné par le masque Button3MotionMask?

Question 15.	Existe-t-il autant de masques que de types d’événements ?

Question 16.	Le masque PointerMotionHintMask permet-il de sélectionner des événements ? Si oui, lesquels, et sinon, à quoi sert-il ?

Question 17.	Qu’est-ce qu’un « automatic grab » ? Quand est-il déclenché ? Donnez un ou deux exemples où ce mécanisme par défaut du système est utile.

Question 18.	A quoi sert le masque OwnerGrabMotionMask?

Question 19.	La fonction XLookupString a le prototype suivant :
int XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return, status_in_out)
      XKeyEvent *event_struct;
      char *buffer_return;
      int bytes_buffer;
      KeySym *keysym_return;
      XComposeStatus *status_in_out;
Expliquez pourquoi cette fonction ne prend pas l’argument dpy habituel figurant dans presque toutes les requêtes de la librairie.

Question 20.	Compléter le programme précédent pour qu’on puisse lire des entrées du clavier quand la souris est dans la seconde fenêtre (subwin2). 
-Pour détecter que la souris est dans subwin2 (et donner alors le focus du clavier à cette fenêtre), on sélectionnera les événements de type EnterNotify et LeaveNotify (avec les masques EnterNotifyMask et LeaveNotifyMask). 
-Pour donner le focus du clavier à cette fenêtre utilisez XSetInputFocus (voir documentation plus loin). 
-Traitez le type KeyPress dans la boucle d’événement en imprimant (avec printf) le caractère tapé, après décodage et si ce dernier est imprimable.
Indiquez le plus clairement possible où vous allez rajouter toutes les modifications nécessaires (déclarations supplémentaires, modification de telle ou telle ligne) et réécrivez la boucle events() pour le traitement de ces nouveaux types d’événements.

Question 21.	Que fait la requête XFlush(dpy) ?

Question 22.	Quelle différence y a-t-il entre un Pixmap et un bitmap ? Est-ce que le type bitmap existe dans la librairie ?

Documentation :
/* les valeurs des masques pour les attributs des fenetres */
#define CWBackPixmap		(1L<<0)
#define CWBackPixel		(1L<<1)
#define CWBorderPixmap	(1L<<2)
#define CWBorderPixel		(1L<<3)
#define CWBitGravity		(1L<<4)
#define CWWinGravity		(1L<<5)
#define CWBackingStore	(1L<<6)
#define CWBackingPlanes	(1L<<7)
#define CWBackingPixel	(1L<<8)
#define CWOverrideRedirect	(1L<<9)
#define CWSaveUnder		(1L<<10)
#define CWEventMask		(1L<<11)
#define CWDontPropagate	(1L<<12)
#define CWColormap		(1L<<13)
#define CWCursor			(1L<<14)

/* la structure pour affecter des valeurs aux attributs */

typedef struct {
	Pixmap background_pixmap;		
unsigned long background_pixel;	
	Pixmap border_pixmap;		
	unsigned long border_pixel;	
	int bit_gravity;		
	int win_gravity;		
	int backing_store;		
	unsigned long backing_planes;
	unsigned long backing_pixel;		
Bool save_under;		
	long event_mask;		
	long do_not_propagate_mask;	
	Bool override_redirect;		
	Colormap colormap;		
	Cursor cursor;			
} XSetWindowAttributes;

/* Entiers définissant les coordonnées des points de gravité  
NorthWestGravity 	(0, 0)
NorthGravity 		(Width/2, 0)
NorthEastGravity 	(Width, 0)
WestGravity 		(0, Height/2)
CenterGravity 		(Width/2, Height/2)
EastGravity 		(Width, Height/2)
SouthWestGravity 	(0, Height)
SouthGravity 		(Width/2, Height)
SouthEastGravity 	(Width, Height)
*/

XSetInputFocus(display, focus, revert_to, time)
      Display *display;
      Window focus;
      int revert_to; 
      Time time; 

display 	Specifies the connection to the X server.
focus 	Specifies the window, PointerRoot, or None.
revert_to 	Specifies where the input focus reverts to if the window becomes not viewable. You can pass RevertToParent, RevertToPointerRoot, or RevertToNone.
time 	Specifies the time. You can pass either a timestamp or CurrentTime.

Description
The XSetInputFocus() function changes the input focus and the last-focus-change time. It has no effect if the specified time is earlier than the current last-focus-change time or is later than the current X server time. Otherwise, the last-focus-change time is set to the specified time (CurrentTime is replaced by the current X server time). XSetInputFocus() causes the X server to generate FocusIn and FocusOut events.

Depending on the focus argument, the following occurs:
* If focus is None, all keyboard events are discarded until a new focus window is set, and the revert_to argument is ignored.
* If focus is a window, it becomes the keyboard's focus window. If a generated keyboard event would normally be reported to this window or one of its inferiors, the event is reported as usual. Otherwise, the event is reported relative to the focus window.
* If focus is PointerRoot, the focus window is dynamically taken to be the root window of whatever screen the pointer is on at each keyboard event. In this case, the revert_to argument is ignored.

      The specified focus window must be viewable at the time XSetInputFocus() is called, or a BadMatch error results. If the focus window later becomes not viewable, the X server evaluates the revert_to argument to determine the new focus window as follows:
* If revert_to is RevertToParent, the focus reverts to the parent (or the closest viewable ancestor), and the new revert_to value is taken to be RevertToNone.
* If revert_to is RevertToPointerRoot or RevertToNone, the focus reverts to PointerRoot or None, respectively. When the focus reverts, the X server generates FocusIn and FocusOut events, but the last-focus-change time is not affected.