[patch] link drag-and-drop to tabs

Christian Persch <[email protected]>
Newsgroups gmane.comp.web.galeon.devel
Message-ID <[email protected]>
Hi,

in galeon 1 you could drag-and-drop a link from the current tab to another tab
or create a new tab by dragging an url to the empty space on the tab notebook.
The patch below re-implements this feature for galeon 2. 
Beware: this is my first attempt at messing with galeon, so the patch just might
be horribly wrong. It seems to work fine, though.

Patch is against current CVS.

diff -urN galeon-cvs/ChangeLog galeon-modified/ChangeLog
--- galeon-cvs/ChangeLog	2003-03-08 22:09:42.000000000 +0100
+++ galeon-modified/ChangeLog	2003-03-08 23:08:44.000000000 +0100
@@ -1,3 +1,12 @@
+2003-03-08  Christian Persch  <[email protected]>
+
+	* utils/galeon-dnd.[ch] (galeon_dnd_uri_list_extract_uris): imported
+	from epiphany
+	* src/galeon-window.c (galeon_window_tab_drag_data_received_cb),
+	(galeon_window_notebook_drag_data_received_cb), (setup_notebook),
+	(galeon_window_add_tab): reimplemented the "url drag-and-drop to tabs"
+	feature from galeon1. Code adapted from galeon 1.
+
 2003-03-08  Tommi Komulainen  <[email protected]>
 
 	* src/galeon-tab.c: Check for is_active before updating window
diff -urN galeon-cvs/src/galeon-window.c galeon-modified/src/galeon-window.c
--- galeon-cvs/src/galeon-window.c	2003-03-08 22:09:41.000000000 +0100
+++ galeon-modified/src/galeon-window.c	2003-03-08 22:45:54.000000000 +0100
@@ -43,6 +43,8 @@
 #include "bookmarks-editor-dockable.h"
 #include "window-recent-history-menu.h"
 #include "galeon-embed-prefs.h"
+#include "galeon-dnd.h"
+#include "galeon-tab.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -225,12 +227,29 @@
 						const char *url, const char *title, 
 						GaleonWindow *w);
 
+static void
+galeon_window_tab_drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
+					 gint x, gint y, GtkSelectionData *selection_data,
+					 guint info, guint time, GaleonEmbed *embed);
+
+static void
+galeon_window_notebook_drag_data_received_cb (GtkWidget* widget, GdkDragContext *context,
+					      gint x, gint y, GtkSelectionData *selection_data,
+					      guint info, guint time, GaleonWindow *window);
+
 /* static class variables */
 static GdkColor _galeon_window_loading_tab_color;
 static GdkColor _galeon_window_new_tab_color;
 
 static GObjectClass *parent_class = NULL;
 
+static GtkTargetEntry url_drag_types [] = 
+{
+        { GALEON_DND_URI_LIST_TYPE,   0, GALEON_DND_URI_LIST },
+        { GALEON_DND_TEXT_TYPE,       0, GALEON_DND_TEXT },
+        { GALEON_DND_URL_TYPE,        0, GALEON_DND_URL }
+};
+
 MAKE_GET_TYPE_IFACE (galeon_window, "GaleonWindow", GaleonWindow,
 		     galeon_window_class_init, galeon_window_init, BONOBO_TYPE_WINDOW,
 		     galeon_window_gb_location_source_init, GB_TYPE_LOCATION_SOURCE);
@@ -436,6 +455,16 @@
 			  G_CALLBACK (galeon_window_tab_detached_cb), 
 			  window);
 
+	/* Setup drag-and-drop target */
+	g_signal_connect (G_OBJECT(notebook), "drag_data_received",
+			  G_CALLBACK(galeon_window_notebook_drag_data_received_cb),
+			  window);
+        gtk_drag_dest_set (GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION |
+			   GTK_DEST_DEFAULT_DROP, 
+                           url_drag_types,G_N_ELEMENTS(url_drag_types),
+                           GDK_ACTION_COPY | GDK_ACTION_MOVE | 
+                           GDK_ACTION_LINK | GDK_ACTION_ASK);
+	
 	gtk_widget_show (GTK_WIDGET (notebook));
 
 	return notebook;
@@ -1232,6 +1261,7 @@
 		       gboolean jump_to)
 {
 	GtkWidget *widget;
+	GtkWidget *tab_label;
 	
 	g_return_if_fail (IS_GALEON_WINDOW (window));
 	g_return_if_fail (IS_GALEON_TAB (tab));
@@ -1244,6 +1274,15 @@
 				  widget,
 				  GUL_NOTEBOOK_INSERT_GROUPED,
 				  jump_to);
+	
+	/* Set up drag-and-drop target */
+	tab_label = gtk_notebook_get_tab_label(window->priv->notebook,widget);
+	g_signal_connect (G_OBJECT(tab_label), "drag_data_received",
+			  G_CALLBACK(galeon_window_tab_drag_data_received_cb),widget);
+	gtk_drag_dest_set (tab_label, GTK_DEST_DEFAULT_ALL, 
+			   url_drag_types,G_N_ELEMENTS(url_drag_types),
+			   GDK_ACTION_COPY | GDK_ACTION_MOVE | 
+			   GDK_ACTION_LINK | GDK_ACTION_ASK);
 }
 
 void 
@@ -2162,3 +2201,83 @@
 		galeon_window_update_control (window, TitleControl);
 	}
 }
+
+static void
+galeon_window_tab_drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
+					 gint x, gint y, GtkSelectionData *selection_data,
+					 guint info, guint time, GaleonEmbed *embed)
+{
+        char *data = selection_data->data;
+	const char *url;
+	GList *uris;
+
+        if (selection_data->length <= 0 || selection_data->data == NULL)
+	        return;
+
+	switch (info)
+	{
+	case GALEON_DND_URI_LIST:
+	        uris = galeon_dnd_uri_list_extract_uris (data);
+		g_return_val_if_fail (uris != NULL, NULL);
+		url = (const char *)uris->data;
+		galeon_embed_load_url(embed,url);
+		/* maybe we should populate the forward history with the remaining uris? */
+		g_list_foreach (uris, (GFunc)g_free, NULL);
+		g_list_free (uris);
+		break;
+	case GALEON_DND_TEXT:
+	case GALEON_DND_URL:
+	        galeon_embed_load_url(embed,data);      
+		break;
+	default:
+                /* shouldn't happen */
+                g_warning ("unexpected dnd type %u\n", info);
+                break;
+        }
+}
+
+/**
+ * galeon_window_notebook_drag_data_received_cb: handles drops on the empty space
+ * in the notebook widget
+ */
+static void
+galeon_window_notebook_drag_data_received_cb (GtkWidget* widget, GdkDragContext *context,
+					      gint x, gint y, GtkSelectionData *selection_data,
+					      guint info, guint time, GaleonWindow *window)
+{
+        char *data = selection_data->data;
+	const char *url;
+	GList *uris;
+        GaleonTab *tab;
+
+        if (selection_data->length <= 0 || selection_data->data == NULL)
+                return;
+
+        tab = galeon_window_get_active_tab (window);
+
+	switch (info)
+	{
+	case GALEON_DND_URI_LIST:
+	        uris = galeon_dnd_uri_list_extract_uris (data);
+		g_return_val_if_fail (uris != NULL, NULL);
+		url = (const char *)uris->data;
+		galeon_shell_new_tab (galeon_shell, window, tab, url,
+				      GALEON_NEW_TAB_APPEND | 
+				      GALEON_NEW_TAB_IN_EXISTING_WINDOW);
+		/* maybe we should populate the forward history with the remaining uris? */
+		g_list_foreach (uris, (GFunc)g_free, NULL);
+		g_list_free (uris);
+		break;
+	case GALEON_DND_TEXT:
+	case GALEON_DND_URL:
+	        galeon_shell_new_tab (galeon_shell, window, tab, data,
+				      GALEON_NEW_TAB_APPEND | 
+				      GALEON_NEW_TAB_IN_EXISTING_WINDOW);
+		break;
+	default:
+                /* shouldn't happen */
+                g_warning ("unexpected dnd type %u\n", info);
+                break;
+        }
+
+}
diff -urN galeon-cvs/utils/galeon-dnd.c galeon-modified/utils/galeon-dnd.c
--- galeon-cvs/utils/galeon-dnd.c	2003-03-08 22:09:42.000000000 +0100
+++ galeon-modified/utils/galeon-dnd.c	2003-03-08 22:38:07.000000000 +0100
@@ -19,6 +19,7 @@
 #include "galeon-dnd.h"
 
 #include <gtk/gtkselection.h>
+#include <string.h>
 
 static GtkTargetEntry url_drag_types [] = 
 {
@@ -98,3 +99,53 @@
 			     G_N_ELEMENTS (url_drag_types),
                              GDK_ACTION_COPY);
 }
+
+GList *
+galeon_dnd_uri_list_extract_uris (const char *uri_list)
+{
+	/* Note that this is mostly very stolen from old libgnome/gnome-mime.c */
+
+	const gchar *p, *q;
+	gchar *retval;
+	GList *result = NULL;
+
+	g_return_val_if_fail (uri_list != NULL, NULL);
+
+	p = uri_list;
+
+	/* We don't actually try to validate the URI according to RFC
+	 * 2396, or even check for allowed characters - we just ignore
+	 * comments and trim whitespace off the ends.  We also
+	 * allow LF delimination as well as the specified CRLF.
+	 */
+	while (p != NULL) {
+		if (*p != '#') {
+			while (g_ascii_isspace (*p))
+				p++;
+
+			q = p;
+			while ((*q != '\0')
+			       && (*q != '\n')
+			       && (*q != '\r'))
+				q++;
+
+			if (q > p) {
+				q--;
+				while (q > p
+				       && g_ascii_isspace (*q))
+					q--;
+
+				retval = g_malloc (q - p + 2);
+				strncpy (retval, p, q - p + 1);
+				retval[q - p + 1] = '\0';
+
+				result = g_list_prepend (result, retval);
+			}
+		}
+		p = strchr (p, '\n');
+		if (p != NULL)
+			p++;
+	}
+
+	return g_list_reverse (result);
+}
diff -urN galeon-cvs/utils/galeon-dnd.h galeon-modified/utils/galeon-dnd.h
--- galeon-cvs/utils/galeon-dnd.h	2003-03-08 22:09:42.000000000 +0100
+++ galeon-modified/utils/galeon-dnd.h	2003-03-08 22:28:27.000000000 +0100
@@ -54,5 +54,6 @@
 
 void     galeon_dnd_url_drag_source_set 	(GtkWidget *widget); 
 
+GList   *galeon_dnd_uri_list_extract_uris       (const char *uri_list);
 
 G_END_DECLS


-------------------------------------------------------
This SF.net email is sponsored by: Etnus, makers of TotalView, The debugger 
for complex code. Debugging C/C++ programs can leave you feeling lost and 
disoriented. TotalView can help you find your way. Available on major UNIX 
and Linux platforms. Try it free. www.etnus.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.