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.
This commit is contained in:
Øyvind Kolås 2008-10-01 13:46:33 +00:00
parent c05af0ed87
commit c606547dcb
3 changed files with 75 additions and 46 deletions

View File

@ -1,3 +1,22 @@
2008-10-01 Øyvind Kolås <pippin@linux.intel.com>
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 <ebassi@linux.intel.com> 2008-09-29 Emmanuele Bassi <ebassi@linux.intel.com>
* configure.ac: Post branch bump to 0.9.0 * configure.ac: Post branch bump to 0.9.0

View File

@ -412,19 +412,6 @@ clutter_event_copy (ClutterEvent *event)
new_event = clutter_event_new (CLUTTER_NOTHING); new_event = clutter_event_new (CLUTTER_NOTHING);
*new_event = *event; *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; return new_event;
} }
@ -439,10 +426,6 @@ clutter_event_free (ClutterEvent *event)
{ {
if (G_LIKELY (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); g_slice_free (ClutterEvent, event);
} }
} }

View File

@ -1718,61 +1718,90 @@ unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
dev->motion_last_actor = NULL; 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 static inline void
generate_enter_leave_events (ClutterEvent *event) generate_enter_leave_events (ClutterEvent *event)
{ {
ClutterMainContext *context = ClutterCntx; ClutterMainContext *context = ClutterCntx;
ClutterActor *motion_current_actor = event->motion.source; ClutterActor *motion_current_actor = event->motion.source;
ClutterActor *last_actor = context->motion_last_actor; ClutterActor *last_actor = context->motion_last_actor;
ClutterInputDevice *device = clutter_event_get_device (event);
if (event->motion.device != NULL) if (device != NULL)
last_actor = event->motion.device->motion_last_actor; last_actor = device->motion_last_actor;
if (last_actor != motion_current_actor) if (last_actor != motion_current_actor)
{ {
if (motion_current_actor) if (motion_current_actor)
{ {
gint x, y;
ClutterEvent cev; ClutterEvent cev;
cev.crossing.device = event->motion.device; cev.crossing.device = device;
clutter_event_get_coords (event, &x, &y);
if (context->motion_last_actor) if (context->motion_last_actor)
{ {
cev.crossing.type = CLUTTER_LEAVE; cev.crossing.type = CLUTTER_LEAVE;
cev.crossing.time = event->any.time; cev.crossing.time = event->any.time;
cev.crossing.flags = 0; cev.crossing.flags = 0;
cev.crossing.x = event->motion.x; cev.crossing.x = x;
cev.crossing.y = event->motion.y; cev.crossing.y = y;
cev.crossing.source = last_actor; cev.crossing.source = last_actor;
cev.crossing.stage = event->any.stage; cev.crossing.stage = event->any.stage;
/* unref in free */
cev.crossing.related = motion_current_actor; cev.crossing.related = motion_current_actor;
g_queue_push_head (context->events_queue, emit_pointer_event (&cev, device);
clutter_event_copy (&cev));
} }
cev.crossing.type = CLUTTER_ENTER; cev.crossing.type = CLUTTER_ENTER;
cev.crossing.time = event->any.time; cev.crossing.time = event->any.time;
cev.crossing.flags = 0; cev.crossing.flags = 0;
cev.crossing.x = event->motion.x; cev.crossing.x = x;
cev.crossing.y = event->motion.y; cev.crossing.y = y;
cev.crossing.source = motion_current_actor; cev.crossing.source = motion_current_actor;
cev.crossing.stage = event->any.stage; cev.crossing.stage = event->any.stage;
if (context->motion_last_actor) if (context->motion_last_actor)
cev.crossing.related = last_actor; cev.crossing.related = last_actor;
else else
{ cev.crossing.related = NULL;
/* the previous actor we were getting events from seems to have
* vanished
*/
cev.crossing.related = NULL;
}
g_queue_push_head (context->events_queue, emit_pointer_event (&cev, device);
clutter_event_copy (&cev));
} }
} }
@ -1781,18 +1810,18 @@ generate_enter_leave_events (ClutterEvent *event)
g_signal_handlers_disconnect_by_func g_signal_handlers_disconnect_by_func
(last_actor, (last_actor,
G_CALLBACK (unset_motion_last_actor), G_CALLBACK (unset_motion_last_actor),
event->motion.device); device);
} }
if (motion_current_actor && last_actor != motion_current_actor) if (motion_current_actor && last_actor != motion_current_actor)
{ {
g_signal_connect (motion_current_actor, "destroy", g_signal_connect (motion_current_actor, "destroy",
G_CALLBACK (unset_motion_last_actor), G_CALLBACK (unset_motion_last_actor),
event->motion.device); device);
} }
if (event->motion.device != NULL) if (device != NULL)
event->motion.device->motion_last_actor = motion_current_actor; device->motion_last_actor = motion_current_actor;
else else
context->motion_last_actor = motion_current_actor; 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", CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p",
x, y, actor); x, y, actor);
if (event->type == CLUTTER_MOTION) /* Create, enter/leave events if needed */
{ generate_enter_leave_events (event);
/* Generate enter leave events (if any) */
generate_enter_leave_events (event); if (event->type != CLUTTER_MOTION)
}
else /* (button event) */
{ {
/* Generate click count */ /* Generate click count */
event_click_count_generate (event); event_click_count_generate (event);