Index: atk/atkobject.c
===================================================================
--- atk/atkobject.c	(revision 1296)
+++ atk/atkobject.c	(working copy)
@@ -1522,32 +1522,22 @@
                                 AtkRelationType relationship,
                                 AtkObject       *target)
 {
-  gint n_relations, i;
   gboolean ret = FALSE;
   AtkRelation *relation;
+  GPtrArray *array;
 
   g_return_val_if_fail (ATK_IS_OBJECT (object), FALSE);
   g_return_val_if_fail (ATK_IS_OBJECT (target), FALSE);
 
-  n_relations = atk_relation_set_get_n_relations (object->relation_set);
-  for (i = 0; i < n_relations; i++)
-    {
-      relation = atk_relation_set_get_relation (object->relation_set, i);
-      if (atk_relation_get_relation_type (relation) == relationship)
-        {
-          GPtrArray *array;
+  relation = atk_relation_set_get_relation_by_type (object->relation_set, relationship);
 
-          array = atk_relation_get_target (relation);
-        
-          if (g_ptr_array_index (array, 0) == target)
-            {
-              atk_relation_set_remove (object->relation_set, relation); 
-              ret = TRUE;
-              break;
-            }
-        }
+  if (relation)
+    {
+      ret = atk_relation_remove_target (relation, target);
+      array = atk_relation_get_target (relation);
+      if (!array || array->len == 0)
+        atk_relation_set_remove (object->relation_set, relation);
     }
-
   return ret;
 }
 
Index: atk/atkrelation.c
===================================================================
--- atk/atkrelation.c	(revision 1296)
+++ atk/atkrelation.c	(working copy)
@@ -333,6 +333,35 @@
   g_object_weak_ref (G_OBJECT (target), (GWeakNotify) delete_object_while_in_relation, relation->target);
 }
 
+/**
+ * atk_relation_remove_target:
+ * @relation: an #AtkRelation
+ * @target: an #AtkObject
+ *
+ * Remove the specified AtkObject from the target for the relation.
+ *
+ * Returns TRUE if the removal is successful.
+ **/
+
+gboolean
+atk_relation_remove_target (AtkRelation *relation,
+                            AtkObject *target)
+{
+  gboolean ret = FALSE;
+  GPtrArray *array;
+
+  array = atk_relation_get_target (relation);
+
+  if (array && g_ptr_array_remove (array, target))
+    {
+      g_object_weak_unref (G_OBJECT (target),
+                           (GWeakNotify) delete_object_while_in_relation,
+                           relation->target);
+      ret = TRUE;
+    }
+  return ret;
+}
+
 static void
 atk_relation_finalize (GObject *object)
 {
Index: atk/atkrelation.h
===================================================================
--- atk/atkrelation.h	(revision 1296)
+++ atk/atkrelation.h	(working copy)
@@ -81,6 +81,8 @@
 GPtrArray*            atk_relation_get_target         (AtkRelation     *relation);
 void                  atk_relation_add_target         (AtkRelation     *relation,
                                                        AtkObject       *target);
+gboolean              atk_relation_remove_target      (AtkRelation     *relation,
+                                                       AtkObject       *target);
 
 G_END_DECLS
 
Index: atk/atkrelationset.c
===================================================================
--- atk/atkrelationset.c	(revision 1296)
+++ atk/atkrelationset.c	(working copy)
@@ -123,17 +123,33 @@
                          AtkRelation    *relation)
 {
   GPtrArray *array_item;
+  AtkRelationType relationship;
+  AtkRelation *exist_relation;
+  gint i;
 
   g_return_if_fail (ATK_IS_RELATION_SET (set));
 
   array_item = set->relations;
   if (array_item == NULL)
     return;
-  
+
   if (g_ptr_array_remove (array_item, relation))
   {
     g_object_unref (relation);
   }
+  else
+  {
+    relationship = atk_relation_get_relation_type (relation);
+    if (atk_relation_set_contains (set, relationship))
+    {
+      exist_relation = atk_relation_set_get_relation_by_type (set, relationship);
+      for (i = 0; i < relation->target->len; i++)
+      {
+        AtkObject *target = g_ptr_array_index(relation->target, i);
+        atk_relation_remove_target (exist_relation, target);
+      }
+    }
+  }
 }
 
 /**
@@ -160,12 +176,24 @@
   {
     set->relations = g_ptr_array_new ();
   }
+
   relationship = atk_relation_get_relation_type (relation);
   if (!atk_relation_set_contains (set, relationship))
   {
     g_ptr_array_add (set->relations, relation);
     g_object_ref (relation);
   }
+  else
+  {
+    AtkRelation *exist_relation;
+    gint i;
+    exist_relation = atk_relation_set_get_relation_by_type (set, relationship);
+    for (i = 0; i < relation->target->len; i++)
+    {
+      AtkObject *target = g_ptr_array_index(relation->target, i);
+      atk_relation_add_target (exist_relation, target); 
+    }
+  }
 }
 
 /**
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1296)
+++ ChangeLog	(working copy)
@@ -1,5 +1,17 @@
 2008-11-10  Li Yuan  <li.yuan@sun.com>
 
+	* atk/atkobject.c: (atk_object_remove_relationship):
+	Bug #477708. Only remove the target, not the relation if
+	there are still are targets.
+	* atk/atkrelation.c: (atk_relation_remove_target):
+	* atk/atkrelation.h: New API.
+	* atk/atkrelationset.c: (atk_relation_set_add),
+	(atk_relation_set_remove): 
+	Add/remove the new relation's targets to/from the existed 
+	relation if there has been a relation with the same type.
+
+2008-11-10  Li Yuan  <li.yuan@sun.com>
+
 	* atk/atkrelationset.c: (atk_relation_set_add):
 	Don't ref the relation if it is not added.
 
