mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
2007-10-10 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c: * clutter/clutter-actor.h: * clutter/clutter-event.c: * clutter/clutter-main.c: * tests/test-events.c: Add basic W3 DOM event 'capture' like functionality.
This commit is contained in:
parent
a4b7abd18e
commit
6216ce659c
@ -1,3 +1,12 @@
|
||||
2007-10-10 Matthew Allum <mallum@openedhand.com>
|
||||
|
||||
* clutter/clutter-actor.c:
|
||||
* clutter/clutter-actor.h:
|
||||
* clutter/clutter-event.c:
|
||||
* clutter/clutter-main.c:
|
||||
* tests/test-events.c:
|
||||
Add basic W3 DOM event 'capture' like functionality.
|
||||
|
||||
2007-10-10 Emmanuele Bassi <ebassi@openedhand.com>
|
||||
|
||||
* clutter/clutter-script-private.h:
|
||||
|
@ -106,6 +106,7 @@ enum
|
||||
PARENT_SET,
|
||||
|
||||
EVENT,
|
||||
EVENT_CAPTURED,
|
||||
EVENT_AFTER,
|
||||
BUTTON_PRESS_EVENT,
|
||||
BUTTON_RELEASE_EVENT,
|
||||
@ -117,7 +118,6 @@ enum
|
||||
FOCUS_OUT,
|
||||
ENTER_EVENT,
|
||||
LEAVE_EVENT,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -1469,9 +1469,10 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterActorClass, enter),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
_clutter_boolean_handled_accumulator, NULL,
|
||||
clutter_marshal_BOOLEAN__BOXED,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
/**
|
||||
* ClutterActor::leave:
|
||||
@ -1486,10 +1487,28 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterActorClass, leave),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
_clutter_boolean_handled_accumulator, NULL,
|
||||
clutter_marshal_BOOLEAN__BOXED,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
/**
|
||||
* ClutterActor::captured-event:
|
||||
* @actor: the actor which the pointer has left
|
||||
*
|
||||
* The ::leave signal is emitted when the pointer leaves the @actor.
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
actor_signals[EVENT_CAPTURED] =
|
||||
g_signal_new ("captured-event",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterActorClass, captured),
|
||||
_clutter_boolean_handled_accumulator, NULL,
|
||||
clutter_marshal_BOOLEAN__BOXED,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
klass->show = clutter_actor_real_show;
|
||||
klass->show_all = clutter_actor_show;
|
||||
@ -2977,6 +2996,7 @@ clutter_actor_lower_bottom (ClutterActor *self)
|
||||
* clutter_actor_event:
|
||||
* @actor: a #ClutterActor
|
||||
* @event: a #ClutterEvent
|
||||
* @capture: TRUE if event in in capture phase, FALSE otherwise.
|
||||
*
|
||||
* This function is used to emit an event on the main stage.
|
||||
* You should rarely need to use this function, except for
|
||||
@ -2988,7 +3008,8 @@ clutter_actor_lower_bottom (ClutterActor *self)
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_event (ClutterActor *actor,
|
||||
ClutterEvent *event)
|
||||
ClutterEvent *event,
|
||||
gboolean capture)
|
||||
{
|
||||
gboolean retval = TRUE;
|
||||
gint signal_num = -1;
|
||||
@ -2998,6 +3019,13 @@ clutter_actor_event (ClutterActor *actor,
|
||||
|
||||
g_object_ref (actor);
|
||||
|
||||
if (capture)
|
||||
{
|
||||
g_signal_emit (actor, actor_signals[EVENT_CAPTURED], 0,
|
||||
event, &retval);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_signal_emit (actor, actor_signals[EVENT], 0, event, &retval);
|
||||
|
||||
if (!retval)
|
||||
@ -3037,12 +3065,18 @@ clutter_actor_event (ClutterActor *actor,
|
||||
signal_num = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (signal_num != -1)
|
||||
g_signal_emit (actor, actor_signals[signal_num], 0, event, &retval);
|
||||
g_signal_emit (actor, actor_signals[signal_num], 0,
|
||||
event, &retval);
|
||||
}
|
||||
|
||||
|
||||
if (!retval)
|
||||
g_signal_emit (actor, actor_signals[EVENT_AFTER], 0, event);
|
||||
|
||||
out:
|
||||
|
||||
g_object_unref (actor);
|
||||
|
||||
return retval;
|
||||
|
@ -211,6 +211,8 @@ struct _ClutterActorClass
|
||||
ClutterCrossingEvent *event);
|
||||
void (* leave) (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event);
|
||||
void (* captured) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
void (* focus_in) (ClutterActor *actor);
|
||||
void (* focus_out) (ClutterActor *actor);
|
||||
|
||||
@ -367,7 +369,8 @@ void clutter_actor_apply_transform_to_point (ClutterActor
|
||||
/* Per actor event handling - may change */
|
||||
gboolean
|
||||
clutter_actor_event (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
ClutterEvent *event,
|
||||
gboolean capture);
|
||||
void
|
||||
clutter_actor_set_reactive (ClutterActor *actor);
|
||||
|
||||
|
@ -379,10 +379,8 @@ clutter_event_free (ClutterEvent *event)
|
||||
if (G_LIKELY (event))
|
||||
{
|
||||
ClutterActor *source = NULL;
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (source)
|
||||
g_object_unref (source);
|
||||
if (event->type == CLUTTER_LEAVE || event->type == CLUTTER_ENTER)
|
||||
g_object_unref (event->crossing.related);
|
||||
g_slice_free (ClutterEvent, event);
|
||||
}
|
||||
}
|
||||
|
@ -1133,6 +1133,56 @@ event_click_count_generate (ClutterEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
deliver_event (ClutterEvent *event, ClutterActor *source)
|
||||
{
|
||||
#define MAX_EVENT_DEPTH 512
|
||||
|
||||
static ClutterActor **event_tree = NULL;
|
||||
static gboolean lock = FALSE;
|
||||
|
||||
ClutterActor *actor;
|
||||
gint i = 0, n_tree_events = 0;
|
||||
|
||||
g_return_if_fail (source != NULL);
|
||||
g_return_if_fail (lock == FALSE);
|
||||
|
||||
lock = TRUE; /* Guard against reentrancy */
|
||||
|
||||
/* Sorry Mr Bassi. */
|
||||
if (event_tree == NULL)
|
||||
event_tree = g_new0(ClutterActor*, MAX_EVENT_DEPTH);
|
||||
|
||||
actor = source;
|
||||
|
||||
/* Build 'tree' of events */
|
||||
while (actor && n_tree_events < MAX_EVENT_DEPTH)
|
||||
{
|
||||
if (clutter_actor_is_reactive (actor) ||
|
||||
clutter_actor_get_parent (actor) == NULL)
|
||||
event_tree[n_tree_events++] = g_object_ref (actor);
|
||||
|
||||
actor = clutter_actor_get_parent (actor);
|
||||
}
|
||||
|
||||
/* Capture */
|
||||
for (i=n_tree_events-1; i >= 0; i--)
|
||||
if (clutter_actor_event (event_tree[i], event, TRUE))
|
||||
goto done;
|
||||
|
||||
/* Bubble */
|
||||
for (i=0; i < n_tree_events; i++)
|
||||
if (clutter_actor_event (event_tree[i], event, FALSE))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
|
||||
for (i=0; i < n_tree_events; i++)
|
||||
g_object_unref (event_tree[i]);
|
||||
|
||||
lock = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_do_event
|
||||
* @event: a #ClutterEvent.
|
||||
@ -1151,6 +1201,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
ClutterMainContext *context;
|
||||
ClutterBackend *backend;
|
||||
ClutterActor *stage;
|
||||
|
||||
static ClutterActor *motion_last_actor = NULL;
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
@ -1175,18 +1226,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
|
||||
g_return_if_fail (actor != NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
deliver_event (event, actor);
|
||||
}
|
||||
break;
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
@ -1203,25 +1243,16 @@ clutter_do_event (ClutterEvent *event)
|
||||
|
||||
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);
|
||||
event->key.source = actor;
|
||||
deliver_event (event, actor);
|
||||
}
|
||||
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);
|
||||
event->motion.source = stage;
|
||||
clutter_actor_event (stage, event, FALSE);
|
||||
break;
|
||||
}
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
@ -1246,15 +1277,20 @@ clutter_do_event (ClutterEvent *event)
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p",
|
||||
x, y, actor);
|
||||
|
||||
g_return_if_fail (actor != NULL);
|
||||
|
||||
if (event->type == CLUTTER_SCROLL)
|
||||
event->scroll.source = g_object_ref (actor);
|
||||
event->scroll.source = actor;
|
||||
else
|
||||
event->button.source = g_object_ref (actor);
|
||||
event->button.source = actor;
|
||||
|
||||
/* Motion enter leave events */
|
||||
if (event->type == CLUTTER_MOTION)
|
||||
@ -1270,7 +1306,8 @@ clutter_do_event (ClutterEvent *event)
|
||||
cev.crossing.flags = 0;
|
||||
cev.crossing.x = x;
|
||||
cev.crossing.y = y;
|
||||
cev.crossing.source = g_object_ref (motion_last_actor);
|
||||
cev.crossing.source = motion_last_actor;
|
||||
/* unref in free */
|
||||
cev.crossing.related = g_object_ref (actor);
|
||||
|
||||
clutter_event_put (&cev); /* copys */
|
||||
@ -1280,7 +1317,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
cev.crossing.flags = 0;
|
||||
cev.crossing.x = x;
|
||||
cev.crossing.y = y;
|
||||
cev.crossing.source = g_object_ref (actor);
|
||||
cev.crossing.source = actor;
|
||||
cev.crossing.related = g_object_ref (motion_last_actor);
|
||||
|
||||
clutter_event_put (&cev);
|
||||
@ -1291,27 +1328,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
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);
|
||||
}
|
||||
deliver_event (event, actor);
|
||||
}
|
||||
break;
|
||||
case CLUTTER_STAGE_STATE:
|
||||
|
@ -828,7 +828,7 @@ clutter_stage_event (ClutterStage *stage,
|
||||
return FALSE;
|
||||
|
||||
/* emit raw event */
|
||||
if (clutter_actor_event (CLUTTER_ACTOR (stage), event))
|
||||
if (clutter_actor_event (CLUTTER_ACTOR (stage), event, FALSE))
|
||||
return TRUE;
|
||||
|
||||
if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN)
|
||||
|
@ -42,6 +42,18 @@ red_button_cb (ClutterActor *actor,
|
||||
IsMotion = TRUE;
|
||||
|
||||
clutter_enable_motion_events (IsMotion);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
capture_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
printf("captured event for type '%s'\n", G_OBJECT_TYPE_NAME(actor));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -152,6 +164,7 @@ main (int argc, char *argv[])
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
||||
|
||||
g_signal_connect (stage, "fullscreen",
|
||||
G_CALLBACK (stage_state_cb), "fullscreen");
|
||||
g_signal_connect (stage, "unfullscreen",
|
||||
@ -161,6 +174,8 @@ main (int argc, char *argv[])
|
||||
g_signal_connect (stage, "deactivate",
|
||||
G_CALLBACK (stage_state_cb), "deactivate");
|
||||
|
||||
g_signal_connect (stage, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||
|
||||
focus_box = clutter_rectangle_new_with_color (&ncol);
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||
|
||||
@ -193,6 +208,8 @@ main (int argc, char *argv[])
|
||||
g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&bcol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 400, 100);
|
||||
|
Loading…
Reference in New Issue
Block a user