vai alla Homepage di Apogeonline

 



Cos'è OpenPress
Glossario
Linux-FAQ
Documenti:

Open Source Definition

GNU General Public License

La cattedrale e il bazaar

Colonizzare la noosfera

Il calderone magico


Libri:

Italian crackdown

Open Sources

MediaMorfosi

GTK+/GNOME
sviluppo applicazioni


Telematica per la pace

Linux HOWTO: Installazione e configurazione

Linux HOWTO: Networking


Risorse
Feedback
vai alla Homepage di Apogeo Editore

Vai alla homepage di OpenPress

GTK+ / Gnome Sviluppo di Applicazioni


Gli eventi

Gli eventi sono inviati alla vostra applicazione per indicare cambiamenti in una GdkWindow oppure azioni dell'utente a cui potreste essere interessati. Tutti gli eventi sono associati con una GdkWindow. Vengono anche associati con GtkWidget; il loop di GTK+ passa gli eventi da GDK all'albero di widget di GTK+.

Tipi di evento

Ci sono molti tipi di eventi; la union GdkEvent rappresenta uno qualunque di essi. Un tipo di evento speciale, GdkEventAny, contiene i tre campi comuni a tutti gli eventi; ogni evento può "subire un cast" a GdkEventAny. Il primo campo di GdkEventAny è un identificatore di tipo, GdkEventType; GdkEventType è anche incluso nell'unione GdkEvent. Confusi? Dare un occhiata al codice dovrebbe aiutarvi. Ecco la struttura GdkEventAny:


struct _GdkEventAny
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
};

e la union GdkEvent:


union _GdkEvent
{
  GdkEventType              type;
  GdkEventAny               any;
  GdkEventExpose            expose;
  GdkEventNoExpose          no_expose;
  GdkEventVisibility        visibility;
  GdkEventMotion            motion;
  GdkEventButton            button;
  GdkEventKey               key;
  GdkEventCrossing          crossing;
  GdkEventFocus             focus_change;
  GdkEventConfigure         configure;
  GdkEventProperty          property;
  GdkEventSelection         selection;
  GdkEventProximity         proximity;
  GdkEventClient            client;
  GdkEventDND               dnd;
};

Ogni tipo di evento ha i tre membri di GdkEventAny come i suoi primi tre membri. Quindi il campo type può essere richiamato in diversi modi (supponete di avere un GdkEvent* chiamato event):

  • event->type

  • event->any.type

  • event->button.type

  • ((GdkEventAny*)event)->type

  • ((GdkEventButton*)event)->type

Probabilmente avete visto tutti questi esempi nel codice sorgente di GTK+. Certamente, ogni sottotipo di evento ha i suoi membri unici; il campo type vi dice quale sottotipo è valido.

Il campo window di GdkEventAny è la finestra GdkWindow a cui è indirizzato l'evento. Se il flag send_event è TRUE, allora l'evento è stato sintetizzato da un'altra (o la vostra) applicazione; se è FALSE, l'evento è stato originato dal server. GDK non esporta un'interfaccia per XSendEvent(). Comunque, GTK+ spesso costruisce un evento dichiarando una struttura GdkEvent, riempiendola ed emettendo il segnale corrispondente del widget. Questi eventi sintetizzati avranno send_event uguale a TRUE. la sezione Ricevere gli eventi di GDK in GTK+ spiega come GTK+ associa gli eventi alle finestre.

Ci sono più valori possibili per GdkEventType dei membri dell'unione GdkEvent. Molti tipi di evento condividono gli stessi dati; per esempio, GDK_BUTTON_PRESS e GDK_BUTTON_RELEASE usano entrambi button membro di GdkEvent, poiché le informazioni che vengono passate quando il pulsante del mouse viene premuto e rilasciato sono le stesse. Tabella 2 mostra tutti i possibili valori dell'enumerazione GdkEventType, e i corrispondenti membri di GdkEvent. Il significato di ogni tipo di evento verrà spiegato più avanti in questa sezione.

Tabella 2. I valori di GdkEventType

ValoreGdkEvent Membro
GDK_NOTHING nessuno
GDK_DELETE GdkEventAny
GDK_DESTROY GdkEventAny
GDK_EXPOSE GdkEventExpose
GDK_MOTION_NOTIFY GdkEventMotion
GDK_BUTTON_PRESS GdkEventButton
GDK_2BUTTON_PRESS GdkEventButton
GDK_3BUTTON_PRESS GdkEventButton
GDK_BUTTON_RELEASE GdkEventButton
GDK_KEY_PRESS GdkEventKey
GDK_KEY_RELEASE GdkEventKey
GDK_ENTER_NOTIFY GdkEventCrossing
GDK_LEAVE_NOTIFY GdkEventCrossing
GDK_FOCUS_CHANGE GdkEventFocus
GDK_CONFIGURE GdkEventConfigure
GDK_MAP GdkEventAny
GDK_UNMAP GdkEventAny
GDK_PROPERTY_NOTIFY GdkEventProperty
GDK_SELECTION_CLEAR GdkEventSelection
GDK_SELECTION_REQUEST GdkEventSelection
GDK_SELECTION_NOTIFY GdkEventSelection
GDK_PROXIMITY_IN GdkEventProximity
GDK_PROXIMITY_OUT GdkEventProximity
GDK_DRAG_ENTER GdkEventDND
GDK_DRAG_LEAVE GdkEventDND
GDK_DRAG_MOTION GdkEventDND
GDK_DRAG_STATUS GdkEventDND
GDK_DROP_START GdkEventDND
GDK_DROP_FINISHED GdkEventDND
GDK_CLIENT_EVENT GdkEventClient
GDK_VISIBILITY_NOTIFY GdkEventVisibility
GDK_NO_EXPOSE GdkEventNoExpose

La maschera degli eventi

Ogni GdkWindow ha una event mask (maschera degli eventi) associata, la quale determina gli eventi che il server X direzionerà alla vostra applicazione. Specificate una maschera degli eventi all'atto di creazione di una GdkWindow, come parte della struttura GdkWindowAttr ( la sezione Attributi di GdkWindow ). Potete controllare e cambiare la maschera successivamente usando le funzioni gdk_window_set_events() e gdk_window_get_events(). Se la GdkWindow appartiene a un widget, non dovreste cambiare la maschera direttamente; dovreste chiamare gtk_widget_set_events() oppure gtk_widget_add_events(). gtk_widget_set_events() dovrebbe essere utilizzata dopo che il widget è stato realizzato; gtk_widget_add_events() può essere usata per aggiungere eventi alla maschera esistente. Figura 5 e Figura 6 mostrano queste funzioni.

