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

clutter_ungrab_keyboard and clutter_get_keyboard_grab, in
clutter_do_event deliver keyboard related events only to the
actor with the keyboard grab if a grab exists.
* clutter/clutter-private.h: added keyboard_grab_actor to context.
* tests/test-grab.c: added testing for testing the keyboard grab.
This commit is contained in:
Øyvind Kolås 2007-11-15 18:00:24 +00:00
parent c640b05182
commit 3b4f603368
5 changed files with 132 additions and 6 deletions

View File

@ -1,3 +1,12 @@
2007-11-15 Øyvind Kolås <pippin@o-hand.com>
* clutter/clutter-main.[ch]: added clutter_grab_keyboard,
clutter_ungrab_keyboard and clutter_get_keyboard_grab, in
clutter_do_event deliver keyboard related events only to the
actor with the keyboard grab if a grab exists.
* clutter/clutter-private.h: added keyboard_grab_actor to context.
* tests/test-grab.c: added testing for testing the keyboard grab.
2007-11-15 Emmanuele Bassi <ebassi@openedhand.com> 2007-11-15 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-texture.c: * clutter/clutter-texture.c:

View File

@ -1285,7 +1285,6 @@ clutter_do_event (ClutterEvent *event)
clutter_actor_event (context->pointer_grab_actor, event, FALSE); clutter_actor_event (context->pointer_grab_actor, event, FALSE);
return; return;
} }
deliver_event (event); deliver_event (event);
break; break;
case CLUTTER_DESTROY_NOTIFY: case CLUTTER_DESTROY_NOTIFY:
@ -1304,6 +1303,11 @@ clutter_do_event (ClutterEvent *event)
g_return_if_fail (actor != NULL); g_return_if_fail (actor != NULL);
if (context->keyboard_grab_actor != NULL)
{
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
return;
}
deliver_event (event); deliver_event (event);
} }
break; break;
@ -1355,7 +1359,6 @@ clutter_do_event (ClutterEvent *event)
event, FALSE); event, FALSE);
return; return;
} }
deliver_event (event); deliver_event (event);
} }
break; break;
@ -1557,3 +1560,88 @@ clutter_get_pointer_grab (void)
return context->pointer_grab_actor; return context->pointer_grab_actor;
} }
static void
on_keyboard_grab_weak_notify (gpointer data,
GObject *where_the_object_was)
{
ClutterMainContext *context;
context = clutter_context_get_default ();
context->keyboard_grab_actor = NULL;
clutter_ungrab_keyboard ();
}
/**
* clutter_grab_keyboard:
* @actor: a #ClutterActor
*
* Grabs keyboard events, after the grab is done keyboard events ("key-press-event"
* and "key-release-event") are delivered to this actor directly. The source
* set in the event will be the actor that would have received the event if the
* keyboard grab was not in effect.
*
* Since: 0.6
*/
void
clutter_grab_keyboard (ClutterActor *actor)
{
ClutterMainContext *context;
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
context = clutter_context_get_default ();
if (context->keyboard_grab_actor == actor)
return;
if (context->keyboard_grab_actor)
{
g_object_weak_unref (G_OBJECT (context->keyboard_grab_actor),
on_keyboard_grab_weak_notify,
NULL);
context->keyboard_grab_actor = NULL;
}
if (actor)
{
context->keyboard_grab_actor = actor;
g_object_weak_ref (G_OBJECT (actor),
on_keyboard_grab_weak_notify,
NULL);
}
}
/**
* clutter_ungrab_keyboard:
*
* Removes an existing grab of the keyboard.
*
* Since: 0.6
*/
void
clutter_ungrab_keyboard (void)
{
clutter_grab_keyboard (NULL);
}
/**
* clutter_get_keyboard_grab:
*
* Queries the current keyboard grab of clutter.
*
* Return value: the actor currently holding the keyboard grab, or NULL if there is no grab.
*
* Since: 0.6
*/
ClutterActor *
clutter_get_keyboard_grab (void)
{
ClutterMainContext *context;
context = clutter_context_get_default ();
return context->keyboard_grab_actor;
}

View File

