[clutter] Clean up grab implementation
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter] Clean up grab implementation
- Date: Tue, 11 Oct 2011 16:55:51 +0000 (UTC)
commit b6dd306998e626cbc86051dc1237894d515aa3dd
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon Oct 10 16:45:20 2011 +0100
Clean up grab implementation
The grab API is a relic of Clutter 0.6, and hasn't been through proper
vetting in a *long* time â mostly due to the fact that we don't really
like grabs, and point to the ::captured-event as a way to implement
"soft grabs" in toolkits and applications.
The implementation of full and device grabs uses weak references on
actors instead of using the ::destroy signal, which is meant exactly for
the case of releasing pointers to actors when they are disposed.
The API naming scheme is also fairly broken, especially for
device-related grabs.
Finally, keyboard device grabs are just not implemented.
We can, in one go, clean up this mess and deprecate a bunch of badly
named API by introducing generic device grab/ungrab methods on
ClutterInputDevice, and re-implement the current API on top of them.
clutter/clutter-device-manager-private.h | 1 +
clutter/clutter-input-device.h | 5 +
clutter/clutter-main.c | 268 ++++++++++++++++++++++-------
clutter/clutter-main.h | 10 +-
4 files changed, 215 insertions(+), 69 deletions(-)
---
diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h
index 223cdde..4ae5940 100644
--- a/clutter/clutter-device-manager-private.h
+++ b/clutter/clutter-device-manager-private.h
@@ -75,6 +75,7 @@ struct _ClutterInputDevice
/* the actor that has a grab in place for the device */
ClutterActor *pointer_grab_actor;
+ ClutterActor *keyboard_grab_actor;
/* the current click count */
gint click_count;
diff --git a/clutter/clutter-input-device.h b/clutter/clutter-input-device.h
index 7b3a75b..0128920 100644
--- a/clutter/clutter-input-device.h
+++ b/clutter/clutter-input-device.h
@@ -167,6 +167,11 @@ void clutter_input_device_update_from_event (ClutterInputDev
ClutterEvent *event,
gboolean update_stage);
+void clutter_input_device_grab (ClutterInputDevice *device,
+ ClutterActor *actor);
+void clutter_input_device_ungrab (ClutterInputDevice *device);
+ClutterActor * clutter_input_device_get_grabbed_actor (ClutterInputDevice *device);
+
G_END_DECLS
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c
index 7ef9edb..f6f5806 100644
--- a/clutter/clutter-main.c
+++ b/clutter/clutter-main.c
@@ -2007,14 +2007,27 @@ emit_pointer_event (ClutterEvent *event,
}
static inline void
-emit_keyboard_event (ClutterEvent *event)
+emit_keyboard_event (ClutterEvent *event,
+ ClutterInputDevice *device)
{
ClutterMainContext *context = _clutter_context_get_default ();
- if (context->keyboard_grab_actor == NULL)
- emit_event (event, TRUE);
+ if (context->keyboard_grab_actor == NULL &&
+ (device == NULL || device->keyboard_grab_actor == NULL))
+ {
+ emit_event (event, FALSE);
+ }
else
- clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
+ {
+ if (context->keyboard_grab_actor != NULL)
+ {
+ clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
+ }
+ else if (device != NULL && device->keyboard_grab_actor != NULL)
+ {
+ clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
+ }
+ }
}
static gboolean
@@ -2102,7 +2115,7 @@ _clutter_process_event_details (ClutterActor *stage,
}
}
- emit_keyboard_event (event);
+ emit_keyboard_event (event, device);
}
break;
@@ -2411,23 +2424,34 @@ clutter_set_default_frame_rate (guint frames_per_sec)
static void
-on_pointer_grab_weak_notify (gpointer data,
- GObject *where_the_object_was)
+on_grab_actor_destroy (ClutterActor *actor,
+ ClutterInputDevice *device)
{
- ClutterInputDevice *dev = (ClutterInputDevice *)data;
- ClutterMainContext *context;
+ if (device == NULL)
+ {
+ ClutterMainContext *context = _clutter_context_get_default ();
- context = _clutter_context_get_default ();
+ if (context->pointer_grab_actor == actor)
+ clutter_ungrab_pointer ();
- if (dev)
- {
- dev->pointer_grab_actor = NULL;
- clutter_ungrab_pointer_for_device (dev->id);
+ if (context->keyboard_grab_actor == actor)
+ clutter_ungrab_keyboard ();
+
+ return;
}
- else
+
+ switch (device->device_type)
{
- context->pointer_grab_actor = NULL;
- clutter_ungrab_pointer ();
+ case CLUTTER_POINTER_DEVICE:
+ device->pointer_grab_actor = NULL;
+ break;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ device->keyboard_grab_actor = NULL;
+ break;
+
+ default:
+ g_assert_not_reached ();
}
}
@@ -2446,8 +2470,10 @@ on_pointer_grab_weak_notify (gpointer data,
* using the #ClutterActor::captured-event signal should always be the
* preferred way to intercept event delivery to reactive actors.</para></note>
*
- * If you wish to grab all the pointer events for a specific input device,
- * you should use clutter_grab_pointer_for_device().
+ * This function should rarely be used.
+ *
+ * If a grab is required, you are strongly encouraged to use a specific
+ * input device by calling clutter_input_device_grab().
*
* Since: 0.6
*/
@@ -2463,22 +2489,150 @@ clutter_grab_pointer (ClutterActor *actor)
if (context->pointer_grab_actor == actor)
return;
- if (context->pointer_grab_actor)
+ if (context->pointer_grab_actor != NULL)
{
- g_object_weak_unref (G_OBJECT (context->pointer_grab_actor),
- on_pointer_grab_weak_notify,
- NULL);
+ g_signal_handlers_disconnect_by_func (context->pointer_grab_actor,
+ G_CALLBACK (on_grab_actor_destroy),
+ NULL);
context->pointer_grab_actor = NULL;
}
- if (actor)
+ if (actor != NULL)
{
context->pointer_grab_actor = actor;
- g_object_weak_ref (G_OBJECT (actor),
- on_pointer_grab_weak_notify,
- NULL);
+ g_signal_connect (context->pointer_grab_actor, "destroy",
+ G_CALLBACK (on_grab_actor_destroy),
+ NULL);
+ }
+}
+
+/**
+ * clutter_input_device_grab:
+ * @device: a #ClutterInputDevice
+ * @actor: a #ClutterActor
+ *
+ * Acquires a grab on @actor for the given @device.
+ *
+ * Any event coming from @device will be delivered to @actor, bypassing
+ * the usual event delivery mechanism, until the grab is released by
+ * calling clutter_input_device_ungrab().
+ *
+ * The grab is client-side: even if the windowing system used by the Clutter
+ * backend has the concept of "device grabs", Clutter will not use them.
+ *
+ * Only #ClutterInputDevice of types %CLUTTER_POINTER_DEVICE and
+ * %CLUTTER_KEYBOARD_DEVICE can hold a grab.
+ *
+ * Since: 1.10
+ */
+void
+clutter_input_device_grab (ClutterInputDevice *device,
+ ClutterActor *actor)
+{
+ ClutterActor **grab_actor;
+
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
+
+ switch (device->device_type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ grab_actor = &(device->pointer_grab_actor);
+ break;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ grab_actor = &(device->keyboard_grab_actor);
+ break;
+
+ default:
+ g_critical ("Only pointer and keyboard devices can grab an actor");
+ return;
+ }
+
+ if (*grab_actor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (*grab_actor,
+ G_CALLBACK (on_grab_actor_destroy),
+ device);
+ }
+
+ *grab_actor = actor;
+
+ g_signal_connect (*grab_actor,
+ "destroy",
+ G_CALLBACK (on_grab_actor_destroy),
+ device);
+}
+
+/**
+ * clutter_input_device_ungrab:
+ * @device: a #ClutterInputDevice
+ *
+ * Releases the grab on the @device, if one is in place.
+ *
+ * Since: 1.10
+ */
+void
+clutter_input_device_ungrab (ClutterInputDevice *device)
+{
+ ClutterActor **grab_actor;
+
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+
+ switch (device->device_type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ grab_actor = &(device->pointer_grab_actor);
+ break;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ grab_actor = &(device->keyboard_grab_actor);
+ break;
+
+ default:
+ return;
+ }
+
+ if (*grab_actor == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (*grab_actor,
+ G_CALLBACK (on_grab_actor_destroy),
+ device);
+
+ *grab_actor = NULL;
+}
+
+/**
+ * clutter_input_device_get_grabbed_actor:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves a pointer to the #ClutterActor currently grabbing all
+ * the events coming from @device.
+ *
+ * Return value: (transfer none): a #ClutterActor, or %NULL
+ *
+ * Since: 1.10
+ */
+ClutterActor *
+clutter_input_device_get_grabbed_actor (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
+
+ switch (device->device_type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ return device->pointer_grab_actor;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ return device->keyboard_grab_actor;
+
+ default:
+ g_critical ("Only pointer and keyboard devices can grab an actor");
}
+
+ return NULL;
}
/**
@@ -2491,6 +2645,8 @@ clutter_grab_pointer (ClutterActor *actor)
* If @id is -1 then this function is equivalent to clutter_grab_pointer().
*
* Since: 0.8
+ *
+ * Deprecated: 1.10: Use clutter_input_device_grab() instead.
*/
void
clutter_grab_pointer_for_device (ClutterActor *actor,
@@ -2503,7 +2659,11 @@ clutter_grab_pointer_for_device (ClutterActor *actor,
/* essentially a global grab */
if (id_ == -1)
{
- clutter_grab_pointer (actor);
+ if (actor == NULL)
+ clutter_ungrab_pointer ();
+ else
+ clutter_grab_pointer (actor);
+
return;
}
@@ -2511,25 +2671,13 @@ clutter_grab_pointer_for_device (ClutterActor *actor,
if (dev == NULL)
return;
- if (dev->pointer_grab_actor == actor)
+ if (dev->device_type != CLUTTER_POINTER_DEVICE)
return;
- if (dev->pointer_grab_actor)
- {
- g_object_weak_unref (G_OBJECT (dev->pointer_grab_actor),
- on_pointer_grab_weak_notify,
- dev);
- dev->pointer_grab_actor = NULL;
- }
-
- if (actor)
- {
- dev->pointer_grab_actor = actor;
-
- g_object_weak_ref (G_OBJECT (actor),
- on_pointer_grab_weak_notify,
- dev);
- }
+ if (actor == NULL)
+ clutter_input_device_ungrab (dev);
+ else
+ clutter_input_device_grab (dev, actor);
}
@@ -2553,6 +2701,8 @@ clutter_ungrab_pointer (void)
* Removes an existing grab of the pointer events for device @id_.
*
* Since: 0.8
+ *
+ * Deprecated: 1.10: Use clutter_input_device_ungrab() instead.
*/
void
clutter_ungrab_pointer_for_device (gint id_)
@@ -2580,18 +2730,6 @@ clutter_get_pointer_grab (void)
}
-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
@@ -2622,21 +2760,21 @@ clutter_grab_keyboard (ClutterActor *actor)
if (context->keyboard_grab_actor == actor)
return;
- if (context->keyboard_grab_actor)
+ if (context->keyboard_grab_actor != NULL)
{
- g_object_weak_unref (G_OBJECT (context->keyboard_grab_actor),
- on_keyboard_grab_weak_notify,
- NULL);
+ g_signal_handlers_disconnect_by_func (context->keyboard_grab_actor,
+ G_CALLBACK (on_grab_actor_destroy),
+ NULL);
context->keyboard_grab_actor = NULL;
}
- if (actor)
+ if (actor != NULL)
{
context->keyboard_grab_actor = actor;
- g_object_weak_ref (G_OBJECT (actor),
- on_keyboard_grab_weak_notify,
- NULL);
+ g_signal_connect (context->keyboard_grab_actor, "destroy",
+ G_CALLBACK (on_grab_actor_destroy),
+ NULL);
}
}
diff --git a/clutter/clutter-main.h b/clutter/clutter-main.h
index 3ddc263..34328e8 100644
--- a/clutter/clutter-main.h
+++ b/clutter/clutter-main.h
@@ -96,7 +96,7 @@ void clutter_main (void);
void clutter_main_quit (void);
gint clutter_main_level (void);
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
void clutter_redraw (ClutterStage *stage)
G_GNUC_DEPRECATED_FOR (clutter_stage_ensure_redraw);
#endif
@@ -110,7 +110,7 @@ gulong clutter_get_timestamp (void);
gboolean clutter_get_accessibility_enabled (void);
/* Threading functions */
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
void clutter_threads_init (void);
#endif
@@ -133,7 +133,7 @@ guint clutter_threads_add_timeout_full (gint priority,
gpointer data,
GDestroyNotify notify);
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
guint clutter_threads_add_frame_source (guint fps,
GSourceFunc func,
gpointer data);
@@ -149,7 +149,7 @@ guint clutter_threads_add_repaint_func (GSourceFunc func,
GDestroyNotify notify);
void clutter_threads_remove_repaint_func (guint handle_id);
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
void clutter_set_motion_events_enabled (gboolean enable);
gboolean clutter_get_motion_events_enabled (void);
#endif /* CLUTTER_DISABLE_DEPRECATED */
@@ -171,9 +171,11 @@ ClutterFontFlags clutter_get_font_flags (void);
ClutterInputDevice *clutter_get_input_device_for_id (gint id_);
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
void clutter_grab_pointer_for_device (ClutterActor *actor,
gint id_);
void clutter_ungrab_pointer_for_device (gint id_);
+#endif
PangoFontMap * clutter_get_font_map (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]