#include <gdk/gdk.h>

GdkEventMask gdk_window_get_events(GdkWindow* window);

void gdk_window_set_events(GdkWindow* window, GdkEventMask event_mask);

Figura 5. La maschera degli eventi di GdkWindow

#include <gtk/gtkwidget.h>

gint gdk_widget_get_events(GtkWidget* widget);

void gtk_widget_add_events(GtkWidget* widget, gint event_mask);

void gtk_widget_set_events(GtkWidget* widget, gint event_mask);

Figura 6. La maschera degli eventi di un widget

Tabella 3 mostra mostra alcune corrispondenze fra maschere ed eventi che esse selezioneranno. Alcuni eventi non devono essere selezionati per essere ricevuti, in particolare:

  • Eventi di Mapping , unmapping , distruzione (destroy) e configurazione (configure) sono selezionati con GDK_STRUCTURE_MASK, ma GDK li selezionerà automaticamente in tutte le nuove finestre. (Attenzione programmatori Xlib: Xlib non si comporta in questo modo.)

  • Gli eventi di selezione, drag-and-drop, client e cancellazione (delete) non hanno maschere, poiché sono automaticamente selezionati (Xlib li seleziona per ogni finestra).

Tabella 3. Maschere degli eventi

MascheraTipo di evento
GDK_EXPOSURE_MASK GDK_EXPOSE
GDK_POINTER_MOTION_MASK GDK_MOTION_NOTIFY
GDK_POINTER_MOTION_HINT_MASK N/A (vedi la sezione Eventi di movimento del mouse )
GDK_BUTTON_MOTION_MASK GDK_MOTION_NOTIFY (mentre un pulsante è premuto)
GDK_BUTTON1_MOTION_MASK GDK_MOTION_NOTIFY (mentre il pulsante 1 è premuto)
GDK_BUTTON2_MOTION_MASK GDK_MOTION_NOTIFY (mentre il pulsante 2 è premuto)
GDK_BUTTON3_MOTION_MASK GDK_MOTION_NOTIFY (mentre il pulsante 3 è premuto)
GDK_BUTTON_PRESS_MASK GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_3BUTTON_PRESS
GDK_BUTTON_RELEASE_MASK GDK_BUTTON_RELEASE
GDK_KEY_PRESS_MASK GDK_KEY_PRESS
GDK_KEY_RELEASE_MASK GDK_KEY_RELEASE
GDK_ENTER_NOTIFY_MASK GDK_ENTER_NOTIFY
GDK_LEAVE_NOTIFY_MASK GDK_LEAVE_NOTIFY
GDK_FOCUS_CHANGE_MASK GDK_FOCUS_IN, GDK_FOCUS_OUT
GDK_STRUCTURE_MASK GDK_CONFIGURE, GDK_DESTROY, GDK_MAP, GDK_UNMAP
GDK_PROPERTY_CHANGE_MASK GDK_PROPERTY_NOTIFY
GDK_VISIBILITY_NOTIFY_MASK GDK_VISIBILITY_NOTIFY
GDK_PROXIMITY_IN_MASK GDK_PROXIMITY_IN
GDK_PROXIMITY_OUT_MASK GDK_PROXIMITY_OUT
GDK_SUBSTRUCTURE_MASK Ricevi gli eventi GDK_STRUCTURE_MASK per finestre figlie
GDK_ALL_EVENTS_MASK Tutti gli eventi

Ricevere gli eventi di GDK in GTK+

In un programma GTK+, non riceverete mai gli eventi di GDK direttamente. Tutti gli eventi sono passati a GtkWidget, il quale emette un segnale corrispondente. Potete rispondere agli eventi connettendo i segnali di GtkWidget.

Il server X spedisce a ogni client uno stream di eventi. Essi sono spediti (e ricevuti) nell'ordine in cui accadono. GDK converte ogni XEvent che riceve in una struttura GdkEvent, e mette l'evento in coda. GTK+ controlla la coda degli eventi di GDK; per ogni evento ricevuto, decide quale widget deve ricevere l'evento. La classe base di GtkWidget definisce segnali per la maggior parte degli eventi (come "button_press_event"); viene definito perfino un generico segnale "event". Il loop principale di GTK+ chiama gtk_widget_event() per spedire un evento ad un widget; questa funzione emette il segnale "event", poi emette il segnale per il tipo specifico di evento (se necessario). Alcuni eventi sono manipolati in modo particolare; per esempio, gli eventi di drag-and-drop non corrispondono direttamente ai segnali d'n'd.

In generale, gli eventi vanno al widget proprietario della GdkWindow in cui è accaduto l'evento. Comunque, ci sono delle eccezioni.

