mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
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 */
|
||||
ClutterActor *pointer_grab_actor;
|
||||
ClutterActor *keyboard_grab_actor;
|
||||
|
||||
/* the current click count */
|
||||
gint click_count;
|
||||
|
@ -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__ */
|
||||
|
@ -2007,15 +2007,28 @@ 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
|
||||
{
|
||||
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
|
||||
is_off_stage (ClutterActor *stage,
|
||||
@ -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 (dev)
|
||||
{
|
||||
dev->pointer_grab_actor = NULL;
|
||||
clutter_ungrab_pointer_for_device (dev->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
context->pointer_grab_actor = NULL;
|
||||
if (context->pointer_grab_actor == actor)
|
||||
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
|
||||
* 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,24 +2489,152 @@ 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,
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_grab_pointer_for_device:
|
||||
* @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().
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
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,20 +2760,20 @@ 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,
|
||||
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,
|
||||
g_signal_connect (context->keyboard_grab_actor, "destroy",
|
||||
G_CALLBACK (on_grab_actor_destroy),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user