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.
This commit is contained in:
parent
33846dcf4d
commit
b6dd306998
@ -75,6 +75,7 @@ struct _ClutterInputDevice
|
|||||||
|
|
||||||
/* the actor that has a grab in place for the device */
|
/* the actor that has a grab in place for the device */
|
||||||
ClutterActor *pointer_grab_actor;
|
ClutterActor *pointer_grab_actor;
|
||||||
|
ClutterActor *keyboard_grab_actor;
|
||||||
|
|
||||||
/* the current click count */
|
/* the current click count */
|
||||||
gint click_count;
|
gint click_count;
|
||||||
|
@ -167,6 +167,11 @@ void clutter_input_device_update_from_event (ClutterInputDev
|
|||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
gboolean update_stage);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
||||||
|
@ -2007,14 +2007,27 @@ emit_pointer_event (ClutterEvent *event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emit_keyboard_event (ClutterEvent *event)
|
emit_keyboard_event (ClutterEvent *event,
|
||||||
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = _clutter_context_get_default ();
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
|
|
||||||
if (context->keyboard_grab_actor == NULL)
|
if (context->keyboard_grab_actor == NULL &&
|
||||||
emit_event (event, TRUE);
|
(device == NULL || device->keyboard_grab_actor == NULL))
|
||||||
|
{
|
||||||
|
emit_event (event, FALSE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (context->keyboard_grab_actor != NULL)
|
||||||
|
{
|
||||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
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
|
static gboolean
|
||||||
@ -2102,7 +2115,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_keyboard_event (event);
|
emit_keyboard_event (event, device);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2411,23 +2424,34 @@ clutter_set_default_frame_rate (guint frames_per_sec)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_pointer_grab_weak_notify (gpointer data,
|
on_grab_actor_destroy (ClutterActor *actor,
|
||||||
GObject *where_the_object_was)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
ClutterInputDevice *dev = (ClutterInputDevice *)data;
|
if (device == NULL)
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
if (dev)
|
|
||||||
{
|
{
|
||||||
dev->pointer_grab_actor = NULL;
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
clutter_ungrab_pointer_for_device (dev->id);
|
|
||||||
}
|
if (context->pointer_grab_actor == actor)
|
||||||
else
|
|
||||||
{
|
|
||||||
context->pointer_grab_actor = NULL;
|
|
||||||
clutter_ungrab_pointer ();
|
clutter_ungrab_pointer ();
|
||||||
|
|
||||||
|
if (context->keyboard_grab_actor == actor)
|
||||||
|
clutter_ungrab_keyboard ();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (device->device_type)
|
||||||
|
{
|
||||||
|
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
|
* using the #ClutterActor::captured-event signal should always be the
|
||||||
* preferred way to intercept event delivery to reactive actors.</para></note>
|
* 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,
|
* This function should rarely be used.
|
||||||
* you should use clutter_grab_pointer_for_device().
|
*
|
||||||
|
* If a grab is required, you are strongly encouraged to use a specific
|
||||||
|
* input device by calling clutter_input_device_grab().
|
||||||
*
|
*
|
||||||
* Since: 0.6
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
@ -2463,24 +2489,152 @@ clutter_grab_pointer (ClutterActor *actor)
|
|||||||
if (context->pointer_grab_actor == actor)
|
if (context->pointer_grab_actor == actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (context->pointer_grab_actor)
|
if (context->pointer_grab_actor != NULL)
|
||||||
{
|
{
|
||||||
g_object_weak_unref (G_OBJECT (context->pointer_grab_actor),
|
g_signal_handlers_disconnect_by_func (context->pointer_grab_actor,
|
||||||
on_pointer_grab_weak_notify,
|
G_CALLBACK (on_grab_actor_destroy),
|
||||||
NULL);
|
NULL);
|
||||||
context->pointer_grab_actor = NULL;
|
context->pointer_grab_actor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor)
|
if (actor != NULL)
|
||||||
{
|
{
|
||||||
context->pointer_grab_actor = actor;
|
context->pointer_grab_actor = actor;
|
||||||
|
|
||||||
g_object_weak_ref (G_OBJECT (actor),
|
g_signal_connect (context->pointer_grab_actor, "destroy",
|
||||||
on_pointer_grab_weak_notify,
|
G_CALLBACK (on_grab_actor_destroy),
|
||||||
NULL);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_grab_pointer_for_device:
|
* clutter_grab_pointer_for_device:
|
||||||
* @actor: a #ClutterActor
|
* @actor: a #ClutterActor
|
||||||
@ -2491,6 +2645,8 @@ clutter_grab_pointer (ClutterActor *actor)
|
|||||||
* If @id is -1 then this function is equivalent to clutter_grab_pointer().
|
* If @id is -1 then this function is equivalent to clutter_grab_pointer().
|
||||||
*
|
*
|
||||||
* Since: 0.8
|
* Since: 0.8
|
||||||
|
*
|
||||||
|
* Deprecated: 1.10: Use clutter_input_device_grab() instead.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_grab_pointer_for_device (ClutterActor *actor,
|
clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||||
@ -2503,7 +2659,11 @@ clutter_grab_pointer_for_device (ClutterActor *actor,
|
|||||||
/* essentially a global grab */
|
/* essentially a global grab */
|
||||||
if (id_ == -1)
|
if (id_ == -1)
|
||||||
{
|
{
|
||||||
|
if (actor == NULL)
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
|
else
|
||||||
clutter_grab_pointer (actor);
|
clutter_grab_pointer (actor);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2511,25 +2671,13 @@ clutter_grab_pointer_for_device (ClutterActor *actor,
|
|||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->pointer_grab_actor == actor)
|
if (dev->device_type != CLUTTER_POINTER_DEVICE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->pointer_grab_actor)
|
if (actor == NULL)
|
||||||
{
|
clutter_input_device_ungrab (dev);
|
||||||
g_object_weak_unref (G_OBJECT (dev->pointer_grab_actor),
|
else
|
||||||
on_pointer_grab_weak_notify,
|
clutter_input_device_grab (dev, actor);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2553,6 +2701,8 @@ clutter_ungrab_pointer (void)
|
|||||||
* Removes an existing grab of the pointer events for device @id_.
|
* Removes an existing grab of the pointer events for device @id_.
|
||||||
*
|
*
|
||||||
* Since: 0.8
|
* Since: 0.8
|
||||||
|
*
|
||||||
|
* Deprecated: 1.10: Use clutter_input_device_ungrab() instead.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_ungrab_pointer_for_device (gint id_)
|
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:
|
* clutter_grab_keyboard:
|
||||||
* @actor: a #ClutterActor
|
* @actor: a #ClutterActor
|
||||||
@ -2622,20 +2760,20 @@ clutter_grab_keyboard (ClutterActor *actor)
|
|||||||
if (context->keyboard_grab_actor == actor)
|
if (context->keyboard_grab_actor == actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (context->keyboard_grab_actor)
|
if (context->keyboard_grab_actor != NULL)
|
||||||
{
|
{
|
||||||
g_object_weak_unref (G_OBJECT (context->keyboard_grab_actor),
|
g_signal_handlers_disconnect_by_func (context->keyboard_grab_actor,
|
||||||
on_keyboard_grab_weak_notify,
|
G_CALLBACK (on_grab_actor_destroy),
|
||||||
NULL);
|
NULL);
|
||||||
context->keyboard_grab_actor = NULL;
|
context->keyboard_grab_actor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor)
|
if (actor != NULL)
|
||||||
{
|
{
|
||||||
context->keyboard_grab_actor = actor;
|
context->keyboard_grab_actor = actor;
|
||||||
|
|
||||||
g_object_weak_ref (G_OBJECT (actor),
|
g_signal_connect (context->keyboard_grab_actor, "destroy",
|
||||||
on_keyboard_grab_weak_notify,
|
G_CALLBACK (on_grab_actor_destroy),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ void clutter_main (void);
|
|||||||
void clutter_main_quit (void);
|
void clutter_main_quit (void);
|
||||||
gint clutter_main_level (void);
|
gint clutter_main_level (void);
|
||||||
|
|
||||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
|
||||||
void clutter_redraw (ClutterStage *stage)
|
void clutter_redraw (ClutterStage *stage)
|
||||||
G_GNUC_DEPRECATED_FOR (clutter_stage_ensure_redraw);
|
G_GNUC_DEPRECATED_FOR (clutter_stage_ensure_redraw);
|
||||||
#endif
|
#endif
|
||||||
@ -110,7 +110,7 @@ gulong clutter_get_timestamp (void);
|
|||||||
gboolean clutter_get_accessibility_enabled (void);
|
gboolean clutter_get_accessibility_enabled (void);
|
||||||
|
|
||||||
/* Threading functions */
|
/* Threading functions */
|
||||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
|
||||||
void clutter_threads_init (void);
|
void clutter_threads_init (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ guint clutter_threads_add_timeout_full (gint priority,
|
|||||||
gpointer data,
|
gpointer data,
|
||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
|
|
||||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
|
||||||
guint clutter_threads_add_frame_source (guint fps,
|
guint clutter_threads_add_frame_source (guint fps,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
@ -149,7 +149,7 @@ guint clutter_threads_add_repaint_func (GSourceFunc func,
|
|||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
void clutter_threads_remove_repaint_func (guint handle_id);
|
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);
|
void clutter_set_motion_events_enabled (gboolean enable);
|
||||||
gboolean clutter_get_motion_events_enabled (void);
|
gboolean clutter_get_motion_events_enabled (void);
|
||||||
#endif /* CLUTTER_DISABLE_DEPRECATED */
|
#endif /* CLUTTER_DISABLE_DEPRECATED */
|
||||||
@ -171,9 +171,11 @@ ClutterFontFlags clutter_get_font_flags (void);
|
|||||||
|
|
||||||
ClutterInputDevice *clutter_get_input_device_for_id (gint id_);
|
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,
|
void clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||||
gint id_);
|
gint id_);
|
||||||
void clutter_ungrab_pointer_for_device (gint id_);
|
void clutter_ungrab_pointer_for_device (gint id_);
|
||||||
|
#endif
|
||||||
|
|
||||||
PangoFontMap * clutter_get_font_map (void);
|
PangoFontMap * clutter_get_font_map (void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user