[gtk+/xi2] GtkComboBox: Add gtk_combo_box_popup_for_device().



commit 63759e1c04404385f5431eb092873cd94345276a
Author: Carlos Garnacho <carlos gnome org>
Date:   Wed Dec 23 01:04:00 2009 +0100

    GtkComboBox: Add gtk_combo_box_popup_for_device().
    
    gtk_combo_box_popup() is now implemented on top of this. Device
    aware API is now used in its internals.

 gtk/gtkcombobox.c |  114 ++++++++++++++++++++++++++++++++++++++++++----------
 gtk/gtkcombobox.h |    2 +
 2 files changed, 94 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index ebe90d9..33e41b1 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -127,6 +127,9 @@ struct _GtkComboBoxPrivate
   gpointer                    row_separator_data;
   GDestroyNotify              row_separator_destroy;
 
+  GdkDevice *grab_pointer;
+  GdkDevice *grab_keyboard;
+
   gchar *tearoff_title;
 };
 
@@ -1857,27 +1860,31 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box,
 
 static gboolean
 popup_grab_on_window (GdkWindow *window,
-		      guint32    activate_time,
-		      gboolean   grab_keyboard)
-{
-  if ((gdk_pointer_grab (window, TRUE,
-			 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-			 GDK_POINTER_MOTION_MASK,
-			 NULL, NULL, activate_time) == 0))
+                      GdkDevice *keyboard,
+                      GdkDevice *pointer,
+		      guint32    activate_time)
+{
+  if (keyboard &&
+      gdk_device_grab (keyboard, window,
+                       GDK_OWNERSHIP_WINDOW, TRUE,
+                       GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
+                       NULL, activate_time) != GDK_GRAB_SUCCESS)
+    return FALSE;
+
+  if (pointer &&
+      gdk_device_grab (pointer, window,
+                       GDK_OWNERSHIP_WINDOW, TRUE,
+                       GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                       GDK_POINTER_MOTION_MASK,
+                       NULL, activate_time) != GDK_GRAB_SUCCESS)
     {
-      if (!grab_keyboard ||
-	  gdk_keyboard_grab (window, TRUE,
-			     activate_time) == 0)
-	return TRUE;
-      else
-	{
-	  gdk_display_pointer_ungrab (gdk_drawable_get_display (window),
-				      activate_time);
-	  return FALSE;
-	}
+      if (keyboard)
+        gdk_device_ungrab (keyboard, activate_time);
+
+      return FALSE;
     }
 
-  return FALSE;
+  return TRUE;
 }
 
 /**
@@ -1899,13 +1906,28 @@ gtk_combo_box_popup (GtkComboBox *combo_box)
   g_signal_emit (combo_box, combo_box_signals[POPUP], 0);
 }
 
-static void
-gtk_combo_box_real_popup (GtkComboBox *combo_box)
+/**
+ * gtk_combo_box_popup_for_device:
+ * @combo_box: a #GtkComboBox
+ * @device: a #GdkDevice
+ *
+ * Pops up the menu or dropdown list of @combo_box, the popup window
+ * will be grabbed so only @device and its associated pointer/keyboard
+ * are the only #GdkDevice<!-- -->s able to send events to it.
+ **/
+void
+gtk_combo_box_popup_for_device (GtkComboBox *combo_box,
+                                GdkDevice   *device)
 {
   GtkComboBoxPrivate *priv = combo_box->priv;
   gint x, y, width, height;
   GtkTreePath *path = NULL, *ppath;
   GtkWidget *toplevel;
+  GdkDevice *keyboard, *pointer;
+  guint32 time;
+
+  g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
+  g_return_if_fail (GDK_IS_DEVICE (device));
 
   if (!GTK_WIDGET_REALIZED (combo_box))
     return;
@@ -1913,6 +1935,22 @@ gtk_combo_box_real_popup (GtkComboBox *combo_box)
   if (GTK_WIDGET_MAPPED (priv->popup_widget))
     return;
 
+  if (priv->grab_pointer && priv->grab_keyboard)
+    return;
+
+  time = gtk_get_current_event_time ();
+
+  if (device->source == GDK_SOURCE_KEYBOARD)
+    {
+      keyboard = device;
+      pointer = gdk_device_get_associated_device (device);
+    }
+  else
+    {
+      pointer = device;
+      keyboard = gdk_device_get_associated_device (device);
+    }
+
   if (GTK_IS_MENU (priv->popup_widget))
     {
       gtk_combo_box_menu_popup (combo_box, 
@@ -1962,13 +2000,40 @@ gtk_combo_box_real_popup (GtkComboBox *combo_box)
     gtk_widget_grab_focus (priv->tree_view);
 
   if (!popup_grab_on_window (priv->popup_window->window,
-			     GDK_CURRENT_TIME, TRUE))
+			     keyboard, pointer, time))
     {
       gtk_widget_hide (priv->popup_window);
       return;
     }
 
   gtk_grab_add (priv->popup_window);
+  priv->grab_pointer = pointer;
+  priv->grab_keyboard = keyboard;
+}
+
+static void
+gtk_combo_box_real_popup (GtkComboBox *combo_box)
+{
+  GdkDevice *device;
+
+  device = gtk_get_current_event_device ();
+
+  if (!device)
+    {
+      GdkDeviceManager *device_manager;
+      GdkDisplay *display;
+      GList *devices;
+
+      display = gtk_widget_get_display (GTK_WIDGET (combo_box));
+      device_manager = gdk_display_get_device_manager (display);
+
+      /* No device was set, pick the first master device */
+      devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+      device = devices->data;
+      g_list_free (devices);
+    }
+
+  gtk_combo_box_popup_for_device (combo_box, device);
 }
 
 static gboolean
@@ -2014,6 +2079,9 @@ gtk_combo_box_popdown (GtkComboBox *combo_box)
   gtk_widget_hide_all (priv->popup_window);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button),
                                 FALSE);
+
+  priv->grab_pointer = NULL;
+  priv->grab_keyboard = NULL;
 }
 
 static gint
@@ -3887,7 +3955,7 @@ gtk_combo_box_list_button_pressed (GtkWidget      *widget,
       !GTK_WIDGET_HAS_FOCUS (priv->button))
     gtk_widget_grab_focus (priv->button);
 
-  gtk_combo_box_popup (combo_box);
+  gtk_combo_box_popup_for_device (combo_box, event->device);
 
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button), TRUE);
 
@@ -4083,7 +4151,9 @@ gtk_combo_box_list_scroll_timeout (GtkComboBox *combo_box)
 
   if (priv->auto_scroll)
     {
-      gdk_window_get_pointer (priv->tree_view->window, &x, &y, NULL);
+      gdk_window_get_device_position (priv->tree_view->window,
+                                      priv->grab_pointer,
+                                      &x, &y, NULL);
       gtk_combo_box_list_auto_scroll (combo_box, x, y);
     }
 
diff --git a/gtk/gtkcombobox.h b/gtk/gtkcombobox.h
index 1da1562..979fc84 100644
--- a/gtk/gtkcombobox.h
+++ b/gtk/gtkcombobox.h
@@ -133,6 +133,8 @@ gchar        *gtk_combo_box_get_active_text  (GtkComboBox     *combo_box);
 
 /* programmatic control */
 void          gtk_combo_box_popup            (GtkComboBox     *combo_box);
+void          gtk_combo_box_popup_for_device (GtkComboBox     *combo_box,
+                                              GdkDevice       *device);
 void          gtk_combo_box_popdown          (GtkComboBox     *combo_box);
 AtkObject*    gtk_combo_box_get_popup_accessible (GtkComboBox *combo_box);
 



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