From c606547dcbbdd0cc83f90c542e074fd5852324a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Wed, 1 Oct 2008 13:46:33 +0000 Subject: [PATCH] Bug 1108 - Enter/Leave events logics wrt. skipped motion events Handle dropped motion events when computing crossing events, based on a patch from Gwenole Beauchesne. * clutter/clutter-main.c: (clutter_event_get_device): internal static utility function. (clutter_do_event): generate enter/leave events for all pointer events. (generate_enter_leave_events): modified enter/leave events generator to work for all pointer event types. Enter/leave events are now delivered before the motion/button event that caused the crossing to happen. * clutter/clutter-event.c: (clutter_event_copy), (clutter_event_free): removed reference counting logic that is not needed when the crossing events are directly delivered. --- ChangeLog | 19 +++++++++ clutter/clutter-event.c | 17 --------- clutter/clutter-main.c | 85 +++++++++++++++++++++++++++-------------- 3 files changed, 75 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 889dcf465..85f80bcf0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-10-01 Øyvind Kolås + + Bug 1108 - Enter/Leave events logics wrt. skipped motion events + + Handle dropped motion events when computing crossing events, + based on a patch from Gwenole Beauchesne. + + * clutter/clutter-main.c: (clutter_event_get_device): internal static + utility function. + (clutter_do_event): generate enter/leave events for all pointer + events. + (generate_enter_leave_events): modified enter/leave events generator + to work for all pointer event types. Enter/leave events are now + delivered before the motion/button event that caused the crossing to + happen. + * clutter/clutter-event.c: (clutter_event_copy), (clutter_event_free): + removed reference counting logic that is not needed when the crossing + events are directly delivered. + 2008-09-29 Emmanuele Bassi * configure.ac: Post branch bump to 0.9.0 diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c index e3e3deb37..87bfa3844 100644 --- a/clutter/clutter-event.c +++ b/clutter/clutter-event.c @@ -412,19 +412,6 @@ clutter_event_copy (ClutterEvent *event) new_event = clutter_event_new (CLUTTER_NOTHING); *new_event = *event; - /* deep copies or references must be added here */ - switch (new_event->type) - { - case CLUTTER_ENTER: - case CLUTTER_LEAVE: - if (new_event->crossing.related) - g_object_ref (new_event->crossing.related); - break; - - default: - break; - } - return new_event; } @@ -439,10 +426,6 @@ clutter_event_free (ClutterEvent *event) { if (G_LIKELY (event)) { - if ((event->type == CLUTTER_LEAVE || event->type == CLUTTER_ENTER) && - event->crossing.related) - g_object_unref (event->crossing.related); - g_slice_free (ClutterEvent, event); } } diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index c73a78b33..ffd1cb01c 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -1718,61 +1718,90 @@ unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev) dev->motion_last_actor = NULL; } +static ClutterInputDevice * clutter_event_get_device (ClutterEvent *event); + +/* This function should perhaps be public and in clutter-event.c ? + */ +static ClutterInputDevice * +clutter_event_get_device (ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + return NULL; + break; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + return event->button.device; + case CLUTTER_MOTION: + return event->motion.device; + case CLUTTER_SCROLL: + return event->scroll.device; + break; + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + break; + } + return NULL; +} + static inline void generate_enter_leave_events (ClutterEvent *event) { ClutterMainContext *context = ClutterCntx; ClutterActor *motion_current_actor = event->motion.source; ClutterActor *last_actor = context->motion_last_actor; + ClutterInputDevice *device = clutter_event_get_device (event); - if (event->motion.device != NULL) - last_actor = event->motion.device->motion_last_actor; + if (device != NULL) + last_actor = device->motion_last_actor; if (last_actor != motion_current_actor) { if (motion_current_actor) { + gint x, y; ClutterEvent cev; - cev.crossing.device = event->motion.device; + 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 = event->motion.x; - cev.crossing.y = event->motion.y; + cev.crossing.x = x; + cev.crossing.y = y; cev.crossing.source = last_actor; cev.crossing.stage = event->any.stage; - - /* unref in free */ cev.crossing.related = motion_current_actor; - g_queue_push_head (context->events_queue, - clutter_event_copy (&cev)); + emit_pointer_event (&cev, device); } cev.crossing.type = CLUTTER_ENTER; cev.crossing.time = event->any.time; cev.crossing.flags = 0; - cev.crossing.x = event->motion.x; - cev.crossing.y = event->motion.y; + 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 - { - /* the previous actor we were getting events from seems to have - * vanished - */ - cev.crossing.related = NULL; - } + cev.crossing.related = NULL; - g_queue_push_head (context->events_queue, - clutter_event_copy (&cev)); + emit_pointer_event (&cev, device); } } @@ -1781,18 +1810,18 @@ generate_enter_leave_events (ClutterEvent *event) g_signal_handlers_disconnect_by_func (last_actor, G_CALLBACK (unset_motion_last_actor), - event->motion.device); + device); } if (motion_current_actor && last_actor != motion_current_actor) { g_signal_connect (motion_current_actor, "destroy", G_CALLBACK (unset_motion_last_actor), - event->motion.device); + device); } - if (event->motion.device != NULL) - event->motion.device->motion_last_actor = motion_current_actor; + if (device != NULL) + device->motion_last_actor = motion_current_actor; else context->motion_last_actor = motion_current_actor; } @@ -2012,12 +2041,10 @@ clutter_do_event (ClutterEvent *event) CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p", x, y, actor); - if (event->type == CLUTTER_MOTION) - { - /* Generate enter leave events (if any) */ - generate_enter_leave_events (event); - } - else /* (button event) */ + /* Create, enter/leave events if needed */ + generate_enter_leave_events (event); + + if (event->type != CLUTTER_MOTION) { /* Generate click count */ event_click_count_generate (event);