diff --git a/ChangeLog b/ChangeLog index e046ad9d6..968b6518f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2007-10-03 Matthew Allum + + * clutter/clutter-actor.c: + * clutter/clutter-event.c: + * clutter/clutter-event.h: + * clutter/clutter-main.c: + * clutter/clutter-private.h: + * clutter/eglnative/clutter-event-egl.c: + * clutter/eglx/clutter-event-egl.c: + * clutter/glx/clutter-event-glx.c: + * clutter/sdl/clutter-event-sdl.c: + Remove seperate double/triple click events and replace with + a click_count member. + Move calculating click counts from backend to do_event() + Initial implementation of ENTER/LEAVE events. + + * tests/test-events.c: + Add code to test above. + + * tests/test-behave.c: + Sync with newer API. + + * clutter/clutter-score.c: + Silence a warning. + 2007-10-01 Emmanuele Bassi * clutter/clutter-fixed.h: Add CLUTTER_FIXED_TO_INT() and diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 622b8ffd1..59e273581 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -2942,8 +2942,6 @@ clutter_actor_event (ClutterActor *actor, 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: diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c index 1f9e426ee..03d69afa2 100644 --- a/clutter/clutter-event.c +++ b/clutter/clutter-event.c @@ -39,12 +39,6 @@ * Windowing events handled by Clutter. */ -/* multiple button click detection */ -static guint32 button_click_time[2] = { 0, 0 }; -static guint32 button_number[2] = { -1, -1 }; -static gint button_x[2] = { 0, 0 }; -static gint button_y[2] = { 0, 0 }; - /** * clutter_event_type: * @event: a #ClutterEvent @@ -76,24 +70,7 @@ clutter_event_get_time (ClutterEvent *event) { g_return_val_if_fail (event != NULL, CLUTTER_CURRENT_TIME); - switch (event->type) - { - case CLUTTER_KEY_PRESS: - case CLUTTER_KEY_RELEASE: - return event->key.time; - case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - return event->button.time; - case CLUTTER_MOTION: - return event->motion.time; - case CLUTTER_SCROLL: - return event->scroll.time; - default: - break; - } - - return CLUTTER_CURRENT_TIME; + return event->any.time; } /** @@ -117,8 +94,6 @@ clutter_event_get_state (ClutterEvent *event) case CLUTTER_KEY_RELEASE: return event->key.modifier_state; case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: return event->button.modifier_state; case CLUTTER_MOTION: return event->motion.modifier_state; @@ -161,10 +136,10 @@ clutter_event_get_coords (ClutterEvent *event, case CLUTTER_DESTROY_NOTIFY: case CLUTTER_CLIENT_MESSAGE: case CLUTTER_DELETE: + case CLUTTER_ENTER: + case CLUTTER_LEAVE: break; case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: - case CLUTTER_3BUTTON_PRESS: case CLUTTER_BUTTON_RELEASE: event_x = event->button.x; event_y = event->button.y; @@ -212,7 +187,6 @@ clutter_event_get_source (ClutterEvent *event) res = event->key.source; break; case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: case CLUTTER_BUTTON_RELEASE: res = event->button.source; break; @@ -504,71 +478,3 @@ clutter_events_pending (void) return g_queue_is_empty (context->events_queue) == FALSE; } -/* Backend helpers (private) */ - -static void -synthesize_click (ClutterBackend *backend, - ClutterEvent *event, - gint n_clicks) -{ - ClutterEvent temp_event; - - temp_event = *event; - temp_event.type = (n_clicks == 2) ? CLUTTER_2BUTTON_PRESS - : CLUTTER_3BUTTON_PRESS; - - clutter_event_put (&temp_event); -} - -/* post process a button to synthesize double clicks etc */ -void -_clutter_event_button_generate (ClutterBackend *backend, - ClutterEvent *event) -{ - guint double_click_time, double_click_distance; - - double_click_distance = clutter_backend_get_double_click_distance (backend); - double_click_time = clutter_backend_get_double_click_time (backend); - - if ((event->button.time < (button_click_time[1] + 2 * double_click_time)) - && (event->button.button == button_number[1]) - && (ABS (event->button.x - button_x[1]) <= double_click_distance) - && (ABS (event->button.y - button_y[1]) <= double_click_distance)) - { - synthesize_click (backend, event, 3); - - button_click_time[1] = 0; - button_click_time[0] = 0; - button_number[1] = -1; - button_number[0] = -1; - button_x[0] = button_x[1] = 0; - button_y[0] = button_y[1] = 0; - } - else if ((event->button.time < (button_click_time[0] + double_click_time)) && - (event->button.button == button_number[0]) && - (ABS (event->button.x - button_x[0]) <= double_click_distance) && - (ABS (event->button.y - button_y[0]) <= double_click_distance)) - { - synthesize_click (backend, event, 2); - - button_click_time[1] = button_click_time[0]; - button_click_time[0] = event->button.time; - button_number[1] = button_number[0]; - button_number[0] = event->button.button; - button_x[1] = button_x[0]; - button_x[0] = event->button.x; - button_y[1] = button_y[0]; - button_y[0] = event->button.y; - } - else - { - button_click_time[1] = 0; - button_click_time[0] = event->button.time; - button_number[1] = -1; - button_number[0] = event->button.button; - button_x[1] = 0; - button_x[0] = event->button.x; - button_y[1] = 0; - button_y[0] = event->button.y; - } -} diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h index 8dda1f68e..351ffa7a7 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -58,13 +58,12 @@ typedef enum { typedef enum { CLUTTER_NOTHING = 0, - CLUTTER_KEY_PRESS, CLUTTER_KEY_RELEASE, CLUTTER_MOTION, + CLUTTER_ENTER, + CLUTTER_LEAVE, CLUTTER_BUTTON_PRESS, - CLUTTER_2BUTTON_PRESS, /* Double click */ - CLUTTER_3BUTTON_PRESS, /* Triple click */ CLUTTER_BUTTON_RELEASE, CLUTTER_SCROLL, CLUTTER_STAGE_STATE, @@ -96,6 +95,7 @@ typedef struct _ClutterKeyEvent ClutterKeyEvent; typedef struct _ClutterMotionEvent ClutterMotionEvent; typedef struct _ClutterScrollEvent ClutterScrollEvent; typedef struct _ClutterStageStateEvent ClutterStageStateEvent; +typedef struct _ClutterCrossingEvent ClutterCrossingEvent; typedef struct _ClutterInputDevice ClutterInputDevice; @@ -132,6 +132,18 @@ struct _ClutterButtonEvent ClutterActor *source; }; +struct _ClutterCrossingEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + gint x; + gint y; + ClutterActor *source; + ClutterActor *related; +}; + + struct _ClutterMotionEvent { ClutterEventType type; @@ -178,6 +190,7 @@ union _ClutterEvent ClutterMotionEvent motion; ClutterScrollEvent scroll; ClutterStageStateEvent stage_state; + ClutterCrossingEvent crossing; }; GType clutter_event_get_type (void) G_GNUC_CONST; diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 9dc88ede7..e21b4e71a 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -188,153 +188,6 @@ clutter_get_motion_events_enabled (void) return context->motion_events_per_actor; } - -/** - * clutter_do_event - * @event: a #ClutterEvent. - * - * Processes an event. This function should never be called by applications. - * - * Since: 0.4 - */ -void -clutter_do_event (ClutterEvent *event) -{ - /* FIXME: This should probably be clutter_cook_event() - it would - * take a raw event from the backend and 'cook' it so its more tasty. - * - */ - ClutterMainContext *context; - ClutterBackend *backend; - ClutterActor *stage; - static ClutterActor *motion_last_actor = NULL; - - context = clutter_context_get_default (); - backend = context->backend; - stage = _clutter_backend_get_stage (backend); - - if (!stage) - return; - - CLUTTER_TIMESTAMP (EVENT, "Event received"); - - switch (event->type) - { - case CLUTTER_NOTHING: - break; - - case CLUTTER_DESTROY_NOTIFY: - case CLUTTER_DELETE: - if (clutter_stage_event (CLUTTER_STAGE (stage), event)) - clutter_main_quit (); - break; - case CLUTTER_KEY_PRESS: - case CLUTTER_KEY_RELEASE: - { - ClutterActor *actor = NULL; - - actor = clutter_stage_get_key_focus (CLUTTER_STAGE(stage)); - - g_return_if_fail (actor != NULL); - - event->key.source = g_object_ref (actor); - - /* bubble up */ - do - { - if (clutter_actor_event (actor, event)) - break; - - actor = clutter_actor_get_parent (actor); - } - while (actor != NULL); - } - break; - case CLUTTER_MOTION: - if (context->motion_events_per_actor == FALSE) - { - /* Only stage gets motion events */ - event->motion.source = g_object_ref (stage); - clutter_actor_event (stage, event); - break; - } - case CLUTTER_BUTTON_PRESS: - case CLUTTER_2BUTTON_PRESS: - case CLUTTER_3BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_SCROLL: - { - ClutterActor *actor; - gint x,y; - - clutter_event_get_coords (event, &x, &y); - - /* 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) - break; - - /* Map the event to a reactive actor */ - actor = _clutter_do_pick (CLUTTER_STAGE (stage), - x, y, - CLUTTER_PICK_REACTIVE); - - CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p", - x, y, actor); - - if (event->type == CLUTTER_SCROLL) - event->scroll.source = g_object_ref (actor); - else - event->button.source = g_object_ref (actor); - - /* Motion enter leave events */ - if (event->type == CLUTTER_MOTION) - { - if (motion_last_actor != actor) - { - if (motion_last_actor) - ; /* FIXME: leave_notify to motion_last_actor */ - if (actor) - ; /* FIXME: Enter notify to actor */ - } - motion_last_actor = actor; - } - - /* Send the event to the actor and all parents always the - * stage. - * - * FIXME: for an optimisation should check if there are - * actually any reactive actors and avoid the pick all togeather - * (signalling just the stage). Should be big help for gles. - * - * FIXME: Actors be able to stop emission. - */ - while (actor) - { - if (clutter_actor_is_reactive (actor) || - clutter_actor_get_parent (actor) == NULL /* STAGE */ ) - { - CLUTTER_NOTE (EVENT, "forwarding event to reactive actor"); - if (clutter_actor_event (actor, event)) - break; - } - - actor = clutter_actor_get_parent (actor); - } - } - break; - case CLUTTER_STAGE_STATE: - /* fullscreen / focus - forward to stage */ - clutter_stage_event (CLUTTER_STAGE (stage), event); - break; - case CLUTTER_CLIENT_MESSAGE: - break; - } -} - ClutterActor * _clutter_do_pick (ClutterStage *stage, gint x, @@ -1213,6 +1066,257 @@ _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint, return continue_emission; } +static void +event_click_count_generate (ClutterEvent *event) +{ + /* multiple button click detection */ + static guint32 button_click_time[2] = { 0, 0 }; + static guint32 button_number[2] = { -1, -1 }; + static gint button_x[2] = { 0, 0 }; + static gint button_y[2] = { 0, 0 }; + + guint double_click_time, double_click_distance; + ClutterBackend *backend; + ClutterMainContext *context; + + context = clutter_context_get_default (); + backend = context->backend; + + double_click_distance = clutter_backend_get_double_click_distance (backend); + double_click_time = clutter_backend_get_double_click_time (backend); + + /* FIXME: below could be reduced in lines and handle >3 clicks */ + if ((event->button.time < (button_click_time[1] + 2 * double_click_time)) + && (event->button.button == button_number[1]) + && (ABS (event->button.x - button_x[1]) <= double_click_distance) + && (ABS (event->button.y - button_y[1]) <= double_click_distance)) + { + event->button.click_count = 2; + + button_click_time[1] = 0; + button_click_time[0] = 0; + button_number[1] = -1; + button_number[0] = -1; + button_x[0] = button_x[1] = 0; + button_y[0] = button_y[1] = 0; + } + else if ((event->button.time < (button_click_time[0] + double_click_time)) && + (event->button.button == button_number[0]) && + (ABS (event->button.x - button_x[0]) <= double_click_distance) && + (ABS (event->button.y - button_y[0]) <= double_click_distance)) + { + event->button.click_count = 3; + + button_click_time[1] = button_click_time[0]; + button_click_time[0] = event->button.time; + button_number[1] = button_number[0]; + button_number[0] = event->button.button; + button_x[1] = button_x[0]; + button_x[0] = event->button.x; + button_y[1] = button_y[0]; + button_y[0] = event->button.y; + } + else + { + event->button.click_count = 1; + + button_click_time[1] = 0; + button_click_time[0] = event->button.time; + button_number[1] = -1; + button_number[0] = event->button.button; + button_x[1] = 0; + button_x[0] = event->button.x; + button_y[1] = 0; + button_y[0] = event->button.y; + } +} + +/** + * clutter_do_event + * @event: a #ClutterEvent. + * + * Processes an event. This function should never be called by applications. + * + * Since: 0.4 + */ +void +clutter_do_event (ClutterEvent *event) +{ + /* FIXME: This should probably be clutter_cook_event() - it would + * take a raw event from the backend and 'cook' it so its more tasty. + * + */ + ClutterMainContext *context; + ClutterBackend *backend; + ClutterActor *stage; + static ClutterActor *motion_last_actor = NULL; + + context = clutter_context_get_default (); + backend = context->backend; + stage = _clutter_backend_get_stage (backend); + + if (!stage) + return; + + CLUTTER_TIMESTAMP (EVENT, "Event received"); + + switch (event->type) + { + case CLUTTER_NOTHING: + break; + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + { + ClutterActor *actor = NULL; + + actor = event->crossing.source; + + while (actor) + { + if (clutter_actor_is_reactive (actor) || + clutter_actor_get_parent (actor) == NULL /* STAGE */ ) + { + CLUTTER_NOTE (EVENT, "forwarding event to reactive actor"); + if (clutter_actor_event (actor, event)) + break; + } + + actor = clutter_actor_get_parent (actor); + } + } + break; + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_DELETE: + if (clutter_stage_event (CLUTTER_STAGE (stage), event)) + clutter_main_quit (); + break; + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + { + ClutterActor *actor = NULL; + + actor = clutter_stage_get_key_focus (CLUTTER_STAGE(stage)); + + g_return_if_fail (actor != NULL); + + event->key.source = g_object_ref (actor); + + /* bubble up */ + do + { + if (clutter_actor_event (actor, event)) + break; + + actor = clutter_actor_get_parent (actor); + } + while (actor != NULL); + } + break; + case CLUTTER_MOTION: + if (context->motion_events_per_actor == FALSE) + { + /* Only stage gets motion events */ + event->motion.source = g_object_ref (stage); + clutter_actor_event (stage, event); + break; + } + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + case CLUTTER_SCROLL: + { + ClutterActor *actor; + gint x,y; + + clutter_event_get_coords (event, &x, &y); + + /* 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) + break; + + /* Map the event to a reactive actor */ + actor = _clutter_do_pick (CLUTTER_STAGE (stage), + x, y, + CLUTTER_PICK_REACTIVE); + + CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p", + x, y, actor); + + if (event->type == CLUTTER_SCROLL) + event->scroll.source = g_object_ref (actor); + else + event->button.source = g_object_ref (actor); + + /* Motion enter leave events */ + if (event->type == CLUTTER_MOTION) + { + if (motion_last_actor != actor) + { + if (motion_last_actor && actor) + { + ClutterEvent cev; + + cev.crossing.type = CLUTTER_LEAVE; + cev.crossing.time = 0; /* FIXME */ + cev.crossing.flags = 0; + cev.crossing.x = x; + cev.crossing.y = y; + cev.crossing.source = g_object_ref (motion_last_actor); + cev.crossing.related = g_object_ref (actor); + + clutter_event_put (&cev); /* copys */ + + cev.crossing.type = CLUTTER_ENTER; + cev.crossing.time = 0; /* FIXME */ + cev.crossing.flags = 0; + cev.crossing.x = x; + cev.crossing.y = y; + cev.crossing.source = g_object_ref (actor); + cev.crossing.related = g_object_ref (motion_last_actor); + + clutter_event_put (&cev); + } + } + motion_last_actor = actor; + } + else + event_click_count_generate (event); + + /* Send the event to the actor and all parents always the + * stage. + * + * FIXME: for an optimisation should check if there are + * actually any reactive actors and avoid the pick all togeather + * (signalling just the stage). Should be big help for gles. + * + * FIXME: Actors be able to stop emission. + */ + while (actor) + { + if (clutter_actor_is_reactive (actor) || + clutter_actor_get_parent (actor) == NULL /* STAGE */ ) + { + CLUTTER_NOTE (EVENT, "forwarding event to reactive actor"); + if (clutter_actor_event (actor, event)) + break; + } + + actor = clutter_actor_get_parent (actor); + } + } + break; + case CLUTTER_STAGE_STATE: + /* fullscreen / focus - forward to stage */ + clutter_stage_event (CLUTTER_STAGE (stage), event); + break; + case CLUTTER_CLIENT_MESSAGE: + break; + } +} + void clutter_base_init (void) { diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index dac00f222..d44b87004 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -117,10 +117,6 @@ void _clutter_backend_init_events (ClutterBackend *backend); ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend); -/* backend helpers */ -void _clutter_event_button_generate (ClutterBackend *backend, - ClutterEvent *event); - void _clutter_feature_init (void); ClutterActor *_clutter_do_pick (ClutterStage *stage, diff --git a/clutter/clutter-score.c b/clutter/clutter-score.c index 9e13e864a..af1b65aa5 100644 --- a/clutter/clutter-score.c +++ b/clutter/clutter-score.c @@ -94,7 +94,7 @@ enum LAST_SIGNAL }; -static int score_signals[LAST_SIGNAL] = { 0 }; +/* static int score_signals[LAST_SIGNAL] = { 0 }; */ static void start_entry (ClutterScoreEntry *entry); diff --git a/clutter/eglnative/clutter-event-egl.c b/clutter/eglnative/clutter-event-egl.c index d36bc673f..a8a9d7c24 100644 --- a/clutter/eglnative/clutter-event-egl.c +++ b/clutter/eglnative/clutter-event-egl.c @@ -235,8 +235,6 @@ clutter_event_dispatch (GSource *source, clicked = FALSE; } - _clutter_event_button_generate (backend, event); - g_queue_push_head (clutter_context->events_queue, event); } diff --git a/clutter/eglx/clutter-event-egl.c b/clutter/eglx/clutter-event-egl.c index 59843cfa4..52757c034 100644 --- a/clutter/eglx/clutter-event-egl.c +++ b/clutter/eglx/clutter-event-egl.c @@ -246,7 +246,6 @@ clutter_event_translate (ClutterBackend *backend, event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; - _clutter_event_button_generate (backend, event); break; } diff --git a/clutter/glx/clutter-event-glx.c b/clutter/glx/clutter-event-glx.c index 0941af0ca..1df599496 100644 --- a/clutter/glx/clutter-event-glx.c +++ b/clutter/glx/clutter-event-glx.c @@ -550,7 +550,6 @@ event_translate (ClutterBackend *backend, event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; - _clutter_event_button_generate (backend, event); break; } diff --git a/clutter/sdl/clutter-event-sdl.c b/clutter/sdl/clutter-event-sdl.c index f9c05e694..431cfe996 100644 --- a/clutter/sdl/clutter-event-sdl.c +++ b/clutter/sdl/clutter-event-sdl.c @@ -257,7 +257,6 @@ event_translate (ClutterBackend *backend, event->button.y = sdl_event->button.y; event->button.modifier_state = sdl_event->button.state; event->button.button = sdl_event->button.button; - _clutter_event_button_generate (backend, event); break; } break; diff --git a/tests/test-behave.c b/tests/test-behave.c index 1b0ab9011..2b499010b 100644 --- a/tests/test-behave.c +++ b/tests/test-behave.c @@ -13,12 +13,12 @@ button_press_cb (ClutterStage *stage, { const gchar *click_type; - switch (event->type) + switch (event->click_count) { - case CLUTTER_2BUTTON_PRESS: + case 2: click_type = "double"; break; - case CLUTTER_3BUTTON_PRESS: + case 3: click_type = "triple"; break; default: diff --git a/tests/test-events.c b/tests/test-events.c index 7886af553..13c232a88 100644 --- a/tests/test-events.c +++ b/tests/test-events.c @@ -1,6 +1,6 @@ #include -gboolean IsFullScreen = FALSE; +gboolean IsFullScreen = FALSE, IsMotion = FALSE; static void stage_state_cb (ClutterStage *stage, @@ -30,6 +30,20 @@ blue_button_cb (ClutterActor *actor, return FALSE; } +static gboolean +red_button_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + + if (IsMotion) + IsMotion = FALSE; + else + IsMotion = TRUE; + + clutter_enable_motion_events (IsMotion); +} + static void key_focus_in_cb (ClutterActor *actor, gpointer data) @@ -79,14 +93,15 @@ input_cb (ClutterActor *actor, case CLUTTER_MOTION: printf("[%s] MOTION", source); break; + case CLUTTER_ENTER: + printf("[%s] ENTER", source); + break; + case CLUTTER_LEAVE: + printf("[%s] LEAVE", source); + break; case CLUTTER_BUTTON_PRESS: - printf("[%s] BUTTON PRESS", source); - break; - case CLUTTER_2BUTTON_PRESS: - printf("[%s] BUTTON 2 PRESS", source); - break; - case CLUTTER_3BUTTON_PRESS: - printf("[%s] BUTTON 3 PRESS", source); + printf("[%s] BUTTON PRESS (click count:%i)", + source, event->button.click_count); break; case CLUTTER_BUTTON_RELEASE: printf("[%s] BUTTON RELEASE", source); @@ -133,6 +148,8 @@ main (int argc, char *argv[]) clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage"); g_signal_connect (stage, "fullscreen", @@ -159,6 +176,9 @@ main (int argc, char *argv[]) g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb), focus_box); + /* Toggle motion - enter/leave capture */ + g_signal_connect (actor, "button-press-event", G_CALLBACK (red_button_cb), NULL); + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor); actor = clutter_rectangle_new_with_color (&gcol); @@ -184,6 +204,7 @@ main (int argc, char *argv[]) g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box"); g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb), focus_box); + /* Fullscreen */ g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL); actor = clutter_rectangle_new_with_color (&ncol);