diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c
index 31b676e..4d5a61a 100644
--- a/libempathy-gtk/empathy-chat.c
+++ b/libempathy-gtk/empathy-chat.c
@@ -1109,6 +1109,8 @@ chat_members_changed_cb (EmpathyTpChat  *tp_chat,
 			 gboolean        is_member,
 			 EmpathyChat    *chat)
 {
+	g_return_if_fail (TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED != reason);
+
 	EmpathyChatPriv *priv = GET_PRIV (chat);
 
 	if (priv->block_events_timeout_id == 0) {
@@ -1130,6 +1132,34 @@ chat_members_changed_cb (EmpathyTpChat  *tp_chat,
 	}
 }
 
+static void
+chat_member_renamed_cb (EmpathyTpChat  *tp_chat,
+			 EmpathyContact *old_contact,
+			 EmpathyContact *new_contact,
+			 guint           reason,
+			 gchar          *message,
+			 EmpathyChat    *chat)
+{
+	g_return_if_fail (TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED == reason);
+
+	EmpathyChatPriv *priv = GET_PRIV (chat);
+
+	if (priv->block_events_timeout_id == 0) {
+		gchar *str;
+
+		empathy_contact_run_until_ready (new_contact,
+						 EMPATHY_CONTACT_READY_NAME,
+						 NULL);
+
+		str = g_strdup_printf (_("%s is now known as %s"),
+				       empathy_contact_get_name (old_contact),
+				       empathy_contact_get_name (new_contact));
+		empathy_chat_view_append_event (chat->view, str);
+		g_free (str);
+	}
+
+}
+
 static gboolean
 chat_reset_size_request (gpointer widget)
 {
@@ -1599,6 +1629,9 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
 	g_signal_connect (tp_chat, "members-changed",
 			  G_CALLBACK (chat_members_changed_cb),
 			  chat);
+	g_signal_connect (tp_chat, "member-renamed",
+			  G_CALLBACK (chat_member_renamed_cb),
+			  chat);
 	g_signal_connect_swapped (tp_chat, "notify::remote-contact",
 				  G_CALLBACK (chat_remote_contact_changed_cb),
 				  chat);
diff --git a/libempathy-gtk/empathy-contact-list-store.c b/libempathy-gtk/empathy-contact-list-store.c
index d4946e4..5bca33e 100644
--- a/libempathy-gtk/empathy-contact-list-store.c
+++ b/libempathy-gtk/empathy-contact-list-store.c
@@ -98,6 +98,12 @@ static void             contact_list_store_members_changed_cb        (EmpathyCon
 								      gchar                         *message,
 								      gboolean                       is_member,
 								      EmpathyContactListStore       *store);
+static void             contact_list_store_member_renamed_cb         (EmpathyContactList            *list_iface,
+								      EmpathyContact                *old_contact,
+								      EmpathyContact                *new_contact,
+								      guint                          reason,
+								      gchar                         *message,
+								      EmpathyContactListStore       *store);
 static void             contact_list_store_groups_changed_cb         (EmpathyContactList            *list_iface,
 								      EmpathyContact                *contact,
 								      gchar                         *group,
@@ -170,6 +176,10 @@ contact_list_store_iface_setup (gpointer user_data)
 
 	/* Signal connection. */
 	g_signal_connect (priv->list,
+			  "member-renamed",
+			  G_CALLBACK (contact_list_store_member_renamed_cb),
+			  store);
+	g_signal_connect (priv->list,
 			  "members-changed",
 			  G_CALLBACK (contact_list_store_members_changed_cb),
 			  store);
@@ -299,6 +309,9 @@ contact_list_store_finalize (GObject *object)
 	g_list_free (contacts);
 
 	g_signal_handlers_disconnect_by_func (priv->list,
+					      G_CALLBACK (contact_list_store_member_renamed_cb),
+					      object);
+	g_signal_handlers_disconnect_by_func (priv->list,
 					      G_CALLBACK (contact_list_store_members_changed_cb),
 					      object);
 	g_signal_handlers_disconnect_by_func (priv->list,
@@ -772,6 +785,38 @@ contact_list_store_inibit_active_cb (EmpathyContactListStore *store)
 }
 
 static void
+contact_list_store_add_contact_and_connect (EmpathyContactListStore *store, EmpathyContact *contact)
+{
+	g_signal_connect (contact, "notify::presence",
+			  G_CALLBACK (contact_list_store_contact_updated_cb),
+			  store);
+	g_signal_connect (contact, "notify::presence-message",
+			  G_CALLBACK (contact_list_store_contact_updated_cb),
+			  store);
+	g_signal_connect (contact, "notify::name",
+			  G_CALLBACK (contact_list_store_contact_updated_cb),
+			  store);
+	g_signal_connect (contact, "notify::avatar",
+			  G_CALLBACK (contact_list_store_contact_updated_cb),
+			  store);
+	g_signal_connect (contact, "notify::capabilities",
+			  G_CALLBACK (contact_list_store_contact_updated_cb),
+			  store);
+
+	contact_list_store_add_contact (store, contact);
+}
+
+static void
+contact_list_store_remove_contact_and_disconnect (EmpathyContactListStore *store, EmpathyContact *contact)
+{
+	g_signal_handlers_disconnect_by_func (contact,
+					      G_CALLBACK (contact_list_store_contact_updated_cb),
+					      store);
+
+	contact_list_store_remove_contact (store, contact);
+}
+
+static void
 contact_list_store_members_changed_cb (EmpathyContactList      *list_iface,
 				       EmpathyContact          *contact,
 				       EmpathyContact          *actor,
@@ -790,33 +835,38 @@ contact_list_store_members_changed_cb (EmpathyContactList      *list_iface,
 		is_member ? "added" : "removed");
 
 	if (is_member) {
-		g_signal_connect (contact, "notify::presence",
-				  G_CALLBACK (contact_list_store_contact_updated_cb),
-				  store);
-		g_signal_connect (contact, "notify::presence-message",
-				  G_CALLBACK (contact_list_store_contact_updated_cb),
-				  store);
-		g_signal_connect (contact, "notify::name",
-				  G_CALLBACK (contact_list_store_contact_updated_cb),
-				  store);
-		g_signal_connect (contact, "notify::avatar",
-				  G_CALLBACK (contact_list_store_contact_updated_cb),
-				  store);
-		g_signal_connect (contact, "notify::capabilities",
-				  G_CALLBACK (contact_list_store_contact_updated_cb),
-				  store);
-
-		contact_list_store_add_contact (store, contact);
+		contact_list_store_add_contact_and_connect (store, contact);
 	} else {
-		g_signal_handlers_disconnect_by_func (contact,
-						      G_CALLBACK (contact_list_store_contact_updated_cb),
-						      store);
-
-		contact_list_store_remove_contact (store, contact);
+		contact_list_store_remove_contact_and_disconnect (store, contact);
 	}
 }
 
 static void
+contact_list_store_member_renamed_cb (EmpathyContactList      *list_iface,
+				      EmpathyContact          *old_contact,
+				      EmpathyContact          *new_contact,
+				      guint                    reason,
+				      gchar                   *message,
+				      EmpathyContactListStore *store)
+{
+	EmpathyContactListStorePriv *priv;
+
+	priv = GET_PRIV (store);
+
+	DEBUG ("Contact %s (%d) renamed to %s (%d)",
+		empathy_contact_get_id (old_contact),
+		empathy_contact_get_handle (old_contact),
+		empathy_contact_get_id (new_contact),
+		empathy_contact_get_handle (new_contact));
+
+	/* add the new contact */
+	contact_list_store_add_contact_and_connect (store, new_contact);
+
+	/* remove old contact */
+	contact_list_store_remove_contact_and_disconnect (store, old_contact);
+}
+
+static void
 contact_list_store_groups_changed_cb (EmpathyContactList      *list_iface,
 				      EmpathyContact          *contact,
 				      gchar                   *group,
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c
index 1fe894e..295eb2e 100644
--- a/libempathy/empathy-contact-list.c
+++ b/libempathy/empathy-contact-list.c
@@ -54,6 +54,15 @@ contact_list_base_init (gpointer klass)
 	static gboolean initialized = FALSE;
 
 	if (!initialized) {
+		g_signal_new ("member-renamed",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
+			      G_TYPE_NONE,
+			      4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
+
 		g_signal_new ("members-changed",
 			      G_TYPE_FROM_CLASS (klass),
 			      G_SIGNAL_RUN_LAST,
diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c
index 8517c1c..c7d9d2b 100644
--- a/libempathy/empathy-tp-chat.c
+++ b/libempathy/empathy-tp-chat.c
@@ -190,6 +190,18 @@ tp_chat_member_removed_cb (EmpathyTpGroup *group,
 }
 
 static void
+tp_chat_member_renamed_cb (EmpathyTpGroup *group,
+			   EmpathyContact *old_contact,
+			   EmpathyContact *new_contact,
+			   guint           reason,
+			   const gchar    *message,
+			   EmpathyTpChat  *chat)
+{
+	g_signal_emit_by_name (chat, "member-renamed",
+			       old_contact, new_contact, reason, message);
+}
+
+static void
 tp_chat_local_pending_cb  (EmpathyTpGroup *group,
 			   EmpathyContact *contact,
 			   EmpathyContact *actor,
@@ -812,6 +824,9 @@ tp_chat_channel_ready_cb (EmpathyTpChat *chat)
 		g_signal_connect (priv->group, "member-removed",
 				  G_CALLBACK (tp_chat_member_removed_cb),
 				  chat);
+		g_signal_connect (priv->group, "member-renamed",
+				  G_CALLBACK (tp_chat_member_renamed_cb),
+				  chat);
 		g_signal_connect (priv->group, "local-pending",
 				  G_CALLBACK (tp_chat_local_pending_cb),
 				  chat);
diff --git a/libempathy/empathy-tp-group.c b/libempathy/empathy-tp-group.c
index c922038..8673dbe 100644
--- a/libempathy/empathy-tp-group.c
+++ b/libempathy/empathy-tp-group.c
@@ -26,6 +26,7 @@
 
 #include <telepathy-glib/util.h>
 #include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/handle-repo.h>
 
 #include "empathy-tp-group.h"
 #include "empathy-contact-factory.h"
@@ -52,6 +53,7 @@ typedef struct {
 enum {
 	MEMBER_ADDED,
 	MEMBER_REMOVED,
+	MEMBER_RENAMED,
 	LOCAL_PENDING,
 	REMOTE_PENDING,
 	DESTROY,
@@ -202,8 +204,6 @@ tp_group_update_members (EmpathyTpGroup *group,
 	EmpathyContact     *actor_contact = NULL;
 	GList              *contacts, *l, *ll;
 
-	actor_contact = tp_group_get_contact (group, actor);
-
 	DEBUG ("Members changed for list %s:\n"
 		"  added-len=%d, current-len=%d\n"
 		"  removed-len=%d\n"
@@ -216,6 +216,41 @@ tp_group_update_members (EmpathyTpGroup *group,
 		remote_pending ? remote_pending->len : 0,
 		g_list_length (priv->remote_pendings));
 
+	/* Contact renamed */
+	if (reason == TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED) {
+		g_warn_if_fail(removed->len == 1);
+		g_warn_if_fail(added->len == 1);
+
+		TpHandle old_handle = g_array_index (removed, TpHandle, 0);
+		TpHandle new_handle = g_array_index (added, TpHandle, 0);
+
+		EmpathyContact *old_contact = tp_group_get_contact (group, old_handle);
+		EmpathyContact *new_contact = tp_group_get_contact (group, new_handle);
+		if (old_contact && new_contact) {
+			tp_group_remove_from_pendings (group, old_contact);
+			tp_group_remove_from_pendings (group, new_contact);
+
+			/* If the new contact is not yet member, add it */
+			if (!g_list_find (priv->members, new_contact)) {
+				priv->members = g_list_prepend (priv->members,
+								g_object_ref (new_contact));
+			}
+			/* If the old contact is a member, remove it and emit signal */
+			if ((l = g_list_find (priv->members, old_contact))) {
+				g_object_unref (l->data);
+				priv->members = g_list_delete_link (priv->members, l);
+			}
+			g_signal_emit (group, signals[MEMBER_RENAMED], 0,
+				       old_contact, new_contact, reason, message);
+
+			g_object_unref (new_contact);
+			g_object_unref (old_contact);
+		}
+		return;
+	}
+
+	actor_contact = tp_group_get_contact (group, actor);
+
 	/* Contacts added */
 	contacts = tp_group_get_contacts (group, added);
 	for (l = contacts; l; l = l->next) {
@@ -672,6 +707,16 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
 			      G_TYPE_NONE,
 			      4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
 
+	signals[MEMBER_RENAMED] =
+		g_signal_new ("member-renamed",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
+			      G_TYPE_NONE,
+			      4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
+
 	signals[LOCAL_PENDING] =
 		g_signal_new ("local-pending",
 			      G_TYPE_FROM_CLASS (klass),
