if (state & GDK_BUTTON1_MASK && pixmap != NULL)
 draw_brush (widget, event->source, x, y, pressure);
 return TRUE;
On doit aussi faire quelquechose de cette nouvelle information. Notre nouvelle fonction draw_brush() dessine avec une couleur différente pour chaque event->source et change la taille du pinceau selon la pression.
/* Dessine un rectangle à l'écran, la taille dépend de la pression,
 et la couleur dépend du type de périphérique */
static void
draw_brush (GtkWidget *widget, GdkInputSource source,
 gdouble x, gdouble y, gdouble pressure)
 GdkGC *gc;
 GdkRectangle update_rect;
 switch (source)
 case GDK_SOURCE_MOUSE:
 gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
 break;
 case GDK_SOURCE_PEN:
 gc = widget->style->black_gc;
 break;
 case GDK_SOURCE_ERASER:
 gc = widget->style->white_gc;
 break;
 default:
 gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
 update_rect.x = x - 10 * pressure;
 update_rect.y = y - 10 * pressure;
 update_rect.width = 20 * pressure;
 update_rect.height = 20 * pressure;
 gdk_draw_rectangle (pixmap, gc, TRUE,
 update_rect.x, update_rect.y,
 update_rect.width, update_rect.height);
 gtk_widget_draw (widget, &update_rect);
En savoir plus sur un périphérique
Notre programme affichera le nom du périphérique qui a généré chaque appui de bouton. Pour trouver le nom d'un périphérique, nous appelons la fonction :
GList *gdk_input_list_devices (void);
qui retourne une GList (un type de liste chaînée de la bibliothèque glib) de structures GdkDeviceInfo. La structure GdkDeviceInfo est définie de la façon suivante&nbsp:
struct _GdkDeviceInfo
 guint32 deviceid;
 gchar *name;
 GdkInputSource source;
 GdkInputMode mode;
 gint has_cursor;
 gint num_axes;
 GdkAxisUse *axes;
 gint num_keys;
 GdkDeviceKey *keys;
La plupart de ces champs sont des informations de configuration que l'on peut ignorer sauf si l'on implante la sauvegarde de la configuration XInput. Celui qui nous intéresse est name qui est, tout simplement, le nom que X donne au périphérique. L'autre champ, qui n'est pas une information de configuration, est has_cursor. Si has_cursor est faux, on doit dessiner notre propre curseur, mais puisque nous avons précisé GDK_EXTENSION_EVENTS_CURSOR, nous n'avons pas à nous en préoccuper.
Notre fonction print_button_press() ne fait parcourir la liste retournée jusqu'à trouver une correspondance, puis affiche le nom du périphérique.
static void
print_button_press (guint32 deviceid)
 GList *tmp_list;
 /* gdk_input_list_devices retourne une liste interne, nous ne devons donc
 pas la libérer après */
 tmp_list = gdk_input_list_devices();
 while (tmp_list)
 GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
 if (info->deviceid == deviceid)
 printf("Bouton pressé sur le périphérique '%s'\n", info->name);
 return;
 tmp_list = tmp_list->next;
