Index: gtk/gdkcolor.override
===================================================================
--- gtk/gdkcolor.override	(revision 3013)
+++ gtk/gdkcolor.override	(working copy)
@@ -190,6 +190,37 @@
     return _wrap_gdk_colormap_alloc_color(self, args, kwargs);
 }
 %%
+override-slot GdkColor.tp_richcompare
+static PyObject *
+_wrap_gdk_color_tp_richcompare(PyObject *self, PyObject *other, int op)
+{
+    PyObject *result;
+
+    if (PyObject_TypeCheck(self, &PyGdkColor_Type)
+        && PyObject_TypeCheck(other, &PyGdkColor_Type)) {
+        GdkColor *color1 = pyg_boxed_get(self, GdkColor);
+        GdkColor *color2 = pyg_boxed_get(other, GdkColor);
+
+        switch (op) {
+        case Py_EQ:
+            result = (gdk_color_equal(color1, color2)
+                      ? Py_True : Py_False);
+            break;
+        case Py_NE:
+            result = (!gdk_color_equal(color1, color2)
+                      ? Py_True : Py_False);
+            break;
+        default:
+            result = Py_NotImplemented;
+        }
+    }
+    else
+        result = Py_NotImplemented;
+
+    Py_INCREF(result);
+    return result;
+}
+%%
 override gdk_colormap_query_color kwargs
 static PyObject *
 _wrap_gdk_colormap_query_color(PyGObject *self, PyObject *args,
Index: gtk/gdk.override
===================================================================
--- gtk/gdk.override	(revision 3013)
+++ gtk/gdk.override	(working copy)
@@ -534,6 +534,37 @@
     return py_rects;
 }
 %%
+override-slot GdkRegion.tp_richcompare
+static PyObject *
+_wrap_pygdk_region_tp_richcompare(PyObject *self, PyObject *other, int op)
+{
+    PyObject *result;
+
+    if (PyObject_TypeCheck(self, &PyGdkRegion_Type)
+        && PyObject_TypeCheck(other, &PyGdkRegion_Type)) {
+        GdkRegion *region1 = pyg_boxed_get(self, GdkRegion);
+        GdkRegion *region2 = pyg_boxed_get(other, GdkRegion);
+
+        switch (op) {
+        case Py_EQ:
+            result = (gdk_region_equal(region1, region2)
+                      ? Py_True : Py_False);
+            break;
+        case Py_NE:
+            result = (!gdk_region_equal(region1, region2)
+                      ? Py_True : Py_False);
+            break;
+        default:
+            result = Py_NotImplemented;
+        }
+    }
+    else
+        result = Py_NotImplemented;
+
+    Py_INCREF(result);
+    return result;
+}
+%%
 override-attr GdkDevice.axes
 static PyObject *
 _wrap_gdk_device__get_axes(PyGObject *self, void *closure)
Index: gtk/gdkrectangle.override
===================================================================
--- gtk/gdkrectangle.override	(revision 3013)
+++ gtk/gdkrectangle.override	(working copy)
@@ -214,3 +214,36 @@
                             
     return pyg_boxed_new(GDK_TYPE_RECTANGLE, &dest, TRUE, TRUE);
 }
+%%
+override-slot GdkRectangle.tp_richcompare
+static PyObject *
+_wrap_gdk_rectangle_tp_richcompare(PyObject *self, PyObject *other, int op)
+{
+    PyObject *result;
+
+    if (PyObject_TypeCheck(self, &PyGdkRectangle_Type)
+        && PyObject_TypeCheck(other, &PyGdkRectangle_Type)) {
+        GdkRectangle *rect1 = pyg_boxed_get(self, GdkRectangle);
+        GdkRectangle *rect2 = pyg_boxed_get(other, GdkRectangle);
+
+        switch (op) {
+        case Py_EQ:
+            result = (rect1->x == rect2->x && rect1->y == rect2->y
+                      && rect1->width == rect2->width && rect1->height == rect2->height
+                      ? Py_True : Py_False);
+            break;
+        case Py_NE:
+            result = (rect1->x != rect2->x || rect1->y != rect2->y
+                      || rect1->width != rect2->width || rect1->height != rect2->height
+                      ? Py_True : Py_False);
+            break;
+        default:
+            result = Py_NotImplemented;
+        }
+    }
+    else
+        result = Py_NotImplemented;
+
+    Py_INCREF(result);
+    return result;
+}
Index: docs/reference/pygtk-gdkcolor.xml
===================================================================
--- docs/reference/pygtk-gdkcolor.xml	(revision 3013)
+++ docs/reference/pygtk-gdkcolor.xml	(working copy)
@@ -109,6 +109,14 @@
 the <link linkend="class-gtkstyle"><classname>gtk.Style</classname></link>
 object.</para>
 
