[gtk+/xi2: 923/1239] GdkDisplay: Make pointer_grabs per-device.



commit d336841544c0e604d01dd8be8c269eed08b107dc
Author: Carlos Garnacho <carlos lanedo com>
Date:   Sat Aug 29 15:06:14 2009 +0200

    GdkDisplay: Make pointer_grabs per-device.
    
    Now all the stored grab info is multidevice-aware, although some callers still
    aren't. Also replaced _gdk_windowing_pointer_grab() with
    _gdk_windowing_device_grab(), gdk_pointer_grab() now tries to grab all devices,
    (sort of what it did before inside the X11 backend), this might not be
    the best thing to do in other backends though.

 gdk/gdkdisplay.c         |  180 +++++++++++++++++++++++++++-------------------
 gdk/gdkdisplay.h         |    2 +-
 gdk/gdkinternals.h       |   33 +++++----
 gdk/gdkwindow.c          |   80 ++++++++++++++-------
 gdk/x11/gdkdisplay-x11.c |    4 +-
 gdk/x11/gdkmain-x11.c    |   77 ++++++--------------
 6 files changed, 206 insertions(+), 170 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index dfeefd3..38a8b6c 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -180,6 +180,27 @@ free_pointer_info (GdkPointerWindowInfo *info)
 }
 
 static void
+free_pointer_grab (GdkPointerGrabInfo *info)
+{
+  g_object_unref (info->window);
+  g_object_unref (info->native_window);
+  g_free (info);
+}
+
+static gboolean
+free_pointer_grabs_foreach (gpointer key,
+                            gpointer value,
+                            gpointer user_data)
+{
+  GList *list = value;
+
+  g_list_foreach (list, (GFunc) free_pointer_grab, NULL);
+  g_list_free (list);
+
+  return TRUE;
+}
+
+static void
 gdk_display_init (GdkDisplay *display)
 {
   _gdk_displays = g_slist_prepend (_gdk_displays, display);
@@ -189,6 +210,8 @@ gdk_display_init (GdkDisplay *display)
 
   display->device_hooks = &default_device_hooks;
 
+  display->device_grabs = g_hash_table_new (NULL, NULL);
+
   display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
                                                   (GDestroyNotify) free_pointer_info);
 
@@ -226,6 +249,11 @@ gdk_display_finalize (GObject *object)
 {
   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
 
+  g_hash_table_foreach_remove (display->device_grabs,
+                               free_pointer_grabs_foreach,
+                               NULL);
+  g_hash_table_destroy (display->device_grabs);
+
   g_hash_table_destroy (display->pointers_info);
   g_hash_table_destroy (display->multiple_click_info);
 
@@ -923,31 +951,35 @@ generate_grab_broken_event (GdkWindow *window,
 }
 
 GdkPointerGrabInfo *
-_gdk_display_get_last_pointer_grab (GdkDisplay *display)
+_gdk_display_get_last_pointer_grab (GdkDisplay *display,
+                                    GdkDevice  *device)
 {
   GList *l;
 
-  l = g_list_last (display->pointer_grabs);
+  l = g_hash_table_lookup (display->device_grabs, device);
 
-  if (l == NULL)
-    return NULL;
-  else
-    return (GdkPointerGrabInfo *)l->data;
-}
+  if (l)
+    {
+      l = g_list_last (l);
+      return l->data;
+    }
 
+  return NULL;
+}
 
 GdkPointerGrabInfo *
