[gtk+/xi2: 1000/1239] Implement grab ownership.



commit 0c7953c09c3c528814643216235059c35e91be5f
Author: Carlos Garnacho <carlos gnome org>
Date:   Fri Sep 4 00:48:02 2009 +0200

    Implement grab ownership.
    
    There are some things missing, such as sending crossing events when the
    device events are blocked/unblocked by other device grab.

 gdk/gdkdisplay.c   |   95 +++++++++++++++++++++++++++++++++++++++++----------
 gdk/gdkinternals.h |   23 ++++++++-----
 gdk/gdktypes.h     |    7 ++++
 gdk/gdkwindow.c    |   14 +++++++-
 4 files changed, 110 insertions(+), 29 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 3aa5596..32da14a 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -1009,15 +1009,16 @@ _gdk_display_get_last_pointer_grab (GdkDisplay *display,
 }
 
 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)
+_gdk_display_add_pointer_grab (GdkDisplay       *display,
+                               GdkDevice        *device,
+                               GdkWindow        *window,
+                               GdkWindow        *native_window,
+                               GdkGrabOwnership  grab_ownership,
+                               gboolean          owner_events,
+                               GdkEventMask      event_mask,
+                               unsigned long     serial_start,
+                               guint32           time,
+                               gboolean          implicit)
 {
   GdkPointerGrabInfo *info, *other_info;
   GList *grabs, *l;
@@ -1032,6 +1033,7 @@ _gdk_display_add_pointer_grab (GdkDisplay    *display,
   info->event_mask = event_mask;
   info->time = time;
   info->implicit = implicit;
+  info->ownership = grab_ownership;
 
   grabs = g_hash_table_lookup (display->device_grabs, device);
 
@@ -1367,28 +1369,35 @@ _gdk_display_pointer_grab_update (GdkDisplay *display,
 }
 
 static GList *
-find_pointer_grab (GdkDisplay *display,
-                   GdkDevice  *device,
-                   gulong      serial)
+grab_list_find (GList  *grabs,
+                gulong  serial)
 {
   GdkPointerGrabInfo *grab;
-  GList *l;
-
-  l = g_hash_table_lookup (display->device_grabs, device);
 
-  while (l)
+  while (grabs)
     {
-      grab = l->data;
+      grab = grabs->data;
 
       if (serial >= grab->serial_start && serial < grab->serial_end)
-	return l;
+	return grabs;
 
-      l = l->next;
+      grabs = grabs->next;
     }
 
   return NULL;
 }
 
+static GList *
+find_pointer_grab (GdkDisplay *display,
+                   GdkDevice  *device,
+                   gulong      serial)
+{
+  GList *l;
+
+  l = g_hash_table_lookup (display->device_grabs, device);
+  return grab_list_find (l, serial);
+}
+
 GdkPointerGrabInfo *
 _gdk_display_has_pointer_grab (GdkDisplay *display,
                                GdkDevice  *device,
@@ -1432,6 +1441,54 @@ _gdk_display_end_pointer_grab (GdkDisplay *display,
   return FALSE;
 }
 
+/* Returns TRUE if device events are not blocked by any grab */
+gboolean
+_gdk_display_check_grab_ownership (GdkDisplay *display,
+                                   GdkDevice  *device,
+                                   gulong      serial)
+{
+  GHashTableIter iter;
+  gpointer key, value;
+  GdkGrabOwnership higher_ownership, device_ownership;
+
+  g_hash_table_iter_init (&iter, display->device_grabs);
+  higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
+
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      GdkPointerGrabInfo *grab;
+      GdkDevice *dev;
+      GList *grabs;
+
+      dev = key;
+      grabs = value;
+      grabs = grab_list_find (grabs, serial);
+
+      if (!grabs)
+        continue;
+
+      grab = grabs->data;
+
+      if (dev == device)
+        device_ownership = grab->ownership;
+      else
+        {
+          if (grab->ownership > higher_ownership)
+            higher_ownership = grab->ownership;
+        }
+    }
+
+  if (higher_ownership > device_ownership)
+    {
+      /* There's a higher priority ownership
+       * going on for other device(s)
+       */
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 void
 _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
 				    GdkWindow *window,
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 4bc4b9d..7065f74 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -182,6 +182,7 @@ typedef struct
   guint event_mask;
   gboolean implicit;
   guint32 time;
+  GdkGrabOwnership ownership;
 
   gboolean activated;
   gboolean implicit_ungrab;
@@ -597,15 +598,16 @@ void _gdk_display_pointer_grab_update                    (GdkDisplay *display,
                                                           gulong      current_serial);
 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_add_pointer_grab  (GdkDisplay       *display,
+                                                    GdkDevice        *device,
+						    GdkWindow        *window,
+						    GdkWindow        *native_window,
+                                                    GdkGrabOwnership  grab_ownership,
+						    gboolean          owner_events,
+						    GdkEventMask      event_mask,
+						    unsigned long     serial_start,
+						    guint32           time,
+						    gboolean          implicit);
 GdkPointerGrabInfo * _gdk_display_has_pointer_grab (GdkDisplay *display,
                                                     GdkDevice  *device,
 						    gulong      serial);
@@ -614,6 +616,9 @@ gboolean _gdk_display_end_pointer_grab (GdkDisplay *display,
 					gulong      serial,
 					GdkWindow  *if_child,
 					gboolean    implicit);
+gboolean _gdk_display_check_grab_ownership (GdkDisplay *display,
+                                            GdkDevice  *device,
+                                            gulong      serial);
 void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
 					 GdkWindow *window,
 					 GdkWindow *native_window,
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
index ac8e443..54113ab 100644
--- a/gdk/gdktypes.h
+++ b/gdk/gdktypes.h
@@ -175,6 +175,13 @@ typedef enum
   GDK_GRAB_FROZEN          = 4
 } GdkGrabStatus;
 
+typedef enum
+{
+  GDK_OWNERSHIP_NONE,
+  GDK_OWNERSHIP_WINDOW,
+  GDK_OWNERSHIP_APPLICATION
+} GdkGrabOwnership;
+
 typedef void (*GdkInputFunction) (gpointer	    data,
 				  gint		    source,
 				  GdkInputCondition condition);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 5656936..b0f46d1 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -9324,6 +9324,7 @@ gdk_pointer_grab (GdkWindow *	  window,
                                        device,
                                        window,
                                        native,
+                                       GDK_OWNERSHIP_NONE,
                                        owner_events,
                                        event_mask,
                                        serial,
@@ -9748,6 +9749,7 @@ proxy_button_event (GdkEvent *source_event,
                                       device,
 				      pointer_window,
 				      toplevel_window,
+                                      GDK_OWNERSHIP_NONE,
 				      FALSE,
 				      gdk_window_get_events (pointer_window),
 				      serial,
@@ -9906,7 +9908,16 @@ _gdk_windowing_got_event (GdkDisplay *display,
   device = gdk_event_get_device (event);
 
   if (device)
-    _gdk_display_pointer_grab_update (display, device, serial);
+    {
+      _gdk_display_pointer_grab_update (display, device, serial);
+
+      if (!_gdk_display_check_grab_ownership (display, device, serial))
+        {
+          /* Device events are blocked by another device grab */
+          unlink_event = TRUE;
+          goto out;
+        }
+    }
 
   event_window = event->any.window;
   if (!event_window)
@@ -9921,6 +9932,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
                                           device,
 					  event_window,
 					  event_window,
+                                          GDK_OWNERSHIP_NONE,
 					  FALSE,
 					  gdk_window_get_events (event_window),
 					  serial,



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