Bug 1108 - Enter/Leave events logics wrt. skipped motion events
authorØyvind Kolås <pippin@openedhand.com>
Wed, 1 Oct 2008 13:46:33 +0000 (13:46 +0000)
committerØyvind Kolås <pippin@openedhand.com>
Wed, 1 Oct 2008 13:46:33 +0000 (13:46 +0000)
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
clutter/clutter-event.c
clutter/clutter-main.c

index 889dcf4..85f80bc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index e3e3deb..87bfa38 100644 (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);
     }
 }
index c73a78b..ffd1cb0 100644 (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);