From a9a9d27ead078c9720f0d9e7a3d6d5df78524236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Thu, 15 Oct 2020 16:46:08 +0200 Subject: [PATCH] clutter: Add function to update input device actors to clutter-main We're moving keeping track of input devices and their associated actors out of ClutterInputDevice, this commit basically adds replacements for clutter_input_device_update() and clutter_input_device_set_actor() to clutter-main and shuffles the internals of those functions around a bit for clarity. clutter_stage_update_device() is made available in clutter-mutter.h because we need to update the actor of input devices not only from ClutterStage (when repicking after relayout), but also from MetaWaylandPointer (inside meta_wayland_pointer_repick()). Part-of: --- clutter/clutter/clutter-main.c | 146 +++++++++++++++++++++++++++++++ clutter/clutter/clutter-mutter.h | 9 ++ 2 files changed, 155 insertions(+) diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c index f3475c696..cd2e41c59 100644 --- a/clutter/clutter/clutter-main.c +++ b/clutter/clutter/clutter-main.c @@ -65,6 +65,7 @@ #include "clutter-paint-node-private.h" #include "clutter-private.h" #include "clutter-settings-private.h" +#include "clutter-stage.h" #include "clutter-stage-manager.h" #include "clutter-stage-private.h" #include "clutter-backend-private.h" @@ -1553,6 +1554,151 @@ clutter_do_event (ClutterEvent *event) _clutter_stage_queue_event (event->any.stage, event, TRUE); } +static void +create_crossing_event (ClutterStage *stage, + ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterEventType event_type, + ClutterActor *source, + ClutterActor *related, + graphene_point_t coords, + uint32_t time) +{ + ClutterEvent *event; + + event = clutter_event_new (event_type); + event->crossing.time = time; + event->crossing.flags = 0; + event->crossing.stage = stage; + event->crossing.source = source; + event->crossing.x = coords.x; + event->crossing.y = coords.y; + event->crossing.related = related; + event->crossing.sequence = sequence; + clutter_event_set_device (event, device); + + /* we need to make sure that this event is processed + * before any other event we might have queued up until + * now, so we go on, and synthesize the event emission + * ourselves + */ + _clutter_process_event (event); + + clutter_event_free (event); +} + +void +clutter_stage_update_device (ClutterStage *stage, + ClutterInputDevice *device, + ClutterEventSequence *sequence, + graphene_point_t point, + uint32_t time, + ClutterActor *new_actor, + gboolean emit_crossing) +{ + ClutterInputDeviceType device_type; + ClutterActor *old_actor; + gboolean device_actor_changed; + + device_type = clutter_input_device_get_device_type (device); + + g_assert (device_type != CLUTTER_KEYBOARD_DEVICE && + device_type != CLUTTER_PAD_DEVICE); + + old_actor = clutter_stage_get_device_actor (stage, device, sequence); + device_actor_changed = new_actor != old_actor; + + if (device_actor_changed) + { + CLUTTER_NOTE (EVENT, + "Updating actor under cursor (device %s, at %.2f, %.2f): %s", + clutter_input_device_get_device_name (device), + point.x, + point.y, + _clutter_actor_get_debug_name (new_actor)); + + if (old_actor && emit_crossing) + { + create_crossing_event (stage, + device, sequence, + CLUTTER_LEAVE, + old_actor, new_actor, + point, time); + } + } + + clutter_stage_update_device_entry (stage, + device, sequence, + point, + new_actor); + + if (device_actor_changed) + { + if (new_actor && emit_crossing) + { + create_crossing_event (stage, + device, sequence, + CLUTTER_ENTER, + new_actor, old_actor, + point, time); + } + } +} + +static ClutterActor * +update_device_for_event (ClutterStage *stage, + ClutterEvent *event, + gboolean emit_crossing) +{ + ClutterInputDevice *device = clutter_event_get_device (event); + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + ClutterActor *new_actor; + graphene_point_t point; + uint32_t time; + + clutter_event_get_coords (event, &point.x, &point.y); + time = clutter_event_get_time (event); + + new_actor = + _clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE); + + /* Picking should never fail, but if it does, we bail out here */ + g_return_val_if_fail (new_actor != NULL, NULL); + + clutter_stage_update_device (stage, + device, sequence, + point, + time, + new_actor, + emit_crossing); + + return new_actor; +} + +static void +remove_device_for_event (ClutterStage *stage, + ClutterEvent *event, + gboolean emit_crossing) +{ + ClutterInputDevice *device = clutter_event_get_device (event); + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + graphene_point_t point; + uint32_t time; + + clutter_event_get_coords (event, &point.x, &point.y); + time = clutter_event_get_time (event); + + clutter_stage_update_device (stage, + device, sequence, + point, + time, + NULL, + TRUE); + + clutter_stage_remove_device_entry (stage, device, sequence); +} + + static void _clutter_process_event_details (ClutterActor *stage, ClutterMainContext *context, diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h index 6e1f43930..63b3fbf35 100644 --- a/clutter/clutter/clutter-mutter.h +++ b/clutter/clutter/clutter-mutter.h @@ -75,6 +75,15 @@ CLUTTER_EXPORT gboolean clutter_seat_handle_event_post (ClutterSeat *seat, const ClutterEvent *event); +CLUTTER_EXPORT +void clutter_stage_update_device (ClutterStage *stage, + ClutterInputDevice *device, + ClutterEventSequence *sequence, + graphene_point_t point, + uint32_t time, + ClutterActor *new_actor, + gboolean emit_crossing); + CLUTTER_EXPORT void clutter_stage_get_device_coords (ClutterStage *stage, ClutterInputDevice *device,