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>
* 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 = *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);
}
}

View File

@ -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);