[gtk+/xi2] Implement per-device motion hints emulation.



commit a689e6624a07cd84698d458865534ffa08ef99ef
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Feb 18 01:30:42 2010 +0100

    Implement per-device motion hints emulation.
    
    Most of the points where the motion hint serial was
    being updated had a GdkDevice around, so it's been
    quite straightforward.
    
    The only point without information about an specific
    device was gdk_window_set_events(). In this case all
    devices within the window are updated, as any other
    device entering the window would have the motion hint
    serial updated anyway on crossing events.

 gdk/gdkdisplay.c   |   24 ++++++++++++++++++------
 gdk/gdkdisplay.h   |    3 +--
 gdk/gdkevents.c    |    2 +-
 gdk/gdkinternals.h |    3 ++-
 gdk/gdkwindow.c    |   34 ++++++++++++++++++++++++----------
 5 files changed, 46 insertions(+), 20 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 44e11a2..fee23ae 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -248,6 +248,8 @@ gdk_display_init (GdkDisplay *display)
   display->device_hooks = &default_device_hooks;
 
   display->device_grabs = g_hash_table_new (NULL, NULL);
+  display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
+                                                     (GDestroyNotify) g_free);
 
   display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
                                                   (GDestroyNotify) free_pointer_info);
@@ -653,11 +655,21 @@ _gdk_get_sm_client_id (void)
 }
 
 void
-_gdk_display_enable_motion_hints (GdkDisplay *display)
+_gdk_display_enable_motion_hints (GdkDisplay *display,
+                                  GdkDevice  *device)
 {
-  gulong serial;
-  
-  if (display->motion_hint_serial != 0)
+  gulong *device_serial, serial;
+
+  device_serial = g_hash_table_lookup (display->motion_hint_info, device);
+
+  if (!device_serial)
+    {
+      device_serial = g_new0 (gulong, 1);
+      *device_serial = G_MAXULONG;
+      g_hash_table_insert (display->motion_hint_info, device, device_serial);
+    }
+
+  if (*device_serial != 0)
     {
       serial = _gdk_windowing_window_get_next_serial (display);
       /* We might not actually generate the next request, so
@@ -666,8 +678,8 @@ _gdk_display_enable_motion_hints (GdkDisplay *display)
 	 anyway. */
       if (serial > 0)
 	serial--;
-      if (serial < display->motion_hint_serial)
-	display->motion_hint_serial = serial;
+      if (serial < *device_serial)
+	*device_serial = serial;
     }
 }
 
diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h
index f57fa49..714cac5 100644
--- a/gdk/gdkdisplay.h
+++ b/gdk/gdkdisplay.h
@@ -104,8 +104,7 @@ struct _GdkDisplay
   guint double_click_distance;	/* Maximum distance between clicks in pixels */
 
   GHashTable *device_grabs;
-
-  gulong motion_hint_serial; /* 0 == didn't deliver hinted motion event */
+  GHashTable *motion_hint_info;
 
   /* Hashtable containing a GdkPointerWindowInfo for each device */
   GHashTable *pointers_info;
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 61d5059..d717883 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -1041,7 +1041,7 @@ gdk_event_request_motions (const GdkEventMotion *event)
       gdk_device_get_state (event->device, event->window, NULL, NULL);
       
       display = gdk_drawable_get_display (event->window);
-      _gdk_display_enable_motion_hints (display);
+      _gdk_display_enable_motion_hints (display, event->device);
     }
 }
 
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 07cc7d0..b154c57 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -625,7 +625,8 @@ gboolean _gdk_display_end_device_grab  (GdkDisplay *display,
 gboolean _gdk_display_check_grab_ownership (GdkDisplay *display,
                                             GdkDevice  *device,
                                             gulong      serial);
-void _gdk_display_enable_motion_hints     (GdkDisplay *display);
+void _gdk_display_enable_motion_hints     (GdkDisplay *display,
+                                           GdkDevice  *device);
 
 GdkPointerWindowInfo * _gdk_display_get_pointer_info (GdkDisplay *display,
                                                       GdkDevice  *device);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 6be4f01..b326886 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -6366,7 +6366,7 @@ gdk_window_get_device_position (GdkWindow       *window,
   if (mask)
     *mask = tmp_mask;
 
-  _gdk_display_enable_motion_hints (display);
+  _gdk_display_enable_motion_hints (display, device);
 
   return child;
 }
@@ -7165,7 +7165,15 @@ gdk_window_set_events (GdkWindow       *window,
   display = gdk_drawable_get_display (window);
   if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
-    _gdk_display_enable_motion_hints (display);
+    {
+      GList *devices = private->devices_inside;
+
+      while (devices)
+        {
+          _gdk_display_enable_motion_hints (display, (GdkDevice *) devices->data);
+          devices = devices->next;
+        }
+    }
 
   private->event_mask = event_mask;
 
@@ -7235,7 +7243,7 @@ gdk_window_set_device_events (GdkWindow    *window,
   display = gdk_drawable_get_display (window);
   if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
-    _gdk_display_enable_motion_hints (display);
+    _gdk_display_enable_motion_hints (display, device);
 
   if (G_UNLIKELY (!private->device_events))
     private->device_events = g_hash_table_new (NULL, NULL);
@@ -10096,7 +10104,7 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
       update_cursor (display, device);
     }
 
-  _gdk_display_enable_motion_hints (display);
+  _gdk_display_enable_motion_hints (display, device);
 }
 
 /*
@@ -10625,13 +10633,18 @@ proxy_pointer_event (GdkDisplay                 *display,
       if (event_win &&
 	  (evmask & GDK_POINTER_MOTION_HINT_MASK))
 	{
-	  if (display->motion_hint_serial != 0 &&
-	      serial < display->motion_hint_serial)
+          gulong *device_serial;
+
+          device_serial = g_hash_table_lookup (display->motion_hint_info, device);
+
+          if (!device_serial ||
+              (*device_serial != 0 &&
+               serial < *device_serial))
 	    event_win = NULL; /* Ignore event */
 	  else
 	    {
 	      is_hint = TRUE;
-	      display->motion_hint_serial = G_MAXULONG;
+              *device_serial = G_MAXULONG;
 	    }
 	}
 
@@ -11038,9 +11051,10 @@ _gdk_windowing_got_event (GdkDisplay *display,
       event->type == GDK_BUTTON_RELEASE)
     pointer_info->button = event->button.button;
 
-  if (pointer_info->state != old_state ||
-      pointer_info->button != old_button)
-    _gdk_display_enable_motion_hints (display);
+  if (device &&
+      (pointer_info->state != old_state ||
+       pointer_info->button != old_button))
+    _gdk_display_enable_motion_hints (display, device);
 
   unlink_event = FALSE;
   if (is_motion_type (event->type))



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]