Index: gtk/gtkrecentmanager.c
===================================================================
--- gtk/gtkrecentmanager.c	(revision 19932)
+++ gtk/gtkrecentmanager.c	(working copy)
@@ -797,6 +797,96 @@ gtk_recent_manager_get_limit (GtkRecentM
   return priv->limit;
 }
 
+static inline gboolean
+gtk_recent_manager_add_internal (GtkRecentManager    *manager,
+                                 const gchar         *uri,
+                                 const GtkRecentData *data)
+{
+  GtkRecentManagerPrivate *priv = manager->priv;
+
+  /* sanity checks */
+  if ((data->display_name) &&
+      (!g_utf8_validate (data->display_name, -1, NULL)))
+    {
+      g_warning ("Attempting to add `%s' to the list of recently used "
+		 "resources, but the display name is not a valid UTF-8 "
+          	 "encoded string",
+		 uri);
+      return FALSE;
+    }
+
+  if ((data->description) &&
+      (!g_utf8_validate (data->description, -1, NULL)))
+    {
+      g_warning ("Attempting to add `%s' to the list of recently used "
+		 "resources, but the description is not a valid UTF-8 "
+          	 "encoded string",
+		 uri);
+      return FALSE;
+    }
+
+  if (!data->mime_type)
+    {
+      g_warning ("Attempting to add `%s' to the list of recently used "
+		 "resources, but not MIME type was defined",
+		 uri);
+      return FALSE;
+    }
+
+  if (!data->app_name)
+    {
+      g_warning ("Attempting to add `%s' to the list of recently used "
+		 "resources, but no name of the application that is "
+		 "registering it was defined",
+      		 uri);
+      return FALSE;
+    }
+
+  if (!data->app_exec)
+    {
+      g_warning ("Attempting to add `%s' to the list of recently used "
+		 "resources, but no command line for the application "
+		 "that is registering it was defined",
+		 uri);
+      return FALSE;
+    }
+
+  if (!priv->recent_items)
+    {
+      priv->recent_items = g_bookmark_file_new ();
+      priv->size = 0;
+    }
+
+  if (data->display_name)  
+    g_bookmark_file_set_title (priv->recent_items, uri, data->display_name);
+
+  if (data->description)
+    g_bookmark_file_set_description (priv->recent_items, uri, data->description);
+
+  g_bookmark_file_set_mime_type (priv->recent_items, uri, data->mime_type);
+
+  if (data->groups && data->groups[0] != '\0')
+    {
+      gint j;
+
+      for (j = 0; (data->groups)[j] != NULL; j++)
+        g_bookmark_file_add_group (priv->recent_items, uri, (data->groups)[j]);
+    }
+
+  /* register the application; this will take care of updating the
+   * registration count and time in case the application has
+   * already registered the same document inside the list
+   */
+  g_bookmark_file_add_application (priv->recent_items, uri,
+		  		   data->app_name,
+				   data->app_exec);
+
+  g_bookmark_file_set_is_private (priv->recent_items, uri,
+		  		  data->is_private);
+
+  return TRUE;
+}
+
 /**
  * gtk_recent_manager_add_item:
  * @manager: a #GtkRecentManager
@@ -823,7 +913,7 @@ gtk_recent_manager_add_item (GtkRecentMa
 {
   GtkRecentData recent_data;
   gboolean retval;
-  
+
   g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), FALSE);
   g_return_val_if_fail (uri != NULL, FALSE);
 
@@ -836,14 +926,14 @@ gtk_recent_manager_add_item (GtkRecentMa
     {
       gchar *filename;
       const gchar *mime_type;
-      
+
       filename = g_filename_from_uri (uri, NULL, NULL);
       if (filename)
         {
           mime_type = xdg_mime_get_mime_type_for_file (filename, NULL);
           if (mime_type)
             recent_data.mime_type = g_strdup (mime_type);
-      
+
           g_free (filename);
         }
 
@@ -853,14 +943,23 @@ gtk_recent_manager_add_item (GtkRecentMa
   else
 #endif
     recent_data.mime_type = g_strdup (GTK_RECENT_DEFAULT_MIME);
-  
+
   recent_data.app_name = g_strdup (g_get_application_name ());
   recent_data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
   recent_data.groups = NULL;
   recent_data.is_private = FALSE;
-  
-  retval = gtk_recent_manager_add_full (manager, uri, &recent_data);
-  
+
+  retval = gtk_recent_manager_add_internal (manager, uri, &recent_data);
+  if (G_LIKELY (retval))
+    {
+      /* mark us as dirty, so that when emitting the "changed" signal we
+       * will dump our changes
+       */
+      manager->priv->is_dirty = TRUE;
+
+      gtk_recent_manager_changed (manager);
+    }
+
   g_free (recent_data.mime_type);
   g_free (recent_data.app_name);
   g_free (recent_data.app_exec);
@@ -904,102 +1003,75 @@ gtk_recent_manager_add_full (GtkRecentMa
 			     const gchar          *uri,
 			     const GtkRecentData  *data)
 {
-  GtkRecentManagerPrivate *priv;
+  gboolean res;
   
   g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), FALSE);
   g_return_val_if_fail (uri != NULL, FALSE);
   g_return_val_if_fail (data != NULL, FALSE);
 
