Correction du TD X-Window numéro 1
#include <X11/Xlib.h>
#include <stdio.h>
#include <math.h>
/* Les ecrans (screen) et les displays sont des arguments de presque toutes les
fonctions Xlib. C'est plus simple de les declarer en variables globales
Les mettre en extern, si on decoupe l'application en plusieurs modules. */
/* Declarer une variable du type Display */
Display *display;
/* Specifier le nom du serveur X auquel on veut se connecter NULL
signifie que l'on veut se connecter sur le serveur precise dans la
variable d'environnement DISPLAY */
char *display_name=NULL;
/* Declarer une variable contenant le numero d'ecran (screen) */
int screen;
/*-----*/
main()
/*-----*/
{
Window win; /* descripteur de la fenetre */
int display_width, display_height; /* taille de l'ecran (root window) */
int width, height; /* taille de la fenetre */
unsigned int border_width=4; /* largeur de la bordure */
int x=0, y=0; /* position de la fenetre */
XEvent report; /* structure des evenements */
GC gc; /* ID du contexte graphique */
/* Ouvrir une connection avec le serveur X a l'aide de la fonction
XOpenDisplay(). Nous allons egalement traiter le cas ou la
connexion n'a pu etre realisee en affichant un message d'erreur
du type "pas de connexion avec le serveur <nom du
serveur>. Attention, comme nous avons initialise le nom du
serveur a NULL, le nom du serveur sera obtenu a l'aide de la
fonction XDisplayName() */
if((display=XOpenDisplay(display_name))==NULL) {
fprintf(stderr,"fenetre de base: ne peut pas se connecter ");
fprintf(stderr,"au serveur %s\n",XDisplayName(display_name));
exit(-1);
}
/* Recuperer les informations concernant l'ecran (root window) sur
lequel on va afficher notre application. Le numero de l'ecran
par defaut s'obtient a l'aide de la macro DefaultScreen(), la
taille a l'aide des macros DisplayWidth() et
DisplayHeight(). Il existe de nombreuses macros de ce type.*/
screen = DefaultScreen(display);
display_width = DisplayWidth(display,screen);
display_height = DisplayHeight(display,screen);
/* Initialiser la taille de la fenetre en fonction de la taille de l'ecran */
width = display_width/3;
height = display_height/4;
/* creation d'une fenetre opaque a l'aide de la fonction
XCreateSimpleWindow(). L'appel de XCreateSimpleWindow au lieu de
XCreateWindow fait que la fenetre cree herite de tous les
attributs de la fenetre parent */
win = XCreateSimpleWindow(display, RootWindow(display, screen), x, y,
width, height, border_width,
BlackPixel(display,screen),
WhitePixel(display,screen));
/* selection des evenements que l'on desirera traiter pour cette fenetre */
XSelectInput(display, win, ExposureMask | KeyPressMask |
ButtonPressMask | StructureNotifyMask | PointerMotionMask);
/* creation d'un contexte graphique pour cette fenetre,
indispensable pour dessiner ou afficher du texte */
get_GC(win, &gc);
/* affichage (mapping) de la fenetre, on mappe les differentes
fenetres juste avant la gestion des evenements */
XMapWindow(display,win);
/* gestion des evenements:
-prend un evenement
-utilise le premier expose pour afficher texte et graphiques
-utilise ConfigureNotify pour reafficher la fenetre a la taille
voulue.
-utilise ButtonPress ou KeyPress pour sortir du programme */
while(1) {
XNextEvent(display, &report);
switch (report.type) {
case Expose:
/* on purge la queue des evenements de tous les Expose, pour
ne redessiner la fenetre qu'une seule fois */
while(XCheckTypedEvent(display, Expose, &report));
break;
case ConfigureNotify:
/* La fenetre a ete resizee. On met a jour les variables width
et height pour que les routines draw_text et draw_graphics
reaffichent correctement la fenetre, lors du prochain Expose */
width = report.xconfigure.width;
height = report.xconfigure.height;
printf("fenetre retaillee: width = %d height = %d\n", width, height);
break;
case ButtonPress:
printf("Bouton %d enfonce\n", report.xbutton.button);
draw_rectangle(report.xbutton.window, gc, report.xbutton.x, report.xbutton.y);
break;
case KeyPress:
{
char buffer;
int bufsize=1;
int charcount;
charcount = XLookupString(&report, &buffer, bufsize, NULL,
NULL);
printf("Touche %c appuyee\n", buffer);
if(buffer=='q') {
XCloseDisplay(display);
exit(1);
}
}
break;
case MotionNotify:
printf("Position curseur = %d %d\n",report.xmotion.x, report.xmotion.y);
break;
default:
/* tous les evenements selectionnes par StructureNotifyMask
(DestroyNotify, GravityNotify, etc...) sont filtres ici. */
break;
}
}
}
/*----------------------*/
get_GC(win, gc)
/*----------------------*/
Window win;
GC *gc;
{
unsigned long valuemask = 0; /* Ignore XGCvalues et prend les
valeurs par defaut */
XGCValues values;
/* creation d'un contexte graphique par defaut */
*gc = XCreateGC(display, win, valuemask, &values);
/* specification d'un background noir, puisque par defaut on fait du
blanc sur du blanc */
XSetForeground(display, *gc, BlackPixel(display, screen));
}
/*-----------------------*/
draw_rectangle(win, gc, x, y)
/*-----------------------*/
Window win;
GC gc;
int x, y;
{
XDrawRectangle(display, win, gc, x, y, 50, 50);
}
michel.buffa@essi.fr