+    <para>
+      Starting with PyGTK 2.14 <classname>gtk.gdk.Color</classname> objects are properly
+      comparable.  By Python rules, colors (being mutable) are now unhashable.  If you
+      need to use them as dictionary keys, use string representation instead.  You can
+      convert string representation to <classname>gtk.gdk.Color</classname> objects using
+      the constructor.
+    </para>
+
   </refsect1>
 
   <refsect1 id="constructor-gdkcolor">
@@ -128,6 +136,11 @@
 	<methodparam><parameter
 		       role="keyword">pixel</parameter>
 	  <initializer>0</initializer></methodparam>
+    </constructorsynopsis></programlisting>
+    <programlisting><constructorsynopsis language="python">
+	<methodname>gtk.gdk.Color</methodname>
+	<methodparam><parameter
+		       role="keyword">spec</parameter></methodparam>
       </constructorsynopsis></programlisting>
     <variablelist>
       <varlistentry>
@@ -151,6 +164,10 @@
 colormap</simpara></listitem>
       </varlistentry>
       <varlistentry>
+	<term><parameter role="keyword">spec</parameter>&nbsp;:</term>
+	<listitem><simpara>String containing color specification</simpara></listitem>
+      </varlistentry>
+      <varlistentry>
 	<term><emphasis>Returns</emphasis>&nbsp;:</term>
 	<listitem><simpara>a new <link
 linkend="class-gdkcolor"><classname>gtk.gdk.Color</classname></link>
@@ -158,6 +175,10 @@
       </varlistentry>
     </variablelist>
 
+    <note>
+      <para>Second form of the constructor is available in PyGTK 2.14 and above.</para>
+    </note>
+
     <para>Creates a new <link
 linkend="class-gdkcolor"><classname>gtk.gdk.Color</classname></link> object
 with the color component values specified by <parameter>red</parameter>,
@@ -166,6 +187,9 @@
 value of <parameter>pixel</parameter> will be overwritten when the color is
 allocated.</para>
 
+    <para>Second form of the constructor is analogous to
+      <link linkend="function-gdk--color-parse"><function>gtk.gdk.color_parse</function></link>.</para>
+
   </refsect1>
   
     <refsect1>
Index: docs/reference/pygtk-gdkregion.xml
===================================================================
--- docs/reference/pygtk-gdkregion.xml	(revision 3013)
+++ docs/reference/pygtk-gdkregion.xml	(working copy)
@@ -125,6 +125,12 @@
     linkend="method-gdkgc--set-clip-region"><methodname>gtk.gdk.GC.set_clip_region</methodname>()</link>
     method).</para>
 
+    <para>
+      Starting with PyGTK 2.14 <classname>gtk.gdk.Region</classname> objects are
+      properly comparable.  By Python rules, regions (being mutable) are now
+      unhashable.
+    </para>
+
   </refsect1>
 
   <refsect1 id="constructor-gdkregion">
@@ -228,6 +234,11 @@
       region specified by <parameter>other</parameter> is equal to this
       region.</para>
 
+      <note>
+        <para>Since PyGTK 2.14 Python comparison operator (<literal>==</literal>) can be
+	  used for the same result.</para>
+      </note>
+
     </refsect2>
 
     <refsect2 id="method-gdkregion--point-in">
