From 090c1d11b484d617c011a31d9b4bdf3b4b560c38 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 2 Oct 2007 14:03:36 +0000 Subject: [PATCH] 2007-10-01 Emmanuele Bassi * clutter/clutter-actor.[ch]: Remove the ::event-after signal class handler, as it's not meant to be overridden by sub-classes. (clutter_actor_class_init): Make every event-related signal return a boolean: return TRUE in a signal handler to block the emission. The value is accumulated automatically by the signal API. (clutter_actor_event): If ::event returns TRUE, skip to emitting ::event-after. Return the value accumulated by the signal emission chain. * clutter/clutter-private.h: Rename _clutter_boolean_accumlator(). * clutter/clutter-main.c (clutter_do_event): If clutter_actor_event() returns TRUE then stop the event emission chain from child to parent. * clutter/clutter-stage.c (clutter_stage_event): Behave like clutter_actor_event(). (clutter_stage_get_key_focus), (clutter_stage_set_key_focus): Avoid a nasty circular reference issue: if the actor passed to set_key_focus is NULL then the stage has the key focus. * tests/test-events.c: Update the events test with the API changes. --- ChangeLog | 30 ++++++++ clutter/clutter-actor.c | 144 ++++++++++++++++++++++---------------- clutter/clutter-actor.h | 34 +++++---- clutter/clutter-main.c | 36 +++++----- clutter/clutter-private.h | 17 +++-- clutter/clutter-stage.c | 43 +++++++----- tests/test-events.c | 25 ++++--- 7 files changed, 196 insertions(+), 133 deletions(-) diff --git a/ChangeLog b/ChangeLog index 274113e0b..9ce1543f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2007-10-01 Emmanuele Bassi + + * clutter/clutter-actor.[ch]: Remove the ::event-after signal + class handler, as it's not meant to be overridden by sub-classes. + + (clutter_actor_class_init): + Make every event-related signal return a boolean: return TRUE + in a signal handler to block the emission. The value is accumulated + automatically by the signal API. + + (clutter_actor_event): If ::event returns TRUE, skip to emitting + ::event-after. Return the value accumulated by the signal emission + chain. + + * clutter/clutter-private.h: Rename _clutter_boolean_accumlator(). + + * clutter/clutter-main.c (clutter_do_event): If clutter_actor_event() + returns TRUE then stop the event emission chain from child to parent. + + * clutter/clutter-stage.c (clutter_stage_event): Behave like + clutter_actor_event(). + + (clutter_stage_get_key_focus), + (clutter_stage_set_key_focus): Avoid a nasty circular reference + issue: if the actor passed to set_key_focus is NULL then the stage + has the key focus. + + * tests/test-events.c: Update the events test with the API + changes. + 2007-10-01 Tomas Frydrych * clutter/clutter-actor.c: diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index a69d96002..81d5ee9ae 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -1241,6 +1241,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::event signal is emitted each time and event is received * by the @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[EVENT] = @@ -1248,9 +1251,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::event-after: @@ -1265,8 +1268,8 @@ clutter_actor_class_init (ClutterActorClass *klass) actor_signals[EVENT_AFTER] = g_signal_new ("event-after", G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ClutterActorClass, event_after), + 0, + 0, NULL, NULL, clutter_marshal_VOID__BOXED, G_TYPE_NONE, 1, @@ -1279,6 +1282,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::button-press-event signal is emitted each time a mouse button * is pressed on @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[BUTTON_PRESS_EVENT] = @@ -1286,9 +1292,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, button_press_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::button-release-event: @@ -1298,6 +1304,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::button-release-event signal is emitted each time a mouse button * is released on @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[BUTTON_RELEASE_EVENT] = @@ -1305,9 +1314,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, button_release_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::scroll-event: @@ -1317,6 +1326,8 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::scroll-event signal is emitted each time a the mouse is * scrolled on @actor * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. * * Since: 0.6 */ @@ -1325,9 +1336,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, scroll_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::key-press-event: @@ -1337,6 +1348,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::key-press-event signal is emitted each time a keyboard button * is pressed on @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[KEY_PRESS_EVENT] = @@ -1344,9 +1358,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, key_press_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::key-release-event: @@ -1356,6 +1370,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::key-release-event signal is emitted each time a keyboard button * is released on @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[KEY_RELEASE_EVENT] = @@ -1363,9 +1380,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, key_release_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * ClutterActor::motion-event: @@ -1375,6 +1392,9 @@ clutter_actor_class_init (ClutterActorClass *klass) * The ::motion-event signal is emitted each time the mouse pointer is * moved on @actor. * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * * Since: 0.6 */ actor_signals[MOTION_EVENT] = @@ -1382,9 +1402,9 @@ clutter_actor_class_init (ClutterActorClass *klass) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterActorClass, motion_event), - NULL, NULL, - clutter_marshal_VOID__BOXED, - G_TYPE_NONE, 1, + _clutter_boolean_handled_accumulator, NULL, + clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** @@ -2899,7 +2919,7 @@ gboolean clutter_actor_event (ClutterActor *actor, ClutterEvent *event) { - gboolean res = TRUE; + gboolean retval = TRUE; gint signal_num = -1; g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); @@ -2907,50 +2927,50 @@ clutter_actor_event (ClutterActor *actor, g_object_ref (actor); - g_signal_emit (actor, actor_signals[EVENT], 0, event); - - switch (event->type) + g_signal_emit (actor, actor_signals[EVENT], 0, event, &retval); + + if (!retval) { - case CLUTTER_NOTHING: - break; - case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: - case CLUTTER_3BUTTON_PRESS: - signal_num = BUTTON_PRESS_EVENT; - break; - case CLUTTER_BUTTON_RELEASE: - signal_num = BUTTON_RELEASE_EVENT; - break; - case CLUTTER_SCROLL: - signal_num = SCROLL_EVENT; - break; - case CLUTTER_KEY_PRESS: - signal_num = KEY_PRESS_EVENT; - break; - case CLUTTER_KEY_RELEASE: - signal_num = KEY_RELEASE_EVENT; - break; - case CLUTTER_MOTION: - signal_num = MOTION_EVENT; - break; - case CLUTTER_DELETE: - case CLUTTER_DESTROY_NOTIFY: - case CLUTTER_CLIENT_MESSAGE: - default: - signal_num = -1; - break; + switch (event->type) + { + case CLUTTER_NOTHING: + break; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_2BUTTON_PRESS: + case CLUTTER_3BUTTON_PRESS: + signal_num = BUTTON_PRESS_EVENT; + break; + case CLUTTER_BUTTON_RELEASE: + signal_num = BUTTON_RELEASE_EVENT; + break; + case CLUTTER_SCROLL: + signal_num = SCROLL_EVENT; + break; + case CLUTTER_KEY_PRESS: + signal_num = KEY_PRESS_EVENT; + break; + case CLUTTER_KEY_RELEASE: + signal_num = KEY_RELEASE_EVENT; + break; + case CLUTTER_MOTION: + signal_num = MOTION_EVENT; + break; + case CLUTTER_DELETE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + default: + signal_num = -1; + break; + } + if (signal_num != -1) + g_signal_emit (actor, actor_signals[signal_num], 0, event, &retval); } - if (signal_num != -1) - { - g_signal_emit (actor, actor_signals[signal_num], 0, event); - g_signal_emit (actor, actor_signals[EVENT_AFTER], 0, event); - res = TRUE; - } + g_signal_emit (actor, actor_signals[EVENT_AFTER], 0, event); g_object_unref (actor); - return res; + return retval; } void diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index d9fe08869..708b7668c 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -193,24 +193,22 @@ struct _ClutterActorClass const ClutterColor *color); /* event signals */ - void (* event) (ClutterActor *actor, - ClutterEvent *event); - void (* event_after) (ClutterActor *actor, - ClutterEvent *event); - void (* button_press_event) (ClutterActor *actor, - ClutterButtonEvent *event); - void (* button_release_event) (ClutterActor *actor, - ClutterButtonEvent *event); - void (* scroll_event) (ClutterActor *actor, - ClutterScrollEvent *event); - void (* key_press_event) (ClutterActor *actor, - ClutterKeyEvent *event); - void (* key_release_event) (ClutterActor *actor, - ClutterKeyEvent *event); - void (* motion_event) (ClutterActor *actor, - ClutterMotionEvent *event); - void (* focus_in) (ClutterActor *actor); - void (* focus_out) (ClutterActor *actor); + gboolean (* event) (ClutterActor *actor, + ClutterEvent *event); + gboolean (* button_press_event) (ClutterActor *actor, + ClutterButtonEvent *event); + gboolean (* button_release_event) (ClutterActor *actor, + ClutterButtonEvent *event); + gboolean (* scroll_event) (ClutterActor *actor, + ClutterScrollEvent *event); + gboolean (* key_press_event) (ClutterActor *actor, + ClutterKeyEvent *event); + gboolean (* key_release_event) (ClutterActor *actor, + ClutterKeyEvent *event); + gboolean (* motion_event) (ClutterActor *actor, + ClutterMotionEvent *event); + void (* focus_in) (ClutterActor *actor); + void (* focus_out) (ClutterActor *actor); /*< private >*/ /* padding for future expansion */ diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index b3940d198..9dc88ede7 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -237,12 +237,14 @@ clutter_do_event (ClutterEvent *event) g_return_if_fail (actor != NULL); - event->key.source = g_object_ref(actor); + event->key.source = g_object_ref (actor); /* bubble up */ do { - clutter_actor_event (actor, event); + if (clutter_actor_event (actor, event)) + break; + actor = clutter_actor_get_parent (actor); } while (actor != NULL); @@ -252,7 +254,7 @@ clutter_do_event (ClutterEvent *event) if (context->motion_events_per_actor == FALSE) { /* Only stage gets motion events */ - event->motion.source = g_object_ref(stage); + event->motion.source = g_object_ref (stage); clutter_actor_event (stage, event); break; } @@ -270,10 +272,9 @@ clutter_do_event (ClutterEvent *event) /* Safety on - probably a release off stage ? * FIXME: should likely deliver the release somehow - grabs ? */ - if (x > CLUTTER_STAGE_WIDTH() - || y > CLUTTER_STAGE_HEIGHT() - || x < 0 - || y < 0) + if (x > CLUTTER_STAGE_WIDTH () || + y > CLUTTER_STAGE_HEIGHT() || + x < 0 || y < 0) break; /* Map the event to a reactive actor */ @@ -285,9 +286,9 @@ clutter_do_event (ClutterEvent *event) x, y, actor); if (event->type == CLUTTER_SCROLL) - event->scroll.source = g_object_ref(actor); + event->scroll.source = g_object_ref (actor); else - event->button.source = g_object_ref(actor); + event->button.source = g_object_ref (actor); /* Motion enter leave events */ if (event->type == CLUTTER_MOTION) @@ -317,7 +318,8 @@ clutter_do_event (ClutterEvent *event) clutter_actor_get_parent (actor) == NULL /* STAGE */ ) { CLUTTER_NOTE (EVENT, "forwarding event to reactive actor"); - clutter_actor_event (actor, event); + if (clutter_actor_event (actor, event)) + break; } actor = clutter_actor_get_parent (actor); @@ -326,14 +328,14 @@ clutter_do_event (ClutterEvent *event) break; case CLUTTER_STAGE_STATE: /* fullscreen / focus - forward to stage */ - clutter_stage_event (CLUTTER_STAGE(stage), event); + clutter_stage_event (CLUTTER_STAGE (stage), event); break; case CLUTTER_CLIENT_MESSAGE: break; } } -ClutterActor* +ClutterActor * _clutter_do_pick (ClutterStage *stage, gint x, gint y, @@ -369,7 +371,7 @@ _clutter_do_pick (ClutterStage *stage, glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) - return CLUTTER_ACTOR(stage); + return CLUTTER_ACTOR (stage); cogl_get_bitmasks (&r, &g, &b, NULL); @@ -1196,10 +1198,10 @@ clutter_init (int *argc, } gboolean -_clutter_boolean_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy) +_clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) { gboolean continue_emission; gboolean signal_handled; diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 4d25a68a7..dac00f222 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -97,12 +97,6 @@ ClutterMainContext *clutter_context_get_default (void); #define CLUTTER_PARAM_READWRITE \ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB -/* signal accumulators */ -gboolean _clutter_boolean_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy); - /* vfuncs implemnted by backend */ GType _clutter_backend_impl_get_type (void); @@ -129,11 +123,20 @@ void _clutter_event_button_generate (ClutterBackend *backend, void _clutter_feature_init (void); -ClutterActor* _clutter_do_pick (ClutterStage *stage, +ClutterActor *_clutter_do_pick (ClutterStage *stage, gint x, gint y, ClutterPickMode mode); +/* use this function as the accumulator if you have a signal with + * a G_TYPE_BOOLEAN return value; this will stop the emission as + * soon as one handler returns TRUE + */ +gboolean _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + /* Does this need to be private ? */ void clutter_do_event (ClutterEvent *event); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 7f434a7cf..2195f207d 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -397,8 +397,7 @@ clutter_stage_init (ClutterStage *self) clutter_actor_set_size (CLUTTER_ACTOR (self), 640, 480); clutter_actor_set_reactive (CLUTTER_ACTOR (self)); - clutter_stage_set_key_focus (self, CLUTTER_ACTOR (self)); - + clutter_stage_set_key_focus (self, NULL); } /** @@ -830,7 +829,8 @@ clutter_stage_event (ClutterStage *stage, return FALSE; /* emit raw event */ - clutter_actor_event (CLUTTER_ACTOR(stage), event); + if (clutter_actor_event (CLUTTER_ACTOR (stage), event)) + return TRUE; if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN) { @@ -904,7 +904,7 @@ on_key_focused_weak_notify (gpointer data, GObject *where_the_object_was) { ClutterStagePrivate *priv; - ClutterStage *stage = CLUTTER_STAGE(data); + ClutterStage *stage = CLUTTER_STAGE (data); g_return_if_fail (CLUTTER_IS_STAGE (stage)); @@ -914,12 +914,12 @@ on_key_focused_weak_notify (gpointer data, /* focused actor has dissapeared - fall back to stage * FIXME: need some kind of signal dance/block here. */ - clutter_stage_set_key_focus (stage, CLUTTER_ACTOR(stage)); + clutter_stage_set_key_focus (stage, NULL); } void -clutter_stage_set_key_focus (ClutterStage *stage, - ClutterActor *actor) +clutter_stage_set_key_focus (ClutterStage *stage, + ClutterActor *actor) { ClutterStagePrivate *priv; @@ -933,33 +933,38 @@ clutter_stage_set_key_focus (ClutterStage *stage, if (priv->key_focused_actor) { - g_object_weak_unref (G_OBJECT(priv->key_focused_actor), + g_object_weak_unref (G_OBJECT (priv->key_focused_actor), on_key_focused_weak_notify, stage); - g_signal_emit_by_name (G_OBJECT(priv->key_focused_actor), "focus-out"); + g_signal_emit_by_name (priv->key_focused_actor, "focus-out"); + + priv->key_focused_actor = NULL; } - - priv->key_focused_actor = actor; + else + g_signal_emit_by_name (stage, "focus-out"); if (actor) { - g_object_weak_ref (G_OBJECT(actor), + priv->key_focused_actor = actor; + + g_object_weak_ref (G_OBJECT (actor), on_key_focused_weak_notify, stage); - g_signal_emit_by_name (G_OBJECT(actor), "focus-in"); + g_signal_emit_by_name (priv->key_focused_actor, "focus-in"); } + else + g_signal_emit_by_name (stage, "focus-in"); } -ClutterActor* -clutter_stage_get_key_focus (ClutterStage *stage) +ClutterActor * +clutter_stage_get_key_focus (ClutterStage *stage) { - ClutterStagePrivate *priv; - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); - priv = stage->priv; + if (stage->priv->key_focused_actor) + return stage->priv->key_focused_actor; - return priv->key_focused_actor; + return CLUTTER_ACTOR (stage); } diff --git a/tests/test-events.c b/tests/test-events.c index 2d87bcecb..7886af553 100644 --- a/tests/test-events.c +++ b/tests/test-events.c @@ -11,7 +11,7 @@ stage_state_cb (ClutterStage *stage, printf("[stage signal] %s\n", detail); } -static void +static gboolean blue_button_cb (ClutterActor *actor, ClutterEvent *event, gpointer data) @@ -26,9 +26,11 @@ blue_button_cb (ClutterActor *actor, IsFullScreen = TRUE; g_object_set (stage, "fullscreen", IsFullScreen, NULL); + + return FALSE; } -void +static void key_focus_in_cb (ClutterActor *actor, gpointer data) { @@ -40,7 +42,6 @@ key_focus_in_cb (ClutterActor *actor, } else { - clutter_actor_show (focus_box); clutter_actor_set_position (focus_box, clutter_actor_get_x (actor) - 5, clutter_actor_get_y (actor) - 5); @@ -48,15 +49,16 @@ key_focus_in_cb (ClutterActor *actor, clutter_actor_set_size (focus_box, clutter_actor_get_width (actor) + 10, clutter_actor_get_height (actor) + 10); + clutter_actor_show (focus_box); } } -static void +static gboolean input_cb (ClutterActor *actor, ClutterEvent *event, gpointer data) { - + ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ()); gchar keybuf[9], *source = (gchar*)data; int len = 0; @@ -88,9 +90,10 @@ input_cb (ClutterActor *actor, break; case CLUTTER_BUTTON_RELEASE: printf("[%s] BUTTON RELEASE", source); - if (clutter_event_get_source (event) == actor) - clutter_stage_set_key_focus - (CLUTTER_STAGE(clutter_stage_get_default ()), actor); + if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage)) + clutter_stage_set_key_focus (stage, NULL); + else if (clutter_event_get_source (event) == actor) + clutter_stage_set_key_focus (stage, actor); break; case CLUTTER_SCROLL: printf("[%s] BUTTON SCROLL", source); @@ -113,8 +116,10 @@ input_cb (ClutterActor *actor, if (clutter_event_get_source (event) == actor) printf(" *source*"); + printf("\n"); + return FALSE; } int @@ -148,7 +153,7 @@ main (int argc, char *argv[]) clutter_actor_set_reactive (actor); - clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box"); g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb), @@ -162,7 +167,7 @@ main (int argc, char *argv[]) clutter_actor_set_reactive (actor); - clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box"); g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb),