From 687c70dffa70a3256e9f734b090cb4a088e97bb1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 24 Nov 2009 16:33:03 +0000 Subject: [PATCH] Rework the emission of LEAVE/ENTER event pairs The LEAVE/ENTER event pairs should be queued during the InputDevice update process, when we change the actor under the device pointer. This commit cleans up the event emission code inside clutter-main.c and the logic of the event processing. --- clutter/clutter-device-manager.c | 4 +- clutter/clutter-input-device.c | 81 +++++++++++++++-- clutter/clutter-main.c | 190 ++++++--------------------------------- clutter/clutter-private.h | 2 - 4 files changed, 104 insertions(+), 173 deletions(-) diff --git a/clutter/clutter-device-manager.c b/clutter/clutter-device-manager.c index 5bde10d..c38cdd6 100644 --- a/clutter/clutter-device-manager.c +++ b/clutter/clutter-device-manager.c @@ -75,7 +75,7 @@ clutter_device_manager_class_init (ClutterDeviceManagerClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - clutter_marshal_VOID__POINTER, + clutter_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -85,7 +85,7 @@ clutter_device_manager_class_init (ClutterDeviceManagerClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - clutter_marshal_VOID__POINTER, + clutter_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_POINTER); } diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c index 913ba13..f22a9cf 100644 --- a/clutter/clutter-input-device.c +++ b/clutter/clutter-input-device.c @@ -242,25 +242,91 @@ cursor_weak_unref (gpointer user_data, device->cursor_actor = NULL; } +/* + * _clutter_input_device_set_actor: + * @device: a #ClutterInputDevice + * @actor: a #ClutterActor + * + * Sets the actor under the pointer coordinates of @device + * + * This function is called by _clutter_input_device_update() + * and it will: + * + * - queue a %CLUTTER_LEAVE event on the previous pointer actor + * of @device, if any + * - set to %FALSE the :has-pointer property of the previous + * pointer actor of @device, if any + * - queue a %CLUTTER_ENTER event on the new pointer actor + * - set to %TRUE the :has-pointer property of the new pointer + * actor + */ void _clutter_input_device_set_actor (ClutterInputDevice *device, ClutterActor *actor) { + ClutterActor *old_actor; + ClutterEvent cev; + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - if (device->cursor_actor != NULL) + if (actor == device->cursor_actor) + return; + + old_actor = device->cursor_actor; + if (old_actor != NULL) { + cev.crossing.type = CLUTTER_LEAVE; + cev.crossing.time = device->previous_time; + cev.crossing.flags = 0; + cev.crossing.stage = device->stage; + cev.crossing.source = device->cursor_actor; + cev.crossing.x = device->previous_x; + cev.crossing.y = device->previous_y; + cev.crossing.device = device; + cev.crossing.related = actor; + + /* 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 + */ + _clutter_process_event (&cev); + _clutter_actor_set_has_pointer (device->cursor_actor, FALSE); g_object_weak_unref (G_OBJECT (device->cursor_actor), cursor_weak_unref, device); + + device->cursor_actor = NULL; + } + + if (actor != NULL) + { + cev.crossing.type = CLUTTER_ENTER; + cev.crossing.time = device->current_time; + cev.crossing.flags = 0; + cev.crossing.stage = device->stage; + cev.crossing.source = actor; + cev.crossing.x = device->current_x; + cev.crossing.y = device->current_y; + cev.crossing.device = device; + cev.crossing.related = old_actor; + + /* as above: 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 + */ + _clutter_process_event (&cev); } device->cursor_actor = actor; - g_object_weak_ref (G_OBJECT (device->cursor_actor), - cursor_weak_unref, - device); - _clutter_actor_set_has_pointer (device->cursor_actor, TRUE); + + if (device->cursor_actor != NULL) + { + g_object_weak_ref (G_OBJECT (device->cursor_actor), + cursor_weak_unref, + device); + _clutter_actor_set_has_pointer (device->cursor_actor, TRUE); + } } /** @@ -345,7 +411,7 @@ _clutter_input_device_update (ClutterInputDevice *device) * in which case this is the safest course of action anyway */ if (new_cursor_actor == NULL) - new_cursor_actor = CLUTTER_ACTOR (stage); + return NULL; CLUTTER_NOTE (EVENT, "Actor under cursor (device %d, at %d, %d): %s", @@ -355,6 +421,9 @@ _clutter_input_device_update (ClutterInputDevice *device) ? clutter_actor_get_name (new_cursor_actor) : G_OBJECT_TYPE_NAME (new_cursor_actor)); + if (new_cursor_actor == old_cursor_actor) + return old_cursor_actor; + _clutter_input_device_set_actor (device, new_cursor_actor); return device->cursor_actor; diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index c177d3a..644d20e 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -2182,27 +2182,26 @@ static inline void emit_pointer_event (ClutterEvent *event, ClutterInputDevice *device) { - /* Using the global variable directly, since it has to be initialized - * at this point - */ - ClutterMainContext *context = ClutterCntx; + ClutterMainContext *context = _clutter_context_get_default (); - if (G_UNLIKELY (context->pointer_grab_actor != NULL && - device == NULL)) + if (context->pointer_grab_actor == NULL && + (device == NULL || device->pointer_grab_actor == NULL)) { - /* global grab */ - clutter_actor_event (context->pointer_grab_actor, event, FALSE); - } - else if (G_UNLIKELY (device != NULL && - device->pointer_grab_actor != NULL)) - { - /* per device grab */ - clutter_actor_event (device->pointer_grab_actor, event, FALSE); + /* no grab, time to capture and bubble */ + emit_event (event, FALSE); } else { - /* no grab, time to capture and bubble */ - emit_event (event, FALSE); + if (context->pointer_grab_actor != NULL) + { + /* global grab */ + clutter_actor_event (context->pointer_grab_actor, event, FALSE); + } + else if (device != NULL && device->pointer_grab_actor != NULL) + { + /* per device grab */ + clutter_actor_event (device->pointer_grab_actor, event, FALSE); + } } } @@ -2211,107 +2210,10 @@ emit_keyboard_event (ClutterEvent *event) { ClutterMainContext *context = _clutter_context_get_default (); - if (G_UNLIKELY (context->keyboard_grab_actor != NULL)) - clutter_actor_event (context->keyboard_grab_actor, event, FALSE); - else + if (context->keyboard_grab_actor == NULL) emit_event (event, TRUE); -} - -static void -unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev) -{ - ClutterMainContext *context = _clutter_context_get_default (); - - if (dev == NULL) - context->motion_last_actor = NULL; else - dev->motion_last_actor = NULL; -} - -static void -set_motion_last_actor (ClutterActor *motion_current_actor, - ClutterInputDevice *device) -{ - ClutterMainContext *context = _clutter_context_get_default (); - ClutterActor *last_actor = context->motion_last_actor; - - if (device != NULL) - last_actor = device->motion_last_actor; - - if (last_actor && last_actor != motion_current_actor) - { - g_signal_handlers_disconnect_by_func - (last_actor, - G_CALLBACK (unset_motion_last_actor), - device); - } - - if (motion_current_actor && last_actor != motion_current_actor) - { - g_signal_connect (motion_current_actor, "destroy", - G_CALLBACK (unset_motion_last_actor), - device); - } - - if (device != NULL) - device->motion_last_actor = motion_current_actor; - else - context->motion_last_actor = motion_current_actor; -} - -static inline void -generate_enter_leave_events (ClutterEvent *event) -{ - ClutterMainContext *context = _clutter_context_get_default (); - ClutterActor *motion_current_actor = event->motion.source; - ClutterActor *last_actor = context->motion_last_actor; - ClutterInputDevice *device = clutter_event_get_device (event); - - if (device != NULL) - last_actor = device->motion_last_actor; - - if (last_actor != motion_current_actor) - { - if (motion_current_actor) - { - ClutterEvent cev; - gfloat x, y; - - cev.crossing.device = device; - clutter_event_get_coords (event, &x, &y); - - if (context->motion_last_actor) - { - cev.crossing.type = CLUTTER_LEAVE; - cev.crossing.time = event->any.time; - cev.crossing.flags = 0; - cev.crossing.x = x; - cev.crossing.y = y; - cev.crossing.source = last_actor; - cev.crossing.stage = event->any.stage; - cev.crossing.related = motion_current_actor; - - emit_pointer_event (&cev, device); - } - - cev.crossing.type = CLUTTER_ENTER; - cev.crossing.time = event->any.time; - cev.crossing.flags = 0; - cev.crossing.x = x; - cev.crossing.y = y; - cev.crossing.source = motion_current_actor; - cev.crossing.stage = event->any.stage; - - if (context->motion_last_actor) - cev.crossing.related = last_actor; - else - cev.crossing.related = NULL; - - emit_pointer_event (&cev, device); - } - } - - set_motion_last_actor (motion_current_actor, device); + clutter_actor_event (context->keyboard_grab_actor, event, FALSE); } /** @@ -2343,7 +2245,9 @@ _clutter_process_event_details (ClutterActor *stage, ClutterMainContext *context, ClutterEvent *event) { - ClutterInputDevice *device = NULL; + ClutterInputDevice *device = NULL; + + device = clutter_event_get_device (event); switch (event->type) { @@ -2352,23 +2256,8 @@ _clutter_process_event_details (ClutterActor *stage, break; case CLUTTER_LEAVE: - /* The source is set for generated events, not for events - * resulting from the cursor leaving the stage - */ - if (event->any.source == NULL) - { - ClutterActor *last_actor = context->motion_last_actor; - - if (event->crossing.device != NULL) - last_actor = event->crossing.device->motion_last_actor; - - event->any.source = last_actor; - - set_motion_last_actor (NULL, event->crossing.device); - } - /* flow through */ case CLUTTER_ENTER: - emit_pointer_event (event, event->crossing.device); + emit_pointer_event (event, device); break; case CLUTTER_DESTROY_NOTIFY: @@ -2400,8 +2289,6 @@ _clutter_process_event_details (ClutterActor *stage, break; case CLUTTER_MOTION: - device = event->motion.device; - /* Only stage gets motion events if clutter_set_motion_events is TRUE, * and the event is not a synthetic event with source set. */ @@ -2434,8 +2321,7 @@ _clutter_process_event_details (ClutterActor *stage, break; } - /* fallthrough */ - + /* fallthrough from motion */ case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_RELEASE: case CLUTTER_SCROLL: @@ -2445,24 +2331,6 @@ _clutter_process_event_details (ClutterActor *stage, clutter_event_get_coords (event, &x, &y); - if (device == NULL) - { - switch (event->type) - { - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - device = event->button.device; - break; - case CLUTTER_SCROLL: - device = event->scroll.device; - break; - case CLUTTER_MOTION: - /* already handled in the MOTION case of the switch */ - default: - break; - } - } - /* Only do a pick to find the source if source is not already set * (as it could be in a synthetic event) */ @@ -2480,7 +2348,7 @@ _clutter_process_event_details (ClutterActor *stage, x, y); event->button.source = stage; - emit_pointer_event (event, event->button.device); + emit_pointer_event (event, device); } break; } @@ -2489,20 +2357,19 @@ _clutter_process_event_details (ClutterActor *stage, * already have everything we need to update it and * get the actor underneath */ - if (device == NULL) + if (device != NULL) + actor = _clutter_input_device_update (device); + else { CLUTTER_NOTE (EVENT, "No device found: picking"); - /* Map the event to a reactive actor */ actor = _clutter_do_pick (CLUTTER_STAGE (stage), x, y, CLUTTER_PICK_REACTIVE); } - else - actor = _clutter_input_device_update (device); event->any.source = actor; - if (actor == NULL) + if (event->any.source == NULL) break; } else @@ -2521,9 +2388,6 @@ _clutter_process_event_details (ClutterActor *stage, x, y, actor); - /* Create, enter/leave events if needed */ - generate_enter_leave_events (event); - if (event->type != CLUTTER_MOTION) { /* Generate click count */ diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index dbbc96f..0280067 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -92,9 +92,7 @@ struct _ClutterInputDevice ClutterInputDeviceType device_type; ClutterActor *cursor_actor; - ClutterActor *pointer_grab_actor; - ClutterActor *motion_last_actor; gint click_count; -- 2.7.4