mirror of
https://github.com/brl/mutter.git
synced 2025-01-22 09:29:25 +00:00
clutter/stage: Add infrastructure to track devices and their actors
With the introduction of the input thread, we want to avoid modifying ClutterInputDevices from the main thread, since they're owned and updated by the thread. There's one part of ClutterInputDevice that's still modified from the main thread though, that is device-actors of pointer devices, and we're going to move that state-tracking into ClutterStage instead. So start that by adding the infrastructure to ClutterStage to keep track of those things. It consists of two hashtables which associate devices and touch sequences with actors, those hashtables get updated using clutter_stage_update_device_entry() and clutter_stage_remove_device_entry(), they can be queried by calling clutter_stage_get_device_actor(), which will replace clutter_input_device_get_actor(). clutter_stage_get_device_coords() is added and made available in clutter-mutter.h because we need to get the coordinates when repicking in meta_wayland_pointer_repick(). Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1633>
This commit is contained in:
parent
0a456b4808
commit
98a5cb37d9
@ -75,6 +75,12 @@ CLUTTER_EXPORT
|
||||
gboolean clutter_seat_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_get_device_coords (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords);
|
||||
|
||||
#undef __CLUTTER_H_INSIDE__
|
||||
|
||||
#endif /* __CLUTTER_MUTTER_H__ */
|
||||
|
@ -128,6 +128,16 @@ GList * clutter_stage_get_views_for_rect (ClutterStage *stage,
|
||||
|
||||
void clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage);
|
||||
|
||||
void clutter_stage_update_device_entry (ClutterStage *self,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t coords,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_stage_remove_device_entry (ClutterStage *self,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
||||
|
@ -98,6 +98,15 @@ typedef struct _PickClipRecord
|
||||
graphene_point_t vertex[4];
|
||||
} PickClipRecord;
|
||||
|
||||
typedef struct _PointerDeviceEntry
|
||||
{
|
||||
ClutterStage *stage;
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
graphene_point_t coords;
|
||||
ClutterActor *current_actor;
|
||||
} PointerDeviceEntry;
|
||||
|
||||
struct _ClutterStagePrivate
|
||||
{
|
||||
/* the stage implementation */
|
||||
@ -126,6 +135,9 @@ struct _ClutterStagePrivate
|
||||
gboolean needs_update_devices;
|
||||
gboolean pending_finish_queue_redraws;
|
||||
|
||||
GHashTable *pointer_devices;
|
||||
GHashTable *touch_sequences;
|
||||
|
||||
guint throttle_motion_events : 1;
|
||||
guint min_size_changed : 1;
|
||||
guint motion_events_enabled : 1;
|
||||
@ -165,6 +177,7 @@ static guint stage_signals[LAST_SIGNAL] = { 0, };
|
||||
static const ClutterColor default_stage_color = { 255, 255, 255, 255 };
|
||||
|
||||
static void free_queue_redraw_entry (QueueRedrawEntry *entry);
|
||||
static void free_pointer_device_entry (PointerDeviceEntry *entry);
|
||||
static void capture_view_into (ClutterStage *stage,
|
||||
gboolean paint,
|
||||
ClutterStageView *view,
|
||||
@ -1301,6 +1314,9 @@ clutter_stage_finalize (GObject *object)
|
||||
g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL);
|
||||
g_queue_free (priv->event_queue);
|
||||
|
||||
g_hash_table_destroy (priv->pointer_devices);
|
||||
g_hash_table_destroy (priv->touch_sequences);
|
||||
|
||||
g_free (priv->title);
|
||||
|
||||
g_array_free (priv->paint_volume_stack, TRUE);
|
||||
@ -1596,6 +1612,13 @@ clutter_stage_init (ClutterStage *self)
|
||||
priv->sync_delay = -1;
|
||||
priv->motion_events_enabled = TRUE;
|
||||
|
||||
priv->pointer_devices =
|
||||
g_hash_table_new_full (NULL, NULL,
|
||||
NULL, (GDestroyNotify) free_pointer_device_entry);
|
||||
priv->touch_sequences =
|
||||
g_hash_table_new_full (NULL, NULL,
|
||||
NULL, (GDestroyNotify) free_pointer_device_entry);
|
||||
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
|
||||
&default_stage_color);
|
||||
|
||||
@ -3392,3 +3415,182 @@ clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage)
|
||||
|
||||
priv->actor_needs_immediate_relayout = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_actor_reactive_changed (ClutterActor *actor,
|
||||
GParamSpec *pspec,
|
||||
PointerDeviceEntry *entry)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_actor_destroyed (ClutterActor *actor,
|
||||
PointerDeviceEntry *entry)
|
||||
{
|
||||
/* Simply unset the current_actor pointer here, there's no need to
|
||||
* unset has_pointer or to disconnect any signals because the actor
|
||||
* is gone anyway.
|
||||
* Also, as soon as the next repaint happens, a repick should be triggered
|
||||
* and the PointerDeviceEntry will get updated again, so no need to
|
||||
* trigger a repick here.
|
||||
*/
|
||||
entry->current_actor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pointer_device_entry (PointerDeviceEntry *entry)
|
||||
{
|
||||
if (entry->current_actor)
|
||||
{
|
||||
ClutterActor *actor = entry->current_actor;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (actor,
|
||||
G_CALLBACK (on_device_actor_reactive_changed),
|
||||
entry);
|
||||
g_signal_handlers_disconnect_by_func (actor,
|
||||
G_CALLBACK (on_device_actor_destroyed),
|
||||
entry);
|
||||
|
||||
_clutter_actor_set_has_pointer (actor, FALSE);
|
||||
}
|
||||
|
||||
g_free (entry);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_update_device_entry (ClutterStage *self,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t coords,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterStagePrivate *priv = self->priv;
|
||||
PointerDeviceEntry *entry = NULL;
|
||||
|
||||
g_assert (device != NULL);
|
||||
|
||||
if (sequence != NULL)
|
||||
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
|
||||
else
|
||||
entry = g_hash_table_lookup (priv->pointer_devices, device);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
entry = g_new0 (PointerDeviceEntry, 1);
|
||||
|
||||
if (sequence != NULL)
|
||||
g_hash_table_insert (priv->touch_sequences, sequence, entry);
|
||||
else
|
||||
g_hash_table_insert (priv->pointer_devices, device, entry);
|
||||
|
||||
entry->stage = self;
|
||||
entry->device = device;
|
||||
entry->sequence = sequence;
|
||||
}
|
||||
|
||||
entry->coords = coords;
|
||||
|
||||
if (entry->current_actor != actor)
|
||||
{
|
||||
if (entry->current_actor)
|
||||
{
|
||||
ClutterActor *old_actor = entry->current_actor;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (old_actor,
|
||||
G_CALLBACK (on_device_actor_reactive_changed),
|
||||
entry);
|
||||
g_signal_handlers_disconnect_by_func (old_actor,
|
||||
G_CALLBACK (on_device_actor_destroyed),
|
||||
entry);
|
||||
|
||||
_clutter_actor_set_has_pointer (old_actor, FALSE);
|
||||
}
|
||||
|
||||
entry->current_actor = actor;
|
||||
|
||||
if (actor)
|
||||
{
|
||||
g_signal_connect (actor, "notify::reactive",
|
||||
G_CALLBACK (on_device_actor_reactive_changed), entry);
|
||||
g_signal_connect (actor, "destroy",
|
||||
G_CALLBACK (on_device_actor_destroyed), entry);
|
||||
|
||||
_clutter_actor_set_has_pointer (actor, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_remove_device_entry (ClutterStage *self,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterStagePrivate *priv = self->priv;
|
||||
gboolean removed;
|
||||
|
||||
g_assert (device != NULL);
|
||||
|
||||
if (sequence != NULL)
|
||||
removed = g_hash_table_remove (priv->touch_sequences, sequence);
|
||||
else
|
||||
removed = g_hash_table_remove (priv->pointer_devices, device);
|
||||
|
||||
g_assert (removed);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_get_device_actor:
|
||||
* @stage: a #ClutterStage
|
||||
* @device: a #ClutterInputDevice
|
||||
* @sequence: (allow-none): an optional #ClutterEventSequence
|
||||
*
|
||||
* Retrieves the #ClutterActor underneath the pointer or touch point
|
||||
* of @device and @sequence.
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #ClutterActor or %NULL
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_stage_get_device_actor (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
PointerDeviceEntry *entry = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
g_return_val_if_fail (device != NULL, NULL);
|
||||
|
||||
if (sequence != NULL)
|
||||
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
|
||||
else
|
||||
entry = g_hash_table_lookup (priv->pointer_devices, device);
|
||||
|
||||
if (entry)
|
||||
return entry->current_actor;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_get_device_coords: (skip):
|
||||
*/
|
||||
void
|
||||
clutter_stage_get_device_coords (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
PointerDeviceEntry *entry = NULL;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
g_return_if_fail (device != NULL);
|
||||
|
||||
if (sequence != NULL)
|
||||
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
|
||||
else
|
||||
entry = g_hash_table_lookup (priv->pointer_devices, device);
|
||||
|
||||
if (entry && coords)
|
||||
*coords = entry->coords;
|
||||
}
|
||||
|
@ -236,6 +236,11 @@ ClutterStageView * clutter_stage_get_view_at (ClutterStage *stage,
|
||||
float x,
|
||||
float y);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_stage_get_device_actor (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_H__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user