Index: gobject/gtype.c
===================================================================
--- gobject/gtype.c	(Revision 7780)
+++ gobject/gtype.c	(Arbeitskopie)
@@ -309,6 +309,7 @@
   GClassFinalizeFunc class_finalize;
   gconstpointer      class_data;
   gpointer           class;
+  guint16            class_private_size;
 };
 
 struct _InstanceData
@@ -324,6 +325,7 @@
   gpointer           class;
   guint16            instance_size;
   guint16            private_size;
+  guint16            class_private_size;
   guint16            n_preallocs;
   GInstanceInitFunc  instance_init;
 };
@@ -1006,6 +1008,8 @@
    
   if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
     {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+
       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
       if (vtable_size)
 	vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
@@ -1022,6 +1026,9 @@
        * after the parent class has been initialized
        */
       data->instance.private_size = 0;
+      data->instance.class_private_size = 0;
+      if (pnode)
+        data->instance.class_private_size = pnode->data->instance.class_private_size;
 #ifdef	DISABLE_MEM_POOLS
       data->instance.n_preallocs = 0;
 #else	/* !DISABLE_MEM_POOLS */
@@ -1031,6 +1038,8 @@
     }
   else if (node->is_classed) /* only classed */
     {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+
       data = g_malloc0 (sizeof (ClassData) + vtable_size);
       if (vtable_size)
 	vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
@@ -1041,6 +1050,9 @@
       data->class.class_finalize = info->class_finalize;
       data->class.class_data = info->class_data;
       data->class.class = NULL;
+      data->class.class_private_size = 0;
+      if (pnode)
+        data->instance.class_private_size = pnode->data->instance.class_private_size;
       data->class.init_state = UNINITIALIZED;
     }
   else if (NODE_IS_IFACE (node))
@@ -1889,7 +1901,10 @@
 	    !node->data->class.class &&
 	    node->data->class.init_state == UNINITIALIZED);
 
-  class = g_malloc0 (node->data->class.class_size);
+  if (node->data->class.class_private_size)
+    class = g_malloc0 (ALIGN_STRUCT (node->data->class.class_size) + node->data->class.class_private_size);
+  else
+    class = g_malloc0 (node->data->class.class_size);
   node->data->class.class = class;
   node->data->class.init_state = BASE_CLASS_INIT;
   
@@ -1898,6 +1913,7 @@
       TypeNode *pnode = lookup_type_node_I (pclass->g_type);
       
       memcpy (class, pclass, pnode->data->class.class_size);
+      memcpy (G_STRUCT_MEMBER_P (class, ALIGN_STRUCT (node->data->class.class_size)), G_STRUCT_MEMBER_P (pclass, ALIGN_STRUCT (pnode->data->class.class_size)), pnode->data->class.class_private_size);
 
       if (node->is_instantiatable)
 	{
@@ -4231,5 +4247,111 @@
   return G_STRUCT_MEMBER_P (instance, offset);
 }
 
