summaryrefslogtreecommitdiffstats
path: root/app/widgets/gimpdnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/widgets/gimpdnd.c')
-rw-r--r--app/widgets/gimpdnd.c2465
1 files changed, 2465 insertions, 0 deletions
diff --git a/app/widgets/gimpdnd.c b/app/widgets/gimpdnd.c
new file mode 100644
index 0000000..7be8622
--- /dev/null
+++ b/app/widgets/gimpdnd.c
@@ -0,0 +1,2465 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * 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 3 of the License, 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrush.h"
+#include "core/gimpbuffer.h"
+#include "core/gimpchannel.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpgradient.h"
+#include "core/gimpimage.h"
+#include "core/gimpimagefile.h"
+#include "core/gimplayer.h"
+#include "core/gimplayermask.h"
+#include "core/gimppalette.h"
+#include "core/gimppattern.h"
+#include "core/gimptemplate.h"
+#include "core/gimptoolitem.h"
+
+#include "text/gimpfont.h"
+
+#include "vectors/gimpvectors.h"
+
+#include "gimpdnd.h"
+#include "gimpdnd-xds.h"
+#include "gimppixbuf.h"
+#include "gimpselectiondata.h"
+#include "gimpview.h"
+#include "gimpviewrendererimage.h"
+
+#include "gimp-log.h"
+#include "gimp-intl.h"
+
+
+#define DRAG_PREVIEW_SIZE GIMP_VIEW_SIZE_LARGE
+#define DRAG_ICON_OFFSET -8
+
+
+typedef GtkWidget * (* GimpDndGetIconFunc) (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_data_func,
+ gpointer get_data_data);
+typedef void (* GimpDndDragDataFunc) (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_data_func,
+ gpointer get_data_data,
+ GtkSelectionData *selection);
+typedef gboolean (* GimpDndDropDataFunc) (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_data_func,
+ gpointer set_data_data,
+ GtkSelectionData *selection);
+
+
+typedef struct _GimpDndDataDef GimpDndDataDef;
+
+struct _GimpDndDataDef
+{
+ GtkTargetEntry target_entry;
+
+ const gchar *get_data_func_name;
+ const gchar *get_data_data_name;
+
+ const gchar *set_data_func_name;
+ const gchar *set_data_data_name;
+
+ GimpDndGetIconFunc get_icon_func;
+ GimpDndDragDataFunc get_data_func;
+ GimpDndDropDataFunc set_data_func;
+};
+
+
+static GtkWidget * gimp_dnd_get_viewable_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_viewable_func,
+ gpointer get_viewable_data);
+static GtkWidget * gimp_dnd_get_component_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_comp_func,
+ gpointer get_comp_data);
+static GtkWidget * gimp_dnd_get_color_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_color_func,
+ gpointer get_color_data);
+
+static void gimp_dnd_get_uri_list_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_uri_list_func,
+ gpointer get_uri_list_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_uri_list_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_uri_list_func,
+ gpointer set_uri_list_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_xds_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_image_func,
+ gpointer get_image_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_color_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_color_func,
+ gpointer get_color_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_color_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_color_func,
+ gpointer set_color_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_stream_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_stream_func,
+ gpointer get_stream_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_stream_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_stream_func,
+ gpointer set_stream_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_pixbuf_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_pixbuf_func,
+ gpointer get_pixbuf_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_pixbuf_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_pixbuf_func,
+ gpointer set_pixbuf_data,
+ GtkSelectionData *selection);
+static void gimp_dnd_get_component_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_comp_func,
+ gpointer get_comp_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_component_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_comp_func,
+ gpointer set_comp_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_image_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_image_func,
+ gpointer get_image_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_image_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_image_func,
+ gpointer set_image_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_item_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_item_func,
+ gpointer get_item_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_item_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_item_func,
+ gpointer set_item_data,
+ GtkSelectionData *selection);
+
+static void gimp_dnd_get_object_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_object_func,
+ gpointer get_object_data,
+ GtkSelectionData *selection);
+
+static gboolean gimp_dnd_set_brush_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_brush_func,
+ gpointer set_brush_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_pattern_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_pattern_func,
+ gpointer set_pattern_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_gradient_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_gradient_func,
+ gpointer set_gradient_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_palette_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_palette_func,
+ gpointer set_palette_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_font_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_font_func,
+ gpointer set_font_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_buffer_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_buffer_func,
+ gpointer set_buffer_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_imagefile_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_imagefile_func,
+ gpointer set_imagefile_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_template_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_template_func,
+ gpointer set_template_data,
+ GtkSelectionData *selection);
+static gboolean gimp_dnd_set_tool_item_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_tool_item_func,
+ gpointer set_tool_item_data,
+ GtkSelectionData *selection);
+
+
+
+static const GimpDndDataDef dnd_data_defs[] =
+{
+ {
+ { NULL, 0, -1 },
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL
+ },
+
+ {
+ GIMP_TARGET_URI_LIST,
+
+ "gimp-dnd-get-uri-list-func",
+ "gimp-dnd-get-uri-list-data",
+
+ "gimp-dnd-set-uri-list-func",
+ "gimp-dnd-set-uri-list-data",
+
+ NULL,
+ gimp_dnd_get_uri_list_data,
+ gimp_dnd_set_uri_list_data
+ },
+
+ {
+ GIMP_TARGET_TEXT_PLAIN,
+
+ NULL,
+ NULL,
+
+ "gimp-dnd-set-uri-list-func",
+ "gimp-dnd-set-uri-list-data",
+
+ NULL,
+ NULL,
+ gimp_dnd_set_uri_list_data
+ },
+
+ {
+ GIMP_TARGET_NETSCAPE_URL,
+
+ NULL,
+ NULL,
+
+ "gimp-dnd-set-uri-list-func",
+ "gimp-dnd-set-uri-list-data",
+
+ NULL,
+ NULL,
+ gimp_dnd_set_uri_list_data
+ },
+
+ {
+ GIMP_TARGET_XDS,
+
+ "gimp-dnd-get-xds-func",
+ "gimp-dnd-get-xds-data",
+
+ NULL,
+ NULL,
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_xds_data,
+ NULL
+ },
+
+ {
+ GIMP_TARGET_COLOR,
+
+ "gimp-dnd-get-color-func",
+ "gimp-dnd-get-color-data",
+
+ "gimp-dnd-set-color-func",
+ "gimp-dnd-set-color-data",
+
+ gimp_dnd_get_color_icon,
+ gimp_dnd_get_color_data,
+ gimp_dnd_set_color_data
+ },
+
+ {
+ GIMP_TARGET_SVG,
+
+ "gimp-dnd-get-svg-func",
+ "gimp-dnd-get-svg-data",
+
+ "gimp-dnd-set-svg-func",
+ "gimp-dnd-set-svg-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_stream_data,
+ gimp_dnd_set_stream_data
+ },
+
+ {
+ GIMP_TARGET_SVG_XML,
+
+ "gimp-dnd-get-svg-xml-func",
+ "gimp-dnd-get-svg-xml-data",
+
+ "gimp-dnd-set-svg-xml-func",
+ "gimp-dnd-set-svg-xml-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_stream_data,
+ gimp_dnd_set_stream_data
+ },
+
+ {
+ GIMP_TARGET_PIXBUF,
+
+ "gimp-dnd-get-pixbuf-func",
+ "gimp-dnd-get-pixbuf-data",
+
+ "gimp-dnd-set-pixbuf-func",
+ "gimp-dnd-set-pixbuf-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_pixbuf_data,
+ gimp_dnd_set_pixbuf_data
+ },
+
+ {
+ GIMP_TARGET_IMAGE,
+
+ "gimp-dnd-get-image-func",
+ "gimp-dnd-get-image-data",
+
+ "gimp-dnd-set-image-func",
+ "gimp-dnd-set-image-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_image_data,
+ gimp_dnd_set_image_data,
+ },
+
+ {
+ GIMP_TARGET_COMPONENT,
+
+ "gimp-dnd-get-component-func",
+ "gimp-dnd-get-component-data",
+
+ "gimp-dnd-set-component-func",
+ "gimp-dnd-set-component-data",
+
+ gimp_dnd_get_component_icon,
+ gimp_dnd_get_component_data,
+ gimp_dnd_set_component_data,
+ },
+
+ {
+ GIMP_TARGET_LAYER,
+
+ "gimp-dnd-get-layer-func",
+ "gimp-dnd-get-layer-data",
+
+ "gimp-dnd-set-layer-func",
+ "gimp-dnd-set-layer-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_item_data,
+ gimp_dnd_set_item_data,
+ },
+
+ {
+ GIMP_TARGET_CHANNEL,
+
+ "gimp-dnd-get-channel-func",
+ "gimp-dnd-get-channel-data",
+
+ "gimp-dnd-set-channel-func",
+ "gimp-dnd-set-channel-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_item_data,
+ gimp_dnd_set_item_data,
+ },
+
+ {
+ GIMP_TARGET_LAYER_MASK,
+
+ "gimp-dnd-get-layer-mask-func",
+ "gimp-dnd-get-layer-mask-data",
+
+ "gimp-dnd-set-layer-mask-func",
+ "gimp-dnd-set-layer-mask-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_item_data,
+ gimp_dnd_set_item_data,
+ },
+
+ {
+ GIMP_TARGET_VECTORS,
+
+ "gimp-dnd-get-vectors-func",
+ "gimp-dnd-get-vectors-data",
+
+ "gimp-dnd-set-vectors-func",
+ "gimp-dnd-set-vectors-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_item_data,
+ gimp_dnd_set_item_data,
+ },
+
+ {
+ GIMP_TARGET_BRUSH,
+
+ "gimp-dnd-get-brush-func",
+ "gimp-dnd-get-brush-data",
+
+ "gimp-dnd-set-brush-func",
+ "gimp-dnd-set-brush-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_brush_data
+ },
+
+ {
+ GIMP_TARGET_PATTERN,
+
+ "gimp-dnd-get-pattern-func",
+ "gimp-dnd-get-pattern-data",
+
+ "gimp-dnd-set-pattern-func",
+ "gimp-dnd-set-pattern-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_pattern_data
+ },
+
+ {
+ GIMP_TARGET_GRADIENT,
+
+ "gimp-dnd-get-gradient-func",
+ "gimp-dnd-get-gradient-data",
+
+ "gimp-dnd-set-gradient-func",
+ "gimp-dnd-set-gradient-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_gradient_data
+ },
+
+ {
+ GIMP_TARGET_PALETTE,
+
+ "gimp-dnd-get-palette-func",
+ "gimp-dnd-get-palette-data",
+
+ "gimp-dnd-set-palette-func",
+ "gimp-dnd-set-palette-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_palette_data
+ },
+
+ {
+ GIMP_TARGET_FONT,
+
+ "gimp-dnd-get-font-func",
+ "gimp-dnd-get-font-data",
+
+ "gimp-dnd-set-font-func",
+ "gimp-dnd-set-font-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_font_data
+ },
+
+ {
+ GIMP_TARGET_BUFFER,
+
+ "gimp-dnd-get-buffer-func",
+ "gimp-dnd-get-buffer-data",
+
+ "gimp-dnd-set-buffer-func",
+ "gimp-dnd-set-buffer-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_buffer_data
+ },
+
+ {
+ GIMP_TARGET_IMAGEFILE,
+
+ "gimp-dnd-get-imagefile-func",
+ "gimp-dnd-get-imagefile-data",
+
+ "gimp-dnd-set-imagefile-func",
+ "gimp-dnd-set-imagefile-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_imagefile_data
+ },
+
+ {
+ GIMP_TARGET_TEMPLATE,
+
+ "gimp-dnd-get-template-func",
+ "gimp-dnd-get-template-data",
+
+ "gimp-dnd-set-template-func",
+ "gimp-dnd-set-template-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_template_data
+ },
+
+ {
+ GIMP_TARGET_TOOL_ITEM,
+
+ "gimp-dnd-get-tool-item-func",
+ "gimp-dnd-get-tool-item-data",
+
+ "gimp-dnd-set-tool-item-func",
+ "gimp-dnd-set-tool-item-data",
+
+ gimp_dnd_get_viewable_icon,
+ gimp_dnd_get_object_data,
+ gimp_dnd_set_tool_item_data
+ },
+
+ {
+ GIMP_TARGET_DIALOG,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL
+ }
+};
+
+
+static Gimp *the_dnd_gimp = NULL;
+
+
+void
+gimp_dnd_init (Gimp *gimp)
+{
+ g_return_if_fail (GIMP_IS_GIMP (gimp));
+ g_return_if_fail (the_dnd_gimp == NULL);
+
+ the_dnd_gimp = gimp;
+}
+
+
+/**********************/
+/* helper functions */
+/**********************/
+
+static void
+gimp_dnd_target_list_add (GtkTargetList *list,
+ const GtkTargetEntry *entry)
+{
+ GdkAtom atom = gdk_atom_intern (entry->target, FALSE);
+ guint info;
+
+ if (! gtk_target_list_find (list, atom, &info) || info != entry->info)
+ {
+ gtk_target_list_add (list, atom, entry->flags, entry->info);
+ }
+}
+
+
+/********************************/
+/* general data dnd functions */
+/********************************/
+
+static void
+gimp_dnd_data_drag_begin (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ const GimpDndDataDef *dnd_data;
+ GimpDndType data_type;
+ GCallback get_data_func = NULL;
+ gpointer get_data_data = NULL;
+ GtkWidget *icon_widget;
+
+ data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-get-data-type"));
+
+ GIMP_LOG (DND, "data type %d", data_type);
+
+ if (! data_type)
+ return;
+
+ dnd_data = dnd_data_defs + data_type;
+
+ if (dnd_data->get_data_func_name)
+ get_data_func = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_func_name);
+
+ if (dnd_data->get_data_data_name)
+ get_data_data = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_data_name);
+
+ if (! get_data_func)
+ return;
+
+ icon_widget = dnd_data->get_icon_func (widget,
+ context,
+ get_data_func,
+ get_data_data);
+
+ if (icon_widget)
+ {
+ GtkWidget *frame;
+ GtkWidget *window;
+
+ window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
+ gtk_window_set_screen (GTK_WINDOW (window),
+ gtk_widget_get_screen (widget));
+
+ gtk_widget_realize (window);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (window), frame);
+ gtk_widget_show (frame);
+
+ gtk_container_add (GTK_CONTAINER (frame), icon_widget);
+ gtk_widget_show (icon_widget);
+
+ g_object_set_data_full (G_OBJECT (widget), "gimp-dnd-data-widget",
+ window, (GDestroyNotify) gtk_widget_destroy);
+
+ gtk_drag_set_icon_widget (context, window,
+ DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
+
+ /* remember for which drag context the widget was made */
+ g_object_set_data (G_OBJECT (window), "gimp-gdk-drag-context", context);
+ }
+}
+
+static void
+gimp_dnd_data_drag_end (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GimpDndType data_type;
+ GtkWidget *icon_widget;
+
+ data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-get-data-type"));
+
+ GIMP_LOG (DND, "data type %d", data_type);
+
+ icon_widget = g_object_get_data (G_OBJECT (widget), "gimp-dnd-data-widget");
+
+ if (icon_widget)
+ {
+ /* destroy the icon_widget only if it was made for this drag
+ * context. See bug #139337.
+ */
+ if (g_object_get_data (G_OBJECT (icon_widget),
+ "gimp-gdk-drag-context") ==
+ (gpointer) context)
+ {
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-data-widget", NULL);
+ }
+ }
+}
+
+static void
+gimp_dnd_data_drag_handle (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ GCallback get_data_func = NULL;
+ gpointer get_data_data = NULL;
+ GimpDndType data_type;
+
+ GIMP_LOG (DND, "data type %d", info);
+
+ for (data_type = GIMP_DND_TYPE_NONE + 1;
+ data_type <= GIMP_DND_TYPE_LAST;
+ data_type++)
+ {
+ const GimpDndDataDef *dnd_data = dnd_data_defs + data_type;
+
+ if (dnd_data->target_entry.info == info)
+ {
+ GIMP_LOG (DND, "target %s", dnd_data->target_entry.target);
+
+ if (dnd_data->get_data_func_name)
+ get_data_func = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_func_name);
+
+ if (dnd_data->get_data_data_name)
+ get_data_data = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_data_name);
+
+ if (! get_data_func)
+ return;
+
+ dnd_data->get_data_func (widget,
+ context,
+ get_data_func,
+ get_data_data,
+ selection_data);
+
+ return;
+ }
+ }
+}
+
+static void
+gimp_dnd_data_drop_handle (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ GimpDndType data_type;
+
+ GIMP_LOG (DND, "data type %d", info);
+
+ if (gtk_selection_data_get_length (selection_data) <= 0)
+ {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ return;
+ }
+
+ for (data_type = GIMP_DND_TYPE_NONE + 1;
+ data_type <= GIMP_DND_TYPE_LAST;
+ data_type++)
+ {
+ const GimpDndDataDef *dnd_data = dnd_data_defs + data_type;
+
+ if (dnd_data->target_entry.info == info)
+ {
+ GCallback set_data_func = NULL;
+ gpointer set_data_data = NULL;
+
+ GIMP_LOG (DND, "target %s", dnd_data->target_entry.target);
+
+ if (dnd_data->set_data_func_name)
+ set_data_func = g_object_get_data (G_OBJECT (widget),
+ dnd_data->set_data_func_name);
+
+ if (dnd_data->set_data_data_name)
+ set_data_data = g_object_get_data (G_OBJECT (widget),
+ dnd_data->set_data_data_name);
+
+ if (set_data_func &&
+ dnd_data->set_data_func (widget, x, y,
+ set_data_func,
+ set_data_data,
+ selection_data))
+ {
+ gtk_drag_finish (context, TRUE, FALSE, time);
+ return;
+ }
+
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ return;
+ }
+ }
+}
+
+static void
+gimp_dnd_data_source_add (GimpDndType data_type,
+ GtkWidget *widget,
+ GCallback get_data_func,
+ gpointer get_data_data)
+{
+ const GimpDndDataDef *dnd_data;
+ gboolean drag_connected;
+
+ dnd_data = dnd_data_defs + data_type;
+
+ /* set a default drag source if not already done */
+ if (! g_object_get_data (G_OBJECT (widget), "gtk-site-data"))
+ gtk_drag_source_set (widget, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+ NULL, 0,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ drag_connected =
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-drag-connected"));
+
+ if (! drag_connected)
+ {
+ g_signal_connect (widget, "drag-begin",
+ G_CALLBACK (gimp_dnd_data_drag_begin),
+ NULL);
+ g_signal_connect (widget, "drag-end",
+ G_CALLBACK (gimp_dnd_data_drag_end),
+ NULL);
+ g_signal_connect (widget, "drag-data-get",
+ G_CALLBACK (gimp_dnd_data_drag_handle),
+ NULL);
+
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-drag-connected",
+ GINT_TO_POINTER (TRUE));
+ }
+
+ g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name,
+ get_data_func);
+ g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name,
+ get_data_data);
+
+ /* remember the first set source type for drag view creation */
+ if (! g_object_get_data (G_OBJECT (widget), "gimp-dnd-get-data-type"))
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type",
+ GINT_TO_POINTER (data_type));
+
+ if (dnd_data->target_entry.target)
+ {
+ GtkTargetList *target_list;
+
+ target_list = gtk_drag_source_get_target_list (widget);
+
+ if (target_list)
+ {
+ gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
+ }
+ else
+ {
+ target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
+
+ gtk_drag_source_set_target_list (widget, target_list);
+ gtk_target_list_unref (target_list);
+ }
+ }
+}
+
+static gboolean
+gimp_dnd_data_source_remove (GimpDndType data_type,
+ GtkWidget *widget)
+{
+ const GimpDndDataDef *dnd_data;
+ gboolean drag_connected;
+ gboolean list_changed = FALSE;
+
+ drag_connected =
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-drag-connected"));
+
+ if (! drag_connected)
+ return FALSE;
+
+ dnd_data = dnd_data_defs + data_type;
+
+ g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name, NULL);
+ g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name, NULL);
+
+ /* remove the dnd type remembered for the dnd icon */
+ if (data_type ==
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-get-data-type")))
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type", NULL);
+
+ if (dnd_data->target_entry.target)
+ {
+ /* Don't just remove the target from the existing list, create a
+ * new list without the target and replace the old list. The
+ * source's target list is part of a drag operation's state, but
+ * only by reference, it's not copied. So when we change the
+ * list, we would change the state of that ongoing drag, making
+ * it impossible to drop anything. See bug #676522.
+ */
+ GtkTargetList *target_list = gtk_drag_source_get_target_list (widget);
+
+ if (target_list)
+ {
+ GtkTargetList *new_list;
+ GtkTargetEntry *targets;
+ gint n_targets_old;
+ gint n_targets_new;
+ gint i;
+
+ targets = gtk_target_table_new_from_list (target_list, &n_targets_old);
+
+ new_list = gtk_target_list_new (NULL, 0);
+
+ for (i = 0; i < n_targets_old; i++)
+ {
+ if (targets[i].info != data_type)
+ {
+ gtk_target_list_add (new_list,
+ gdk_atom_intern (targets[i].target, FALSE),
+ targets[i].flags,
+ targets[i].info);
+ }
+ }
+
+ gtk_target_table_free (targets, n_targets_old);
+
+ targets = gtk_target_table_new_from_list (new_list, &n_targets_new);
+ gtk_target_table_free (targets, n_targets_new);
+
+ if (n_targets_old != n_targets_new)
+ {
+ list_changed = TRUE;
+
+ if (n_targets_new > 0)
+ gtk_drag_source_set_target_list (widget, new_list);
+ else
+ gtk_drag_source_set_target_list (widget, NULL);
+ }
+
+ gtk_target_list_unref (new_list);
+ }
+ }
+
+ return list_changed;
+}
+
+static void
+gimp_dnd_data_dest_add (GimpDndType data_type,
+ GtkWidget *widget,
+ gpointer set_data_func,
+ gpointer set_data_data)
+{
+ const GimpDndDataDef *dnd_data;
+ gboolean drop_connected;
+
+ /* set a default drag dest if not already done */
+ if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
+ gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
+
+ drop_connected =
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-drop-connected"));
+
+ if (set_data_func && ! drop_connected)
+ {
+ g_signal_connect (widget, "drag-data-received",
+ G_CALLBACK (gimp_dnd_data_drop_handle),
+ NULL);
+
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-drop-connected",
+ GINT_TO_POINTER (TRUE));
+ }
+
+ dnd_data = dnd_data_defs + data_type;
+
+ if (set_data_func)
+ {
+ g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name,
+ set_data_func);
+ g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name,
+ set_data_data);
+ }
+
+ if (dnd_data->target_entry.target)
+ {
+ GtkTargetList *target_list;
+
+ target_list = gtk_drag_dest_get_target_list (widget);
+
+ if (target_list)
+ {
+ gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
+ }
+ else
+ {
+ target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
+
+ gtk_drag_dest_set_target_list (widget, target_list);
+ gtk_target_list_unref (target_list);
+ }
+ }
+}
+
+static void
+gimp_dnd_data_dest_remove (GimpDndType data_type,
+ GtkWidget *widget)
+{
+ const GimpDndDataDef *dnd_data;
+
+ dnd_data = dnd_data_defs + data_type;
+
+ g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name, NULL);
+ g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name, NULL);
+
+ if (dnd_data->target_entry.target)
+ {
+ GtkTargetList *target_list;
+
+ target_list = gtk_drag_dest_get_target_list (widget);
+
+ if (target_list)
+ {
+ GdkAtom atom = gdk_atom_intern (dnd_data->target_entry.target, TRUE);
+
+ if (atom != GDK_NONE)
+ gtk_target_list_remove (target_list, atom);
+ }
+ }
+}
+
+
+/****************************/
+/* uri list dnd functions */
+/****************************/
+
+static void
+gimp_dnd_get_uri_list_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_uri_list_func,
+ gpointer get_uri_list_data,
+ GtkSelectionData *selection)
+{
+ GList *uri_list;
+
+ uri_list = (* (GimpDndDragUriListFunc) get_uri_list_func) (widget,
+ get_uri_list_data);
+
+ GIMP_LOG (DND, "uri_list %p", uri_list);
+
+ if (uri_list)
+ {
+ gimp_selection_data_set_uri_list (selection, uri_list);
+
+ g_list_free_full (uri_list, (GDestroyNotify) g_free);
+ }
+}
+
+static gboolean
+gimp_dnd_set_uri_list_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_uri_list_func,
+ gpointer set_uri_list_data,
+ GtkSelectionData *selection)
+{
+ GList *uri_list = gimp_selection_data_get_uri_list (selection);
+
+ GIMP_LOG (DND, "uri_list %p", uri_list);
+
+ if (! uri_list)
+ return FALSE;
+
+ (* (GimpDndDropUriListFunc) set_uri_list_func) (widget, x, y, uri_list,
+ set_uri_list_data);
+
+ g_list_free_full (uri_list, (GDestroyNotify) g_free);
+
+ return TRUE;
+}
+
+void
+gimp_dnd_uri_list_source_add (GtkWidget *widget,
+ GimpDndDragUriListFunc get_uri_list_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_URI_LIST, widget,
+ G_CALLBACK (get_uri_list_func),
+ data);
+}
+
+void
+gimp_dnd_uri_list_source_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_URI_LIST, widget);
+}
+
+void
+gimp_dnd_uri_list_dest_add (GtkWidget *widget,
+ GimpDndDropUriListFunc set_uri_list_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ /* Set a default drag dest if not already done. Explicitly set
+ * COPY and MOVE for file drag destinations. Some file managers
+ * such as Konqueror only offer MOVE by default.
+ */
+ if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
+ gtk_drag_dest_set (widget,
+ GTK_DEST_DEFAULT_ALL, NULL, 0,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_URI_LIST, widget,
+ G_CALLBACK (set_uri_list_func),
+ data);
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_TEXT_PLAIN, widget,
+ G_CALLBACK (set_uri_list_func),
+ data);
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_NETSCAPE_URL, widget,
+ G_CALLBACK (set_uri_list_func),
+ data);
+}
+
+void
+gimp_dnd_uri_list_dest_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_URI_LIST, widget);
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_TEXT_PLAIN, widget);
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_NETSCAPE_URL, widget);
+}
+
+
+/******************************/
+/* Direct Save Protocol (XDS) */
+/******************************/
+
+static void
+gimp_dnd_get_xds_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_image_func,
+ gpointer get_image_data,
+ GtkSelectionData *selection)
+{
+ GimpImage *image;
+ GimpContext *gimp_context;
+
+ image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
+
+ if (! image)
+ image = (GimpImage *)
+ (* (GimpDndDragViewableFunc) get_image_func) (widget, &gimp_context,
+ get_image_data);
+
+ GIMP_LOG (DND, "image %p", image);
+
+ if (image)
+ gimp_dnd_xds_save_image (context, image, selection);
+}
+
+static void
+gimp_dnd_xds_drag_begin (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ const GimpDndDataDef *dnd_data = dnd_data_defs + GIMP_DND_TYPE_XDS;
+ GCallback get_data_func;
+ gpointer get_data_data;
+
+ get_data_func = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_func_name);
+ get_data_data = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_data_name);
+
+ if (get_data_func)
+ {
+ GimpImage *image;
+ GimpContext *gimp_context;
+
+ image = (GimpImage *)
+ (* (GimpDndDragViewableFunc) get_data_func) (widget, &gimp_context,
+ get_data_data);
+
+ GIMP_LOG (DND, "image %p", image);
+
+ gimp_dnd_xds_source_set (context, image);
+ }
+}
+
+static void
+gimp_dnd_xds_drag_end (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ gimp_dnd_xds_source_set (context, NULL);
+}
+
+void
+gimp_dnd_xds_source_add (GtkWidget *widget,
+ GimpDndDragViewableFunc get_image_func,
+ gpointer data)
+{
+ gulong handler;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_XDS, widget,
+ G_CALLBACK (get_image_func),
+ data);
+
+ handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-xds-drag-begin"));
+
+ if (! handler)
+ {
+ handler = g_signal_connect (widget, "drag-begin",
+ G_CALLBACK (gimp_dnd_xds_drag_begin),
+ NULL);
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-begin",
+ GUINT_TO_POINTER (handler));
+ }
+
+ handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-xds-drag-end"));
+
+ if (! handler)
+ {
+ handler = g_signal_connect (widget, "drag-end",
+ G_CALLBACK (gimp_dnd_xds_drag_end),
+ NULL);
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-end",
+ GUINT_TO_POINTER (handler));
+ }
+}
+
+void
+gimp_dnd_xds_source_remove (GtkWidget *widget)
+{
+ gulong handler;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-xds-drag-begin"));
+ if (handler)
+ {
+ g_signal_handler_disconnect (widget, handler);
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-begin", NULL);
+ }
+
+ handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-xds-drag-end"));
+ if (handler)
+ {
+ g_signal_handler_disconnect (widget, handler);
+ g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-end", NULL);
+ }
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_XDS, widget);
+}
+
+
+/*************************/
+/* color dnd functions */
+/*************************/
+
+static GtkWidget *
+gimp_dnd_get_color_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_color_func,
+ gpointer get_color_data)
+{
+ GtkWidget *color_area;
+ GimpRGB color;
+
+ (* (GimpDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
+
+ GIMP_LOG (DND, "called");
+
+ g_object_set_data_full (G_OBJECT (context),
+ "gimp-dnd-color", g_memdup (&color, sizeof (GimpRGB)),
+ (GDestroyNotify) g_free);
+
+ color_area = gimp_color_area_new (&color, GIMP_COLOR_AREA_SMALL_CHECKS, 0);
+ gimp_color_area_set_color_config (GIMP_COLOR_AREA (color_area),
+ the_dnd_gimp->config->color_management);
+ gtk_widget_set_size_request (color_area,
+ DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);
+
+ return color_area;
+}
+
+static void
+gimp_dnd_get_color_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_color_func,
+ gpointer get_color_data,
+ GtkSelectionData *selection)
+{
+ GimpRGB *c;
+ GimpRGB color;
+
+ c = g_object_get_data (G_OBJECT (context), "gimp-dnd-color");
+
+ if (c)
+ color = *c;
+ else
+ (* (GimpDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
+
+ GIMP_LOG (DND, "called");
+
+ gimp_selection_data_set_color (selection, &color);
+}
+
+static gboolean
+gimp_dnd_set_color_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_color_func,
+ gpointer set_color_data,
+ GtkSelectionData *selection)
+{
+ GimpRGB color;
+
+ GIMP_LOG (DND, "called");
+
+ if (! gimp_selection_data_get_color (selection, &color))
+ return FALSE;
+
+ (* (GimpDndDropColorFunc) set_color_func) (widget, x, y, &color,
+ set_color_data);
+
+ return TRUE;
+}
+
+void
+gimp_dnd_color_source_add (GtkWidget *widget,
+ GimpDndDragColorFunc get_color_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_COLOR, widget,
+ G_CALLBACK (get_color_func),
+ data);
+}
+
+void
+gimp_dnd_color_source_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_COLOR, widget);
+}
+
+void
+gimp_dnd_color_dest_add (GtkWidget *widget,
+ GimpDndDropColorFunc set_color_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_COLOR, widget,
+ G_CALLBACK (set_color_func),
+ data);
+}
+
+void
+gimp_dnd_color_dest_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_COLOR, widget);
+}
+
+
+/**************************/
+/* stream dnd functions */
+/**************************/
+
+static void
+gimp_dnd_get_stream_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_stream_func,
+ gpointer get_stream_data,
+ GtkSelectionData *selection)
+{
+ guchar *stream;
+ gsize stream_length;
+
+ stream = (* (GimpDndDragStreamFunc) get_stream_func) (widget, &stream_length,
+ get_stream_data);
+
+ GIMP_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
+
+ if (stream)
+ {
+ gimp_selection_data_set_stream (selection, stream, stream_length);
+ g_free (stream);
+ }
+}
+
+static gboolean
+gimp_dnd_set_stream_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_stream_func,
+ gpointer set_stream_data,
+ GtkSelectionData *selection)
+{
+ const guchar *stream;
+ gsize stream_length;
+
+ stream = gimp_selection_data_get_stream (selection, &stream_length);
+
+ GIMP_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
+
+ if (! stream)
+ return FALSE;
+
+ (* (GimpDndDropStreamFunc) set_stream_func) (widget, x, y,
+ stream, stream_length,
+ set_stream_data);
+
+ return TRUE;
+}
+
+void
+gimp_dnd_svg_source_add (GtkWidget *widget,
+ GimpDndDragStreamFunc get_svg_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_SVG, widget,
+ G_CALLBACK (get_svg_func),
+ data);
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_SVG_XML, widget,
+ G_CALLBACK (get_svg_func),
+ data);
+}
+
+void
+gimp_dnd_svg_source_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_SVG, widget);
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_SVG_XML, widget);
+}
+
+void
+gimp_dnd_svg_dest_add (GtkWidget *widget,
+ GimpDndDropStreamFunc set_svg_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_SVG, widget,
+ G_CALLBACK (set_svg_func),
+ data);
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_SVG_XML, widget,
+ G_CALLBACK (set_svg_func),
+ data);
+}
+
+void
+gimp_dnd_svg_dest_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_SVG, widget);
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_SVG_XML, widget);
+}
+
+
+/**************************/
+/* pixbuf dnd functions */
+/**************************/
+
+static void
+gimp_dnd_get_pixbuf_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_pixbuf_func,
+ gpointer get_pixbuf_data,
+ GtkSelectionData *selection)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = (* (GimpDndDragPixbufFunc) get_pixbuf_func) (widget,
+ get_pixbuf_data);
+
+ GIMP_LOG (DND, "pixbuf %p", pixbuf);
+
+ if (pixbuf)
+ {
+ gimp_set_busy (the_dnd_gimp);
+
+ gtk_selection_data_set_pixbuf (selection, pixbuf);
+ g_object_unref (pixbuf);
+
+ gimp_unset_busy (the_dnd_gimp);
+ }
+}
+
+static gboolean
+gimp_dnd_set_pixbuf_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_pixbuf_func,
+ gpointer set_pixbuf_data,
+ GtkSelectionData *selection)
+{
+ GdkPixbuf *pixbuf;
+
+ gimp_set_busy (the_dnd_gimp);
+
+ pixbuf = gtk_selection_data_get_pixbuf (selection);
+
+ gimp_unset_busy (the_dnd_gimp);
+
+ GIMP_LOG (DND, "pixbuf %p", pixbuf);
+
+ if (! pixbuf)
+ return FALSE;
+
+ (* (GimpDndDropPixbufFunc) set_pixbuf_func) (widget, x, y,
+ pixbuf,
+ set_pixbuf_data);
+
+ g_object_unref (pixbuf);
+
+ return TRUE;
+}
+
+void
+gimp_dnd_pixbuf_source_add (GtkWidget *widget,
+ GimpDndDragPixbufFunc get_pixbuf_func,
+ gpointer data)
+{
+ GtkTargetList *target_list;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_PIXBUF, widget,
+ G_CALLBACK (get_pixbuf_func),
+ data);
+
+ target_list = gtk_drag_source_get_target_list (widget);
+
+ if (target_list)
+ gtk_target_list_ref (target_list);
+ else
+ target_list = gtk_target_list_new (NULL, 0);
+
+ gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, TRUE);
+
+ gtk_drag_source_set_target_list (widget, target_list);
+ gtk_target_list_unref (target_list);
+}
+
+void
+gimp_dnd_pixbuf_source_remove (GtkWidget *widget)
+{
+ GtkTargetList *target_list;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_PIXBUF, widget);
+
+ target_list = gtk_drag_source_get_target_list (widget);
+
+ if (target_list)
+ gimp_pixbuf_targets_remove (target_list);
+}
+
+void
+gimp_dnd_pixbuf_dest_add (GtkWidget *widget,
+ GimpDndDropPixbufFunc set_pixbuf_func,
+ gpointer data)
+{
+ GtkTargetList *target_list;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_PIXBUF, widget,
+ G_CALLBACK (set_pixbuf_func),
+ data);
+
+ target_list = gtk_drag_dest_get_target_list (widget);
+
+ if (target_list)
+ gtk_target_list_ref (target_list);
+ else
+ target_list = gtk_target_list_new (NULL, 0);
+
+ gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, FALSE);
+
+ gtk_drag_dest_set_target_list (widget, target_list);
+ gtk_target_list_unref (target_list);
+}
+
+void
+gimp_dnd_pixbuf_dest_remove (GtkWidget *widget)
+{
+ GtkTargetList *target_list;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_PIXBUF, widget);
+
+ target_list = gtk_drag_dest_get_target_list (widget);
+
+ if (target_list)
+ gimp_pixbuf_targets_remove (target_list);
+}
+
+
+/*****************************/
+/* component dnd functions */
+/*****************************/
+
+static GtkWidget *
+gimp_dnd_get_component_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_comp_func,
+ gpointer get_comp_data)
+{
+ GtkWidget *view;
+ GimpImage *image;
+ GimpContext *gimp_context;
+ GimpChannelType channel;
+
+ image = (* (GimpDndDragComponentFunc) get_comp_func) (widget, &gimp_context,
+ &channel,
+ get_comp_data);
+
+ GIMP_LOG (DND, "image %p, component %d", image, channel);
+
+ if (! image)
+ return NULL;
+
+ g_object_set_data_full (G_OBJECT (context),
+ "gimp-dnd-viewable", g_object_ref (image),
+ (GDestroyNotify) g_object_unref);
+ g_object_set_data (G_OBJECT (context),
+ "gimp-dnd-component", GINT_TO_POINTER (channel));
+
+ view = gimp_view_new (gimp_context, GIMP_VIEWABLE (image),
+ DRAG_PREVIEW_SIZE, 0, TRUE);
+
+ GIMP_VIEW_RENDERER_IMAGE (GIMP_VIEW (view)->renderer)->channel = channel;
+
+ return view;
+}
+
+static void
+gimp_dnd_get_component_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_comp_func,
+ gpointer get_comp_data,
+ GtkSelectionData *selection)
+{
+ GimpImage *image;
+ GimpContext *gimp_context;
+ GimpChannelType channel = 0;
+
+ image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
+ channel = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
+ "gimp-dnd-component"));
+
+ if (! image)
+ image = (* (GimpDndDragComponentFunc) get_comp_func) (widget, &gimp_context,
+ &channel,
+ get_comp_data);
+
+ GIMP_LOG (DND, "image %p, component %d", image, channel);
+
+ if (image)
+ gimp_selection_data_set_component (selection, image, channel);
+}
+
+static gboolean
+gimp_dnd_set_component_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_comp_func,
+ gpointer set_comp_data,
+ GtkSelectionData *selection)
+{
+ GimpImage *image;
+ GimpChannelType channel = 0;
+
+ image = gimp_selection_data_get_component (selection, the_dnd_gimp,
+ &channel);
+
+ GIMP_LOG (DND, "image %p, component %d", image, channel);
+
+ if (! image)
+ return FALSE;
+
+ (* (GimpDndDropComponentFunc) set_comp_func) (widget, x, y,
+ image, channel,
+ set_comp_data);
+
+ return TRUE;
+}
+
+void
+gimp_dnd_component_source_add (GtkWidget *widget,
+ GimpDndDragComponentFunc get_comp_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_add (GIMP_DND_TYPE_COMPONENT, widget,
+ G_CALLBACK (get_comp_func),
+ data);
+}
+
+void
+gimp_dnd_component_source_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_source_remove (GIMP_DND_TYPE_COMPONENT, widget);
+}
+
+void
+gimp_dnd_component_dest_add (GtkWidget *widget,
+ GimpDndDropComponentFunc set_comp_func,
+ gpointer data)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_add (GIMP_DND_TYPE_COMPONENT, widget,
+ G_CALLBACK (set_comp_func),
+ data);
+}
+
+void
+gimp_dnd_component_dest_remove (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gimp_dnd_data_dest_remove (GIMP_DND_TYPE_COMPONENT, widget);
+}
+
+
+/*******************************************/
+/* GimpViewable (by GType) dnd functions */
+/*******************************************/
+
+static GtkWidget *
+gimp_dnd_get_viewable_icon (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_viewable_func,
+ gpointer get_viewable_data)
+{
+ GimpViewable *viewable;
+ GimpContext *gimp_context;
+ GtkWidget *view;
+ gchar *desc;
+
+ viewable = (* (GimpDndDragViewableFunc) get_viewable_func) (widget,
+ &gimp_context,
+ get_viewable_data);
+
+ GIMP_LOG (DND, "viewable %p", viewable);
+
+ if (! viewable)
+ return NULL;
+
+ g_object_set_data_full (G_OBJECT (context),
+ "gimp-dnd-viewable", g_object_ref (viewable),
+ (GDestroyNotify) g_object_unref);
+
+ view = gimp_view_new (gimp_context, viewable,
+ DRAG_PREVIEW_SIZE, 0, TRUE);
+
+ desc = gimp_viewable_get_description (viewable, NULL);
+
+ if (desc)
+ {
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
+ gtk_box_pack_start (GTK_BOX (hbox), view, FALSE, FALSE, 0);
+ gtk_widget_show (view);
+
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", desc,
+ "xpad", 3,
+ "xalign", 0.0,
+ "yalign", 0.5,
+ "max-width-chars", 30,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ g_free (desc);
+
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ return hbox;
+ }
+
+ return view;
+}
+
+static GimpDndType
+gimp_dnd_data_type_get_by_g_type (GType type)
+{
+ GimpDndType dnd_type = GIMP_DND_TYPE_NONE;
+
+ if (g_type_is_a (type, GIMP_TYPE_IMAGE))
+ {
+ dnd_type = GIMP_DND_TYPE_IMAGE;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_LAYER))
+ {
+ dnd_type = GIMP_DND_TYPE_LAYER;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_LAYER_MASK))
+ {
+ dnd_type = GIMP_DND_TYPE_LAYER_MASK;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_CHANNEL))
+ {
+ dnd_type = GIMP_DND_TYPE_CHANNEL;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_VECTORS))
+ {
+ dnd_type = GIMP_DND_TYPE_VECTORS;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_BRUSH))
+ {
+ dnd_type = GIMP_DND_TYPE_BRUSH;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_PATTERN))
+ {
+ dnd_type = GIMP_DND_TYPE_PATTERN;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_GRADIENT))
+ {
+ dnd_type = GIMP_DND_TYPE_GRADIENT;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_PALETTE))
+ {
+ dnd_type = GIMP_DND_TYPE_PALETTE;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_FONT))
+ {
+ dnd_type = GIMP_DND_TYPE_FONT;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_BUFFER))
+ {
+ dnd_type = GIMP_DND_TYPE_BUFFER;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_IMAGEFILE))
+ {
+ dnd_type = GIMP_DND_TYPE_IMAGEFILE;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_TEMPLATE))
+ {
+ dnd_type = GIMP_DND_TYPE_TEMPLATE;
+ }
+ else if (g_type_is_a (type, GIMP_TYPE_TOOL_ITEM))
+ {
+ dnd_type = GIMP_DND_TYPE_TOOL_ITEM;
+ }
+
+ return dnd_type;
+}
+
+gboolean
+gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
+ GdkModifierType start_button_mask,
+ GType type,
+ GdkDragAction actions)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ gtk_drag_source_set (widget, start_button_mask,
+ &dnd_data_defs[dnd_type].target_entry, 1,
+ actions);
+
+ return TRUE;
+}
+
+gboolean
+gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
+ GtkDestDefaults flags,
+ GType type,
+ GdkDragAction actions)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ gtk_drag_dest_set (widget, flags,
+ &dnd_data_defs[dnd_type].target_entry, 1,
+ actions);
+
+ return TRUE;
+}
+
+gboolean
+gimp_dnd_viewable_source_add (GtkWidget *widget,
+ GType type,
+ GimpDndDragViewableFunc get_viewable_func,
+ gpointer data)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (get_viewable_func != NULL, FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ gimp_dnd_data_source_add (dnd_type, widget,
+ G_CALLBACK (get_viewable_func),
+ data);
+
+ return TRUE;
+}
+
+gboolean
+gimp_dnd_viewable_source_remove (GtkWidget *widget,
+ GType type)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ return gimp_dnd_data_source_remove (dnd_type, widget);
+}
+
+gboolean
+gimp_dnd_viewable_dest_add (GtkWidget *widget,
+ GType type,
+ GimpDndDropViewableFunc set_viewable_func,
+ gpointer data)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ gimp_dnd_data_dest_add (dnd_type, widget,
+ G_CALLBACK (set_viewable_func),
+ data);
+
+ return TRUE;
+}
+
+gboolean
+gimp_dnd_viewable_dest_remove (GtkWidget *widget,
+ GType type)
+{
+ GimpDndType dnd_type;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ dnd_type = gimp_dnd_data_type_get_by_g_type (type);
+
+ if (dnd_type == GIMP_DND_TYPE_NONE)
+ return FALSE;
+
+ gimp_dnd_data_dest_remove (dnd_type, widget);
+
+ return TRUE;
+}
+
+GimpViewable *
+gimp_dnd_get_drag_data (GtkWidget *widget)
+{
+ const GimpDndDataDef *dnd_data;
+ GimpDndType data_type;
+ GimpDndDragViewableFunc get_data_func = NULL;
+ gpointer get_data_data = NULL;
+ GimpContext *context;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dnd-get-data-type"));
+
+ if (! data_type)
+ return NULL;
+
+ dnd_data = dnd_data_defs + data_type;
+
+ if (dnd_data->get_data_func_name)
+ get_data_func = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_func_name);
+
+ if (dnd_data->get_data_data_name)
+ get_data_data = g_object_get_data (G_OBJECT (widget),
+ dnd_data->get_data_data_name);
+
+ if (! get_data_func)
+ return NULL;
+
+ return (GimpViewable *) (* get_data_func) (widget, &context, get_data_data);
+}
+
+
+/*****************************/
+/* GimpImage dnd functions */
+/*****************************/
+
+static void
+gimp_dnd_get_image_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_image_func,
+ gpointer get_image_data,
+ GtkSelectionData *selection)
+{
+ GimpImage *image;
+ GimpContext *gimp_context;
+
+ image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
+
+ if (! image)
+ image = (GimpImage *)
+ (* (GimpDndDragViewableFunc) get_image_func) (widget, &gimp_context,
+ get_image_data);
+
+ GIMP_LOG (DND, "image %p", image);
+
+ if (image)
+ gimp_selection_data_set_image (selection, image);
+}
+
+static gboolean
+gimp_dnd_set_image_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_image_func,
+ gpointer set_image_data,
+ GtkSelectionData *selection)
+{
+ GimpImage *image = gimp_selection_data_get_image (selection, the_dnd_gimp);
+
+ GIMP_LOG (DND, "image %p", image);
+
+ if (! image)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_image_func) (widget, x, y,
+ GIMP_VIEWABLE (image),
+ set_image_data);
+
+ return TRUE;
+}
+
+
+/****************************/
+/* GimpItem dnd functions */
+/****************************/
+
+static void
+gimp_dnd_get_item_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_item_func,
+ gpointer get_item_data,
+ GtkSelectionData *selection)
+{
+ GimpItem *item;
+ GimpContext *gimp_context;
+
+ item = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
+
+ if (! item)
+ item = (GimpItem *)
+ (* (GimpDndDragViewableFunc) get_item_func) (widget, &gimp_context,
+ get_item_data);
+
+ GIMP_LOG (DND, "item %p", item);
+
+ if (item)
+ gimp_selection_data_set_item (selection, item);
+}
+
+static gboolean
+gimp_dnd_set_item_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_item_func,
+ gpointer set_item_data,
+ GtkSelectionData *selection)
+{
+ GimpItem *item = gimp_selection_data_get_item (selection, the_dnd_gimp);
+
+ GIMP_LOG (DND, "item %p", item);
+
+ if (! item)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_item_func) (widget, x, y,
+ GIMP_VIEWABLE (item),
+ set_item_data);
+
+ return TRUE;
+}
+
+
+/******************************/
+/* GimpObject dnd functions */
+/******************************/
+
+static void
+gimp_dnd_get_object_data (GtkWidget *widget,
+ GdkDragContext *context,
+ GCallback get_object_func,
+ gpointer get_object_data,
+ GtkSelectionData *selection)
+{
+ GimpObject *object;
+ GimpContext *gimp_context;
+
+ object = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
+
+ if (! object)
+ object = (GimpObject *)
+ (* (GimpDndDragViewableFunc) get_object_func) (widget, &gimp_context,
+ get_object_data);
+
+ GIMP_LOG (DND, "object %p", object);
+
+ if (GIMP_IS_OBJECT (object))
+ gimp_selection_data_set_object (selection, object);
+}
+
+
+/*****************************/
+/* GimpBrush dnd functions */
+/*****************************/
+
+static gboolean
+gimp_dnd_set_brush_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_brush_func,
+ gpointer set_brush_data,
+ GtkSelectionData *selection)
+{
+ GimpBrush *brush = gimp_selection_data_get_brush (selection, the_dnd_gimp);
+
+ GIMP_LOG (DND, "brush %p", brush);
+
+ if (! brush)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_brush_func) (widget, x, y,
+ GIMP_VIEWABLE (brush),
+ set_brush_data);
+
+ return TRUE;
+}
+
+
+/*******************************/
+/* GimpPattern dnd functions */
+/*******************************/
+
+static gboolean
+gimp_dnd_set_pattern_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_pattern_func,
+ gpointer set_pattern_data,
+ GtkSelectionData *selection)
+{
+ GimpPattern *pattern = gimp_selection_data_get_pattern (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "pattern %p", pattern);
+
+ if (! pattern)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_pattern_func) (widget, x, y,
+ GIMP_VIEWABLE (pattern),
+ set_pattern_data);
+
+ return TRUE;
+}
+
+
+/********************************/
+/* GimpGradient dnd functions */
+/********************************/
+
+static gboolean
+gimp_dnd_set_gradient_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_gradient_func,
+ gpointer set_gradient_data,
+ GtkSelectionData *selection)
+{
+ GimpGradient *gradient = gimp_selection_data_get_gradient (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "gradient %p", gradient);
+
+ if (! gradient)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_gradient_func) (widget, x, y,
+ GIMP_VIEWABLE (gradient),
+ set_gradient_data);
+
+ return TRUE;
+}
+
+
+/*******************************/
+/* GimpPalette dnd functions */
+/*******************************/
+
+static gboolean
+gimp_dnd_set_palette_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_palette_func,
+ gpointer set_palette_data,
+ GtkSelectionData *selection)
+{
+ GimpPalette *palette = gimp_selection_data_get_palette (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "palette %p", palette);
+
+ if (! palette)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_palette_func) (widget, x, y,
+ GIMP_VIEWABLE (palette),
+ set_palette_data);
+
+ return TRUE;
+}
+
+
+/****************************/
+/* GimpFont dnd functions */
+/****************************/
+
+static gboolean
+gimp_dnd_set_font_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_font_func,
+ gpointer set_font_data,
+ GtkSelectionData *selection)
+{
+ GimpFont *font = gimp_selection_data_get_font (selection, the_dnd_gimp);
+
+ GIMP_LOG (DND, "font %p", font);
+
+ if (! font)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_font_func) (widget, x, y,
+ GIMP_VIEWABLE (font),
+ set_font_data);
+
+ return TRUE;
+}
+
+
+/******************************/
+/* GimpBuffer dnd functions */
+/******************************/
+
+static gboolean
+gimp_dnd_set_buffer_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_buffer_func,
+ gpointer set_buffer_data,
+ GtkSelectionData *selection)
+{
+ GimpBuffer *buffer = gimp_selection_data_get_buffer (selection, the_dnd_gimp);
+
+ GIMP_LOG (DND, "buffer %p", buffer);
+
+ if (! buffer)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_buffer_func) (widget, x, y,
+ GIMP_VIEWABLE (buffer),
+ set_buffer_data);
+
+ return TRUE;
+}
+
+
+/*********************************/
+/* GimpImagefile dnd functions */
+/*********************************/
+
+static gboolean
+gimp_dnd_set_imagefile_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_imagefile_func,
+ gpointer set_imagefile_data,
+ GtkSelectionData *selection)
+{
+ GimpImagefile *imagefile = gimp_selection_data_get_imagefile (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "imagefile %p", imagefile);
+
+ if (! imagefile)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_imagefile_func) (widget, x, y,
+ GIMP_VIEWABLE (imagefile),
+ set_imagefile_data);
+
+ return TRUE;
+}
+
+
+/********************************/
+/* GimpTemplate dnd functions */
+/********************************/
+
+static gboolean
+gimp_dnd_set_template_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_template_func,
+ gpointer set_template_data,
+ GtkSelectionData *selection)
+{
+ GimpTemplate *template = gimp_selection_data_get_template (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "template %p", template);
+
+ if (! template)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_template_func) (widget, x, y,
+ GIMP_VIEWABLE (template),
+ set_template_data);
+
+ return TRUE;
+}
+
+
+/*********************************/
+/* GimpToolEntry dnd functions */
+/*********************************/
+
+static gboolean
+gimp_dnd_set_tool_item_data (GtkWidget *widget,
+ gint x,
+ gint y,
+ GCallback set_tool_item_func,
+ gpointer set_tool_item_data,
+ GtkSelectionData *selection)
+{
+ GimpToolItem *tool_item = gimp_selection_data_get_tool_item (selection,
+ the_dnd_gimp);
+
+ GIMP_LOG (DND, "tool_item %p", tool_item);
+
+ if (! tool_item)
+ return FALSE;
+
+ (* (GimpDndDropViewableFunc) set_tool_item_func) (widget, x, y,
+ GIMP_VIEWABLE (tool_item),
+ set_tool_item_data);
+
+ return TRUE;
+}