Various DND patches
Crispin Flowerday <[email protected]>
| Newsgroups | gmane.comp.web.galeon.devel |
|---|---|
| Message-ID | <1058910011.14565.56.camel@drno> |
Amongst other things recently I have been doing a bit of dnd work. The attached patches enable the following things for dnd: - dropping onto tabs labels - dropping into the space to the right of the tab labels - dropping onto the bookmark folders - dragging from bookmarks I could not work out how to allow dropping onto the bookmark toolbar. I blame that on bonobo (roll on eggtoolbar) The galeon_dnd helper diff is needed for both of the others. The change to the gul_notebook also changes some of the signals emitted. The dropped signal is removed while adding 'tab_removed' 'tab_added' and 'tab_reordered'. These cover the dropped case while being slightly more generic (the dnd hooks onto tab_added for adding the drag signals). We will be able to use these signals to build a proper tab menu as well. Cheers -- Crispin http://patches.theflowerdays.com
galeon_bookmark_dnd.diff
(text/plain, 6.5 KB)
--- bookmarks/Makefile.am.~1.35.~ 2003-02-14 18:58:04.000000000 +0000
+++ bookmarks/Makefile.am 2003-07-16 21:48:20.000000000 +0100
@@ -92,7 +92,9 @@
bookmarks-icon-provider.h \
bookmarks-icon-provider.c \
bookmarks-default-icon-provider.h \
- bookmarks-default-icon-provider.c
+ bookmarks-default-icon-provider.c \
+ bookmarks-dnd.h \
+ bookmarks-dnd.c
testbookmarks_SOURCES= \
testbookmarks.c
--- bookmarks/bookmarks-gtk-menu-item.c.~1.6.~ 2003-01-01 21:48:27.000000000 +0000
+++ bookmarks/bookmarks-gtk-menu-item.c 2003-07-16 21:57:55.000000000 +0100
@@ -26,6 +26,7 @@
#include "galeon-marshal.h"
#include "gul-string.h"
#include "bookmarks-context-menu.h"
+#include "bookmarks-dnd.h"
#include <libgnome/gnome-i18n.h>
#include <gtk/gtkimage.h>
@@ -149,6 +150,8 @@
{
g_signal_connect (ret, "button_press_event",
G_CALLBACK (gb_gtk_menu_item_button_press_cb), NULL);
+
+ gb_bookmark_dnd_drag_source_set (ret, bookmark);
}
gb_gtk_menu_item_rebuild (ret);
--- bookmarks/bookmarks-tb-widget.c.~1.7.~ 2003-06-22 12:31:26.000000000 +0100
+++ bookmarks/bookmarks-tb-widget.c 2003-07-19 00:08:11.000000000 +0100
@@ -22,6 +22,7 @@
#include "bookmarks-tb-widget.h"
#include "bookmarks-context-menu.h"
+#include "bookmarks-dnd.h"
#include "galeon-marshal.h"
#include "gul-gobject-misc.h"
@@ -237,6 +238,13 @@
G_CALLBACK (gb_tb_widget_popup_menu_cb), gtw);
g_signal_connect (w, "button_press_event",
G_CALLBACK (gb_tb_widget_button_press_cb), gtw);
+ if (GB_IS_SITE(gtw->priv->bm)) {
+ gb_bookmark_dnd_drag_source_set (w, gtw->priv->bm);
+ }
+ else if (GB_IS_FOLDER(gtw->priv->bm))
+ {
+ gb_bookmark_dnd_drag_dest_set (w, gtw->priv->bm);
+ }
}
static void
--- bookmarks/bookmarks-dnd.c 2003-07-20 21:33:28.000000000 +0100
+++ bookmarks/bookmarks-dnd.c 2003-07-16 23:14:23.000000000 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2003 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "bookmarks.h"
+#include "bookmarks-dnd.h"
+#include "galeon-dnd.h"
+
+/**
+ * Private functions, only availble from this file
+ */
+
+static void gb_bookmark_drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ GbBookmark *bm);
+
+static void gb_bookmark_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *dc,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint t,
+ GbBookmark *bm);
+
+
+static void
+each_url_get_data_binder (GaleonDragEachSelectedItemDataGet iteratee,
+ gpointer iterator_context, gpointer data)
+{
+ GbBookmark *bm = GB_BOOKMARK(iterator_context);
+ const gchar *url = GB_IS_SITE (bm) ? GB_SITE (bm)->url : NULL;
+
+ if ( url )
+ iteratee (url, -1, -1, -1, -1, data);
+}
+
+
+static void
+gb_bookmark_drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ GbBookmark *bm)
+{
+ g_assert (widget != NULL);
+ g_return_if_fail (context != NULL);
+
+ galeon_dnd_drag_data_get (widget, context, selection_data,
+ info, time, bm, each_url_get_data_binder);
+}
+
+
+static void
+each_url_receive_data_binder (const char * url, const char * title, gpointer context)
+{
+ GbBookmark *bm = GB_BOOKMARK(context);
+ GbSite *niu;
+
+ g_return_if_fail (GB_IS_FOLDER (bm));
+
+ if (!title) title = url;
+
+ niu = gb_site_new (bm->set, title, url);
+
+ gb_folder_add_child (GB_FOLDER (bm), GB_BOOKMARK (niu), -1);
+ g_object_unref (niu);
+}
+
+
+
+static void
+gb_bookmark_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *dc,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint t,
+ GbBookmark *bm)
+{
+ galeon_dnd_drag_data_receive( widget, dc, x, y, selection_data,
+ info, t, bm, each_url_receive_data_binder);
+}
+
+
+
+void
+gb_bookmark_dnd_drag_source_set (GtkWidget *widget, GbBookmark *bm)
+{
+ if (GB_IS_SITE(bm)) {
+ galeon_dnd_url_drag_source_set (widget);
+
+ g_signal_connect (G_OBJECT (widget),
+ "drag_data_get",
+ G_CALLBACK (gb_bookmark_drag_data_get_cb),
+ bm);
+ }
+}
+
+
+
+void
+gb_bookmark_dnd_drag_dest_set (GtkWidget *widget, GbBookmark *bm)
+{
+ if (GB_IS_FOLDER(bm)) {
+ galeon_dnd_url_drag_dest_set (widget);
+
+ g_signal_connect (G_OBJECT (widget),
+ "drag_data_received",
+ G_CALLBACK (gb_bookmark_drag_data_received_cb),
+ bm);
+ }
+}
--- bookmarks/bookmarks-dnd.h 2003-07-20 21:33:28.000000000 +0100
+++ bookmarks/bookmarks-dnd.h 2003-07-16 22:36:27.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2003 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __bookmarks_dnd_h
+#define __bookmarks_dnd_h
+
+G_BEGIN_DECLS
+
+void gb_bookmark_dnd_drag_source_set (GtkWidget *widget, GbBookmark *bm);
+
+void gb_bookmark_dnd_drag_dest_set (GtkWidget *widget, GbBookmark *bm);
+
+G_END_DECLS
+
+
+#endif
galeon_dnd_helper.diff
(text/x-patch, 4.3 KB)
Index: utils/galeon-dnd.c
===================================================================
RCS file: /cvs/gnome/galeon/utils/galeon-dnd.c,v
retrieving revision 1.2
diff -u -r1.2 galeon-dnd.c
--- utils/galeon-dnd.c 27 Jun 2002 12:54:02 -0000 1.2
+++ utils/galeon-dnd.c 22 Jul 2003 20:40:44 -0000
@@ -20,6 +20,8 @@
#include <gtk/gtkselection.h>
+#include <string.h>
+
static GtkTargetEntry url_drag_types [] =
{
{ GALEON_DND_URI_LIST_TYPE, 0, GALEON_DND_URI_LIST },
@@ -27,6 +29,13 @@
{ GALEON_DND_URL_TYPE, 0, GALEON_DND_URL }
};
+
+const GtkTargetEntry url_drop_types[] =
+{
+ { GALEON_DND_URI_LIST_TYPE, 0, GALEON_DND_URI_LIST },
+ { GALEON_DND_URL_TYPE, 0, GALEON_DND_URL }
+};
+
/* Encode a "_NETSCAPE_URL_" selection.
* As far as I can tell, Netscape is expecting a single
* URL to be returned. I cannot discover a way to construct
@@ -97,4 +106,81 @@
url_drag_types,
G_N_ELEMENTS (url_drag_types),
GDK_ACTION_COPY);
+}
+
+
+gboolean
+galeon_dnd_drag_data_receive (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ gpointer container_context,
+ GaleonDragEachReceivedItemIterator each_received_item_iterator)
+{
+ char * data = selection_data->data;
+
+ g_signal_stop_emission_by_name (widget, "drag_data_received");
+
+ switch (info) {
+ case GALEON_DND_URI_LIST: {
+ gchar** split = g_strsplit(selection_data->data, "\n", 0);
+ int i;
+ for (i = 0 ; split[i] ; i++) {
+ gchar *url = split[i];
+ int len = strlen( url );
+ if ( len && url[len-1] == '\r' )
+ {
+ len--;
+ url[len] = 0;
+ }
+ if (!len) continue;
+
+ (* each_received_item_iterator) (url, 0, container_context);
+ }
+ g_strfreev (split);
+ break;
+ }
+ case GALEON_DND_URL: {
+ /* Mozilla passes the page title as the second line */
+ gchar** split = g_strsplit(data, "\n", 2);
+ if ( split )
+ {
+ (* each_received_item_iterator) (split[0], split[1], container_context);
+ g_strfreev (split);
+ }
+ else
+ {
+ (* each_received_item_iterator) (data, 0, container_context);
+ }
+ break;
+ }
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void
+galeon_dnd_url_drag_dest_set (GtkWidget *widget)
+{
+ gtk_drag_dest_set (widget,
+ GTK_DEST_DEFAULT_ALL,
+ url_drop_types,
+ G_N_ELEMENTS (url_drop_types),
+ GDK_ACTION_COPY);
+}
+
+void
+galeon_dnd_url_drag_dest_set_with_flags (GtkWidget *widget, GtkDestDefaults flags)
+{
+ gtk_drag_dest_set (widget,
+ flags,
+ url_drop_types,
+ G_N_ELEMENTS (url_drop_types),
+ GDK_ACTION_COPY);
}
Index: utils/galeon-dnd.h
===================================================================
RCS file: /cvs/gnome/galeon/utils/galeon-dnd.h,v
retrieving revision 1.2
diff -u -r1.2 galeon-dnd.h
--- utils/galeon-dnd.h 27 Jun 2002 12:54:02 -0000 1.2
+++ utils/galeon-dnd.h 22 Jul 2003 20:40:44 -0000
@@ -44,6 +44,9 @@
gpointer iterator_context,
gpointer data);
+typedef void (* GaleonDragEachReceivedItemIterator) (const char * url, const char * title,
+ gpointer data);
+
gboolean galeon_dnd_drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
@@ -54,5 +57,21 @@
void galeon_dnd_url_drag_source_set (GtkWidget *widget);
+
+gboolean galeon_dnd_drag_data_receive (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ gpointer container_context,
+ GaleonDragEachReceivedItemIterator each_received_item_iterator);
+
+
+
+void galeon_dnd_url_drag_dest_set (GtkWidget *widget);
+
+void galeon_dnd_url_drag_dest_set_with_flags (GtkWidget *widget, GtkDestDefaults flags);
G_END_DECLS
galeon_tab_dnd.diff
(text/x-patch, 8.3 KB)
Index: utils/gul-notebook.c
===================================================================
RCS file: /cvs/gnome/galeon/utils/gul-notebook.c,v
retrieving revision 1.26
diff -u -r1.26 gul-notebook.c
--- utils/gul-notebook.c 22 Jul 2003 12:19:26 -0000 1.26
+++ utils/gul-notebook.c 22 Jul 2003 20:42:30 -0000
@@ -76,7 +76,9 @@
/* Signals */
enum
{
- TAB_DROPPED,
+ TAB_ADDED,
+ TAB_REMOVED,
+ TABS_REORDERED,
TAB_DETACHED,
LAST_SIGNAL
};
@@ -118,19 +120,26 @@
object_class->finalize = gul_notebook_finalize;
/* init signals */
- gul_notebook_signals[TAB_DROPPED] =
- g_signal_new ("tab_dropped",
+ gul_notebook_signals[TAB_ADDED] =
+ g_signal_new ("tab_added",
G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GulNotebookClass,
- tab_dropped),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GulNotebookClass, tab_added),
NULL, NULL,
- galeon_marshal_VOID__OBJECT_OBJECT_INT,
+ galeon_marshal_VOID__OBJECT,
G_TYPE_NONE,
- 3,
- GTK_TYPE_WIDGET,
- GUL_NOTEBOOK_TYPE,
- G_TYPE_INT);
+ 1,
+ GTK_TYPE_WIDGET);
+ gul_notebook_signals[TAB_REMOVED] =
+ g_signal_new ("tab_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GulNotebookClass, tab_removed),
+ NULL, NULL,
+ galeon_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_WIDGET);
gul_notebook_signals[TAB_DETACHED] =
g_signal_new ("tab_detached",
G_OBJECT_CLASS_TYPE (object_class),
@@ -144,6 +153,16 @@
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT);
+ gul_notebook_signals[TABS_REORDERED] =
+ g_signal_new ("tabs_reordered",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GulNotebookClass, tabs_reordered),
+ NULL, NULL,
+ galeon_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
}
@@ -327,6 +346,18 @@
gul_notebook_move_page (GulNotebook *src, GulNotebook *dest,
GtkWidget *src_page, gint dest_page)
{
+ if (dest == NULL || src == dest)
+ {
+ gtk_notebook_reorder_child (GTK_NOTEBOOK (src), src_page, dest_page);
+
+ if (src->priv->drag_in_progress == FALSE)
+ {
+ g_signal_emit (G_OBJECT (src),
+ gul_notebook_signals[TABS_REORDERED], 0);
+ }
+ return;
+ }
+
GtkWidget *tab_label;
GtkWidget *menu_label;
@@ -464,16 +495,6 @@
cur_page_num, (gint)event->x_root,
(gint)event->y_root);
}
- else
- {
- /* Tab was dragged and dropped (but it may have stayed
- in the same place) */
- g_signal_emit (G_OBJECT(notebook),
- gul_notebook_signals[TAB_DROPPED], 0,
- cur_page,
- notebook->priv->src_notebook,
- notebook->priv->src_page);
- }
/* ungrab the pointer if it's grabbed */
if (gdk_pointer_is_grabbed ())
@@ -799,6 +820,9 @@
g_object_set_data (G_OBJECT (child), "jump_to",
GINT_TO_POINTER (jump_to));
}
+
+ g_signal_emit (G_OBJECT (nb), gul_notebook_signals[TAB_ADDED],
+ 0, child);
}
static void
@@ -862,9 +886,20 @@
smart_tab_switching_on_closure (nb, child);
}
+ /**
+ * we ref the child so that it's still alive while the tabs_removed
+ * signal is processed.
+ */
+ g_object_ref (child);
+
gtk_notebook_remove_page (GTK_NOTEBOOK (nb), position);
update_tabs_visibility (nb, FALSE);
+
+ g_signal_emit (G_OBJECT (nb), gul_notebook_signals[TAB_REMOVED],
+ 0, child);
+
+ g_object_unref (child);
}
void
Index: utils/gul-notebook.h
===================================================================
RCS file: /cvs/gnome/galeon/utils/gul-notebook.h,v
retrieving revision 1.8
diff -u -r1.8 gul-notebook.h
--- utils/gul-notebook.h 6 Feb 2003 16:24:38 -0000 1.8
+++ utils/gul-notebook.h 22 Jul 2003 20:42:30 -0000
@@ -52,11 +52,15 @@
GtkNotebookClass parent_class;
/* Signals */
- void (* tab_dropped) (GulNotebook *dest,
- GtkWidget *widget,
- GulNotebook *src,
- gint src_page);
- void (* tab_detached) (GulNotebook *dest,
+ void (* tab_added) (GulNotebook *notebook,
+ GtkWidget *child);
+
+ void (* tab_removed) (GulNotebook *notebook,
+ GtkWidget *child);
+
+ void (* tabs_reordered) (GulNotebook *notebook);
+
+ void (* tab_detached) (GulNotebook *dest,
gint cur_page,
gint root_x, gint root_y);
Index: src/galeon-window.c
===================================================================
RCS file: /cvs/gnome/galeon/src/galeon-window.c,v
retrieving revision 1.173
diff -u -r1.173 galeon-window.c
--- src/galeon-window.c 12 Jul 2003 17:51:46 -0000 1.173
+++ src/galeon-window.c 22 Jul 2003 20:42:31 -0000
@@ -22,6 +22,7 @@
#include "galeon-window.h"
#include "galeon-sidebar.h"
+#include "galeon-dnd.h"
#include "gul-state.h"
#include "gul-gobject-misc.h"
#include "gul-notebook.h"
@@ -227,9 +232,18 @@
GbBookmarkEventActivated *ev,
GaleonWindow *w);
+static void
+galeon_window_tab_detached_cb (GulNotebook *notebook, gint page,
+ gint x, gint y, GaleonWindow *window);
+
+static void
+galeon_window_tab_drag_data_received_cb (GtkWidget* widget, GdkDragContext *context,
+ gint x, gint y, GtkSelectionData *selection_data,
+ guint info, guint time, GtkWidget *child);
+
static void
-galeon_window_tab_detached_cb (GulNotebook *notebook, gint page,
- gint x, gint y, GaleonWindow *window);
+galeon_window_tab_added_cb (GulNotebook *notebook, GtkWidget* child,
+ GaleonWindow *window);
void /* yes, this is not static */
galeon_window_bookmark_activate (GaleonWindow *w, GbBookmarkEventActivated *ev);
@@ -499,6 +513,18 @@
G_CALLBACK (galeon_window_tab_detached_cb),
window);
+ g_signal_connect (G_OBJECT (notebook), "tab_added",
+ G_CALLBACK (galeon_window_tab_added_cb),
+ window);
+
+ galeon_dnd_url_drag_dest_set_with_flags( GTK_WIDGET(notebook),
+ GTK_DEST_DEFAULT_MOTION |
+ GTK_DEST_DEFAULT_DROP);
+
+ g_signal_connect (G_OBJECT(notebook), "drag_data_received",
+ G_CALLBACK(galeon_window_tab_drag_data_received_cb),
+ NULL);
+
eel_gconf_notification_add(CONF_TABS_TABBED_EDGE,
(GConfClientNotifyFunc)tabbed_position_gconf_changed_cb,
notebook);
@@ -2457,6 +2498,87 @@
GaleonWindow *w)
{
galeon_window_load_url (w, url);
+}
+
+
+struct url_receive_context {
+ GaleonEmbed * embed;
+ GaleonWindow * window;
+ GaleonTab * tab;
+ int num;
+};
+
+static void
+each_url_receive_data_binder (const char * url, const char * title,
+ gpointer data )
+{
+ struct url_receive_context * context = (struct url_receive_context*)data;
+ GaleonEmbed * embed = context->embed;
+ int num = context->num++;
+
+ if (num == 0 && embed != NULL)
+ {
+ /**
+ * The first url is special: if the drag was to an
+ * existing tab, load it there
+ */
+ galeon_embed_load_url (embed, url);
+ }
+ else
+ {
+ context->tab =
+ galeon_shell_new_tab (galeon_shell, context->window,
+ context->tab, url,
+ GALEON_NEW_TAB_IN_EXISTING_WINDOW |
+ GALEON_NEW_TAB_APPEND);
+ }
+}
+
+
+static void
+galeon_window_tab_drag_data_received_cb(GtkWidget *widget,
+ GdkDragContext *dc,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint t,
+ GtkWidget * child)
+{
+ struct url_receive_context context;
+ GtkWidget * toplevel;
+ context.embed = child ? GALEON_EMBED( child ) : 0;
+ context.num = 0;
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ g_return_if_fail (IS_GALEON_WINDOW (toplevel));
+
+ context.window = GALEON_WINDOW (toplevel);
+
+ if (context.embed)
+ {
+ context.tab = GALEON_TAB (g_object_get_data (G_OBJECT (context.embed),
+ "GaleonTab"));
+ }
+ else
+ {
+ context.tab = 0;
+ }
+
+ galeon_dnd_drag_data_receive( widget, dc, x, y, selection_data,
+ info, t, &context, each_url_receive_data_binder);
+}
+
+
+static void
+galeon_window_tab_added_cb (GulNotebook *notebook, GtkWidget *child, GaleonWindow *window)
+{
+ GtkWidget * label = gtk_notebook_get_tab_label( GTK_NOTEBOOK(notebook), child );
+
+ galeon_dnd_url_drag_dest_set( label );
+
+ g_signal_connect (G_OBJECT(label), "drag_data_received",
+ G_CALLBACK(galeon_window_tab_drag_data_received_cb),
+ child);
}
void