* clutter/clutter-main.[ch]: added clutter_grab_pointer,

clutter_ungrab_pointer and clutter_get_pointer_grab, in
clutter_do_event deliver pointer related events only to the
actor with the pointer grab if a grab exists.
* clutter/clutter-private.h: added pointer_grab_actor to context.
* tests/Makefile.am:
* tests/test-grab.c: added test for testing the pointer grab.
This commit is contained in:
Øyvind Kolås
2007-11-15 17:08:48 +00:00
parent 0d082df3a5
commit 53ec33f34c
6 changed files with 360 additions and 13 deletions

View File

@ -1240,9 +1240,14 @@ clutter_do_event (ClutterEvent *event)
break;
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
{
deliver_event (event);
}
if (context->pointer_grab_actor != NULL)
{
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
return;
}
deliver_event (event);
break;
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_DELETE:
@ -1269,6 +1274,12 @@ clutter_do_event (ClutterEvent *event)
/* Only stage gets motion events */
event->any.source = stage;
if (context->pointer_grab_actor != NULL)
{
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
return;
}
/* Trigger handlers on stage in both capture .. */
if (!clutter_actor_event (stage, event, TRUE))
{
@ -1288,14 +1299,24 @@ clutter_do_event (ClutterEvent *event)
clutter_event_get_coords (event, &x, &y);
/* Handle release off stage */
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))
{
if (event->type == CLUTTER_BUTTON_RELEASE)
{
CLUTTER_NOTE (EVENT, "Release off stage received at %i, %i", x, y);
event->button.source = stage;
if (context->pointer_grab_actor != NULL)
{
clutter_actor_event (context->pointer_grab_actor,
event, FALSE);
return;
}
deliver_event (event);
}
break;
@ -1305,6 +1326,9 @@ clutter_do_event (ClutterEvent *event)
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
x, y,
CLUTTER_PICK_REACTIVE);
event->any.source = actor;
if (!actor)
break;
@ -1316,7 +1340,6 @@ clutter_do_event (ClutterEvent *event)
CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p",
x, y, actor);
event->any.source = actor;
/* Motion enter leave events */
if (event->type == CLUTTER_MOTION)
@ -1355,7 +1378,13 @@ clutter_do_event (ClutterEvent *event)
}
else
event_click_count_generate (event);
if (context->pointer_grab_actor != NULL)
{
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
return;
}
deliver_event (event);
}
break;
@ -1429,3 +1458,88 @@ clutter_set_default_frame_rate (guint frames_per_sec)
if (context->frame_rate != frames_per_sec)
context->frame_rate = frames_per_sec;
}
static void
on_pointer_grab_weak_notify (gpointer data,
GObject *where_the_object_was)
{
ClutterMainContext *context;
context = clutter_context_get_default ();
context->pointer_grab_actor = NULL;
clutter_ungrab_pointer ();
}
/**
* clutter_grab_pointer:
* @actor: a #ClutterActor
*
* Grabs pointer events, after the grab is done all pointer related events
* (press, motion, release, enter, leave and scroll) are delivered to this
* actor directly. The source set in the event will be the actor that would
* have received the event if the pointer grab was not in effect.
*
* Since: 0.6
*/
void
clutter_grab_pointer (ClutterActor *actor)
{
ClutterMainContext *context;
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
context = clutter_context_get_default ();
if (context->pointer_grab_actor == actor)
return;
if (context->pointer_grab_actor)
{
g_object_weak_unref (G_OBJECT (context->pointer_grab_actor),
on_pointer_grab_weak_notify,
NULL);
context->pointer_grab_actor = NULL;
}
if (actor)
{
context->pointer_grab_actor = actor;
g_object_weak_ref (G_OBJECT (actor),
on_pointer_grab_weak_notify,
NULL);
}
}
/**
* clutter_ungrab_pointer:
*
* Removes an existing grab of the pointer.
*
* Since: 0.6
*/
void
clutter_ungrab_pointer (void)
{
clutter_grab_pointer (NULL);
}
/**
* clutter_get_pointer_grab:
*
* Queries the current pointer grab of clutter.
*
* Return value: the actor currently holding the pointer grab, or NULL if there is no grab.
*
* Since: 0.6
*/
ClutterActor *
clutter_get_pointer_grab (void)
{
ClutterMainContext *context;
context = clutter_context_get_default ();
return context->pointer_grab_actor;
}