[mutter/wip/carlosg/grabs-pt1: 78/86] 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: 78/86] clutter: Emit crossing events along with ClutterGrabs becoming active
- Date: Wed, 5 Jan 2022 17:36:48 +0000 (UTC)
commit 6683e3901f42c82c91458f1b63e68f59a1eabe42
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, 157 insertions(+)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 5b89080605..d7e4b5ac1b 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -3460,6 +3460,27 @@ clutter_stage_set_device_coords (ClutterStage *stage,
entry->coords = coords;
}
+static ClutterActor *
+find_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);
+ }
+
+ g_warn_if_reached ();
+ }
+
+ return CLUTTER_ACTOR (stage);
+}
+
static ClutterEvent *
create_crossing_event (ClutterStage *stage,
ClutterInputDevice *device,
@@ -3641,6 +3662,140 @@ clutter_stage_pick_and_update_device (ClutterStage *stage,
return new_actor;
}
+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;
+
+ if (!entry->current_actor)
+ return;
+
+ 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 = clutter_actor_get_parent (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 = clutter_actor_get_parent (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 = find_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,
+ event_type == CLUTTER_LEAVE ?
+ grab_actor : old_grab_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_stage_grab (ClutterStage *stage,
ClutterActor *actor)
@@ -3661,6 +3816,7 @@ clutter_stage_grab (ClutterStage *stage,
priv->topmost_grab->prev = grab;
priv->topmost_grab = grab;
+ clutter_stage_notify_grab (stage, grab, grab->next);
return grab;
}
@@ -3687,6 +3843,7 @@ clutter_grab_dismiss (ClutterGrab *grab)
/* This is the active grab */
g_assert (prev == NULL);
priv->topmost_grab = 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]