-_gdk_display_add_pointer_grab (GdkDisplay *display,
-			       GdkWindow *window,
-			       GdkWindow *native_window,
-			       gboolean owner_events,
-			       GdkEventMask event_mask,
-			       unsigned long serial_start,
-			       guint32 time,
-			       gboolean implicit)
+_gdk_display_add_pointer_grab (GdkDisplay    *display,
+                               GdkDevice     *device,
+			       GdkWindow     *window,
+			       GdkWindow     *native_window,
+			       gboolean       owner_events,
+			       GdkEventMask   event_mask,
+			       unsigned long  serial_start,
+			       guint32        time,
+			       gboolean       implicit)
 {
   GdkPointerGrabInfo *info, *other_info;
-  GList *l;
+  GList *grabs, *l;
 
   info = g_new0 (GdkPointerGrabInfo, 1);
 
@@ -960,18 +992,20 @@ _gdk_display_add_pointer_grab (GdkDisplay *display,
   info->time = time;
   info->implicit = implicit;
 
+  grabs = g_hash_table_lookup (display->device_grabs, device);
+
   /* Find the first grab that has a larger start time (if any) and insert
    * before that. I.E we insert after already existing grabs with same
    * start time */
-  for (l = display->pointer_grabs; l != NULL; l = l->next)
+  for (l = grabs; l != NULL; l = l->next)
     {
       other_info = l->data;
-      
+
       if (info->serial_start < other_info->serial_start)
 	break;
     }
-  display->pointer_grabs =
-    g_list_insert_before (display->pointer_grabs, l, info);
+
+  grabs = g_list_insert_before (grabs, l, info);
 
   /* Make sure the new grab end before next grab */
   if (l)
@@ -979,9 +1013,9 @@ _gdk_display_add_pointer_grab (GdkDisplay *display,
       other_info = l->data;
       info->serial_end = other_info->serial_start;
     }
-  
+
   /* Find any previous grab and update its end time */
-  l = g_list_find  (display->pointer_grabs, info);
+  l = g_list_find (grabs, info);
   l = l->prev;
   if (l)
     {
@@ -989,27 +1023,21 @@ _gdk_display_add_pointer_grab (GdkDisplay *display,
       other_info->serial_end = serial_start;
     }
 
-  return info;
-}
+  g_hash_table_insert (display->device_grabs, device, grabs);
 
-static void
-free_pointer_grab (GdkPointerGrabInfo *info)
-{
-  g_object_unref (info->window);
-  g_object_unref (info->native_window);
-  g_free (info);
+  return info;
 }
 
 /* _gdk_synthesize_crossing_events only works inside one toplevel.
    This function splits things into two calls if needed, converting the
    coordinates to the right toplevel */
 static void
-synthesize_crossing_events (GdkDisplay *display,
-			    GdkWindow *src_window,
-			    GdkWindow *dest_window,
-			    GdkCrossingMode crossing_mode,
-			    guint32 time,
-			    gulong serial)
+synthesize_crossing_events (GdkDisplay      *display,
+			    GdkWindow       *src_window,
+			    GdkWindow       *dest_window,
+			    GdkCrossingMode  crossing_mode,
+			    guint32          time,
+			    gulong           serial)
 {
   GdkWindow *src_toplevel, *dest_toplevel;
   GdkModifierType state;
@@ -1143,8 +1171,8 @@ switch_to_pointer_grab (GdkDisplay         *display,
   int x, y;
 
   /* Temporarily unset pointer to make sure we send the crossing events below */
-  old_grabs = display->pointer_grabs;
-  display->pointer_grabs = NULL;
+  old_grabs = g_hash_table_lookup (display->device_grabs, device);
+  g_hash_table_steal (display->device_grabs, device);
   info = _gdk_display_get_pointer_info (display, device);
 
   if (grab)
@@ -1166,11 +1194,9 @@ switch_to_pointer_grab (GdkDisplay         *display,
 	    src_window = info->window_under_pointer;
 
 	  if (src_window != grab->window)
-	    {
-	      synthesize_crossing_events (display,
-					  src_window, grab->window,
-					  GDK_CROSSING_GRAB, time, serial);
-	    }
+            synthesize_crossing_events (display,
+                                        src_window, grab->window,
+                                        GDK_CROSSING_GRAB, time, serial);
 
 	  /* !owner_event Grabbing a window that we're not inside, current status is
 	     now NULL (i.e. outside grabbed window) */
@@ -1219,9 +1245,9 @@ switch_to_pointer_grab (GdkDisplay         *display,
 	    }
 
 	  if (pointer_window != last_grab->window)
-	    synthesize_crossing_events (display,
-					last_grab->window, pointer_window,
-					GDK_CROSSING_UNGRAB, time, serial);
+            synthesize_crossing_events (display,
+                                        last_grab->window, pointer_window,
+                                        GDK_CROSSING_UNGRAB, time, serial);
 
 	  /* We're now ungrabbed, update the window_under_pointer */
 	  _gdk_display_set_window_under_pointer (display, device, pointer_window);
@@ -1233,7 +1259,7 @@ switch_to_pointer_grab (GdkDisplay         *display,
 	}
     }
 
-  display->pointer_grabs = old_grabs;
+  g_hash_table_insert (display->device_grabs, device, old_grabs);
 }
 
 void
@@ -1242,16 +1268,18 @@ _gdk_display_pointer_grab_update (GdkDisplay *display,
                                   gulong      current_serial)
 {
   GdkPointerGrabInfo *current_grab, *next_grab;
+  GList *grabs;
   guint32 time;
 
   time = display->last_event_time;
+  grabs = g_hash_table_lookup (display->device_grabs, device);
 
-  while (display->pointer_grabs != NULL)
+  while (grabs != NULL)
     {
-      current_grab = display->pointer_grabs->data;
+      current_grab = grabs->data;
 
       if (current_grab->serial_start > current_serial)
-	return; /* Hasn't started yet */
+        return; /* Hasn't started yet */
 
       if (current_grab->serial_end > current_serial ||
 	  (current_grab->serial_end == current_serial &&
@@ -1266,12 +1294,11 @@ _gdk_display_pointer_grab_update (GdkDisplay *display,
 	  break;
 	}
 
-
       next_grab = NULL;
-      if (display->pointer_grabs->next)
+      if (grabs->next)
 	{
 	  /* This is the next active grab */
-	  next_grab = display->pointer_grabs->next->data;
+	  next_grab = grabs->next->data;
 
 	  if (next_grab->serial_start > current_serial)
 	    next_grab = NULL; /* Actually its not yet active */
@@ -1283,11 +1310,9 @@ _gdk_display_pointer_grab_update (GdkDisplay *display,
 				    FALSE, current_grab->implicit,
 				    next_grab? next_grab->window : NULL);
 
-
       /* Remove old grab */
-      display->pointer_grabs =
-	g_list_delete_link (display->pointer_grabs,
-			    display->pointer_grabs);
+      grabs = g_list_delete_link (grabs, grabs);
+      g_hash_table_insert (display->device_grabs, device, grabs);
 
       switch_to_pointer_grab (display, device,
 			      next_grab, current_grab,
@@ -1299,49 +1324,54 @@ _gdk_display_pointer_grab_update (GdkDisplay *display,
 
 static GList *
 find_pointer_grab (GdkDisplay *display,
-		   gulong serial)
+                   GdkDevice  *device,
+                   gulong      serial)
 {
   GdkPointerGrabInfo *grab;
   GList *l;
 
-  for (l = display->pointer_grabs; l != NULL; l = l->next)
+  l = g_hash_table_lookup (display->device_grabs, device);
+
+  while (l)
     {
       grab = l->data;
 
       if (serial >= grab->serial_start && serial < grab->serial_end)
 	return l;
+
+      l = l->next;
     }
-  
+
   return NULL;
 }
 
-
-
 GdkPointerGrabInfo *
 _gdk_display_has_pointer_grab (GdkDisplay *display,
-			       gulong serial)
+                               GdkDevice  *device,
+			       gulong      serial)
 {
   GList *l;
 
-  l = find_pointer_grab (display, serial);
+  l = find_pointer_grab (display, device, serial);
   if (l)
     return l->data;
-  
+
   return NULL;
 }
 
 /* Returns true if last grab was ended */
 gboolean
 _gdk_display_end_pointer_grab (GdkDisplay *display,
-			       gulong serial,
-			       GdkWindow *if_child,
-			       gboolean implicit)
+                               GdkDevice  *device,
+			       gulong      serial,
+			       GdkWindow  *if_child,
+			       gboolean    implicit)
 {
   GdkPointerGrabInfo *grab;
   GList *l;
 
-  l = find_pointer_grab (display, serial);
-  
+  l = find_pointer_grab (display, device, serial);
+
   if (l == NULL)
     return FALSE;
 
@@ -1485,7 +1515,8 @@ gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
   /* What we're interested in is the steady state (ie last grab),
      because we're interested e.g. if we grabbed so that we
      can ungrab, even if our grab is not active just yet. */
-  info = _gdk_display_get_last_pointer_grab (display);
+  /* FIXME: which device? */
+  info = _gdk_display_get_last_pointer_grab (display, display->core_pointer);
   
   if (info)
     {
@@ -1515,14 +1546,15 @@ gboolean
 gdk_display_pointer_is_grabbed (GdkDisplay *display)
 {
   GdkPointerGrabInfo *info;
-  
+
   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
 
   /* What we're interested in is the steady state (ie last grab),
      because we're interested e.g. if we grabbed so that we
      can ungrab, even if our grab is not active just yet. */
-  info = _gdk_display_get_last_pointer_grab (display);
-  
+  /* FIXME: which device? */
+  info = _gdk_display_get_last_pointer_grab (display, display->core_pointer);
+
   return (info && !info->implicit);
 }
 
diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h
index 0e56a49..2b562e3 100644
--- a/gdk/gdkdisplay.h
+++ b/gdk/gdkdisplay.h
@@ -102,7 +102,7 @@ struct _GdkDisplay
 
   guint double_click_distance;	/* Maximum distance between clicks in pixels */
 
-  GList *pointer_grabs;
+  GHashTable *device_grabs;
   GdkKeyboardGrabInfo keyboard_grab;
 
   gulong motion_hint_serial; /* 0 == didn't deliver hinted motion event */
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index b3f69ea..4bc4b9d 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -473,7 +473,8 @@ GdkWindow* _gdk_windowing_window_at_device_position  (GdkDisplay       *display,
                                                       gint             *win_x,
                                                       gint             *win_y,
                                                       GdkModifierType  *mask);
-GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
+GdkGrabStatus _gdk_windowing_device_grab     (GdkDevice        *device,
+                                              GdkWindow        *window,
 					      GdkWindow        *native,
 					      gboolean          owner_events,
 					      GdkEventMask      event_mask,
@@ -594,21 +595,25 @@ GdkPointerGrabInfo *_gdk_display_get_active_pointer_grab (GdkDisplay *display);
 void _gdk_display_pointer_grab_update                    (GdkDisplay *display,
                                                           GdkDevice  *device,
                                                           gulong      current_serial);
-GdkPointerGrabInfo *_gdk_display_get_last_pointer_grab (GdkDisplay *display);
-GdkPointerGrabInfo *_gdk_display_add_pointer_grab  (GdkDisplay *display,
-						    GdkWindow *window,
-						    GdkWindow *native_window,
-						    gboolean owner_events,
-						    GdkEventMask event_mask,
-						    unsigned long serial_start,
-						    guint32 time,
-						    gboolean implicit);
+GdkPointerGrabInfo *_gdk_display_get_last_pointer_grab (GdkDisplay *display,
+                                                        GdkDevice  *device);
+GdkPointerGrabInfo *_gdk_display_add_pointer_grab  (GdkDisplay    *display,
+                                                    GdkDevice     *device,
+						    GdkWindow     *window,
+						    GdkWindow     *native_window,
+						    gboolean       owner_events,
+						    GdkEventMask   event_mask,
+						    unsigned long  serial_start,
+						    guint32        time,
+						    gboolean       implicit);
 GdkPointerGrabInfo * _gdk_display_has_pointer_grab (GdkDisplay *display,
-						    gulong serial);
+                                                    GdkDevice  *device,
+						    gulong      serial);
 gboolean _gdk_display_end_pointer_grab (GdkDisplay *display,
-					gulong serial,
-					GdkWindow *if_child,
-					gboolean implicit);
+                                        GdkDevice  *device,
+					gulong      serial,
+					GdkWindow  *if_child,
+					gboolean    implicit);
 void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
 					 GdkWindow *window,
 					 GdkWindow *native_window,
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 10b03a7..4c74ecb 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -6437,7 +6437,9 @@ gdk_window_hide (GdkWindow *window)
       /* May need to break grabs on children */
       display = gdk_drawable_get_display (window);
 
+      /* FIXME: which device(s)? */
       if (_gdk_display_end_pointer_grab (display,
+                                         display->core_pointer,
 					 _gdk_windowing_window_get_next_serial (display),
 					 window,
 					 TRUE))
@@ -8404,7 +8406,7 @@ update_cursor (GdkDisplay *display,
 
   /* We ignore the serials here and just pick the last grab
      we've sent, as that would shortly be used anyway. */
-  grab = _gdk_display_get_last_pointer_grab (display);
+  grab = _gdk_display_get_last_pointer_grab (display, device);
   if (grab != NULL &&
       !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
     cursor_window = (GdkWindowObject *)grab->window;
@@ -8943,7 +8945,7 @@ send_crossing_event (GdkDisplay                 *display,
   GdkPointerGrabInfo *grab;
   gboolean block_event = FALSE;
 
-  grab = _gdk_display_has_pointer_grab (display, serial);
+  grab = _gdk_display_has_pointer_grab (display, device, serial);
 
   if (grab != NULL &&
       !grab->owner_events &&
@@ -9181,7 +9183,7 @@ get_pointer_window (GdkDisplay *display,
   else
     pointer_window = NULL;
 
-  grab = _gdk_display_has_pointer_grab (display, serial);
+  grab = _gdk_display_has_pointer_grab (display, device, serial);
   if (grab != NULL &&
       !grab->owner_events &&
       pointer_window != grab->window)
@@ -9252,8 +9254,11 @@ gdk_pointer_grab (GdkWindow *	  window,
 {
   GdkWindow *native;
   GdkDisplay *display;
+  GdkDeviceManager *device_manager;
+  GdkDevice *device;
   GdkGrabStatus res;
   gulong serial;
+  GList *devices, *dev;
 
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
@@ -9293,24 +9298,39 @@ gdk_pointer_grab (GdkWindow *	  window,
   display = gdk_drawable_get_display (window);
 
   serial = _gdk_windowing_window_get_next_serial (display);
+  device_manager = gdk_device_manager_get_for_display (display);
+  devices = gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+  /* FIXME: Should this be generic to all backends? */
+  for (dev = devices; dev; dev = dev->next)
+    {
+      device = dev->data;
+
+      if (device->source != GDK_SOURCE_MOUSE)
+        continue;
+
+      res = _gdk_windowing_device_grab (device,
+                                        window,
+                                        native,
+                                        owner_events,
+                                        event_mask,
+                                        confine_to,
+                                        cursor,
+                                        time);
 
-  res = _gdk_windowing_pointer_grab (window,
-				     native,
-				     owner_events,
-				     event_mask,
-				     confine_to,
-				     cursor,
-				     time);
-
-  if (res == GDK_GRAB_SUCCESS)
-    _gdk_display_add_pointer_grab (display,
-				   window,
-				   native,
-				   owner_events,
-				   event_mask,
-				   serial,
-				   time,
-				   FALSE);
+      if (res == GDK_GRAB_SUCCESS)
+        _gdk_display_add_pointer_grab (display,
+                                       device,
+                                       window,
+                                       native,
+                                       owner_events,
+                                       event_mask,
+                                       serial,
+                                       time,
+                                       FALSE);
+    }
+
+  /* FIXME: handle errors when grabbing */
 
   return res;
 }
@@ -9414,6 +9434,7 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
 /* Don't use for crossing events */
 static GdkWindow *
 get_event_window (GdkDisplay                 *display,
+                  GdkDevice                  *device,
 		  GdkWindow                  *pointer_window,
 		  GdkEventType                type,
 		  GdkModifierType             mask,
@@ -9425,7 +9446,7 @@ get_event_window (GdkDisplay                 *display,
   GdkWindowObject *w;
   GdkPointerGrabInfo *grab;
 
-  grab = _gdk_display_has_pointer_grab (display, serial);
+  grab = _gdk_display_has_pointer_grab (display, device, serial);
 
   if (grab != NULL && !grab->owner_events)
     {
@@ -9622,6 +9643,7 @@ proxy_pointer_event (GdkDisplay                 *display,
       gboolean is_hint;
 
       event_win = get_event_window (display,
+                                    device,
 				    pointer_window,
 				    source_event->type,
 				    state,
@@ -9700,7 +9722,7 @@ proxy_button_event (GdkEvent *source_event,
 						       &toplevel_x, &toplevel_y);
 
   if (type == GDK_BUTTON_PRESS &&
-      _gdk_display_has_pointer_grab (display, serial) == NULL)
+      _gdk_display_has_pointer_grab (display, device, serial) == NULL)
     {
       pointer_window =
 	_gdk_window_find_descendant_at (toplevel_window,
@@ -9720,6 +9742,7 @@ proxy_button_event (GdkEvent *source_event,
       pointer_window = (GdkWindow *)w;
 
       _gdk_display_add_pointer_grab  (display,
+                                      device,
 				      pointer_window,
 				      toplevel_window,
 				      FALSE,
@@ -9735,6 +9758,7 @@ proxy_button_event (GdkEvent *source_event,
 				       serial);
 
   event_win = get_event_window (display,
+                                device,
 				pointer_window,
 				type, state,
 				NULL, serial);
@@ -9888,9 +9912,10 @@ _gdk_windowing_got_event (GdkDisplay *display,
   if (_gdk_native_windows)
     {
       if (event->type == GDK_BUTTON_PRESS &&
-	  _gdk_display_has_pointer_grab (display, serial) == NULL)
+	  _gdk_display_has_pointer_grab (display, device, serial) == NULL)
 	{
 	  _gdk_display_add_pointer_grab  (display,
+                                          device,
 					  event_window,
 					  event_window,
 					  FALSE,
@@ -9903,7 +9928,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
       if (event->type == GDK_BUTTON_RELEASE)
 	{
 	  button_release_grab =
-	    _gdk_display_has_pointer_grab (display, serial);
+            _gdk_display_has_pointer_grab (display, device, serial);
 	  if (button_release_grab &&
 	      button_release_grab->implicit &&
 	      (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
@@ -9959,7 +9984,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
        event->type == GDK_LEAVE_NOTIFY) &&
       (event->crossing.mode == GDK_CROSSING_GRAB ||
        event->crossing.mode == GDK_CROSSING_UNGRAB) &&
-      (_gdk_display_has_pointer_grab (display, serial) ||
+      (_gdk_display_has_pointer_grab (display, device, serial) ||
        event->crossing.detail == GDK_NOTIFY_INFERIOR))
     {
       /* We synthesize all crossing events due to grabs ourselves,
@@ -10043,7 +10068,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
   if (event->type == GDK_BUTTON_RELEASE)
     {
       button_release_grab =
-	_gdk_display_has_pointer_grab (display, serial);
+	_gdk_display_has_pointer_grab (display, device, serial);
       if (button_release_grab &&
 	  button_release_grab->implicit &&
 	  (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
@@ -10075,7 +10100,8 @@ get_extension_event_window (GdkDisplay                 *display,
   GdkWindowObject *w;
   GdkPointerGrabInfo *grab;
 
-  grab = _gdk_display_has_pointer_grab (display, serial);
+  /* FIXME: which device? */
+  grab = _gdk_display_has_pointer_grab (display, display->core_pointer, serial);
 
   if (grab != NULL && !grab->owner_events)
     {
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 35e8718..fd8ca3f 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -1626,10 +1626,12 @@ gdk_display_pointer_ungrab (GdkDisplay *display,
 #if 0
   _gdk_input_ungrab_pointer (display, time_);
 #endif
+  /* FIXME: Use GdkDevice::ungrab */
   XUngrabPointer (xdisplay, time_);
   XFlush (xdisplay);
 
-  grab = _gdk_display_get_last_pointer_grab (display);
+  /* FIXME: which device? */
+  grab = _gdk_display_get_last_pointer_grab (display, display->core_pointer);
   if (grab &&
       (time_ == GDK_CURRENT_TIME ||
        grab->time == GDK_CURRENT_TIME ||
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index aea89b0..9ac6223 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -145,70 +145,39 @@ has_pointer_grab_callback (GdkDisplay *display,
 			   gpointer data,
 			   gulong serial)
 {
-  /* FIXME: which device? */
-  _gdk_display_pointer_grab_update (display, display->core_pointer, serial);
+  GdkDevice *device = data;
+
+  _gdk_display_pointer_grab_update (display, device, serial);
 }
 
 GdkGrabStatus
-_gdk_windowing_pointer_grab (GdkWindow *window,
-			     GdkWindow *native,
-			     gboolean owner_events,
-			     GdkEventMask event_mask,
-			     GdkWindow *confine_to,
-			     GdkCursor *cursor,
-			     guint32 time)
+_gdk_windowing_device_grab (GdkDevice    *device,
+                            GdkWindow    *window,
+                            GdkWindow    *native,
+                            gboolean      owner_events,
+                            GdkEventMask  event_mask,
+                            GdkWindow    *confine_to,
+                            GdkCursor    *cursor,
+                            guint32       time)
 {
-  GdkDeviceManager *device_manager;
   GdkDisplay *display;
-  GList *devices, *dev;
   GdkGrabStatus status = GDK_GRAB_SUCCESS;
-  GdkDevice *device;
 
   if (!window || GDK_WINDOW_DESTROYED (window))
     return GDK_GRAB_NOT_VIEWABLE;
 
-  display = gdk_drawable_get_display (window);
-  device_manager = gdk_device_manager_get_for_display (display);
-  devices = gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
-
-  /* FIXME: What to do with floating devices the window is listening to? */
-
-  for (dev = devices; dev; dev = dev->next)
-    {
-      device = dev->data;
-
-      if (device->source != GDK_SOURCE_MOUSE)
-        continue;
-
-      status = GDK_DEVICE_GET_CLASS (device)->grab (device,
-                                                    native,
-                                                    owner_events,
-                                                    event_mask,
-                                                    confine_to,
-                                                    cursor,
-                                                    time);
-
-      if (status != GDK_GRAB_SUCCESS)
-        break;
-    }
-
-  if (status != GDK_GRAB_SUCCESS)
-    {
-      /* Something went wrong, ungrab already grabbed devices */
-      while (dev)
-        {
-          device = dev->data;
-          dev = dev->prev;
-
-          if (device->source == GDK_SOURCE_MOUSE)
-            GDK_DEVICE_GET_CLASS (device)->ungrab (device, time);
-        }
-    }
-
+  display = gdk_device_get_display (device);
+  status = GDK_DEVICE_GET_CLASS (device)->grab (device,
+                                                native,
+                                                owner_events,
+                                                event_mask,
+                                                confine_to,
+                                                cursor,
+                                                time);
   if (status == GDK_GRAB_SUCCESS)
     _gdk_x11_roundtrip_async (display,
 			      has_pointer_grab_callback,
-			      NULL);
+                              device);
   return status;
 }
 
@@ -302,7 +271,8 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
 {
   GdkDisplay *display = gdk_drawable_get_display (window);
 
-  _gdk_display_end_pointer_grab (display, serial, window, TRUE);
+  /* FIXME: which device? */
+  _gdk_display_end_pointer_grab (display, display->core_pointer, serial, window, TRUE);
 
   if (display->keyboard_grab.window &&
       serial >= display->keyboard_grab.serial)
@@ -333,7 +303,8 @@ _gdk_xgrab_check_destroy (GdkWindow *window)
 
   /* Make sure there is no lasting grab in this native
      window */
-  grab = _gdk_display_get_last_pointer_grab (display);
+  /* FIXME: which device? */
+  grab = _gdk_display_get_last_pointer_grab (display, display->core_pointer);
   if (grab && grab->native_window == window)
     {
       /* We don't know the actual serial to end, but it



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