* clutter/clutter-main.[ch]: added clutter_grab_keyboard,
authorØyvind Kolås <pippin@openedhand.com>
Thu, 15 Nov 2007 18:00:24 +0000 (18:00 +0000)
committerØyvind Kolås <pippin@openedhand.com>
Thu, 15 Nov 2007 18:00:24 +0000 (18:00 +0000)
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.

ChangeLog
clutter/clutter-main.c
clutter/clutter-main.h
clutter/clutter-private.h
tests/test-grab.c

index cb4b428..dee8698 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * clutter/clutter-texture.c:
index d63b59c..e9f0db6 100644 (file)
@@ -1285,7 +1285,6 @@ clutter_do_event (ClutterEvent *event)
           clutter_actor_event (context->pointer_grab_actor, event, FALSE);
           return;
         }
-
       deliver_event (event);
       break;
     case CLUTTER_DESTROY_NOTIFY:
@@ -1304,6 +1303,11 @@ clutter_do_event (ClutterEvent *event)
 
        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);
       }
       break;
@@ -1355,7 +1359,6 @@ clutter_do_event (ClutterEvent *event)
                                          event, FALSE);
                     return;
                   }
-
                deliver_event (event);
               }
             break;
@@ -1557,3 +1560,88 @@ clutter_get_pointer_grab (void)
 
   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;
+}
index abb70d9..a620441 100644 (file)
@@ -111,6 +111,10 @@ void             clutter_grab_pointer               (ClutterActor *actor);
 void             clutter_ungrab_pointer             (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
 
 #endif /* _HAVE_CLUTTER_MAIN_H */
index d69208a..16048da 100644 (file)
@@ -89,6 +89,9 @@ struct _ClutterMainContext
   ClutterActor    *pointer_grab_actor; /* The actor having the 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 ())
index 9c5210e..924df0b 100644 (file)
@@ -47,10 +47,6 @@ debug_event_cb (ClutterActor *actor,
       break;
     case CLUTTER_BUTTON_RELEASE:
       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;
     case CLUTTER_SCROLL:
       printf("[%s] BUTTON SCROLL", source);
@@ -133,6 +129,19 @@ toggle_grab_pointer_cb (ClutterActor    *actor,
   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
 main (int argc, char *argv[])
@@ -141,6 +150,7 @@ main (int argc, char *argv[])
   ClutterColor    rcol = { 0xff, 0, 0, 0xff}, 
                   bcol = { 0, 0, 0xff, 0xff },
                  gcol = { 0, 0xff, 0, 0xff },
+                 ccol = { 0, 0xff, 0xff, 0xff },
                  ycol = { 0xff, 0xff, 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 ("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 ("Cyan  box:  toggle grab (from cyan box) for keyboard events.\n\n");
 
   stage = clutter_stage_get_default ();
   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_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_main();