Ceci termine les modifications de notre programme « XInputize ». Comme pour la première version, le code complet est disponible à l'endroit où vous avez obtenu ce didacticiel.
Sophistications supplémentaires
Bien que notre programme supporte maintenant XInput, il y manque des caractéristiques que l'on souhaite trouver dans les applications complètes. D'abord, l'utilisateur ne veut probablement pas avoir à configurer ses périphériques à chaque fois qu'il lance le programme et nous devons donc lui permettre de sauvegarder la configuration du périphérique. Ceci est réalisé en parcourant ce que retourne gdk_input_list_devices() et en écrivant la configuration dans un fichier.
Pour restaurer un état au prochain démarrage du programme, GDK dispose de fonctions pour changer la configuration des périphériques :
gdk_input_set_extension_events()
gdk_input_set_source()
gdk_input_set_mode()
gdk_input_set_axes()
gdk_input_set_key()
(La liste retournée par gdk_input_list_devices() ne doit pas être modifiée directement). Un exemple est donné dans le programme de dessin gsumi (disponible à l'adresse http://www.msc.cornell.edu/~otaylor/gsumi/). De plus, ce serait pratique d'avoir une méthode standard pour faire cela pour toutes les applications. Ceci appartient probablement à un niveau légèrement supérieur à GTK, peut-être dans la bibliothèque GNOME.
Une autre grosse omission que nous avons mentionnée plus haut est l'absence de dessin du curseur. Les plates-formes autres qu'XFree86 n'autorisent pas encore l'utilisation simultanée d'un périphérique comme pointeur de base et comme pointeur d'une application. Lisez le XInput-HOWTO pour plus d'informations là-dessus. Ceci signifie que les applications qui veulent atteindre le plus de monde possible doivent dessiner leur propre curseur.
Une application qui dessine son propre curseur doit faire deux choses&nbsp: déterminer si le périphérique courant a besoin ou non d'un curseur dessiné et déterminer si le périphérique courant est à proximité (si celui-ci est une tablette de dessin, il est pratique de faire disparaître le curseur lorsque le stylet est en dehors de la tablette. Lorsque le périphérique voit le stylet, on dit qu'il est « à proximité »). La première vérification est faite en recherchant dans la liste des périphériques, comme nous l'avons fait pour obtenir le nom du périphérique. La deuxième est réalisée en choisissant des événements "proximity_out". Un exemple de dessin d'un curseur personnel est donné dans le programme testinput de la distribution GTK.
Previous Next Table of Contents

Programmation GTK/Types de données
Vous avez probablement noté certaines choses qui nécessitent des explications dans les exemples précédents. les codice_1, codice_2, etc. que vous avez pu voir sont des redéfinitions de codice_3 et codice_4, respectivement. Leur raison d'être est de s'affranchir des dépendances ennuyeuses concernant la taille des types de données simples lorsqu'on réalise des calculs. Un bon exemple est codice_5 qui désignera un entier codé sur 32 bits pour toutes les plateformes, que ce soit une station Alpha 64 bits ou un PC i386 32 bits. Les redéfinitions de type sont très simples et intuitives. Elles sont toutes décrites dans le fichier codice_6 (qui est inclus par codice_7).
On notera aussi la possibilité d'utiliser un codice_8 lorsque la fonction attend un codice_9. GTK possède une architecture orientée objet, et un widget est un objet.

Programmation GTK/Compléments sur les gestionnaires de signaux

Regardons à nouveau la déclaration de gtk_signal_connect.
 gint gtk_signal_connect (GtkObject *object, gchar *name,
 GtkSignalFunc func, gpointer func_data);
Vous avez remarqué que le valeur de retour est de type codice_1 ? Il s'agit d'un marqueur qui identifie votre fonction de rappel. Comme on le disait plus haut, on peut avoir autant de fonctions de rappel que l'on a besoin, par signal et par objet, et chacune sera exécutée à son tour, dans l'ordre dans lequel elle a été attachée. Ce marqueur vous permet d'ôter ce rappel de la liste en faisant :
 void gtk_signal_disconnect (GtkObject *object, gint id);
Ainsi, en passant le widget dont on veut supprimer le gestionnaire et le marqueur ou identificateur retourné par l'une des fonctions signal_connect, on peut déconnecter un gestionnaire de signal.
Une autre fonction permettant de supprimer tous les gestionnaires de signaux pour un objet est :
 gtk_signal_handlers_destroy (GtkObject *object); 
Cet appel n'a pas trop besoin d'explications. Il ôte simplement tous les gestionnaires de signaux de l'objet passé en paramètre.

Programmation GTK/Un Bonjour tout le monde amélioré

3.3 Un « Bonjour tout le monde » amélioré
Étudions une version légèrement améliorée avec de meilleurs exemples de fonctions de rappel. Ceci permettra aussi d'introduire le sujet suivant : le placement des wigdets.
 #include <gtk/gtk.h>
 /* Notre nouveau rappel amélioré. La donnée passée à cette fonction est
 * imprimée sur stdout. */
 void rappel (GtkWidget *widget, gpointer *data)
 g_print ("Re-Bonjour - %s a été pressé\n", (char *) data);