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_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 */

View File

@ -38,6 +38,9 @@
* @short_description: User and window system events
*
* 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_RELEASE:
return event->key.modifier_state;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
return event->button.modifier_state;
case CLUTTER_MOTION:
return event->motion.modifier_state;
case CLUTTER_SCROLL:
return event->scroll.modifier_state;
default:
break;
}
@ -177,7 +184,7 @@ clutter_event_get_coords (ClutterEvent *event,
*
* Since: 0.6
*/
ClutterActor*
ClutterActor *
clutter_event_get_source (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, NULL);
@ -190,13 +197,13 @@ clutter_event_get_source (ClutterEvent *event)
* @event: a #ClutterEvent
*
* 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
*
* Since: 0.8
*/
ClutterStage*
ClutterStage *
clutter_event_get_stage (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, NULL);
@ -205,59 +212,151 @@ clutter_event_get_stage (ClutterEvent *event)
}
/**
* clutter_button_event_button:
* @buttev: a #ClutterButtonEvent
* clutter_event_get_flags:
* @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
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 */
/**
* clutter_key_event_symbol:
* @keyev: A #ClutterKeyEvent
* clutter_event_get_key_symbol:
* @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
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:
* @keyev: A #ClutterKeyEvent
* clutter_event_get_key_code:
* @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
*
* Since: 1.0
*/
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
*
* 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
*/
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)
return keyev->unicode_value;
if (event->key.unicode_value)
return event->key.unicode_value;
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)
* character.
*
* Return value: the corresponding unicode character, or 0 if there
* is no corresponding character.
**/
* Return value: a Unicode character, or 0 if there is no corresponding
* character.
*/
guint32
clutter_keysym_to_unicode (guint keyval)
{
@ -303,13 +404,16 @@ clutter_keysym_to_unicode (guint keyval)
return keyval & 0x00ffffff;
/* binary search in table */
while (max >= min) {
while (max >= min)
{
mid = (min + max) / 2;
if (clutter_keysym_to_unicode_tab[mid].keysym < keyval)
min = mid + 1;
else if (clutter_keysym_to_unicode_tab[mid].keysym > keyval)
max = mid - 1;
else {
else
{
/* found it */
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
* no specific device set.
**/
*/
gint
clutter_event_get_device_id (ClutterEvent *event)
{
@ -357,16 +461,16 @@ clutter_event_get_device_id (ClutterEvent *event)
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
device = event->scroll.device;
break;
}
if (device)
if (device != NULL)
return device->id;
else
return -1;
}
GType
clutter_event_get_type (void)
{
@ -428,10 +532,8 @@ clutter_event_copy (ClutterEvent *event)
void
clutter_event_free (ClutterEvent *event)
{
if (G_LIKELY (event))
{
if (G_LIKELY (event != NULL))
g_slice_free (ClutterEvent, event);
}
}
/**
@ -488,11 +590,11 @@ clutter_event_peek (void)
* clutter_event_put:
* @event: a #ClutterEvent
*
* Puts a copy of the event on the back of the event queue. The event will have
* the #CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set event
* signals will be emitted for this source and capture/bubbling for it's
* ancestors. If the source is not set it will be generated by picking or use
* the actor that currently has keyboard focus.
* Puts a copy of the event on the back of the event queue. The event will
* have the %CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set
* event signals will be emitted for this source and capture/bubbling for
* its ancestors. If the source is not set it will be generated by picking
* or use the actor that currently has keyboard focus
*
* Since: 0.6
*/

View File

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

View File

@ -1280,13 +1280,10 @@ clutter_text_key_press (ClutterActor *actor,
ClutterTextPrivate *priv = self->priv;
ClutterBindingPool *pool;
gboolean res;
gint keyval;
if (!priv->editable)
return FALSE;
keyval = clutter_key_event_symbol (event);
/* we need to use the ClutterText type name to find our own
* key bindings; subclasses will override or chain up this
* 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
* 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;
else
res = clutter_binding_pool_activate (pool, keyval,
res = clutter_binding_pool_activate (pool, event->keyval,
event->modifier_state,
G_OBJECT (actor));
@ -1313,7 +1310,9 @@ clutter_text_key_press (ClutterActor *actor,
return TRUE;
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 */
if (key_unichar == '\r')

View File

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

View File

@ -70,17 +70,15 @@ input_cb (ClutterActor *stage,
}
else if (event->type == CLUTTER_KEY_RELEASE)
{
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
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 ();
return TRUE;
}
else if (clutter_key_event_symbol (kev) == CLUTTER_r)
else if (clutter_event_get_key_symbol (event) == CLUTTER_r)
{
gint i;

View File

@ -70,17 +70,15 @@ input_cb (ClutterActor *stage,
}
else if (event->type == CLUTTER_KEY_RELEASE)
{
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
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 ();
return TRUE;
}
else if (clutter_key_event_symbol (kev) == CLUTTER_r)
else if (clutter_event_get_key_symbol (event) == CLUTTER_r)
{
gint i;

View File

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

View File

@ -69,12 +69,10 @@ input_cb (ClutterStage *stage,
}
else if (event->type == CLUTTER_KEY_RELEASE)
{
ClutterKeyEvent *kev = (ClutterKeyEvent *) event;
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 ();
return TRUE;

View File

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

View File

@ -141,14 +141,14 @@ static ClutterActor *count_label = NULL;
static ClutterActor *help_label = NULL;
static ClutterActor *progress_rect = NULL;
static void
static gboolean
on_key_press_event (ClutterStage *stage,
ClutterKeyEvent *event,
ClutterEvent *event,
gpointer user_data)
{
TestThreadData *data;
switch (clutter_key_event_symbol (event))
switch (clutter_event_get_key_symbol (event))
{
case CLUTTER_s:
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->timeline = g_object_ref (timeline);
g_thread_create (test_thread_func, data, FALSE, NULL);
break;
return TRUE;
case CLUTTER_q:
clutter_main_quit ();
return TRUE;
default:
break;
}
return FALSE;
}
G_MODULE_EXPORT int