[gtk+/xi2: 449/1239] Add GtkDeviceGroup and GtkWidget-related API.



commit 8298cdb0f150556e86194f25c8f72bce35dc38a0
Author: Carlos Garnacho <carlos lanedo com>
Date:   Sun Jul 5 15:24:44 2009 +0100

    Add GtkDeviceGroup and GtkWidget-related API.
    
    GtkDeviceGroup is a simple object to group devices together, GtkDeviceGroups
    are tied to a GtkWidget, and will be used internally to deliver multidevice
    events.
    
    GdkDevices can just be in one group for a given widget.
    
    GtkWidget API:
    - gtk_widget_create_device_group(): Creates a GtkDeviceGroup attached to
      the widget.
    - gtk_widget_remove_device_group(): Removes and detaches a GtkDeviceGroup fr
    - gtk_widget_get_group_for_device(): Returns the group containing the passed
      GdkDevice in the GtkWidget, if any.

 gtk/Makefile.am |    2 +
 gtk/gtkwidget.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkwidget.h |    6 ++
 3 files changed, 157 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 6d7a038..477925d 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -192,6 +192,7 @@ gtk_public_h_sources =          \
 	gtkcontainer.h		\
 	gtkcurve.h		\
 	gtkdebug.h              \
+	gtkdevicegroup.h	\
 	gtkdialog.h		\
 	gtkdnd.h		\
 	gtkdrawingarea.h	\
@@ -442,6 +443,7 @@ gtk_base_c_sources =            \
 	gtkcomboboxentry.c	\
 	gtkcontainer.c		\
 	gtkcurve.c		\
+	gtkdevicegroup.c	\
 	gtkdialog.c		\
 	gtkdrawingarea.c	\
 	gtkeditable.c           \
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index d574032..0e66ab2 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -158,6 +158,7 @@ enum {
 };
 
 typedef	struct	_GtkStateData	 GtkStateData;
+typedef struct  _GtkMultiDeviceData GtkMultiDeviceData;
 
 struct _GtkStateData
 {
@@ -167,6 +168,12 @@ struct _GtkStateData
   guint		use_forall : 1;
 };
 
+struct _GtkMultiDeviceData
+{
+  GList *groups;
+  GHashTable *by_dev;
+};
+
 /* --- prototypes --- */
 static void	gtk_widget_class_init		(GtkWidgetClass     *klass);
 static void	gtk_widget_base_class_finalize	(GtkWidgetClass     *klass);
@@ -309,6 +316,7 @@ static GQuark		quark_mnemonic_labels = 0;
 static GQuark		quark_tooltip_markup = 0;
 static GQuark		quark_has_tooltip = 0;
 static GQuark		quark_tooltip_window = 0;
+static GQuark           quark_multidevice_data = 0;
 GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
 GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;
 
@@ -397,6 +405,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
   quark_has_tooltip = g_quark_from_static_string ("gtk-has-tooltip");
   quark_tooltip_window = g_quark_from_static_string ("gtk-tooltip-window");
+  quark_multidevice_data = g_quark_from_static_string ("gtk-multidevice-data");
 
   style_property_spec_pool = g_param_spec_pool_new (FALSE);
   _gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
@@ -10355,5 +10364,145 @@ gtk_widget_set_support_multidevice (GtkWidget *widget,
     }
 }
 