-  /* sanity checks */
-  if ((data->display_name) &&
-      (!g_utf8_validate (data->display_name, -1, NULL)))
+  res = gtk_recent_manager_add_internal (manager, uri, data);
+  if (G_LIKELY (res))
     {
-      g_warning ("Attempting to add `%s' to the list of recently used "
-		 "resources, but the display name is not a valid UTF-8 "
-          	 "encoded string",
-		 uri);
-      return FALSE;
-    }
-  
-  if ((data->description) &&
-      (!g_utf8_validate (data->description, -1, NULL)))
-    {
-      g_warning ("Attempting to add `%s' to the list of recently used "
-		 "resources, but the description is not a valid UTF-8 "
-          	 "encoded string",
-		 uri);
-      return FALSE;
-    }
+      /* mark us as dirty, so that when emitting the "changed" signal we
+       * will dump our changes
+       */
+      manager->priv->is_dirty = TRUE;
 
- 
-  if (!data->mime_type)
-    {
-      g_warning ("Attempting to add `%s' to the list of recently used "
-		 "resources, but not MIME type was defined",
-		 uri);
-      return FALSE;
-    }
-  
-  if (!data->app_name)
-    {
-      g_warning ("Attempting to add `%s' to the list of recently used "
-		 "resources, but no name of the application that is "
-		 "registering it was defined",
-      		 uri);
-      return FALSE;
+      gtk_recent_manager_changed (manager);
     }
-  
-  if (!data->app_exec)
-    {
-      g_warning ("Attempting to add `%s' to the list of recently used "
-		 "resources, but no command line for the application "
-		 "that is registering it was defined",
-		 uri);
-      return FALSE;
-    }
-  
-  priv = manager->priv;
 
-  if (!priv->recent_items)
-    {
-      priv->recent_items = g_bookmark_file_new ();
-      priv->size = 0;
-    }
+  return res;
+}
 
-  if (data->display_name)  
-    g_bookmark_file_set_title (priv->recent_items, uri, data->display_name);
-  
-  if (data->description)
-    g_bookmark_file_set_description (priv->recent_items, uri, data->description);
+/**
+ * gtk_recent_manager_add_fullv:
+ * @manager: a #GtkRecentManager
+ * @n_items: the number of items to add
+ * @uris: an array of URIs to add
+ * @data: an array of #GtkRecentData
+ *
+ * Adds new resources, pointed by the URIs inside the @uris array, into
+ * the recently used resources list, using the metadata specified inside
+ * the corresponding #GtkRecentData structure at the same index.
+ *
+ * This function should be used to add multiple items inside the recently
+ * used resources list in one pass, as it will emit a single ::changed
+ * signal for the entire list of items.
+ *
+ * See gtk_recent_manager_add_full() for the contents of #GtkRecentData.
+ *
+ * Return value: %TRUE if the new item was successfully added to the
+ * recently used resources list, %FALSE otherwise.
+ *
+ * Since: 2.14
+ */
+gboolean
+gtk_recent_manager_add_fullv (GtkRecentManager     *manager,
+                              guint                 n_items,
+                              const gchar * const   uris[],
+                              const GtkRecentData **data)
+{
+  guint i;
 
-  g_bookmark_file_set_mime_type (priv->recent_items, uri, data->mime_type);
-  
-  if (data->groups && data->groups[0] != '\0')
+  g_return_val_if_fail (GTK_IS_RECENT_MANAGER (manager), FALSE);
+  g_return_val_if_fail (n_items > 0, FALSE);
+  g_return_val_if_fail (uris != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  for (i = 0; i < n_items; i++)
     {
-      gint j;
-      
-      for (j = 0; (data->groups)[j] != NULL; j++)
-        g_bookmark_file_add_group (priv->recent_items, uri, (data->groups)[j]);
+      const gchar *uri = uris[i];
+      const GtkRecentData *d = data[i];
+      gboolean res;
+
+      res = gtk_recent_manager_add_internal (manager, uri, d);
+      if (G_UNLIKELY (!res))
+        return FALSE;
     }
-  
-  /* register the application; this will take care of updating the
-   * registration count and time in case the application has
-   * already registered the same document inside the list
-   */
-  g_bookmark_file_add_application (priv->recent_items, uri,
-		  		   data->app_name,
-				   data->app_exec);
-  
-  g_bookmark_file_set_is_private (priv->recent_items, uri,
-		  		  data->is_private);
-  
-  /* mark us as dirty, so that when emitting the "changed" signal we
-   * will dump our changes
-   */
-  priv->is_dirty = TRUE;
-  
+
+  manager->priv->is_dirty = TRUE;
   gtk_recent_manager_changed (manager);
-  
+
   return TRUE;
 }
 
Index: gtk/gtkrecentmanager.h
===================================================================
--- gtk/gtkrecentmanager.h	(revision 19932)
+++ gtk/gtkrecentmanager.h	(working copy)
@@ -148,6 +148,10 @@ gboolean          gtk_recent_manager_add
 gboolean          gtk_recent_manager_add_full       (GtkRecentManager     *manager,
 						     const gchar          *uri,
 						     const GtkRecentData  *recent_data);
+gboolean          gtk_recent_manager_add_fullv      (GtkRecentManager     *manager,
+                                                     guint                 n_items,
+                                                     const gchar * const   uris[],
+                                                     const GtkRecentData **data);
 gboolean          gtk_recent_manager_remove_item    (GtkRecentManager     *manager,
 						     const gchar          *uri,
 						     GError              **error);
