introspection-friendly ClutterEvent accessors

ClutterEvent is not really gobject-introspection friendly because
of the whole discriminated union thing. In particular, if you get
a ClutterEvent in a signal handler, you probably can't access the
event-type-specific fields, and you probably can't call methods
like clutter_key_event_symbol() either, because you can't cast the
ClutterEvent to a ClutterKeyEvent.

The cleanest solution is to turn every accessor into ClutterEvent
methods, accepting a ClutterEvent* and internally checking the event
type.

Fixes bug:

  http://bugzilla.openedhand.com/show_bug.cgi?id=1585
This commit is contained in:
Emmanuele Bassi 2009-06-06 15:27:37 +01:00
parent 04dc4106e5
commit 41e85f3073
11 changed files with 240 additions and 116 deletions

View File

@ -168,4 +168,9 @@
#define clutter_actor_get_positionu clutter_actor_get_positionu_DEPRECATED_BY_clutter_actor_get_position #define clutter_actor_get_positionu clutter_actor_get_positionu_DEPRECATED_BY_clutter_actor_get_position
#define clutter_actor_get_sizeu clutter_actor_get_sizeu_DEPRECATED_BY_clutter_actor_get_size #define clutter_actor_get_sizeu clutter_actor_get_sizeu_DEPRECATED_BY_clutter_actor_get_size
#define clutter_key_event_symbol clutter_key_event_symbol_REPLACED_BY_clutter_event_get_key_symbol
#define clutter_key_event_code clutter_key_event_code_REPLACED_BY_clutter_event_get_key_code
#define clutter_key_event_unicode clutter_key_event_unicode_REPLACED_BY_clutter_event_get_key_unicode
#define clutter_button_event_button clutter_button_event_button_REPLACED_BY_clutter_event_get_button
#endif /* CLUTTER_DEPRECATED_H */ #endif /* CLUTTER_DEPRECATED_H */

View File

@ -38,6 +38,9 @@
* @short_description: User and window system events * @short_description: User and window system events
* *
* Windowing events handled by Clutter. * Windowing events handled by Clutter.
*
* The events usually come from the windowing backend, but can also
* be synthesized by Clutter itself or by the application code.
*/ */
/** /**
@ -94,13 +97,17 @@ clutter_event_get_state (ClutterEvent *event)
case CLUTTER_KEY_PRESS: case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE: case CLUTTER_KEY_RELEASE:
return event->key.modifier_state; return event->key.modifier_state;
case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE: case CLUTTER_BUTTON_RELEASE:
return event->button.modifier_state; return event->button.modifier_state;
case CLUTTER_MOTION: case CLUTTER_MOTION:
return event->motion.modifier_state; return event->motion.modifier_state;
case CLUTTER_SCROLL: case CLUTTER_SCROLL:
return event->scroll.modifier_state; return event->scroll.modifier_state;
default: default:
break; break;
} }
@ -177,7 +184,7 @@ clutter_event_get_coords (ClutterEvent *event,
* *
* Since: 0.6 * Since: 0.6
*/ */
ClutterActor* ClutterActor *
clutter_event_get_source (ClutterEvent *event) clutter_event_get_source (ClutterEvent *event)
{ {
g_return_val_if_fail (event != NULL, NULL); g_return_val_if_fail (event != NULL, NULL);
@ -190,13 +197,13 @@ clutter_event_get_source (ClutterEvent *event)
* @event: a #ClutterEvent * @event: a #ClutterEvent
* *
* Retrieves the source #ClutterStage the event originated for, or * Retrieves the source #ClutterStage the event originated for, or
* NULL if the event has no stage. * %NULL if the event has no stage.
* *
* Return value: (transfer none): a #ClutterStage * Return value: (transfer none): a #ClutterStage
* *
* Since: 0.8 * Since: 0.8
*/ */
ClutterStage* ClutterStage *
clutter_event_get_stage (ClutterEvent *event) clutter_event_get_stage (ClutterEvent *event)
{ {
g_return_val_if_fail (event != NULL, NULL); g_return_val_if_fail (event != NULL, NULL);
@ -205,59 +212,151 @@ clutter_event_get_stage (ClutterEvent *event)
} }
/** /**
* clutter_button_event_button: * clutter_event_get_flags:
* @buttev: a #ClutterButtonEvent * @event: a #ClutterEvent
* *
* Retrieve the button number of the event. * Retrieves the #ClutterEventFlags of @event
* *
* Return value: the button number. * Return value: the event flags
* *
* Since: 0.4 * Since: 1.0
*/
ClutterEventFlags
clutter_event_get_flags (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, CLUTTER_EVENT_NONE);
return event->any.flags;
}
/**
* clutter_event_get_related:
* @event: a #ClutterEvent of type %CLUTTER_ENTER or of
* type %CLUTTER_LEAVE
*
* Retrieves the related actor of a crossing event.
*
* Return value: (transfer none): the related #ClutterActor, or %NULL
*
* Since: 1.0
*/
ClutterActor *
clutter_event_get_related (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, NULL);
g_return_val_if_fail (event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE, NULL);
return event->crossing.related;
}
/**
* clutter_event_get_scroll_direction:
* @event: a #ClutterEvent of type %CLUTTER_SCROLL
*
* Retrieves the direction of the scrolling of @event
*
* Return value: the scrolling direction
*
* Since: 1.0
*/
ClutterScrollDirection
clutter_event_get_scroll_direction (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_UP);
g_return_val_if_fail (event->type == CLUTTER_SCROLL, CLUTTER_SCROLL_UP);
return event->scroll.direction;
}
/**
* clutter_event_get_button:
* @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or
* of type %CLUTTER_BUTTON_RELEASE
*
* Retrieves the button number of @event
*
* Return value: the button number
*
* Since: 1.0
*/ */
guint32 guint32
clutter_button_event_button (ClutterButtonEvent *buttev) clutter_event_get_button (ClutterEvent *event)
{ {
g_return_val_if_fail (buttev != NULL, 0); g_return_val_if_fail (event != NULL, 0);
g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
event->type == CLUTTER_BUTTON_RELEASE, 0);
return buttev->button; return event->button.button;
}
/**
* clutter_event_get_click_count:
* @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or
* of type %CLUTTER_BUTTON_RELEASE
*
* Retrieves the number of clicks of @event
*
* Return value: the click count
*
* Since: 1.0
*/
guint32
clutter_event_get_click_count (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, 0);
g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
event->type == CLUTTER_BUTTON_RELEASE, 0);
return event->button.click_count;
} }
/* keys */ /* keys */
/** /**
* clutter_key_event_symbol: * clutter_event_get_key_symbol:
* @keyev: A #ClutterKeyEvent * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
* of type %CLUTTER_KEY_RELEASE
* *
* Retrieves the symbol of the key that caused @keyev. * Retrieves the key symbol of @event
* *
* Return value: The key symbol representing the key * Return value: the key symbol representing the key
*
* Since: 1.0
*/ */
guint guint
clutter_key_event_symbol (ClutterKeyEvent *keyev) clutter_event_get_key_symbol (ClutterEvent *event)
{ {
g_return_val_if_fail (keyev != NULL, 0); g_return_val_if_fail (event != NULL, 0);
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE, 0);
return keyev->keyval; return event->key.keyval;
} }
/** /**
* clutter_key_event_code: * clutter_event_get_key_code:
* @keyev: A #ClutterKeyEvent * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
* of type %CLUTTER_KEY_RELEASE
* *
* Retrieves the keycode of the key that caused @keyev. * Retrieves the keycode of the key that caused @event
* *
* Return value: The keycode representing the key * Return value: The keycode representing the key
*
* Since: 1.0
*/ */
guint16 guint16
clutter_key_event_code (ClutterKeyEvent *keyev) clutter_event_get_key_code (ClutterEvent *event)
{ {
g_return_val_if_fail (keyev != NULL, 0); g_return_val_if_fail (event != NULL, 0);
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE, 0);
return keyev->hardware_keycode; return event->key.hardware_keycode;
} }
/** /**
* clutter_key_event_unicode: * clutter_event_get_key_unicode:
* @keyev: A #ClutterKeyEvent * @keyev: A #ClutterKeyEvent
* *
* Retrieves the unicode value for the key that caused @keyev. * Retrieves the unicode value for the key that caused @keyev.
@ -265,14 +364,16 @@ clutter_key_event_code (ClutterKeyEvent *keyev)
* Return value: The unicode value representing the key * Return value: The unicode value representing the key
*/ */
guint32 guint32
clutter_key_event_unicode (ClutterKeyEvent *keyev) clutter_event_get_key_unicode (ClutterEvent *event)
{ {
g_return_val_if_fail (keyev != NULL, 0); g_return_val_if_fail (event != NULL, 0);
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE, 0);
if (keyev->unicode_value) if (event->key.unicode_value)
return keyev->unicode_value; return event->key.unicode_value;
else else
return clutter_keysym_to_unicode (keyev->keyval); return clutter_keysym_to_unicode (event->key.keyval);
} }
/** /**
@ -282,9 +383,9 @@ clutter_key_event_unicode (ClutterKeyEvent *keyev)
* Convert from a Clutter key symbol to the corresponding ISO10646 (Unicode) * Convert from a Clutter key symbol to the corresponding ISO10646 (Unicode)
* character. * character.
* *
* Return value: the corresponding unicode character, or 0 if there * Return value: a Unicode character, or 0 if there is no corresponding
* is no corresponding character. * character.
**/ */
guint32 guint32
clutter_keysym_to_unicode (guint keyval) clutter_keysym_to_unicode (guint keyval)
{ {
@ -303,13 +404,16 @@ clutter_keysym_to_unicode (guint keyval)
return keyval & 0x00ffffff; return keyval & 0x00ffffff;
/* binary search in table */ /* binary search in table */
while (max >= min) { while (max >= min)
{
mid = (min + max) / 2; mid = (min + max) / 2;
if (clutter_keysym_to_unicode_tab[mid].keysym < keyval) if (clutter_keysym_to_unicode_tab[mid].keysym < keyval)
min = mid + 1; min = mid + 1;
else if (clutter_keysym_to_unicode_tab[mid].keysym > keyval) else if (clutter_keysym_to_unicode_tab[mid].keysym > keyval)
max = mid - 1; max = mid - 1;
else { else
{
/* found it */ /* found it */
return clutter_keysym_to_unicode_tab[mid].ucs; return clutter_keysym_to_unicode_tab[mid].ucs;
} }
@ -327,7 +431,7 @@ clutter_keysym_to_unicode (guint keyval)
* *
* Return value: A unique identifier for the device or -1 if the event has * Return value: A unique identifier for the device or -1 if the event has
* no specific device set. * no specific device set.
**/ */
gint gint
clutter_event_get_device_id (ClutterEvent *event) clutter_event_get_device_id (ClutterEvent *event)
{ {
@ -357,16 +461,16 @@ clutter_event_get_device_id (ClutterEvent *event)
break; break;
case CLUTTER_KEY_PRESS: case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE: case CLUTTER_KEY_RELEASE:
device = event->scroll.device;
break; break;
} }
if (device) if (device != NULL)
return device->id; return device->id;
else else
return -1; return -1;
} }
GType GType
clutter_event_get_type (void) clutter_event_get_type (void)
{ {
@ -428,10 +532,8 @@ clutter_event_copy (ClutterEvent *event)
void void
clutter_event_free (ClutterEvent *event) clutter_event_free (ClutterEvent *event)
{ {
if (G_LIKELY (event)) if (G_LIKELY (event != NULL))
{
g_slice_free (ClutterEvent, event); g_slice_free (ClutterEvent, event);
}
} }
/** /**
@ -488,11 +590,11 @@ clutter_event_peek (void)
* clutter_event_put: * clutter_event_put:
* @event: a #ClutterEvent * @event: a #ClutterEvent
* *
* Puts a copy of the event on the back of the event queue. The event will have * Puts a copy of the event on the back of the event queue. The event will
* the #CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set event * have the %CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set
* signals will be emitted for this source and capture/bubbling for it's * event signals will be emitted for this source and capture/bubbling for
* ancestors. If the source is not set it will be generated by picking or use * its ancestors. If the source is not set it will be generated by picking
* the actor that currently has keyboard focus. * or use the actor that currently has keyboard focus
* *
* Since: 0.6 * Since: 0.6
*/ */

View File

@ -106,6 +106,7 @@ typedef enum {
/** /**
* ClutterEventFlags: * ClutterEventFlags:
* @CLUTTER_EVENT_NONE: No flag set
* @CLUTTER_EVENT_FLAG_SYNTHETIC: Synthetic event * @CLUTTER_EVENT_FLAG_SYNTHETIC: Synthetic event
* *
* Flags for the #ClutterEvent * Flags for the #ClutterEvent
@ -113,6 +114,7 @@ typedef enum {
* Since: 0.6 * Since: 0.6
*/ */
typedef enum { typedef enum {
CLUTTER_EVENT_NONE = 0,
CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0, CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0,
} ClutterEventFlags; } ClutterEventFlags;
@ -444,28 +446,36 @@ gboolean clutter_events_pending (void);
ClutterEvent * clutter_event_get (void); ClutterEvent * clutter_event_get (void);
ClutterEvent * clutter_event_peek (void); ClutterEvent * clutter_event_peek (void);
void clutter_event_put (ClutterEvent *event); void clutter_event_put (ClutterEvent *event);
ClutterEvent * clutter_event_new (ClutterEventType type); ClutterEvent * clutter_event_new (ClutterEventType type);
ClutterEvent * clutter_event_copy (ClutterEvent *event); ClutterEvent * clutter_event_copy (ClutterEvent *event);
void clutter_event_free (ClutterEvent *event); void clutter_event_free (ClutterEvent *event);
ClutterEventType clutter_event_type (ClutterEvent *event); ClutterEventType clutter_event_type (ClutterEvent *event);
ClutterEventFlags clutter_event_get_flags (ClutterEvent *event);
guint32 clutter_event_get_time (ClutterEvent *event); guint32 clutter_event_get_time (ClutterEvent *event);
ClutterModifierType clutter_event_get_state (ClutterEvent *event); ClutterModifierType clutter_event_get_state (ClutterEvent *event);
gint clutter_event_get_device_id (ClutterEvent *event);
ClutterActor * clutter_event_get_source (ClutterEvent *event);
ClutterStage * clutter_event_get_stage (ClutterEvent *event);
void clutter_event_get_coords (ClutterEvent *event, void clutter_event_get_coords (ClutterEvent *event,
gfloat *x, gfloat *x,
gfloat *y); gfloat *y);
gint clutter_event_get_device_id (ClutterEvent *event);
ClutterActor* clutter_event_get_source (ClutterEvent *event);
guint clutter_key_event_symbol (ClutterKeyEvent *keyev); guint clutter_event_get_key_symbol (ClutterEvent *event);
guint16 clutter_key_event_code (ClutterKeyEvent *keyev); guint16 clutter_event_get_key_code (ClutterEvent *event);
guint32 clutter_key_event_unicode (ClutterKeyEvent *keyev); guint32 clutter_event_get_key_unicode (ClutterEvent *event);
guint32 clutter_button_event_button (ClutterButtonEvent *buttev); guint32 clutter_event_get_button (ClutterEvent *event);
guint clutter_event_get_click_count (ClutterEvent *event);
ClutterActor * clutter_event_get_related (ClutterEvent *event);
ClutterScrollDirection clutter_event_get_scroll_direction (ClutterEvent *event);
guint32 clutter_keysym_to_unicode (guint keyval); guint32 clutter_keysym_to_unicode (guint keyval);
ClutterStage* clutter_event_get_stage (ClutterEvent *event);
guint32 clutter_get_current_event_time (void); guint32 clutter_get_current_event_time (void);
G_END_DECLS G_END_DECLS

View File

@ -1280,13 +1280,10 @@ clutter_text_key_press (ClutterActor *actor,
ClutterTextPrivate *priv = self->priv; ClutterTextPrivate *priv = self->priv;
ClutterBindingPool *pool; ClutterBindingPool *pool;
gboolean res; gboolean res;
gint keyval;
if (!priv->editable) if (!priv->editable)
return FALSE; return FALSE;
keyval = clutter_key_event_symbol (event);
/* we need to use the ClutterText type name to find our own /* we need to use the ClutterText type name to find our own
* key bindings; subclasses will override or chain up this * key bindings; subclasses will override or chain up this
* event handler, so they can do whatever they want there * event handler, so they can do whatever they want there
@ -1297,10 +1294,10 @@ clutter_text_key_press (ClutterActor *actor,
/* we allow passing synthetic events that only contain /* we allow passing synthetic events that only contain
* the Unicode value and not the key symbol * the Unicode value and not the key symbol
*/ */
if (keyval == 0 && (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)) if (event->keyval == 0 && (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
res = FALSE; res = FALSE;
else else
res = clutter_binding_pool_activate (pool, keyval, res = clutter_binding_pool_activate (pool, event->keyval,
event->modifier_state, event->modifier_state,
G_OBJECT (actor)); G_OBJECT (actor));
@ -1313,7 +1310,9 @@ clutter_text_key_press (ClutterActor *actor,
return TRUE; return TRUE;
else else
{ {
gunichar key_unichar = clutter_key_event_unicode (event); gunichar key_unichar;
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) event);
/* return is reported as CR, but we want LF */ /* return is reported as CR, but we want LF */
if (key_unichar == '\r') if (key_unichar == '\r')

View File

@ -925,6 +925,7 @@ clutter_event_get_state
clutter_event_get_time clutter_event_get_time
clutter_event_get_source clutter_event_get_source
clutter_event_get_stage clutter_event_get_stage
clutter_event_get_flags
<SUBSECTION> <SUBSECTION>
clutter_event_get clutter_event_get
@ -933,14 +934,21 @@ clutter_event_put
clutter_events_pending clutter_events_pending
<SUBSECTION> <SUBSECTION>
clutter_button_event_button clutter_event_get_button
clutter_event_get_click_count
<SUBSECTION> <SUBSECTION>
clutter_key_event_symbol clutter_event_get_key_symbol
clutter_key_event_code clutter_event_get_key_code
clutter_key_event_unicode clutter_event_get_key_unicode
clutter_keysym_to_unicode clutter_keysym_to_unicode
<SUBSECTION>
clutter_event_get_related
<SUBSECTION>
clutter_event_get_scroll_direction
<SUBSECTION> <SUBSECTION>
clutter_event_get_device_id clutter_event_get_device_id
clutter_get_input_device_for_id clutter_get_input_device_for_id

View File

@ -70,17 +70,15 @@ input_cb (ClutterActor *stage,
} }
else if (event->type == CLUTTER_KEY_RELEASE) else if (event->type == CLUTTER_KEY_RELEASE)
{ {
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
g_print ("*** key press event (key:%c) ***\n", g_print ("*** key press event (key:%c) ***\n",
clutter_key_event_symbol (kev)); clutter_event_get_key_symbol (event));
if (clutter_key_event_symbol (kev) == CLUTTER_q) if (clutter_event_get_key_symbol (event) == CLUTTER_q)
{ {
clutter_main_quit (); clutter_main_quit ();
return TRUE; return TRUE;
} }
else if (clutter_key_event_symbol (kev) == CLUTTER_r) else if (clutter_event_get_key_symbol (event) == CLUTTER_r)
{ {
gint i; gint i;

View File

@ -70,17 +70,15 @@ input_cb (ClutterActor *stage,
} }
else if (event->type == CLUTTER_KEY_RELEASE) else if (event->type == CLUTTER_KEY_RELEASE)
{ {
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
g_print ("*** key press event (key:%c) ***\n", g_print ("*** key press event (key:%c) ***\n",
clutter_key_event_symbol (kev)); clutter_event_get_key_symbol (event));
if (clutter_key_event_symbol (kev) == CLUTTER_q) if (clutter_event_get_key_symbol (event) == CLUTTER_q)
{ {
clutter_main_quit (); clutter_main_quit ();
return TRUE; return TRUE;
} }
else if (clutter_key_event_symbol (kev) == CLUTTER_r) else if (clutter_event_get_key_symbol (event) == CLUTTER_r)
{ {
gint i; gint i;

View File

@ -635,10 +635,10 @@ create_item (void)
static gboolean static gboolean
keypress_cb (ClutterActor *actor, keypress_cb (ClutterActor *actor,
ClutterKeyEvent *event, ClutterEvent *event,
gpointer data) gpointer data)
{ {
switch (clutter_key_event_symbol (event)) switch (clutter_event_get_key_symbol (event))
{ {
case CLUTTER_q: case CLUTTER_q:
{ {

View File

@ -69,12 +69,10 @@ input_cb (ClutterStage *stage,
} }
else if (event->type == CLUTTER_KEY_RELEASE) else if (event->type == CLUTTER_KEY_RELEASE)
{ {
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
g_print ("*** key press event (key:%c) ***\n", g_print ("*** key press event (key:%c) ***\n",
clutter_key_event_symbol (kev)); clutter_event_get_key_symbol (event));
if (clutter_key_event_symbol (kev) == CLUTTER_q) if (clutter_event_get_key_symbol (event) == CLUTTER_q)
{ {
clutter_main_quit (); clutter_main_quit ();
return TRUE; return TRUE;

View File

@ -47,7 +47,7 @@ stage_key_release_cb (ClutterActor *actor,
ClutterEvent *event, ClutterEvent *event,
gpointer data) gpointer data)
{ {
switch (clutter_key_event_symbol (&event->key)) switch (clutter_event_get_key_symbol (event))
{ {
case CLUTTER_q: case CLUTTER_q:
case CLUTTER_Q: case CLUTTER_Q:

View File

@ -141,14 +141,14 @@ static ClutterActor *count_label = NULL;
static ClutterActor *help_label = NULL; static ClutterActor *help_label = NULL;
static ClutterActor *progress_rect = NULL; static ClutterActor *progress_rect = NULL;
static void static gboolean
on_key_press_event (ClutterStage *stage, on_key_press_event (ClutterStage *stage,
ClutterKeyEvent *event, ClutterEvent *event,
gpointer user_data) gpointer user_data)
{ {
TestThreadData *data; TestThreadData *data;
switch (clutter_key_event_symbol (event)) switch (clutter_event_get_key_symbol (event))
{ {
case CLUTTER_s: case CLUTTER_s:
clutter_text_set_text (CLUTTER_TEXT (help_label), "Press 'q' to quit"); clutter_text_set_text (CLUTTER_TEXT (help_label), "Press 'q' to quit");
@ -161,11 +161,17 @@ on_key_press_event (ClutterStage *stage,
data->progress = g_object_ref (progress_rect); data->progress = g_object_ref (progress_rect);
data->timeline = g_object_ref (timeline); data->timeline = g_object_ref (timeline);
g_thread_create (test_thread_func, data, FALSE, NULL); g_thread_create (test_thread_func, data, FALSE, NULL);
break; return TRUE;
case CLUTTER_q: case CLUTTER_q:
clutter_main_quit (); clutter_main_quit ();
return TRUE;
default:
break; break;
} }
return FALSE;
} }
G_MODULE_EXPORT int G_MODULE_EXPORT int