+static void
+device_group_device_added (GtkDeviceGroup *group,
+                           GdkDevice      *device,
+                           GtkWidget      *widget)
+{
+  GtkMultiDeviceData *data;
+  GtkDeviceGroup *old_group;
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_multidevice_data);
+
+  if (G_UNLIKELY (!data))
+    return;
+
+  /* Remove device from old group, if any */
+  old_group = g_hash_table_lookup (data->by_dev, device);
+
+  if (old_group)
+    gtk_device_group_remove_device (old_group, device);
+
+  g_hash_table_insert (data->by_dev,
+                       g_object_ref (device),
+                       g_object_ref (group));
+}
+
+static void
+device_group_device_removed (GtkDeviceGroup *group,
+                             GdkDevice      *device,
+                             GtkWidget      *widget)
+{
+  GtkMultiDeviceData *data;
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_multidevice_data);
+
+  g_assert (data != NULL);
+
+  g_hash_table_remove (data->by_dev, device);
+}
+
+static void
+free_multidevice_data (GtkMultiDeviceData *data)
+{
+  g_list_foreach (data->groups, (GFunc) g_object_unref, NULL);
+  g_list_free (data->groups);
+
+  g_hash_table_destroy (data->by_dev);
+
+  g_slice_free (GtkMultiDeviceData, data);
+}
+
+GtkDeviceGroup *
+gtk_widget_create_device_group (GtkWidget *widget)
+{
+  GtkMultiDeviceData *data;
+  GtkDeviceGroup *group;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  group = g_object_new (GTK_TYPE_DEVICE_GROUP, NULL);
+
+  g_signal_connect (group, "device-added",
+                    G_CALLBACK (device_group_device_added), widget);
+  g_signal_connect (group, "device-removed",
+                    G_CALLBACK (device_group_device_removed), widget);
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_multidevice_data);
+
+  if (G_UNLIKELY (!data))
+    {
+      data = g_slice_new0 (GtkMultiDeviceData);
+      data->by_dev = g_hash_table_new_full (g_direct_hash,
+                                            g_direct_equal,
+                                            (GDestroyNotify) g_object_unref,
+                                            (GDestroyNotify) g_object_unref);
+
+      g_object_set_qdata_full (G_OBJECT (widget),
+                               quark_multidevice_data,
+                               data,
+                               (GDestroyNotify) free_multidevice_data);
+    }
+
+  data->groups = g_list_prepend (data->groups, group);
+
+  return group;
+}
+
+void
+gtk_widget_remove_device_group (GtkWidget      *widget,
+                                GtkDeviceGroup *group)
+{
+  GtkMultiDeviceData *data;
+  GList *devices, *g;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_DEVICE_GROUP (group));
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_multidevice_data);
+
+  if (G_UNLIKELY (!data))
+    return;
+
+  g = g_list_find (data->groups, group);
+
+  if (G_UNLIKELY (!g))
+    return;
+
+  devices = gtk_device_group_get_devices (group);
+
+  /* Free per-device data */
+  while (devices)
+    {
+      g_hash_table_remove (data->by_dev, devices->data);
+      devices = devices->next;
+    }
+
+  /* Free group */
+  data->groups = g_list_remove_link (data->groups, g);
+  g_object_unref (g->data);
+  g_list_free_1 (g);
+}
+
+GtkDeviceGroup *
+gtk_widget_get_group_for_device (GtkWidget *widget,
+                                 GdkDevice *device)
+{
+  GtkMultiDeviceData *data;
+  GtkDeviceGroup *group = NULL;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_multidevice_data);
+
+  if (!data)
+    return NULL;
+
+  group = g_hash_table_lookup (data->by_dev, device);
+
+  return group;
+}
+
 #define __GTK_WIDGET_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 476b9ba..bb35e14 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -37,6 +37,7 @@
 #include <gtk/gtkadjustment.h>
 #include <gtk/gtkstyle.h>
 #include <gtk/gtksettings.h>
+#include <gtk/gtkdevicegroup.h>
 #include <atk/atk.h>
 
 G_BEGIN_DECLS
@@ -625,6 +626,11 @@ GdkPixmap *   gtk_widget_get_snapshot    (GtkWidget    *widget,
 /* Multidevice support */
 void             gtk_widget_set_support_multidevice (GtkWidget      *widget,
                                                      gboolean        support_multidevice);
+GtkDeviceGroup * gtk_widget_get_group_for_device    (GtkWidget      *widget,
+                                                     GdkDevice      *device);
+GtkDeviceGroup * gtk_widget_create_device_group     (GtkWidget      *widget);
+void             gtk_widget_remove_device_group     (GtkWidget      *widget,
+                                                     GtkDeviceGroup *group);
 
 
 #ifndef GTK_DISABLE_DEPRECATED



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