Index: docs/reference/pygtk-gdkrectangle.xml
===================================================================
--- docs/reference/pygtk-gdkrectangle.xml	(revision 3013)
+++ docs/reference/pygtk-gdkrectangle.xml	(working copy)
@@ -101,6 +101,18 @@
 "x" and "y" attributes and the size, by the "width" and "height"
 attributes.</para>
 
+    <para>
+      Starting with PyGTK 2.14 <classname>gtk.gdk.Rectangle</classname> objects are
+      properly comparable.  By Python rules, rectangles (being mutable) are now
+      unhashable.  If you need to use them as dictionary keys, convert rectangle objects
+      to tuples first.  You can convert such tuples back
+      to <classname>gtk.gdk.Rectangle</classname> using the following code:
+    </para>
+
+    <programlisting>
+  rectangle = gtk.gdk.Rectangle(*tuple)
+    </programlisting>
+
   </refsect1>
 
   <refsect1 id="constructor-gdkrectangle">
Index: tests/test_rectangle.py
===================================================================
--- tests/test_rectangle.py	(revision 0)
+++ tests/test_rectangle.py	(revision 0)
@@ -0,0 +1,28 @@
+# -*- Mode: Python -*-
+
+import unittest
+
+from common import gtk
+
+
+class Tests(unittest.TestCase):
+
+    def test_equal(self):
+        self.assertEqual(gtk.gdk.Rectangle(0, 0, 1, 1), gtk.gdk.Rectangle(0, 0, 1, 1))
+
+    def test_not_equal(self):
+        self.assertNotEqual(gtk.gdk.Rectangle(1, 0, 10, 10), gtk.gdk.Rectangle(0, 0, 10, 10))
+        self.assertNotEqual(gtk.gdk.Rectangle(0, 1, 10, 10), gtk.gdk.Rectangle(0, 0, 10, 10))
+        self.assertNotEqual(gtk.gdk.Rectangle(0, 0, 11, 10), gtk.gdk.Rectangle(0, 0, 10, 10))
+        self.assertNotEqual(gtk.gdk.Rectangle(0, 0, 10, 11), gtk.gdk.Rectangle(0, 0, 10, 10))
+
+    def test_non_hashable(self):
+        self.assertRaises(TypeError, lambda: hash(gtk.gdk.Rectangle()))
+
+        def dict_key():
+            {} [gtk.gdk.Rectangle()] = 'must raise'
+        self.assertRaises(TypeError, dict_key)
+
+
+if __name__ == '__main__':
+    unittest.main()
Index: tests/test_color.py
===================================================================
--- tests/test_color.py	(revision 0)
+++ tests/test_color.py	(revision 0)
@@ -0,0 +1,60 @@
+# -*- Mode: Python -*-
+
+import unittest
+
+from common import gtk
+
+
+class Tests(unittest.TestCase):
+
+    def test_constructor(self):
+        """ Test GdkColor creation """
+
+        c = gtk.gdk.Color(1, 2, 3)
+        self.assertEqual(c.red, 1)
+        self.assertEqual(c.green, 2)
+        self.assertEqual(c.blue, 3)
+
+        c = gtk.gdk.Color(pixel=0xffff)
+        self.assertEqual(c.pixel, 0xffff)
+
+        c = gtk.gdk.Color(pixel=0xffffL)
+        self.assertEqual(c.pixel, 0xffff)
+
+        c = gtk.gdk.Color(pixel=0xffffffffL)
+        self.assertEqual(c.pixel, 0xffffffffL)
+
+        c = gtk.gdk.Color('red')
+        self.assertEqual(c.red, 65535)
+        self.assertEqual(c.green, 0)
+        self.assertEqual(c.blue, 0)
+
+        c = gtk.gdk.Color('#ff0000')
+        self.assertEqual(c.red, 65535)
+        self.assertEqual(c.green, 0)
+        self.assertEqual(c.blue, 0)
+
+        self.assertRaises(TypeError, lambda: gtk.gdk.Color([]))
+
+    def test_equal(self):
+        self.assertEqual(gtk.gdk.Color(0, 0, 0), gtk.gdk.Color(0, 0, 0))
+        self.assertEqual(gtk.gdk.Color(100, 200, 300), gtk.gdk.Color(100, 200, 300))
+        self.assertEqual(gtk.gdk.Color('#abc'), gtk.gdk.Color('#aabbcc'))
+        self.assertEqual(gtk.gdk.Color('#100020003000'), gtk.gdk.Color(0x1000, 0x2000, 0x3000))
+
+    def test_not_equal(self):
+        self.assertNotEqual(gtk.gdk.Color('red'), gtk.gdk.Color('blue'))
+        self.assertNotEqual(gtk.gdk.Color(1, 0, 0), gtk.gdk.Color(0, 0, 0))
+        self.assertNotEqual(gtk.gdk.Color(0, 1, 0), gtk.gdk.Color(0, 0, 0))
+        self.assertNotEqual(gtk.gdk.Color(0, 0, 1), gtk.gdk.Color(0, 0, 0))
+
+    def test_non_hashable(self):
+        self.assertRaises(TypeError, lambda: hash(gtk.gdk.Color()))
+
+        def dict_key():
+            {} [gtk.gdk.Color()] = 'must raise'
+        self.assertRaises(TypeError, dict_key)
+
+
+if __name__ == '__main__':
+    unittest.main()
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 3013)
+++ tests/Makefile.am	(working copy)
@@ -1,24 +1,26 @@
 EXTRA_DIST = $(tests) common.py runtests.py testmodule.py leak.glade
 
