The base ClutterActor has several signals that are emitted when the user interacts with the actor:
button-press-event: Emitted when the user presses the mouse over the actor.
button-release-event: Emitted when the user releases the mouse over the actor.
motion-event: Emitted when the user moves the mouse over the actor.
enter-event: Emitted when the user moves the mouse in to the actor's area.
leave-event: Emitted when the user moves the mouse out of the actor's area.
For instance, you can detect button clicks on an actor like so:
g_signal_connect (rect, "button-press-event", G_CALLBACK (on_rect_button_press), NULL);
Alternatively, you might just handle signals from the parent ClutterStage and use
clutter_stage_get_actor_at_pos to discover which actor should be affected.
However, as a performance optimization, Clutter does not emit all event signals by default. For instance, to
receive event signals for an actor instead of just the stage, you must call clutter_actor_set_reactive().
If you don't need the motion event signals (motion-event, enter-event and leave-event),
you may call the global clutter_set_motion_events_enabled() function with FALSE to further optimize performance.
Your event signal handler should return true when it has fully handled the event, or false if you want the event to be sent also
to the next actor in the event chain. Clutter first allows the stage to handle each event via the captured-event signal. But if the stage does not handle the
event then it will be passed down to the child actor, first passing through the actor's parent containers, giving each actor in the hierarchy a chance to handle the event via a
captured-event signal handler.
If the event has still not been handled fully by any actor then the event will then be emitted via a specific signal (such as button-press-event or
key-press-event. These specific signals are emitted first from the child actor, then by its parent, passing all they way back up to the stage if no signal handler
returns true to indicate that it has handled the event fully.
Actors usually only receive keyboard events when the actor has key focus, but you can give an actor exclusive access to any events by grabbing either the pointer or
the keyboard, using clutter_grab_pointer or clutter_grab_keyboard.
The following example demonstrates handing of clicks on an actor:
File: main.c
#include <clutter/clutter.h>
#include <stdlib.h>
static gboolean
on_stage_button_press (ClutterStage *stage, ClutterEvent *event, gpointer data)
{
gfloat x = 0;
gfloat y = 0;
clutter_event_get_coords (event, &x, &y);
g_print ("Clicked stage at (%f, %f)\n", x, y);
/* Discover whether there is an actor at that position.
* Note that you can also connect directly to the actor's signals instead.
*/
ClutterActor *rect = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, x, y);
if (!rect)
return FALSE;
if (CLUTTER_IS_RECTANGLE (rect))
g_print (" A rectangle is at that position.\n");
return TRUE; /* Stop further handling of this event. */
}
static gboolean
on_rect_button_press (ClutterRectangle *rect, ClutterEvent *event, gpointer data)
{
gfloat x = 0;
gfloat y = 0;
clutter_event_get_coords (event, &x, &y);
g_print ("Clicked rectangle at (%f, %f)\n", x, y);
/* clutter_main_quit(); */
return TRUE; /* Stop further handling of this event. */
}
static gboolean
on_rect_button_release (ClutterRectangle *rect, ClutterEvent *event, gpointer data)
{
gfloat x = 0;
gfloat y = 0;
clutter_event_get_coords (event, &x, &y);
g_print ("Click-release on rectangle at (%f, %f)\n", x, y);
return TRUE; /* Stop further handling of this event. */
}
static gboolean
on_rect_motion (ClutterRectangle *rect, ClutterEvent *event, gpointer data)
{
g_print ("Motion in the rectangle.\n");
return TRUE; /* Stop further handling of this event. */
}
static gboolean
on_rect_enter (ClutterRectangle *rect, ClutterEvent *event, gpointer data)
{
g_print ("Entered rectangle.\n");
return TRUE; /* Stop further handling of this event. */
}
static gboolean
on_rect_leave (ClutterRectangle *rect, ClutterEvent *event, gpointer data)
{
g_print ("Left rectangle.\n");
return TRUE; /* Stop further handling of this event. */
}
int main(int argc, char *argv[])
{
ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
ClutterColor label_color = { 0xff, 0xff, 0xff, 0x99 };
clutter_init (&argc, &argv);
/* Get the stage and set its size and color: */
ClutterActor *stage = clutter_stage_get_default ();
clutter_actor_set_size (stage, 200, 200);
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
/* Connect signal handlers to handle mouse clicks on the stage: */
g_signal_connect (stage, "button-press-event",
G_CALLBACK (on_stage_button_press), NULL);
/* Add a Rectangle to the stage: */
ClutterActor *rect = clutter_rectangle_new_with_color (&label_color);
clutter_actor_set_size (rect, 100, 100);
clutter_actor_set_position (rect, 50, 50);
clutter_actor_show (rect);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
/* Allow the actor to emit events.
* By default only the stage does this.
*/
clutter_actor_set_reactive (rect, TRUE);
/* Connect signal handlers for events: */
g_signal_connect (rect, "button-press-event",
G_CALLBACK (on_rect_button_press), NULL);
g_signal_connect (rect, "button-release-event",
G_CALLBACK (on_rect_button_release), NULL);
g_signal_connect (rect, "motion-event",
G_CALLBACK (on_rect_motion), NULL);
g_signal_connect (rect, "enter-event",
G_CALLBACK (on_rect_enter), NULL);
g_signal_connect (rect, "leave-event",
G_CALLBACK (on_rect_leave), NULL);
/* Show the stage: */
clutter_actor_show (stage);
/* Start the main loop, so we can respond to events: */
clutter_main ();
return EXIT_SUCCESS;
}