@ -111,6 +111,10 @@ void clutter_grab_pointer (ClutterActor *actor);
void clutter_ungrab_pointer (void); void clutter_ungrab_pointer (void);
ClutterActor * clutter_get_pointer_grab (void); ClutterActor * clutter_get_pointer_grab (void);
void clutter_grab_keyboard (ClutterActor *actor);
void clutter_ungrab_keyboard (void);
ClutterActor * clutter_get_keyboard_grab (void);
G_END_DECLS G_END_DECLS
#endif /* _HAVE_CLUTTER_MAIN_H */ #endif /* _HAVE_CLUTTER_MAIN_H */

View File

@ -89,6 +89,9 @@ struct _ClutterMainContext
ClutterActor *pointer_grab_actor; /* The actor having the pointer grab ClutterActor *pointer_grab_actor; /* The actor having the pointer grab
(or NULL if there is no pointer grab) (or NULL if there is no pointer grab)
*/ */
ClutterActor *keyboard_grab_actor; /* The actor having the pointer grab
(or NULL if there is no pointer grab)
*/
}; };
#define CLUTTER_CONTEXT() (clutter_context_get_default ()) #define CLUTTER_CONTEXT() (clutter_context_get_default ())

View File

@ -47,10 +47,6 @@ debug_event_cb (ClutterActor *actor,
break; break;
case CLUTTER_BUTTON_RELEASE: case CLUTTER_BUTTON_RELEASE:
printf("[%s] BUTTON RELEASE", source); printf("[%s] BUTTON RELEASE", source);
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; break;
case CLUTTER_SCROLL: case CLUTTER_SCROLL:
printf("[%s] BUTTON SCROLL", source); printf("[%s] BUTTON SCROLL", source);
@ -133,6 +129,19 @@ toggle_grab_pointer_cb (ClutterActor *actor,
return FALSE; return FALSE;
} }
static gboolean
cyan_press_cb (ClutterActor *actor,
ClutterEvent *event,
gpointer data)
{
if (clutter_get_keyboard_grab () != NULL)
clutter_ungrab_keyboard ();
else
clutter_grab_keyboard (actor);
return FALSE;
}
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
@ -141,6 +150,7 @@ main (int argc, char *argv[])
ClutterColor rcol = { 0xff, 0, 0, 0xff}, ClutterColor rcol = { 0xff, 0, 0, 0xff},
bcol = { 0, 0, 0xff, 0xff }, bcol = { 0, 0, 0xff, 0xff },
gcol = { 0, 0xff, 0, 0xff }, gcol = { 0, 0xff, 0, 0xff },
ccol = { 0, 0xff, 0xff, 0xff },
ycol = { 0xff, 0xff, 0, 0xff }, ycol = { 0xff, 0xff, 0, 0xff },
ncol = { 0, 0, 0, 0xff }; ncol = { 0, 0, 0, 0xff };
@ -150,6 +160,7 @@ main (int argc, char *argv[])
g_print ("Blue box: aquire grab on press, destroys the blue box actor on release\n"); g_print ("Blue box: aquire grab on press, destroys the blue box actor on release\n");
g_print ("Yellow box: aquire grab on press, releases grab on next press on yellow box\n"); g_print ("Yellow box: aquire grab on press, releases grab on next press on yellow box\n");
g_print ("Green box: toggle per actor motion events.\n\n"); g_print ("Green box: toggle per actor motion events.\n\n");
g_print ("Cyan box: toggle grab (from cyan box) for keyboard events.\n\n");
stage = clutter_stage_get_default (); stage = clutter_stage_get_default ();
g_signal_connect (stage, "event", G_CALLBACK (debug_event_cb), "stage"); g_signal_connect (stage, "event", G_CALLBACK (debug_event_cb), "stage");
@ -205,6 +216,17 @@ main (int argc, char *argv[])
g_signal_connect (actor, "button-press-event", g_signal_connect (actor, "button-press-event",
G_CALLBACK (green_press_cb), NULL); G_CALLBACK (green_press_cb), NULL);
actor = clutter_rectangle_new_with_color (&ccol);
clutter_actor_set_size (actor, 100, 100);
clutter_actor_set_position (actor, 500, 100);
clutter_actor_set_reactive (actor);
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
g_signal_connect (actor, "event",
G_CALLBACK (debug_event_cb), "cyan box");
g_signal_connect (actor, "button-press-event",
G_CALLBACK (cyan_press_cb), NULL);
clutter_actor_show_all (CLUTTER_ACTOR (stage)); clutter_actor_show_all (CLUTTER_ACTOR (stage));
clutter_main(); clutter_main();