TD X-Window numero 1


Quelques infos sur les TDs et Cours à venir :

Je prépare les cours et TDs d'une semaine sur l'autre. Il se peut qu'il y ait des fautes d'orthographe, des inexactitudes, des erreurs dans le support de cours ou dans les sujets de TDs. Je vous serai reconnaissant de me les signaler, ainsi je ne serai pas ridicule l'année prochaine !

Si jamais vous trouvez les cours ou les TDs ennuyeux, mal faits, trop durs ou trop faciles, idem ! N'hésitez pas à venir me voir à la fin du cours, à m'appeler pendant les TDs et TPs, m'envoyer du mail, etc... je suis là pour vous aider !

But du TD:

Comme il s'agit de votre premier programme graphique utilisant la librairie de developpement Xlib, nous allons faire quelque chose de très simple: ouvrir une fenêtre graphique sur l'écran et dessiner à l'intérieur des formes géomètriques simples: lignes, cercles et rectangles.

Vous verrez que malgré la simplicité de la tâche à effectuer, la réalisation est relativement complexe.

A faire avant de commencer:

  1. Recopier le squelette du TD chez vous. Créez un directory xlib/td1 sous votre $HOME (ou ailleurs) et recopier dedans tous les fichiers qui se trouvent dans le répertoire ~buffa/cours/minfo/xlib/td1.
  2. Etudier le Makefile.
  3. Editer le fichier main.c et écrire progressivement les partie manquantes.

Important:

Différentes étapes dans ce TD:

  1. Afficher une fenêtre sur l'écran. Contentez-vous d'écrire le code manquant en dessous des commentaires. Voir la partie du cours sur le Display et sur les fenêtres.
  2. Gérer les interactions: détecter les clicks et mouvements de la souris dans la fenêtre, les appuis des touches du clavier, les changements de taille de la fenêtre. Voir la partie du cours sur les évènements.
  3. Dessiner interactivement dans la fenêtre.
  4. Gérer le rafraichissement de la fenêtre en cas de recouvrement, iconification, changement de taille : gestion des évènements de type EXPOSE et CONFIGURE.

Source du squelette du TD et Makefile :

Squelette du TD :

#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() */
  

  /* 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 =;
  display_width =;
  display_height =;

  /* Initialiser la taille de la fenetre en fonction de la taille de l'ecran */
  width =;
  height =;

  /* creation d'une fenetre opaque a l'aide de la fonction
     XCreateSimpleWindow(). L'appel de XCreateSimleWindow au lieu de
     XCreateWindow fait que la fenetre cree herite de tous les
     attributs de la fenetre parent. Le pere de la fenetre que l'on va creer
     sera la root window. On obtient son ID a l'aide de la macro RootWindow().
     On veut une bordure noire et un fond blanc   pour la fenetre. Utiliser 
     les macros  BlackPixel() et WhitePixel(). */

  win =;

  /* affichage (mapping) de la fenetre, a l'aide de la fonction XMapWindow() */

  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);
  } 
} 

/*----------------------*/
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 a l'aide de la fonction 
     XCreateGC() */
  *gc =;


  /* specification d'un background noir, puisque par defaut on fait du
     blanc sur du blanc. Utiliser XSetForeground() et la macro BlackPixel() */
}

/*-----------------------*/
draw_rectangle(win, gc, x, y)
/*-----------------------*/
Window win;
GC gc;
int x, y;
{
}

Makefile associé :

# differents types de fichiers 
.SUFFIXES:.o.c.ln


#---------------------------------
# INITIALISATION DES VARIABLES 
#---------------------------------

# Indiquer le compilateur (cc ou gcc)
CC=gcc

# Les chemins ou se trouvent les fichiers a inclure
INCLUDES=

# Options de compilation. Mettre -ggdb (gcc) ou -g pour debugger
CFLAGS=  ${INCLUDES} -ggdb -c

# Options pour le linker. Mettre -g -static (gcc) ou -g -Bstatic (cc) pour
# debugger
LFLAGS=  -g -static -o 

# Les librairies avec lesquelle on va effectueller l'edition de liens
LIBS= -lX11

# Les fichiers sources de l'application
FILES=main.c

#-----------
# LES CIBLES
#-----------

td1:  $(FILES:.c=.o)
    $(CC) -ggdb -static -o td1 $(FILES:.c=.o) ${LIBS}

clean:
    /bin/rm $(FILES:.c=.o) td1

lint: $(FILES:.c=.ln)
    @echo ______deuxieme passe_______
    @lint -u $(FILES:.c=.ln)

#-----------------------------------------------------------------------------
# LES REGLES DE DEPENDANCE. Certaines sont implicites mais je recommande d'en 
# mettre une par fichier source. 
#-----------------------------------------------------------------------------

main.o: main.c


#---------------------------------
# REGLES DE COMPILATION IMPLICITES
#---------------------------------

.c.o:; ${CC} ${CFLAGS} $*.c

.c.ln:
    @echo $*.c
    @lint $(INCLUDES) -i $*.c


michel.buffa@essi.fr