Se un widget ha il controllo del mouse (grab) (se è stata chiamata la funzione gtk_grab_add(), vedere la sezione Grabs nel il capitolo Fondamenti di GTK+ ), gli eventi verranno certamente spediti al widget che ha il "grab", oppure ai suoi figli. Gli eventi che avvengono in altre finestre vengono ignorati. Solo alcuni eventi (specificati dall'utente) sono affetti da un grab.

Anche la sensibilità del widget (vedere la sezione Sensibilità nel il capitolo Fondamenti di GTK+ ) contribuisce a determinare gli eventi che vengono spediti a un widget. Gli eventi che rappresentano le azioni dell'utente non vengono spediti a widget che sono insensibili.

Come vi potete aspettare, i widget senza una GdkWindow associata non originano eventi; X spedisce gli eventi soltanto alle finestre. Esiste una sola eccezione: i contenitori sintetizzano eventi di esposizione per i loro figli che non hanno finestre.

Il loop principale di GTK+ propaga certi eventi da widget figli ai loro contenitori (genitori). Cioè, per ogni evento, viene emesso un segnale dal widget figlio, poi dal suo genitore immediato, poi dal genitore del genitore, e così via. Per esempio, se fate clic su un GtkMenuItem, esso ignora il click e lascia al menu a cui appartiene il compito di elaborarlo. Alcuni eventi non vengono propagati; Tabella 4 fornisce ulteriori dettagli.

La propagazione dell'evento termina non appena un widget elabora l'evento. Questo ci assicura che soltanto un cambiamento viene provocato da un unica azione dell'utente. Gli handler per i segnali degli eventi di GtkWidget restituiscono un valore gint. Ricordate che l'handler che viene eseguito per ultimo determina il valore risultato dalla emissione di un segnale -- vedere la sezione Emettere un segnale nel il capitolo I tipi e gli oggetti in GTK+ . Tutti i segnali degli eventi sono GTK_RUN_LAST, quindi il valore di ritorno sarà determinato da:

  • L'ultimo handler connesso con gtk_signal_connect_after(), se esiste.

  • Altrimenti, l'handler predefinito del widget, se esiste.

  • Altrimenti, l'ultimo handler connesso con gtk_signal_connect(), se esiste.

  • Altrimenti il valore di ritorno è FALSE.

La propagazione dell'evento termina quando l'emissione di un segnale di evento restituisce TRUE, altrimenti l'evento viene propagato al genitore del widget. Ricordate che ogni evento risulta in due emissioni di segnale: il generico segnale di "event" e il segnale specifico (come "button_press_event" oppure "key_press_event"). Se una delle due emissioni restituisce TRUE, la propagazione termina. Il valore di ritorno dal segnale generico "event" ha un effetto ulteriore: se è TRUE, il secondo segnale non viene emesso.

Tabella 4 riassume le corrispondenze dei segnali di GtkWidget con i tipi di evento, quali eventi sono influenzati da un "grab" attivo, quali eventi sono propagati dal padre al figlio. Gli handler dei segnali dovrebbero restituire un gint e accettare tre argomenti: il widget che emette il segnale, l'evento che ha causato il segnale e il puntatore di dati utente.

Tabella 4. Gli eventi di GtkWidget

Tipo di eventoGtkWidget SegnalePropagato ?Grab?
GDK_DELETE "delete_event" No No
GDK_DESTROY "destroy_event" No No
GDK_EXPOSE "expose_event" No No
GDK_MOTION_NOTIFY "motion_notify_event" Si Si
GDK_BUTTON_PRESS "button_press_event" Si Si
GDK_2BUTTON_PRESS "button_press_event" Si Si
GDK_3BUTTON_PRESS "button_press_event" Si Si
GDK_BUTTON_RELEASE "button_release_event" Si Si
GDK_KEY_PRESS "key_press_event" Si Si
GDK_KEY_RELEASE "key_release_event" Si Si
GDK_ENTER_NOTIFY "enter_notify_event" No Si
GDK_LEAVE_NOTIFY "leave_notify_event" No Si
GDK_FOCUS_CHANGE "focus_in_event", "focus_out_event" No No
GDK_CONFIGURE "configure_event" No No
GDK_MAP "map_event" No No
GDK_UNMAP "unmap_event" No No
GDK_PROPERTY_NOTIFY "property_notify_event" No No
GDK_SELECTION_CLEAR "selection_clear_event" No No
GDK_SELECTION_REQUEST "selection_request_event" No No
GDK_SELECTION_NOTIFY "selection_notify_event" No No
GDK_PROXIMITY_IN "proximity_in_event" Si Si
GDK_PROXIMITY_OUT "proximity_out_event" Si Si
GDK_CLIENT_EVENT "client_event" No No
GDK_VISIBILITY_NOTIFY "visibility_notify_event" No No
GDK_NO_EXPOSE "no_expose_event" No No

Eventi relativi ai pulsanti del mouse

Quattro eventi differenti utilizzano la struttura GdkEventButton:

  • GDK_BUTTON_PRESS significa che un pulsante del mouse è stato premuto.

  • GDK_BUTTON_RELEASE significa che il pulsante del mouse è stato rilasciato dopo essere stato premuto. Non necessariamente deve seguire a un evento di "button press": se l'utente sposta il mouse verso una GdkWindow differente.

  • GDK_2BUTTON_PRESS significa che il pulsante del mouse è stato premuto due volte in un breve intervallo di tempo: un doppio clic. É sempre preceduto da una coppia GDK_BUTTON_PRESS/GDK_BUTTON_RELEASE.

  • GDK_3BUTTON_PRESS significa che il mouse è stato premuto tre volte in un breve intervallo di tempo: un triplo clic. Sempre preceduto dalla coppia GDK_BUTTON_PRESS/GDK_BUTTON_RELEASE e da un GDK_2BUTTON_PRESS.

Se fate velocemente clic per tre volte sulla stessa GdkWindow, vengono generati i seguenti eventi (nell'ordine):

  1. GDK_BUTTON_PRESS

  2. GDK_BUTTON_RELEASE

  3. GDK_BUTTON_PRESS

  4. GDK_2BUTTON_PRESS

  5. GDK_BUTTON_RELEASE

  6. GDK_BUTTON_PRESS

  7. GDK_3BUTTON_PRESS

  8. GDK_BUTTON_RELEASE

Il server X attua automaticamente un "grab" del puntatore del mouse quando un pulsante viene premuto, e rilascia il grab quando il pulsante viene rilasciato. Questo vuol dire che l'evento di rilascio del pulsante andrà sempre alla finestra che ha ricevuto l'evento di "button press". Xlib permette di cambiare questo comportamento, ma GDK non lo fa. (Nella documentazione di Xlib, il grab automatico viene chiamato "grab passivo". É distino dal grab "attivo" iniziato con gdk_pointer_grab(), descritto nel la sezione Il "grab" del puntatore .)

L'evento GdkEventButton è definito come segue:


typedef struct _GdkEventButton GdkEventButton;

struct _GdkEventButton
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  gdouble x;
  gdouble y;
  gdouble pressure;
  gdouble xtilt;
  gdouble ytilt;
  guint state;
  guint button;
  GdkInputSource source;
  guint32 deviceid;
  gdouble x_root, y_root;
};

Gli eventi relativi ai pulsanti del mouse sono marcati con un "time stamp" (time) dal server X. Il tempo viene dato in millisecondi relativi alla "vita del server"; ogni qualche settimana l'intero va in overflow e il timestamp ricomincia da 0. Quindi, non dovete utilizzarlo come una misura assoluta del tempo; deve essere utilizzato soltanto per determinare il tempo relativo tra gli eventi vicini.

Le coordinate X e Y del mouse (relative alla finestra in cui accade l'evento) sono incluse nella struttura GdkEventButton. Ricordate che il puntatore potrebbe essere fuori dalla finestra (se il grab del pointer è attivo; vedere la sezione Il puntatore del mouse ). Se il puntatore è fuori dalla finestra, le sue coordinate dovrebbero essere negative oppure eccedenti la dimensione della finestra. Le coordinate sono fornite come tipo double anziché come interi, poiché alcune periferiche di input (come tavolette grafiche) hanno una risoluzione più grande di quella dei pixel. Per la maggior parte degli scopi, avrete bisogno di portare i double a interi mediante un cast. pressure, xtilt, e ytilt sono anche caratteristiche speciali di alcune periferiche di input; questi campi possono essere ignorati quasi sempre.

Il membro state di GdkEventButton indica quali "tasti modificatori" oppure quali pulsanti del mouse erano premuti prima che il pulsante che ha generato l'evento fosse premuto. Si tratta di un campo di bit, con un o più flag della Tabella 5 impostati. Poiché i "modificatori" sono letti immediatamente prima dell'azione che scatena l'evento, il membro state non conterrà il pulsante che ha attivato l'evento (gli eventi di rilascio lo hanno).

Fate attenzione a controllare la presenza di certe bit mask anziché valori esatti di state. Ecco la forma preferita:


 if ( (state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK )

e la forma da evitare:


 if ( state == GDK_SHIFT_MASK )

Se tentate di controllare il valore esatto di state, la vostra applicazione potrebbre smettere di funzionare se l'utente ha il "Num Lock" o qualche altro oscuro modificatore attivato.

Tabella 5. Maschere dei modificatori per gli eventi relativi alla tastiera e al mouse

Maschera dei modificatoriSignificato
GDK_SHIFT_MASK Shift
GDK_LOCK_MASK Caps Lock
GDK_CONTROL_MASK Control
GDK_MOD1_MASK Mod1 (spesso Meta o Alt)
GDK_MOD2_MASK Mod2
GDK_MOD3_MASK Mod3
GDK_MOD4_MASK Mod4
GDK_MOD5_MASK Mod5
GDK_BUTTON1_MASK Button 1
GDK_BUTTON2_MASK Button 2
GDK_BUTTON3_MASK Button 3
GDK_BUTTON4_MASK Button 4
GDK_BUTTON5_MASK Button 5
GDK_RELEASE_MASK Rilascio di tasti

Il membro button di GdkEventButton indica quale pulsante ha causato l'effetto (ovvero il pulsante che è stato premuto o rilasciato). I pulsanti sono numerati da uno a cinque; la maggior parte delle volte il "button 1" è il pulsante sinistro del mouse, "button 2" è il pulsante centrale e "button 3" è il pulsante destro. Gli utenti mancini potrebbero rovesciarli. Gli eventi contenenti i pulsanti quattro e cinque sono generati da alcuni mouse con la rotellina per lo scrolling; GTK+ cerca di catturare tali eventi e di muovere le scrollbar di conseguenza. Probabilmente dovete ignorare tutti gli eventi per i pulsanti quattro e cinque.

I tre pulsanti standard hanno significati convenzionali in Gnome. Il pulsante uno è utilizzato per la selezione, drag & drop, e la selezione/attivazione dei widget: le azioni più comuni. Il terzo pulsante di solito attiva un menu pop-up. Il secondo pulsante è tradizionalmente utilizzato per muovere oggetti, come il "panel". Avvolte gli oggetti sono mossi anche per mezzo del pulsante uno; per esempio, le icone del desktop possono essere mosse sia con il primo che con il secondo pulsante. É una buona idea essere coerenti con altre applicazioni, se possibile.

I membri source e deviceid vengono usati per la determinazione della periferica che ha causato l'evento; l'utente potrebbe possedere una tavoletta grafica e il mouse connessi simultaneamente, per esempio. Potete ignorare questi eventi a meno che non scriviate un'applicazione che utilizza una periferica diversa dal comune mouse.

Gli ultimi due membri di GdkEventButton, x_root e y_root sono le coordinate x e y relative alla finestra root anziché alla finestra che riceve l'evento. Potete utilizzare queste coordinate assolute per confrontare eventi indirizzati a finestre diverse.

Eventi relativi alla tastiera

Ci sono solo due tipi di eventi di tastiera: GDK_KEY_PRESS e GDK_KEY_RELEASE. Alcuni hardware non generano gli eventi di rilascio; è meglio evitare di scrivere software dipendente dall'evento GDK_KEY_RELEASE, però il vostro codice dovrebbe rispondere il modo corretto quando uno di essi viene ricevuto.

Ecco i contenuti di un evento relativo alla tastiera:


typedef struct _GdkEventKey GdkEventKey;

struct _GdkEventKey
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  guint state;
  guint keyval;
  gint length;
  gchar *string;
};

I primi tre membri sono i membri della forma standard GdkEventAny; i membri time e state sono identici a quelli che si trovano in GdkEventButton.

keyval contiene un keysym. Il server X mantiene una tabella globale di traslazione la quale converte combinazioni fisiche di tasti e modificatori in simboli di tasto (keysyms). Per esempio, il tasto "A" della tastiera genera il keysym GDK_a senza alcun modificatore e GDK_A con il tasto "shift" premuto. Gli utenti possono cambiare la mappa delle trasformazioni tasto-fisico/keysym; per esempio, potrebbero modificare i loro tasti in modo da creare una tastiera Dworak (più spesso vengono scambiati i tasti Control e Caps Lock, oppure al tasto Alt viene attribuita la funzione di tasto Meta). I keysym sono definiti in gdk/gdkkeysyms.h. Dovrete includere questo file per utilizzare il campo keyval.

I keysym hanno una corrispondenza diretta con una rappresentazione in forma di stringa. Per esempio, il keysym GDK_a è di solito "mappato" alla stringa "a". (Comunque, X permette di modificare il mappaggio keysym-stringa.) Il membro string di GdkEventKey contiene la rappresentazione in stringa di un keysym, ed il membro length contiene la lunghezza della stringa. Ricordate che la lunghezza può essere 0 (molti tasti non alfanumerici non hanno una rappresentazione predefinita in stringa). Se Xlib vi è familiare, il campo string è semplicemente il risultato di una chiamata a XLookupString() oppure a XmbLookupString(). Anche se non conoscete bene Xlib, le pagine di manuale di queste funzioni vi potranno essere di aiuto.)

In generale, se catturate i "key event" per creare una rappresentazione testuale di quello che l'utente digita, dovrete utilizzare il campo string il campo string string di GdkEventKey. GtkEntry e GtkText usano il campo string, per esempio. Anche un word processor leggerebbe questo campo. Se catturate gli eventi di tastiera per altri motivi (come le scorciatoie da tastiera), oppure se siete interessati ai tasti che non hanno una rappresentazione in stringa (come i tasti funzione oppure i tasti cursore), dovrete usare il campo keyval e i keysym definiti in gdk/gdkkeysyms.h.

Ecco una semplice callback per gli eventi da tastiera che mostra come estrarre informazioni da un evento. É costruita per essere connessa al segnale "key_press_event" di un qualunque GtkWidget:


static gint
key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
{
  if (event->length > 0)
    printf("La stringa è `%s'\n", event->string);

  printf("Il nome del keysym è `%s'\n",
         gdk_keyval_name(event->keyval));

  switch (event->keyval)
    {
    case GDK_Home:
      printf("É stato premuto il tasto Home.\n");
      break;
    case GDK_Up:
      printf("É stato premuto il tasto UpArrow.\n");
      break;
    default:
      break;
    }

  if (gdk_keyval_is_lower(event->keyval))
    {
      printf("É stata digitata una lettera minuscola.\n");
    }
  else if (gdk_keyval_is_upper(event->keyval))
    {
      printf("É stata digitata una lettera maiuscola.\n");
    }
}

gdk_keyval_name() è utile per il debug; essa restituisce il nome del keysym senza il prefisso GDK_. Per esempio, restituisce "Home" se riceve il valore GDK_Home come parametro. La stringa è allocata staticamente. gdk_keyval_is_lower() restituisce FALSE se il keysym rappresenta un carattere maiuscolo. Quindi restituisce TRUE per lettere minuscole, numeri, e tutti i caratteri non alfanumerici. Restituisce FALSE solo per caratteri maiuscoli. gdk_keyval_is_upper() restituisce valori opposti.

Eventi di movimento del mouse

Ci sono degli eventi che sono emessi per permettervi di seguire i movimenti del mouse. Eventi di "motion" sono emessi quando il mouse si muove dentro una finestra; eventi di attraversamento sono emessi quando il puntatore entra o esce da una GdkWindow. Il campo type per gli eventi di "motion" (movimento) è GDK_MOTION_NOTIFY. Ci sono due tipi di eventi di attraversamento: GDK_ENTER_NOTIFY e GDK_LEAVE_NOTIFY.

Ci sono due modi per seguire gli eventi di "motion". Specificando GDK_POINTER_MOTION_MASK nella maschera degli eventi di una finestra, riceverete il massimo numero di eventi che il server X può generare. Se l'utente muoverà il mouse rapidamente, sarete sommersi di eventi; dovrete elaborarli molto velocemente, altrimenti la vostra applicazione potrebbe bloccarsi per troppo tempo. Se specificate anche GDK_POINTER_MOTION_HINT_MASK, gli eventi del mouse verranno spediti uno alla volta. Riceverete al massimo un evento finchè non chiamate gdk_window_get_pointer(), il puntatore lascia e rientra nella finestra oppure un pulsante viene premuto. Quindi ogni volta che ricevete un evento di "motion" dovrete chiamare gdk_window_get_pointer() per ottenere la posizione corrente del mouse e segnalare al server che siete pronti per un altro evento. Consultate la sezione Il puntatore del mouse per dettagli su gdk_window_get_pointer().

Il modo da scegliere dipende dal tipo di applicazione. Se avete bisogno di tracciare la traiettoria esatta del mouse, dovete richiedere tutti gli eventi possibili. Se vi interessa soltanto la posizione più recente, dovrete aggiungere GDK_POINTER_MOTION_HINT_MASK alla event mask della vostra finestra per minimizzare il traffico di rete e massimizzare l'efficienza della vostra applicazione. Un cavillo: gdk_window_get_pointer() richiede un viaggio completo (andata e ritorno) tra l'applicazione e il server per ottenere la posizione del mouse; in questo modo stabilisce un certo limite massimo per la capacità della vostra applicazione di rispondere alle azioni dell'utente. Se riuscite ad elaborare gli eventi abbastanza velocemente, la vostra applicazione probabilmente funzionerà meglio senza GDK_POINTER_MOTION_HINT_MASK. Di solito, non arrivano più di duecento eventi di "motion" al secondo: quindi se siete capaci di gestirne uno in meno di 5 millisecondi, dovreste essere a posto.

Potete richiedere di ricevere gli eventi soltanto quando uno o più pulsanti del mouse sono premuti. Per realizzare questo, utilizzate GDK_BUTTON_MOTION_MASK al posto di GDK_POINTER_MOTION_MASK. Potete usare GDK_POINTER_MOTION_HINT_MASK anche con GDK_BUTTON_MOTION_MASK per limitare il numero degli eventi ricevuti, proprio come con GDK_POINTER_MOTION_MASK. Se vi interessano gli eventi soltanto quando certi pulsanti sono premuti, potete utilizzare le costanti più specifiche: GDK_BUTTON1_MOTION_MASK, GDK_BUTTON2_MOTION_MASK, e GDK_BUTTON3_MOTION_MASK. Ogni combinazione di queste tre è una combinazione valida. Possono anche essere combinate con GDK_POINTER_MOTION_HINT_MASK per limitare il numero degli eventi.

Riassumendo, potete scegliere quali eventi ricevere a seconda dei pulsanti premuti usando le seguenti tre maschere:

  • GDK_POINTER_MOTION_MASK: tutti gli eventi del mouse, indipendentemente dallo stato dei pulsanti.

  • GDK_BUTTON_MOTION_MASK: eventi mentre un pulsante è premuto.

  • GDK_BUTTON1_MOTION_MASK: tutti gli eventi in cui il pulsante 1 è premuto.

  • GDK_BUTTON2_MOTION_MASK: tutti gli eventi in cui il pulsante 2 è premuto.

  • GDK_BUTTON3_MOTION_MASK: tutti gli eventi in cui il pulsante 3 è premuto.

Normalmente siete sommersi di eventi di motion, se specificate GDK_POINTER_MOTION_HINT_MASK nella maschera degli eventi ne riceverete uno per volta.

Gli eventi di motion sono rappresentati dalla struttura GdkEventMotion:


typedef struct _GdkEventMotion GdkEventMotion;

struct _GdkEventMotion
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  gdouble x;
  gdouble y;
  gdouble pressure;
  gdouble xtilt;
  gdouble ytilt;
  guint state;
  gint16 is_hint;
  GdkInputSource source;
  guint32 deviceid;
  gdouble x_root, y_root;
};

La maggior parte di questi campi dovrebbe esservi familiare: li avete già utilizzati in GdkEventButton; infatti, l'unico campo unico a GdkEventMotion è il campo is_hint. Se questo campo è TRUE, è stata selezionata la GDK_POINTER_MOTION_HINT_MASK. Potreste utilizzare questo flag mentre state scrivendo un widget che dovrà essere utilizzato da altre persone, e volete lasciare a loro la decisione di come ricevere gli eventi di motion. Potreste impostare il vostro handler per questo tipo di eventi in modo seguente:


  double x, y;

  x = event->motion.x;
  y = event->motion.y;

  if (event->motion.is_hint)
    gdk_window_get_pointer(event->window, &x, &y, NULL);

Quindi, chiamate gdk_window_get_pointer() solo se necessario. Se utilizzate GDK_POINTER_MOTION_HINT_MASK, dovreste preferire i risultati di gdk_window_get_pointer() alle coordinate fornite nella struttura dell'evento, poiché sono semplicemente più recenti. (Se ricevete tutti gli eventi, non ha senso chiamare gdk_window_get_pointer() poiché è relativamente lento).

Gli eventi di attraversamento accadono quando il puntatore del mouse entra o esce dall'area di una finestra. Se muovete rapidamente il mouse sopra le finestre della vostra applicazione, GDK genererà gli eventi per ogni finestra che attraversate. Comunque, GTK+ cercherà di rimuovere gli eventi "nel mezzo" e riferirvi soltanto il primo "leave event" e l'ultimo "enter event". Se credete di dover ricevere degli eventi , e non li ricevete , probabilmente è a causa di questa ottimizzazione.

Ecco la struttura GdkEventCrossing:


typedef struct _GdkEventCrossing GdkEventCrossing;

struct _GdkEventCrossing
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkWindow *subwindow;
  guint32 time;
  gdouble x;
  gdouble y;
  gdouble x_root;
  gdouble y_root;
  GdkCrossingMode mode;
  GdkNotifyType detail;
  gboolean focus;
  guint state;
};

Di nuovo, molti dei campi dovrebbero esservi familiari; le coordinate relative alla finestra dell'evento; un time stamp, il campo di bit state che indica quali modificatori sono attivi e i tre campi standard di GdkEventAny. Ci sono, comunque, dei campi nuovi.

Il campo standard window contiene un puntatore alla finestra in cui entra (o da cui esce) il mouse; x e y sono relative a questa finestra. Comunque, il puntatore potrebbe essere stato un una finestra figlia prima che l'evento di leave sia stato lanciato; il puntatore può finire in una finestra figlia quando un evento di enter viene lanciato. In questi casi, a subwindow viene assegnato il puntatore alla finestra figlia. Altrimenti subwindow è NULL. Notate che la finestra figlia riceverà il proprio evento di enter e leave, se ha GDK_ENTER_NOTIFY_MASK oppure GDK_LEAVE_NOTIFY_MASK nella sua maschera degli eventi.

