[gtk+/xi2] GtkComboBox: Add gtk_combo_box_popup_for_device().
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/xi2] GtkComboBox: Add gtk_combo_box_popup_for_device().
- Date: Wed, 30 Dec 2009 21:17:47 +0000 (UTC)
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]