[mutter/wip/carlosg/grabs-pt1: 20/30] clutter: Emit crossing events along with ClutterGrabs becoming active
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/carlosg/grabs-pt1: 20/30] clutter: Emit crossing events along with ClutterGrabs becoming active
- Date: Fri, 29 Oct 2021 16:29:17 +0000 (UTC)
commit c6bcc03d9125d3806be6049adbb98645178d7496
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Oct 26 18:57:35 2021 +0200
clutter: Emit crossing events along with ClutterGrabs becoming active
Emit crossing events whenever a grab coming or going would cause a
pointer/touchpoint to become inactive on their position. Depending
on whether the pointer lies inside the old or new grab widgets,
enter or leave events would be generated.
clutter/clutter/clutter-stage.c | 157 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 156 insertions(+), 1 deletion(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 3d3c4f1fee..d6ab02b787 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -3425,6 +3425,25 @@ clutter_stage_get_device_actor (ClutterStage *stage,
return NULL;
}
+static ClutterActor *
+common_root_actor (ClutterStage *stage,
+ ClutterActor *a,
+ ClutterActor *b)
+{
+ if (a && b)
+ {
+ while (a)
+ {
+ if (a == b || clutter_actor_contains (a, b))
+ return a;
+
+ a = clutter_actor_get_parent (a);
+ }
+ }
+
+ return CLUTTER_ACTOR (stage);
+}
+
static ClutterEvent *
create_crossing_event (ClutterStage *stage,
ClutterInputDevice *device,
@@ -3535,6 +3554,136 @@ clutter_stage_get_device_coords (ClutterStage *stage,
*coords = entry->coords;
}
+static void
+clutter_stage_notify_grab_on_entry (ClutterStage *stage,
+ PointerDeviceEntry *entry,
+ ClutterActor *grab_actor,
+ ClutterActor *old_grab_actor)
+{
+ gboolean pointer_in_grab, pointer_in_old_grab;
+ ClutterEventType event_type = CLUTTER_NOTHING;
+ ClutterActor *topmost, *deepmost;
+
+ pointer_in_grab =
+ !grab_actor ||
+ grab_actor == entry->current_actor ||
+ clutter_actor_contains (grab_actor, entry->current_actor);
+ pointer_in_old_grab =
+ !old_grab_actor ||
+ old_grab_actor == entry->current_actor ||
+ clutter_actor_contains (old_grab_actor, entry->current_actor);
+
+ /* Equate NULL actors to the stage here, to ease calculations further down. */
+ if (!grab_actor)
+ grab_actor = CLUTTER_ACTOR (stage);
+ if (!old_grab_actor)
+ old_grab_actor = CLUTTER_ACTOR (stage);
+
+ if (grab_actor == old_grab_actor)
+ return;
+
+ if (pointer_in_grab && pointer_in_old_grab)
+ {
+ /* Both grabs happen to contain the pointer actor, we have to figure out
+ * which is topmost, and emit ENTER/LEAVE events accordingly on the actors
+ * between old/new grabs.
+ */
+ if (clutter_actor_contains (grab_actor, old_grab_actor))
+ {
+ /* grab_actor is above old_grab_actor, emit ENTER events in the
+ * line between those two actors.
+ */
+ event_type = CLUTTER_ENTER;
+ deepmost = old_grab_actor;
+ topmost = grab_actor;
+ }
+ else if (clutter_actor_contains (old_grab_actor, grab_actor))
+ {
+ /* old_grab_actor is above grab_actor, emit LEAVE events in the
+ * line between those two actors.
+ */
+ event_type = CLUTTER_LEAVE;
+ deepmost = grab_actor;
+ topmost = old_grab_actor;
+ }
+ }
+ else if (pointer_in_grab)
+ {
+ /* Pointer is somewhere inside the grab_actor hierarchy. Emit ENTER events
+ * from the current grab actor to the pointer actor.
+ */
+ event_type = CLUTTER_ENTER;
+ deepmost = entry->current_actor;
+ topmost = grab_actor;
+ }
+ else if (pointer_in_old_grab)
+ {
+ /* Pointer is somewhere inside the old_grab_actor hierarchy. Emit LEAVE
+ * events from the common root of old/cur grab actors to the pointer
+ * actor.
+ */
+ event_type = CLUTTER_LEAVE;
+ deepmost = entry->current_actor;
+ topmost = common_root_actor (stage, grab_actor, old_grab_actor);
+ }
+
+ if (event_type != CLUTTER_NOTHING)
+ {
+ ClutterEvent *event;
+
+ event = create_crossing_event (stage,
+ entry->device,
+ entry->sequence,
+ event_type,
+ entry->current_actor,
+ entry->current_actor,
+ entry->coords,
+ CLUTTER_CURRENT_TIME);
+ _clutter_actor_handle_event (deepmost, topmost, event);
+ clutter_event_free (event);
+ }
+}
+
+static void
+clutter_stage_notify_grab (ClutterStage *stage,
+ ClutterGrab *cur,
+ ClutterGrab *old)
+{
+ ClutterStagePrivate *priv = stage->priv;
+ ClutterActor *cur_actor = NULL, *old_actor = NULL;
+ PointerDeviceEntry *entry;
+ GHashTableIter iter;
+
+ if (cur)
+ cur_actor = cur->actor;
+ if (old)
+ old_actor = old->actor;
+
+ /* Nothing to notify */
+ if (cur_actor == old_actor)
+ return;
+
+ g_hash_table_iter_init (&iter, priv->pointer_devices);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &entry))
+ {
+ /* Update pointers */
+ clutter_stage_notify_grab_on_entry (stage,
+ entry,
+ cur_actor,
+ old_actor);
+ }
+
+ g_hash_table_iter_init (&iter, priv->touch_sequences);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &entry))
+ {
+ /* Update touch sequences */
+ clutter_stage_notify_grab_on_entry (stage,
+ entry,
+ cur_actor,
+ old_actor);
+ }
+}
+
ClutterGrab *
clutter_grab (ClutterStage *stage,
ClutterActor *actor)
@@ -3547,6 +3696,7 @@ clutter_grab (ClutterStage *stage,
grab->next = priv->grabs;
priv->grabs = grab;
+ clutter_stage_notify_grab (stage, grab, grab->next);
return grab;
}
@@ -3567,7 +3717,12 @@ clutter_ungrab (ClutterStage *stage,
next->prev = prev;
if (!prev)
- priv->grabs = next;
+ {
+ /* This is the active grab */
+ g_assert (priv->grabs == grab);
+ priv->grabs = next;
+ clutter_stage_notify_grab (stage, next, grab);
+ }
g_free (grab);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]