Il campo mode indica se l'evento è accaduto normalmente oppure mentre era attivo un grab. Quando viene attivato o disattivato un grab del puntatore (vedere la sezione Il puntatore del mouse ), il puntatore può essere mosso; gli eventi che hanno il flag GDK_CROSSING_GRAB attivo sono causati da un grab del mouse, quelli causati da una disattivazione del grab hanno il flag GDK_CROSSING_UNGRAB, tutti gli altri eventi hanno il flag GDK_CROSSING_NORMAL. Questo campo sembra non avere un utilizzo; usando grep sui sorgenti di Gnome o GTK+ non se ne trova traccia.

Anche il campo detail viene usato raramente. Fornisce informazioni sulla posizione relativa nell'albero della finestra da cui il puntatore è uscito e di quella in cui è entrato. Ha due semplici (e utili) valori:

  • GDK_NOTIFY_INFERIOR indica un evento di crossing ricevuto da una finestra genitore quando il puntatore entra o esce da una finestra figlia.

  • GDK_NOTIFY_ANCESTOR indica un evento di crossing ricevuto da una finestra figlia quando il puntatore entra o esce da una finestra genitore.

Sono possibili anche altri valori: GDK_NOTIFY_VIRTUAL, GDK_NOTIFY_INFERIOR, GDK_NOTIFY_NONLINEAR, GDK_NOTIFY_NONLINEAR_VIRTUAL e GDK_NOTIFY_UNKNOWN. Comunque, non vengono mai utilizzati e sono troppo complicati per essere spiegati qui.

Il focus di tastiera

Il campo focus negli eventi GdkEventCrossing indica se la finestra dell'evento oppure una delle finestre figlie ha il focus di tastiera. Il focus di tastiera è un concetto di X, utilizzato per determinare la finestra che deve ricevere gli eventi di attivazione dei tasti. Il window manager decide quale finestra toplevel ha il focus (di solito la finestra che ha il focus (finestra attiva) viene evidenziata e portata in cima allo stack delle finestre; molti window manager permettono di scegliere tra diversi modi di spostare il focus tra finestre). Quando un'applicazione ha il focus, è libera di spostarlo tra le sue sottofinestre - magari campi differenti per la modifica del testo. Comunque, GTK+ non usa il meccanismo di X per gestire il focus delle finestre figlie. Le GtkWindow toplevel sono le uniche che ricevono il focus di X. Quindi sono le uniche a ricevere gli eventi di tastiera (tramite GDK). GTK+ implementa un concetto proprio del widget focus, analogo a quello implementato da X, ma in realtà completamente distinto. Quando una GtkWindow toplevel riceve gli eventi, li rispedisce al widget che ha il focus "interno".

Riassumendo, questo significa che il flag focus sarà TRUE se la GtkWindow toplevel contenente la finestra che riceve l'evento ha il focus di X. Il flag focus non è relativo al concetto di focus di GTK+.

Eventi di cambiamento del focus

Nella sezione precedente abbiamo spiegato la differenza tra il concetto di focus di GTK+ e quello di X/GDK. Questo rende un pò confusa la gestione degli eventi di focus. Esiste un solo tipo di eventi di focus, GDK_FOCUS_CHANGE, il quale viene ricevuto quando una finestra perde o acquisice il focus della tastiera. Come detto in precedenza, soltanto le GtkWindow toplevel acquistano il focus dal punto di vista di GDK; quindi, questo evento potrebbe sembrare senza senso. Comunque, ogni GtkWindow attribuisce poi il focus ad un suo widget figlio e gli spedisce i relativi eventi. Quindi, anche se la gestione del focus di GDK non viene utilizzata, i widget ricevono gli eventi nello stesso modo in cui li riceverebbero se fosse usata. Ci sono soltanto delle differenze minime: per esempio, i widget ricevono gli event di focus anche se la event mask della loro GdkWindow non contiene GDK_FOCUS_CHANGE_MASK. Soltanto i widget toplevel devono specificare questo flag.

Gli eventi di focus sono molto semplici. Quando un widget acquista il focus, riceve un GtkEventFocus con il membro in inizializzato a TRUE ("focus in event") e quando il widget perde il focus riceve lo stesso evento con il membro in inizializzato a FALSE ("focus out event"). Gli altri campi sono quelli standard di GdkEventAny:


typedef struct _GdkEventFocus GdkEventFocus;

struct _GdkEventFocus
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  gint16 in;
};

Eventi di esposizione

Gli eventi di esposizione vengono ricevuti quando diventa visibile una regione di una finestra che precedentemente era nascosta. I contenuti di una GdkWindow non vengono mai memorizzati; cioè, se disegnate una GdkWindow, e il server la copre con un'altra finestra la parte grafica sottostante andrà persa. Dopo la rimozione della finestra superiore, la vostra GdkWindow riceverà un "expose event" che indica la regione che deve essere ridisegnata. Eventi di esposizione vengono anche spediti quando la finestra viene mostrata per la prima volta sullo schermo. (Non dovete disegnare in una GdkWindow finchè non ricevete il primo expose event. Questo è il segnale che vi informa che la finestra è attualmente sullo schermo.)

Gli eventi di esposizione hanno una caratteristica unica: GTK+ li sintetizza per widget che non hanno finestre. É l'unico tipo di evento che un widget GTK_NO_WINDOW può ricevere.

Gli expose event sono molto semplici:


typedef struct _GdkEventExpose GdkEventExpose;

struct _GdkEventExpose
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkRectangle area;
  gint count;
};

area è l'area che è stata esposta e dovrebbe essere ridisegnata. count è il numero degli eventi di expose che seguono questo; chiaramente potreste voler "comprimere" eventi successivi in una singola operazione di disegno. Comunque, GDK lavora molto su questo aspetto, quindi aggiungere un altro passo difficilmente vi farà guadagnare qualcosa. GdkRectangle è definito come segue:


typedef struct _GdkRectangle GdkRectangle;

struct _GdkRectangle
{
  gint16 x;
  gint16 y;
  guint16 width;
  guint16 height;
};

C'è un altro caso in cui riceverete gli eventi di esposizione. Se chiamate gdk_window_copy_area() per copiare parte di una finestra in un'altra, la finestra sorgente potrebbe essere parzialmente o totalmente oscurata. Se lo è, X non sarà in grado di copiare qualcosa di "utile" dalla regione oscurata. Gli expose event saranno generati per le aree della finestra di destinazione in cui X non è stato in grado di copiare qualcosa. La routine di disegno standard del vostro programma puó, in questo modo, ridisegnare la finestra destinazione. Potete disattivare questo comportamento chiamando gdk_gc_set_exposures() sul GC passato a gdk_window_copy_area().(I GC sono discussi nel la sezione I graphics contexts .)

Se la regione della finestra non è coperta, gdk_window_copy_area() può disegnare l'intera regione di destinazione. In questo caso non viene generato alcun evento di esposizione; viene generato un singolo evento "no expose", che contiene informazioni soltanto nei campi standard.


typedef struct _GdkEventNoExpose GdkEventNoExpose;

struct _GdkEventNoExpose
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
};

Eventi di cambiamento di stato per finestre

Mentre una GdkWindow viene mostrata, nascosta ridimensionata oppure distrutta, vengono generati degli eventi.

Gli eventi di configurazione ("configure events") indicano che la posizione oppure la dimensione della finestra è cambiata. La nuova posizione e dimensione è specificata nella struttura dell'evento:


typedef struct _GdkEventConfigure GdkEventConfigure;

struct _GdkEventConfigure
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  gint16 x, y;
  gint16 width;
  gint16 height;
};

Tutti i widget ricevono questo evento (poiché GDK_STRUCTURE_MASK è automaticamente inclusa nella maschera degli eventi), ma il sistema di allocazione delle dimensioni apprende automaticamente le informazioni necessarie. Cioè, la maggior parte dei widget ridimensiona automaticamente le loro GdkWindow in risposta a una richiesta di ridimensionamento; gli eventi di configurazione sono semplicemente una conferma dell'azione avvenuta: non molto utili. Ci sono due casi particolari. Le finestre toplevel possono essere ridimensionate tramite le decorazioni fornite dal window manager. In questo caso la finestra toplevel monitora gli eventi di configurazione per determinare la propria dimensione. L'altra eccezione si ha nel caso delle GtkDrawingArea. GtkDrawingArea spedisce un configure event a sé stessa quando riceve l'allocazione della sua dimensione. Questo è conveniente, poiché probabilmente vorrete ridisegnare i contenuti quando la dimensione cambia. Come per tutti i falsi eventi che GTK+ crea, il campo send_event sarà inizializzato a TRUE.

Altri cambiamenti in una GdkWindow sono segnalati con un GdkEventAny; Questi eventi non contengono informazioni speciali, vi dicono soltanto che qualcosa è successo. Si distinguono soltanto dal loro campo type:

  • GDK_DELETE significa che il window manager ha richiesto la distruzione della finestra. Se un widget riceve il segnale corrispondente a questo evento e l'emissione del segnale restituisce FALSE, il widget viene distrutto automaticamente dal loop principale di GTK+. Poiché FALSE è il valore di ritorno predefinito, dovete connettere un handler che restituisce TRUE per non permettere agli utenti di distruggere i widget della vostra GtkWindow.

  • GDK_DESTROY significa che la finestra è stata distrutta. I widget distruggono le loro finestre quando sono "unrealized". Se un widget non viene distrutto dopo l'evento di destroy sulla propria finestra, il loop principale di GTK+ lo distrugge.

  • GDK_MAP significa che le finestra è stata mostrata su schermo. Dovete comunque aspettare il primo evento di esposizione prima di disegnare la finestra.

  • GDK_UNMAP Significa che la finestra è stata nascosta; magari è stata ridotta a icona oppure avete chiamato gtk_widget_hide().

Eventi poco usati

Ci sono degli altri eventi che non sono molto utili; questo libro non li descrive in dettaglio. In questa sezione viene fornita una breve descrizione di ciascuno, per completezza. Potete saltare questa sezione senza problemi.

Eventi di visibilità

Gli eventi di visibilità accadono quando una finestra viene coperta o scoperta. Non sono molto utili, poiché altri eventi vi danno le informazioni necessarie. In particolare, quando una finestra viene scoperta, riceverete un evento di esposizione per intimarvi di ridisegnare le parti visibili. Ecco la struttura:


typedef struct _GdkEventVisibility GdkEventVisibility;

struct _GdkEventVisibility
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkVisibilityState state;
};

state è una enumerazione che indica se la finestra è stata coperta oppure scoperta.

Eventi di proprietà

X associa proprietà con finestre. In pratica, le proprietà sono coppie chiave-valore usate per la comunicazione tra i client; di solito, vengono usate per fornire informazioni al window manager. GTK+ fornisce un'interfaccia di alto livello per tutte le proprietà importanti, quindi non dovrete mai maneggiarle direttamente. Gli eventi di proprietà vengono generati quando il valore di una proprietà cambia.


typedef struct _GdkEventProperty GdkEventProperty;

struct _GdkEventProperty
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkAtom atom;
  guint32 time;
  guint state;
};

Eventi di selezione

X ha un semplice meccanismo di copia-e-incolla (tipicamente, selezionate un testo con il primo pulsante del mouse e lo incollate con il pulsante 2). Il contenuto corrente della "clipboard" è chiamato selection. Avete bisogno di conoscere questo evento solo se scrivete un widget simile a GtkText o GtkEntry che permettono di copiare e incollare testo. Gli eventi di selezione indicano che la selezione corrente è cambiata:


typedef struct _GdkEventSelection GdkEventSelection;

struct _GdkEventSelection
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkAtom selection;
  GdkAtom target;
  GdkAtom property;
  guint32 requestor;
  guint32 time;
};

La maggior parte dei widget di GTK+ manipolano la selezione utilizzando l'interfaccia ad alto livello che si trova in gtk/gtkselection.h. Se siete interessati alla implementazione di codice che lavora con le selezioni, date un occhiata a questo header.

Eventi client

Gli eventi client sono blocchi di dati arbitrari spediti da una applicazione a un'altra. Ci sono messaggi convenzionali che possono essere spediti definiti nel manuale delle convenzioni per comunicazione tra i client (Inter-Client Communication Conventions Manual, ICCCM). Questo manuale viene fornito assieme al sistema X Window. Gli eventi client vengono utilizzati per la comunicazione tra il client e i window manager. (L'evento di Xlib che viene incapsulato è chiamato ClientMessage, quindi cercate ClientMessage in ICCCM.) Un ClientMessage importante viene spedito dal window manager all'applicazione, chiedendo di distruggere certe finestre. Comunque, GDK converte questi messaggi in GdkEventAny di tipo GDK_DELETE, quindi un GdkEventClient non verrà ricevuto. Altri eventi relativi al drag-and-drop sono degli eventi ClientMessage , ma GDK si preoccupa di tradurli in eventi GdkEventDND, quindi un GdkEventClient non sarà ricevuto nemmeno in questo caso. GdkEventClient sarà ricevuto soltanto se qualche altro client vi spedisce un messaggio non convenzionale che GDK e GTK+ non comprendono.

Ecco la struttura dell'evento:


typedef struct _GdkEventClient GdkEventClient;

struct _GdkEventClient
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkAtom message_type;
  gushort data_format;
  union {
    char b[20];
    short s[10];
    long l[5];
  } data;
};

L'union alla fine è utilizzata per contenere i dati del messaggio. send_event è sempre TRUE, poiché questi eventi sono sempre spediti da un client e non dal server X.

Eventi di drag and drop

Gli eventi di drag and drop sono molto utili se implementate un'applicazione che supporta il dnd (drag and drop). Comunque, non molte applicazioni implementano tali operazione, quindi sorvoleremo l'argomento. Troverete maggiore documentazione e alcuni esempi sul drag and drop nella distribuzione di GTK+.


typedef struct _GdkEventDND GdkEventDND;

struct _GdkEventDND {
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  GdkDragContext *context;

  guint32 time;
  gshort x_root, y_root;
};

Eventi di prossimità

Gli eventi di prossimità sono generati quando utilizzate il wrapper di GDK per l'estensione XInput. L'estensione XInput è un aggiunta al server X che permette di utilizzare periferiche di input particolari, come tavolette grafiche. Un evento di prossimità indica che la penna è stata avvicinata oppure allontanata dalla tavoletta, o magari il dito dell'utente si è avvicinato oppure allontanato da un touch-screen. Nella distribuzione di X troverete un po' di documentazione sulla estensione XInput, mentre gsumi di Owen Taylor contiene un po' di codice GDK.


typedef struct _GdkEventProximity GdkEventProximity;

struct _GdkEventProximity
{
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  GdkInputSource source;
  guint32 deviceid;
};


Copyright © 1995-1999 Apogeo srl, Milano