+/**
+ * g_type_add_class_private:
+ * @class_type: GType of an classed type.
+ * @private_size: size of private structure.
+ *
+ * Registers a private class structure for a classed type;
+ * when the class is allocated, the private structures for
+ * the class and all of its parent types are allocated
+ * sequentially in the same memory block as the public
+ * structures. This function should be called in the
+ * type's get_type() function after the type is registered.
+ * The private structure can be retrieved using the
+ * G_TYPE_CLASS_GET_PRIVATE() macro.
+ *
+ * Since: 2.20
+ */
+void
+g_type_add_class_private (GType    class_type,
+			  gsize    private_size)
+{
+  TypeNode *node = lookup_type_node_I (class_type);
+  gsize offset;
+
+  g_return_if_fail (private_size > 0);
+
+  if (!node || !node->is_classed || !node->data)
+    {
+      g_warning ("cannot add class private field to invalid type '%s'",
+		 type_descriptive_name_I (class_type));
+      return;
+    }
+
+  if (NODE_PARENT_TYPE (node))
+    {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+      if ((node->is_instantiatable && node->data->instance.class_private_size != pnode->data->instance.class_private_size) ||
+          (!node->is_instantiatable && node->is_classed && node->data->class.class_private_size != pnode->data->class.class_private_size))
+	{
+	  g_warning ("g_type_add_class_private() called multiple times for the same type");
+	  return;
+	}
+    }
+  
+  G_WRITE_LOCK (&type_rw_lock);
+
+  if (node->is_instantiatable) {
+    offset = ALIGN_STRUCT (node->data->instance.class_private_size);
+    node->data->instance.class_private_size = offset + private_size;
+  } else {
+    offset = ALIGN_STRUCT (node->data->class.class_private_size);
+    node->data->class.class_private_size = offset + private_size;
+  }
+  
+  G_WRITE_UNLOCK (&type_rw_lock);
+}
+
+gpointer
+g_type_class_get_private (GTypeClass *klass,
+			  GType       private_type)
+{
+  TypeNode *class_node;
+  TypeNode *private_node;
+  TypeNode *parent_node;
+  gsize offset;
+
+  g_return_val_if_fail (klass != NULL, NULL);
+
+  class_node = lookup_type_node_I (klass->g_type);
+  if (G_UNLIKELY (!class_node || !class_node->is_classed))
+    {
+      g_warning ("class of invalid type `%s'",
+		 type_descriptive_name_I (klass->g_type));
+      return NULL;
+    }
+
+  private_node = lookup_type_node_I (private_type);
+  if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, class_node)))
+    {
+      g_warning ("attempt to retrieve private data for invalid type '%s'",
+		 type_descriptive_name_I (private_type));
+      return NULL;
+    }
+
+  offset = ALIGN_STRUCT (class_node->data->instance.class_size);
+
+  if (NODE_PARENT_TYPE (private_node))
+    {
+      parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
+      g_assert (parent_node->data && parent_node->data->common.ref_count);
+
+      if (G_UNLIKELY ((private_node->is_instantiatable && private_node->data->instance.class_private_size == parent_node->data->instance.class_private_size) ||
+      (!private_node->is_instantiatable && private_node->is_classed && private_node->data->class.class_private_size == parent_node->data->class.class_private_size)))
+	{
+	  g_warning ("g_type_instance_get_class_private() requires a prior call to g_type_class_add_class_private()");
+	  return NULL;
+	}
+
+      if (private_node->is_instantiatable)
+        offset += ALIGN_STRUCT (parent_node->data->instance.class_private_size);
+      else
+        offset += ALIGN_STRUCT (parent_node->data->class.class_private_size);
+    }
+
+  return G_STRUCT_MEMBER_P (klass, offset);
+}
+
 #define __G_TYPE_C__
 #include "gobjectaliasdef.c"
Index: gobject/gtype.h
===================================================================
--- gobject/gtype.h	(Revision 7780)
+++ gobject/gtype.h	(Arbeitskopie)
@@ -606,6 +606,22 @@
  */
 #define G_TYPE_INSTANCE_GET_PRIVATE(instance, g_type, c_type)   ((c_type*) g_type_instance_get_private ((GTypeInstance*) (instance), (g_type)))
 
+/**
+ * G_TYPE_CLASS_GET_PRIVATE:
+ * @klass: the class of a type deriving from @private_type.
+ * @g_type: the type identifying which private data to retrieve.
+ * @c_type: The C type for the private structure.
+ * 
+ * Gets the private class structure for a particular type.
+ * The private structure must have been registered in the
+ * get_type() function with g_type_add_class_private().
+ * 
+ * This macro should only be used in type implementations.
+ * 
+ * Since: 2.20
+ * Returns: a pointer to the private data structure.
+ */
+#define G_TYPE_CLASS_GET_PRIVATE(klass, g_type, c_type)   ((c_type*) g_type_class_get_private ((GTypeClass*) (klass), (g_type)))
 
 /**
  * GTypeDebugFlags:
@@ -1218,7 +1234,12 @@
 gpointer g_type_instance_get_private    (GTypeInstance              *instance,
                                          GType                       private_type);
 
+void      g_type_add_class_private      (GType    		     class_type,
+					 gsize    		     private_size);
+gpointer  g_type_class_get_private      (GTypeClass 		    *klass,
+					 GType			     private_type);
 
+
 /* --- GType boilerplate --- */
 /**
  * G_DEFINE_TYPE:
