Contexte graphique GC

/* gc.c */

/* creation de GC et dessin de rectangles*/

#include <stdio.h>
#include <X11/Xlib.h>

GC      gc1, gc2; 
Display *display; 
int     screen; 
Window  win, root; 
unsigned long white_pixel, black_pixel,
         val_gc_masq;
XGCValues gc_valeurs; 
int x1, x2, y1, y2; 

main() { 
  display = XOpenDisplay ("");
  screen = DefaultScreen (display); 
  root = RootWindow (display, screen); 
  white_pixel = WhitePixel (display, screen); 
  black_pixel = BlackPixel (display, screen); 
  win = XCreateSimpleWindow (display, root, 0, 0, 200, 200, 2, 
			     black_pixel, white_pixel); 
  XSelectInput (display, win, ButtonReleaseMask | ButtonPressMask); 
  XStoreName (display, win, "gc"); 
  XMapWindow (display, win); 
  gc2 = XCreateGC (display, win, 0, 0);
  val_gc_masq = 0;
  gc_valeurs.background = white_pixel;
  val_gc_masq = val_gc_masq | GCBackground ;
  gc_valeurs.line_width = 3;
  val_gc_masq = val_gc_masq | GCLineWidth ;
  gc_valeurs.plane_mask = black_pixel ^ white_pixel;
  val_gc_masq = val_gc_masq | GCPlaneMask ;
  XChangeGC (display, gc2, val_gc_masq, &gc_valeurs);
  XSetForeground (display, gc2, black_pixel);
  XSetFunction (display, gc2, GXcopy);
  gc1 = XCreateGC (display, win, val_gc_masq, &gc_valeurs);
  XSetFunction (display, gc1, GXinvert);

  for (;;) { 
    XEvent ev;
 
    XNextEvent (display, &ev); 
    switch (ev.type) { 
    case ButtonPress : 
      x1 = ev.xbutton.x ;
      y1 = ev.xbutton.y ;
      break; 
    case ButtonRelease :
      x2 = ev.xbutton.x ;
      y2 = ev.xbutton.y ;
      if ((x2 > x1) && (y2 > y1)) {
	if (ev.xbutton.button == Button1)
	  XDrawRectangle (display, win, gc2, x1, y1, x2-x1, y2-y1);
	else if (ev.xbutton.button == Button3)
	  XDrawRectangle (display, win, gc1, x1, y1, x2-x1, y2-y1);
	else if (ev.xbutton.button == Button2)
	  XFillRectangle (display, win, gc2, x1, y1, x2-x1, y2-y1);
      }
      break; 
    default : 
      break;            
    } 
  } 
}

Exécution :

Enfoncez un bouton de souris pour définir le coin haut gauche puis relachez pour définir le coin bas droite du rectangle à dessiner : Bouton1 pour un cadre rectangulaire normal, Bouton3 idem en mode invert, Bouton2 pour un rectangle plein.

Fonctionnement de ce programme :

GC graphic context : ressource définisant les multiples paramètres nécessaires aux requêtes de dessin : couleur de dessin, couleur de fond, épaisseur de trait, fonte, ... Cela évite de spécifier une longue liste de tous ces paramètres à chaque opération de dessin. Par exemple, XDrawString utilise un gc pour dessiner un texte : fonte, couleur de trait, ...

XCreateGC crée une ressource gc, attachée à l'écran, à partir des valeurs de xgcvaleurs sélectionnées dans le masque xgc_masq.

XChangeGC change certaines valeurs de gc à partir de xgcvaleurs seulement celles sélectionnées dans le masque xgc_masq.

XSetForeground change facilement le foreground de gc. Comme XSetFunction, XSetBackground, XSet....

XGetGCValues récupère dans xgcvaleurs les valeurs de gc sélectionnées dans le masque xgc_masq.

XDrawRectangle dessine un rectangle et XFillRectangle dessine un rectangle plein dans fenêtre selon les spécifications de gc.

Exercice moverect.c :

Dans une fenêtre, dessinez un rectangle de 20 sur 20. Déplacez-le à l'endroit de chaque clic de souris (donc effacez-le de son ancienne position).

programme suivant index général fonctions de la XLib événements types dans XLib