0bc15afd6d040773ef1bde44d7ec8d49c9e2a38e
diff --git a/embed/downloader-view.c b/embed/downloader-view.c
index 067477a..967a9ca 100644
--- a/embed/downloader-view.c
+++ b/embed/downloader-view.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  *  Copyright © 2000-2004 Marco Pesenti Gritti
  *  Copyright © 2003, 2004 Xan Lopez
@@ -232,6 +233,98 @@ prepare_close_cb (EphyEmbedShell *shell,
 }
 
 static void
+copy_download_address_activate_cb (GtkMenuItem *item,
+				   char *source)
+{
+	GtkClipboard *clipboard;
+
+	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+	gtk_clipboard_set_text (clipboard, source, -1);
+}
+
+static void
+popup_menu (DownloaderView *dv, GdkEventButton *event, GtkTreePath *path)
+{
+	GtkWidget *menu;
+	GtkWidget *menu_item;
+	GtkTreeSelection *selection;
+	GtkTreeIter iter;
+	GValue val = { 0, };
+	EphyDownload *download;
+	char *source;
+
+	/* Select the download. */
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dv->priv->treeview));
+	gtk_tree_selection_unselect_all (selection);
+	gtk_tree_selection_select_path (selection, path);
+
+	/* Save the download source URI now that we're sure the download is
+	 * still running. this way we'll be able to give the URL to the user
+	 * even in the case the download finishes before the user activates
+	 * the menu item.
+	 */
+	if (!gtk_tree_model_get_iter (dv->priv->model, &iter, path))
+	{
+		/* something's wrong here, don't show the popup */
+		return;
+	}
+
+	gtk_tree_model_get_value (dv->priv->model, &iter,
+				  COL_DOWNLOAD_OBJECT, &val);
+	download = g_value_get_object (&val);
+	source = ephy_download_get_source (download);
+
+	menu = gtk_menu_new ();
+	menu_item = gtk_image_menu_item_new_with_mnemonic (_("Copy _Download Address"));
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+				       gtk_image_new_from_stock (GTK_STOCK_COPY,
+								 GTK_ICON_SIZE_MENU));
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+	g_signal_connect (menu_item, "activate",
+			  G_CALLBACK (copy_download_address_activate_cb), source);
+
+	gtk_widget_show (menu_item);
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+			event->button, event->time);
+
+	/* free the string anyway when the menu is deactivated */
+	g_signal_connect_swapped (menu, "selection-done",
+				  G_CALLBACK (g_free), source);
+	g_value_unset (&val);
+}
+
+static gboolean
+treeview_button_press_cb (GtkWidget *treeview,
+			  GdkEventButton *event,
+			  DownloaderView *dv)
+{
+	GtkTreePath *path = NULL;
+	gboolean retval = FALSE;
+
+	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (treeview)))
+	{
+		return retval;
+	}
+	if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview),
+					   event->x,
+					   event->y,
+					   &path,
+					   NULL, NULL, NULL))
+	{
+		if (event->button == 3)
+		{
+			popup_menu (dv, event, path);
+			retval = TRUE;
+		}
+	}
+
+	gtk_tree_path_free (path);
+
+	return retval;
+}
+
+static void
 downloader_view_init (DownloaderView *dv)
 {
 	g_object_ref (embed_shell);
@@ -728,6 +821,8 @@ downloader_view_build_ui (DownloaderView *dv)
 
 	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)),
 				     GTK_SELECTION_BROWSE);
+	g_signal_connect (priv->treeview, "button-press-event",
+			  G_CALLBACK (treeview_button_press_cb), dv);
 
 	liststore = gtk_list_store_new (6,
 					G_TYPE_INT,