-tests =  \
-	test_actiongroup.py \
-	test_api.py \
-	test_bin.py \
-	test_button.py \
-	test_container.py
-	test_conversion.py \
-	test_dialog.py \
-	test_enum.py \
-	test_gdk.py \
-	test_glade.py \
-	test_liststore.py
-	test_pango.py \
-	test_plug.py \
-	test_radiobutton.py \
-	test_style.py \
-	test_textview.py \
-	test_treeview.py \
-	test_filechooserdialog.py
+tests =						\
+	test_actiongroup.py			\
+	test_api.py				\
+	test_bin.py				\
+	test_button.py				\
+	test_color.py				\
+	test_container.py			\
+	test_conversion.py			\
+	test_dialog.py				\
+	test_enum.py				\
+	test_filechooserdialog.py		\
+	test_gdk.py				\
+	test_glade.py				\
+	test_liststore.py			\
+	test_pango.py				\
+	test_plug.py				\
+	test_radiobutton.py			\
+	test_rectangle.py			\
+	test_style.py				\
+	test_textview.py			\
+	test_treeview.py
 
 GTK_PY_FILES = __init__.py _lazyutils.py compat.py deprecation.py keysyms.py
 
Index: tests/test_conversion.py
===================================================================
--- tests/test_conversion.py	(revision 3013)
+++ tests/test_conversion.py	(working copy)
@@ -52,35 +52,6 @@
             self.assertEqual(entry.get_property('invisible_char'),
                              valid_value, valid_value)
 
-    def testColorCreation(self):
-        """ Test GdkColor creation """
-
-        c = gtk.gdk.Color(1, 2, 3)
-        self.assertEqual(c.red, 1)
-        self.assertEqual(c.green, 2)
-        self.assertEqual(c.blue, 3)
-
-        c = gtk.gdk.Color(pixel=0xffff)
-        self.assertEqual(c.pixel, 0xffff)
-
-        c = gtk.gdk.Color(pixel=0xffffL)
-        self.assertEqual(c.pixel, 0xffff)
-
-        c = gtk.gdk.Color(pixel=0xffffffffL)
-        self.assertEqual(c.pixel, 0xffffffffL)
-
-        c = gtk.gdk.Color('red')
-        self.assertEqual(c.red, 65535)
-        self.assertEqual(c.green, 0)
-        self.assertEqual(c.blue, 0)
-
-        c = gtk.gdk.Color('#ff0000')
-        self.assertEqual(c.red, 65535)
-        self.assertEqual(c.green, 0)
-        self.assertEqual(c.blue, 0)
-
-        self.assertRaises(TypeError, lambda: gtk.gdk.Color([]))
-
     def testUIntArg(self):
         child = gtk.DrawingArea()
         table = gtk.Table(2, 2, False)
