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+.
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):
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
| Valore | GdkEvent 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
|
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.
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
| Maschera | Tipo 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
|
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 evento | GtkWidget
Segnale | Propagato ? | 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
|
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):
-
GDK_BUTTON_PRESS
-
GDK_BUTTON_RELEASE
-
GDK_BUTTON_PRESS
-
GDK_2BUTTON_PRESS
-
GDK_BUTTON_RELEASE
-
GDK_BUTTON_PRESS
-
GDK_3BUTTON_PRESS
-
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 modificatori | Significato |
| 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.
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.
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 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+.
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;
};
|
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;
};
|
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().
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.
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.
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;
};
|
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.
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.
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;
};
|
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;
};
|