1
0
Fork 0

clutter: Make the stage the central instance emitting events

Right now and due to loads of refactorings lately, the event emission
paths are a bit cluttered (ha ha ha) around in Clutter. For example the
event target actor gets set in clutter-main.c, but event emission is
actually managed by ClutterStage these days.

Since we'll introduce implicit grabbing of touch/button-press sequences
soon, let's shuffle things around a bit to make that easier:

Move event emission to the stage, it now gets a ClutterEvent without any
extra context like the target actor from clutter-main. The stage then
looks up the target actor itself and emits the event to the appropriate
actors in the scenegraph. A special path is introduced for emitting
crossing events, because here the event-receiving actors don't follow
the "capture+bubble from pointer actor to grab actor" rule.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
This commit is contained in:
Jonas Dreßler 2022-04-04 00:07:44 +02:00 committed by Marge Bot
parent ccb49f75e4
commit 0f0466fa8e
3 changed files with 119 additions and 79 deletions

View file

@ -674,29 +674,19 @@ _clutter_boolean_continue_accumulator (GSignalInvocationHint *ihint,
return continue_emission;
}
static inline void
emit_event_chain (ClutterActor *target,
ClutterEvent *event)
{
_clutter_actor_handle_event (target,
clutter_stage_get_grab_actor (event->any.stage),
event);
}
/*
* Emits a pointer event after having prepared the event for delivery (setting
* source, generating enter/leave etc.).
*/
static inline void
emit_event (ClutterActor *target,
ClutterEvent *event)
emit_event (ClutterEvent *event)
{
if (event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE)
cally_snoop_key_event ((ClutterKeyEvent *) event);
emit_event_chain (target, event);
clutter_stage_emit_event (event->any.stage, event);
}
static ClutterActor *
@ -836,10 +826,6 @@ _clutter_process_event_details (ClutterActor *stage,
ClutterMainContext *context,
ClutterEvent *event)
{
ClutterInputDevice *device = clutter_event_get_device (event);
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
ClutterActor *target;
switch (event->type)
{
case CLUTTER_NOTHING:
@ -854,32 +840,8 @@ _clutter_process_event_details (ClutterActor *stage,
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
{
ClutterActor *actor = NULL;
actor = clutter_stage_get_key_focus (CLUTTER_STAGE (stage));
if (G_UNLIKELY (actor == NULL))
{
g_warning ("No key focus set, discarding");
return;
}
emit_event (actor, event);
}
break;
case CLUTTER_ENTER:
target = clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
device, sequence);
emit_event (target, event);
break;
case CLUTTER_LEAVE:
target = clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
device, sequence);
emit_event (target, event);
break;
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
@ -887,48 +849,13 @@ _clutter_process_event_details (ClutterActor *stage,
case CLUTTER_TOUCHPAD_PINCH:
case CLUTTER_TOUCHPAD_SWIPE:
case CLUTTER_TOUCHPAD_HOLD:
{
gfloat x, y;
target = clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
device, sequence);
clutter_event_get_coords (event, &x, &y);
CLUTTER_NOTE (EVENT,
"Reactive event received at %.2f, %.2f - actor: %p",
x, y, target);
emit_event (target, event);
break;
}
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_CANCEL:
case CLUTTER_TOUCH_END:
{
gfloat x, y;
target = clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
device, sequence);
clutter_event_get_coords (event, &x, &y);
CLUTTER_NOTE (EVENT,
"Reactive event received at %.2f, %.2f - actor: %p",
x, y, target);
emit_event (target, event);
break;
}
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
if (!clutter_actor_event (stage, event, TRUE))
{
/* and bubbling phase */
clutter_actor_event (stage, event, FALSE);
}
emit_event (event);
break;
case CLUTTER_DEVICE_REMOVED:

View file

@ -168,6 +168,9 @@ void clutter_stage_invalidate_focus (ClutterStage *self,
void clutter_stage_maybe_invalidate_focus (ClutterStage *self,
ClutterActor *actor);
void clutter_stage_emit_event (ClutterStage *self,
const ClutterEvent *event);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View file

@ -3413,6 +3413,15 @@ create_crossing_event (ClutterStage *stage,
return event;
}
static void
clutter_stage_emit_crossing_event (ClutterStage *self,
const ClutterEvent *event,
ClutterActor *deepmost,
ClutterActor *topmost)
{
_clutter_actor_handle_event (deepmost, topmost, event);
}
void
clutter_stage_update_device (ClutterStage *stage,
ClutterInputDevice *device,
@ -3483,7 +3492,12 @@ clutter_stage_update_device (ClutterStage *stage,
old_actor, new_actor,
point, time_ms);
if (!_clutter_event_process_filters (event, old_actor))
_clutter_actor_handle_event (old_actor, root, event);
{
clutter_stage_emit_crossing_event (stage,
event,
old_actor,
root);
}
clutter_event_free (event);
}
@ -3497,7 +3511,12 @@ clutter_stage_update_device (ClutterStage *stage,
new_actor, old_actor,
point, time_ms);
if (!_clutter_event_process_filters (event, new_actor))
_clutter_actor_handle_event (new_actor, root, event);
{
clutter_stage_emit_crossing_event (stage,
event,
new_actor,
root);
}
clutter_event_free (event);
}
@ -3681,7 +3700,13 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage,
entry->coords,
CLUTTER_CURRENT_TIME);
if (!_clutter_event_process_filters (event, entry->current_actor))
_clutter_actor_handle_event (deepmost, topmost, event);
{
clutter_stage_emit_crossing_event (stage,
event,
deepmost,
topmost);
}
clutter_event_free (event);
}
}
@ -3994,3 +4019,88 @@ clutter_stage_get_event_actor (ClutterStage *stage,
return NULL;
}
void
clutter_stage_emit_event (ClutterStage *self,
const ClutterEvent *event)
{
ClutterStagePrivate *priv = self->priv;
ClutterInputDevice *device = clutter_event_get_device (event);
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
PointerDeviceEntry *entry;
ClutterActor *target_actor = NULL;
if (sequence != NULL)
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
else
entry = g_hash_table_lookup (priv->pointer_devices, device);
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_DEVICE_REMOVED:
case CLUTTER_DEVICE_ADDED:
case CLUTTER_EVENT_LAST:
return;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
case CLUTTER_PAD_BUTTON_PRESS:
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
{
target_actor = priv->key_focused_actor ?
priv->key_focused_actor : CLUTTER_ACTOR (self);
break;
}
/* x11 stage enter/leave events */
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
{
target_actor = entry->current_actor;
break;
}
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
case CLUTTER_TOUCHPAD_PINCH:
case CLUTTER_TOUCHPAD_SWIPE:
case CLUTTER_TOUCHPAD_HOLD:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_CANCEL:
case CLUTTER_TOUCH_END:
{
float x, y;
clutter_event_get_coords (event, &x, &y);
CLUTTER_NOTE (EVENT,
"Reactive event received at %.2f, %.2f - actor: %p",
x, y, entry->current_actor);
target_actor = entry->current_actor;
break;
}
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
{
target_actor = CLUTTER_ACTOR (self);
break;
}
}
g_assert (target_actor != NULL);
_clutter_actor_handle_event (target_actor,
clutter_stage_get_grab_actor (self),
event);
}