1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22
23 #include "libgimpcolor/gimpcolor.h"
24 #include "libgimpwidgets/gimpwidgets.h"
25
26 #include "widgets-types.h"
27
28 #include "config/gimpcoreconfig.h"
29
30 #include "core/gimp.h"
31 #include "core/gimpbrush.h"
32 #include "core/gimpbuffer.h"
33 #include "core/gimpchannel.h"
34 #include "core/gimpcontainer.h"
35 #include "core/gimpdatafactory.h"
36 #include "core/gimpdrawable.h"
37 #include "core/gimpgradient.h"
38 #include "core/gimpimage.h"
39 #include "core/gimpimagefile.h"
40 #include "core/gimplayer.h"
41 #include "core/gimplayermask.h"
42 #include "core/gimppalette.h"
43 #include "core/gimppattern.h"
44 #include "core/gimptemplate.h"
45 #include "core/gimptoolitem.h"
46
47 #include "text/gimpfont.h"
48
49 #include "vectors/gimpvectors.h"
50
51 #include "gimpdnd.h"
52 #include "gimpdnd-xds.h"
53 #include "gimppixbuf.h"
54 #include "gimpselectiondata.h"
55 #include "gimpview.h"
56 #include "gimpviewrendererimage.h"
57
58 #include "gimp-log.h"
59 #include "gimp-intl.h"
60
61
62 #define DRAG_PREVIEW_SIZE GIMP_VIEW_SIZE_LARGE
63 #define DRAG_ICON_OFFSET -8
64
65
66 typedef GtkWidget * (* GimpDndGetIconFunc) (GtkWidget *widget,
67 GdkDragContext *context,
68 GCallback get_data_func,
69 gpointer get_data_data);
70 typedef void (* GimpDndDragDataFunc) (GtkWidget *widget,
71 GdkDragContext *context,
72 GCallback get_data_func,
73 gpointer get_data_data,
74 GtkSelectionData *selection);
75 typedef gboolean (* GimpDndDropDataFunc) (GtkWidget *widget,
76 gint x,
77 gint y,
78 GCallback set_data_func,
79 gpointer set_data_data,
80 GtkSelectionData *selection);
81
82
83 typedef struct _GimpDndDataDef GimpDndDataDef;
84
85 struct _GimpDndDataDef
86 {
87 GtkTargetEntry target_entry;
88
89 const gchar *get_data_func_name;
90 const gchar *get_data_data_name;
91
92 const gchar *set_data_func_name;
93 const gchar *set_data_data_name;
94
95 GimpDndGetIconFunc get_icon_func;
96 GimpDndDragDataFunc get_data_func;
97 GimpDndDropDataFunc set_data_func;
98 };
99
100
101 static GtkWidget * gimp_dnd_get_viewable_icon (GtkWidget *widget,
102 GdkDragContext *context,
103 GCallback get_viewable_func,
104 gpointer get_viewable_data);
105 static GtkWidget * gimp_dnd_get_component_icon (GtkWidget *widget,
106 GdkDragContext *context,
107 GCallback get_comp_func,
108 gpointer get_comp_data);
109 static GtkWidget * gimp_dnd_get_color_icon (GtkWidget *widget,
110 GdkDragContext *context,
111 GCallback get_color_func,
112 gpointer get_color_data);
113
114 static void gimp_dnd_get_uri_list_data (GtkWidget *widget,
115 GdkDragContext *context,
116 GCallback get_uri_list_func,
117 gpointer get_uri_list_data,
118 GtkSelectionData *selection);
119 static gboolean gimp_dnd_set_uri_list_data (GtkWidget *widget,
120 gint x,
121 gint y,
122 GCallback set_uri_list_func,
123 gpointer set_uri_list_data,
124 GtkSelectionData *selection);
125
126 static void gimp_dnd_get_xds_data (GtkWidget *widget,
127 GdkDragContext *context,
128 GCallback get_image_func,
129 gpointer get_image_data,
130 GtkSelectionData *selection);
131
132 static void gimp_dnd_get_color_data (GtkWidget *widget,
133 GdkDragContext *context,
134 GCallback get_color_func,
135 gpointer get_color_data,
136 GtkSelectionData *selection);
137 static gboolean gimp_dnd_set_color_data (GtkWidget *widget,
138 gint x,
139 gint y,
140 GCallback set_color_func,
141 gpointer set_color_data,
142 GtkSelectionData *selection);
143
144 static void gimp_dnd_get_stream_data (GtkWidget *widget,
145 GdkDragContext *context,
146 GCallback get_stream_func,
147 gpointer get_stream_data,
148 GtkSelectionData *selection);
149 static gboolean gimp_dnd_set_stream_data (GtkWidget *widget,
150 gint x,
151 gint y,
152 GCallback set_stream_func,
153 gpointer set_stream_data,
154 GtkSelectionData *selection);
155
156 static void gimp_dnd_get_pixbuf_data (GtkWidget *widget,
157 GdkDragContext *context,
158 GCallback get_pixbuf_func,
159 gpointer get_pixbuf_data,
160 GtkSelectionData *selection);
161 static gboolean gimp_dnd_set_pixbuf_data (GtkWidget *widget,
162 gint x,
163 gint y,
164 GCallback set_pixbuf_func,
165 gpointer set_pixbuf_data,
166 GtkSelectionData *selection);
167 static void gimp_dnd_get_component_data (GtkWidget *widget,
168 GdkDragContext *context,
169 GCallback get_comp_func,
170 gpointer get_comp_data,
171 GtkSelectionData *selection);
172 static gboolean gimp_dnd_set_component_data (GtkWidget *widget,
173 gint x,
174 gint y,
175 GCallback set_comp_func,
176 gpointer set_comp_data,
177 GtkSelectionData *selection);
178
179 static void gimp_dnd_get_image_data (GtkWidget *widget,
180 GdkDragContext *context,
181 GCallback get_image_func,
182 gpointer get_image_data,
183 GtkSelectionData *selection);
184 static gboolean gimp_dnd_set_image_data (GtkWidget *widget,
185 gint x,
186 gint y,
187 GCallback set_image_func,
188 gpointer set_image_data,
189 GtkSelectionData *selection);
190
191 static void gimp_dnd_get_item_data (GtkWidget *widget,
192 GdkDragContext *context,
193 GCallback get_item_func,
194 gpointer get_item_data,
195 GtkSelectionData *selection);
196 static gboolean gimp_dnd_set_item_data (GtkWidget *widget,
197 gint x,
198 gint y,
199 GCallback set_item_func,
200 gpointer set_item_data,
201 GtkSelectionData *selection);
202
203 static void gimp_dnd_get_object_data (GtkWidget *widget,
204 GdkDragContext *context,
205 GCallback get_object_func,
206 gpointer get_object_data,
207 GtkSelectionData *selection);
208
209 static gboolean gimp_dnd_set_brush_data (GtkWidget *widget,
210 gint x,
211 gint y,
212 GCallback set_brush_func,
213 gpointer set_brush_data,
214 GtkSelectionData *selection);
215 static gboolean gimp_dnd_set_pattern_data (GtkWidget *widget,
216 gint x,
217 gint y,
218 GCallback set_pattern_func,
219 gpointer set_pattern_data,
220 GtkSelectionData *selection);
221 static gboolean gimp_dnd_set_gradient_data (GtkWidget *widget,
222 gint x,
223 gint y,
224 GCallback set_gradient_func,
225 gpointer set_gradient_data,
226 GtkSelectionData *selection);
227 static gboolean gimp_dnd_set_palette_data (GtkWidget *widget,
228 gint x,
229 gint y,
230 GCallback set_palette_func,
231 gpointer set_palette_data,
232 GtkSelectionData *selection);
233 static gboolean gimp_dnd_set_font_data (GtkWidget *widget,
234 gint x,
235 gint y,
236 GCallback set_font_func,
237 gpointer set_font_data,
238 GtkSelectionData *selection);
239 static gboolean gimp_dnd_set_buffer_data (GtkWidget *widget,
240 gint x,
241 gint y,
242 GCallback set_buffer_func,
243 gpointer set_buffer_data,
244 GtkSelectionData *selection);
245 static gboolean gimp_dnd_set_imagefile_data (GtkWidget *widget,
246 gint x,
247 gint y,
248 GCallback set_imagefile_func,
249 gpointer set_imagefile_data,
250 GtkSelectionData *selection);
251 static gboolean gimp_dnd_set_template_data (GtkWidget *widget,
252 gint x,
253 gint y,
254 GCallback set_template_func,
255 gpointer set_template_data,
256 GtkSelectionData *selection);
257 static gboolean gimp_dnd_set_tool_item_data (GtkWidget *widget,
258 gint x,
259 gint y,
260 GCallback set_tool_item_func,
261 gpointer set_tool_item_data,
262 GtkSelectionData *selection);
263
264
265
266 static const GimpDndDataDef dnd_data_defs[] =
267 {
268 {
269 { NULL, 0, -1 },
270
271 NULL,
272 NULL,
273
274 NULL,
275 NULL,
276 NULL
277 },
278
279 {
280 GIMP_TARGET_URI_LIST,
281
282 "gimp-dnd-get-uri-list-func",
283 "gimp-dnd-get-uri-list-data",
284
285 "gimp-dnd-set-uri-list-func",
286 "gimp-dnd-set-uri-list-data",
287
288 NULL,
289 gimp_dnd_get_uri_list_data,
290 gimp_dnd_set_uri_list_data
291 },
292
293 {
294 GIMP_TARGET_TEXT_PLAIN,
295
296 NULL,
297 NULL,
298
299 "gimp-dnd-set-uri-list-func",
300 "gimp-dnd-set-uri-list-data",
301
302 NULL,
303 NULL,
304 gimp_dnd_set_uri_list_data
305 },
306
307 {
308 GIMP_TARGET_NETSCAPE_URL,
309
310 NULL,
311 NULL,
312
313 "gimp-dnd-set-uri-list-func",
314 "gimp-dnd-set-uri-list-data",
315
316 NULL,
317 NULL,
318 gimp_dnd_set_uri_list_data
319 },
320
321 {
322 GIMP_TARGET_XDS,
323
324 "gimp-dnd-get-xds-func",
325 "gimp-dnd-get-xds-data",
326
327 NULL,
328 NULL,
329
330 gimp_dnd_get_viewable_icon,
331 gimp_dnd_get_xds_data,
332 NULL
333 },
334
335 {
336 GIMP_TARGET_COLOR,
337
338 "gimp-dnd-get-color-func",
339 "gimp-dnd-get-color-data",
340
341 "gimp-dnd-set-color-func",
342 "gimp-dnd-set-color-data",
343
344 gimp_dnd_get_color_icon,
345 gimp_dnd_get_color_data,
346 gimp_dnd_set_color_data
347 },
348
349 {
350 GIMP_TARGET_SVG,
351
352 "gimp-dnd-get-svg-func",
353 "gimp-dnd-get-svg-data",
354
355 "gimp-dnd-set-svg-func",
356 "gimp-dnd-set-svg-data",
357
358 gimp_dnd_get_viewable_icon,
359 gimp_dnd_get_stream_data,
360 gimp_dnd_set_stream_data
361 },
362
363 {
364 GIMP_TARGET_SVG_XML,
365
366 "gimp-dnd-get-svg-xml-func",
367 "gimp-dnd-get-svg-xml-data",
368
369 "gimp-dnd-set-svg-xml-func",
370 "gimp-dnd-set-svg-xml-data",
371
372 gimp_dnd_get_viewable_icon,
373 gimp_dnd_get_stream_data,
374 gimp_dnd_set_stream_data
375 },
376
377 {
378 GIMP_TARGET_PIXBUF,
379
380 "gimp-dnd-get-pixbuf-func",
381 "gimp-dnd-get-pixbuf-data",
382
383 "gimp-dnd-set-pixbuf-func",
384 "gimp-dnd-set-pixbuf-data",
385
386 gimp_dnd_get_viewable_icon,
387 gimp_dnd_get_pixbuf_data,
388 gimp_dnd_set_pixbuf_data
389 },
390
391 {
392 GIMP_TARGET_IMAGE,
393
394 "gimp-dnd-get-image-func",
395 "gimp-dnd-get-image-data",
396
397 "gimp-dnd-set-image-func",
398 "gimp-dnd-set-image-data",
399
400 gimp_dnd_get_viewable_icon,
401 gimp_dnd_get_image_data,
402 gimp_dnd_set_image_data,
403 },
404
405 {
406 GIMP_TARGET_COMPONENT,
407
408 "gimp-dnd-get-component-func",
409 "gimp-dnd-get-component-data",
410
411 "gimp-dnd-set-component-func",
412 "gimp-dnd-set-component-data",
413
414 gimp_dnd_get_component_icon,
415 gimp_dnd_get_component_data,
416 gimp_dnd_set_component_data,
417 },
418
419 {
420 GIMP_TARGET_LAYER,
421
422 "gimp-dnd-get-layer-func",
423 "gimp-dnd-get-layer-data",
424
425 "gimp-dnd-set-layer-func",
426 "gimp-dnd-set-layer-data",
427
428 gimp_dnd_get_viewable_icon,
429 gimp_dnd_get_item_data,
430 gimp_dnd_set_item_data,
431 },
432
433 {
434 GIMP_TARGET_CHANNEL,
435
436 "gimp-dnd-get-channel-func",
437 "gimp-dnd-get-channel-data",
438
439 "gimp-dnd-set-channel-func",
440 "gimp-dnd-set-channel-data",
441
442 gimp_dnd_get_viewable_icon,
443 gimp_dnd_get_item_data,
444 gimp_dnd_set_item_data,
445 },
446
447 {
448 GIMP_TARGET_LAYER_MASK,
449
450 "gimp-dnd-get-layer-mask-func",
451 "gimp-dnd-get-layer-mask-data",
452
453 "gimp-dnd-set-layer-mask-func",
454 "gimp-dnd-set-layer-mask-data",
455
456 gimp_dnd_get_viewable_icon,
457 gimp_dnd_get_item_data,
458 gimp_dnd_set_item_data,
459 },
460
461 {
462 GIMP_TARGET_VECTORS,
463
464 "gimp-dnd-get-vectors-func",
465 "gimp-dnd-get-vectors-data",
466
467 "gimp-dnd-set-vectors-func",
468 "gimp-dnd-set-vectors-data",
469
470 gimp_dnd_get_viewable_icon,
471 gimp_dnd_get_item_data,
472 gimp_dnd_set_item_data,
473 },
474
475 {
476 GIMP_TARGET_BRUSH,
477
478 "gimp-dnd-get-brush-func",
479 "gimp-dnd-get-brush-data",
480
481 "gimp-dnd-set-brush-func",
482 "gimp-dnd-set-brush-data",
483
484 gimp_dnd_get_viewable_icon,
485 gimp_dnd_get_object_data,
486 gimp_dnd_set_brush_data
487 },
488
489 {
490 GIMP_TARGET_PATTERN,
491
492 "gimp-dnd-get-pattern-func",
493 "gimp-dnd-get-pattern-data",
494
495 "gimp-dnd-set-pattern-func",
496 "gimp-dnd-set-pattern-data",
497
498 gimp_dnd_get_viewable_icon,
499 gimp_dnd_get_object_data,
500 gimp_dnd_set_pattern_data
501 },
502
503 {
504 GIMP_TARGET_GRADIENT,
505
506 "gimp-dnd-get-gradient-func",
507 "gimp-dnd-get-gradient-data",
508
509 "gimp-dnd-set-gradient-func",
510 "gimp-dnd-set-gradient-data",
511
512 gimp_dnd_get_viewable_icon,
513 gimp_dnd_get_object_data,
514 gimp_dnd_set_gradient_data
515 },
516
517 {
518 GIMP_TARGET_PALETTE,
519
520 "gimp-dnd-get-palette-func",
521 "gimp-dnd-get-palette-data",
522
523 "gimp-dnd-set-palette-func",
524 "gimp-dnd-set-palette-data",
525
526 gimp_dnd_get_viewable_icon,
527 gimp_dnd_get_object_data,
528 gimp_dnd_set_palette_data
529 },
530
531 {
532 GIMP_TARGET_FONT,
533
534 "gimp-dnd-get-font-func",
535 "gimp-dnd-get-font-data",
536
537 "gimp-dnd-set-font-func",
538 "gimp-dnd-set-font-data",
539
540 gimp_dnd_get_viewable_icon,
541 gimp_dnd_get_object_data,
542 gimp_dnd_set_font_data
543 },
544
545 {
546 GIMP_TARGET_BUFFER,
547
548 "gimp-dnd-get-buffer-func",
549 "gimp-dnd-get-buffer-data",
550
551 "gimp-dnd-set-buffer-func",
552 "gimp-dnd-set-buffer-data",
553
554 gimp_dnd_get_viewable_icon,
555 gimp_dnd_get_object_data,
556 gimp_dnd_set_buffer_data
557 },
558
559 {
560 GIMP_TARGET_IMAGEFILE,
561
562 "gimp-dnd-get-imagefile-func",
563 "gimp-dnd-get-imagefile-data",
564
565 "gimp-dnd-set-imagefile-func",
566 "gimp-dnd-set-imagefile-data",
567
568 gimp_dnd_get_viewable_icon,
569 gimp_dnd_get_object_data,
570 gimp_dnd_set_imagefile_data
571 },
572
573 {
574 GIMP_TARGET_TEMPLATE,
575
576 "gimp-dnd-get-template-func",
577 "gimp-dnd-get-template-data",
578
579 "gimp-dnd-set-template-func",
580 "gimp-dnd-set-template-data",
581
582 gimp_dnd_get_viewable_icon,
583 gimp_dnd_get_object_data,
584 gimp_dnd_set_template_data
585 },
586
587 {
588 GIMP_TARGET_TOOL_ITEM,
589
590 "gimp-dnd-get-tool-item-func",
591 "gimp-dnd-get-tool-item-data",
592
593 "gimp-dnd-set-tool-item-func",
594 "gimp-dnd-set-tool-item-data",
595
596 gimp_dnd_get_viewable_icon,
597 gimp_dnd_get_object_data,
598 gimp_dnd_set_tool_item_data
599 },
600
601 {
602 GIMP_TARGET_DIALOG,
603
604 NULL,
605 NULL,
606
607 NULL,
608 NULL,
609
610 NULL,
611 NULL,
612 NULL
613 }
614 };
615
616
617 static Gimp *the_dnd_gimp = NULL;
618
619
620 void
gimp_dnd_init(Gimp * gimp)621 gimp_dnd_init (Gimp *gimp)
622 {
623 g_return_if_fail (GIMP_IS_GIMP (gimp));
624 g_return_if_fail (the_dnd_gimp == NULL);
625
626 the_dnd_gimp = gimp;
627 }
628
629
630 /**********************/
631 /* helper functions */
632 /**********************/
633
634 static void
gimp_dnd_target_list_add(GtkTargetList * list,const GtkTargetEntry * entry)635 gimp_dnd_target_list_add (GtkTargetList *list,
636 const GtkTargetEntry *entry)
637 {
638 GdkAtom atom = gdk_atom_intern (entry->target, FALSE);
639 guint info;
640
641 if (! gtk_target_list_find (list, atom, &info) || info != entry->info)
642 {
643 gtk_target_list_add (list, atom, entry->flags, entry->info);
644 }
645 }
646
647
648 /********************************/
649 /* general data dnd functions */
650 /********************************/
651
652 static void
gimp_dnd_data_drag_begin(GtkWidget * widget,GdkDragContext * context,gpointer data)653 gimp_dnd_data_drag_begin (GtkWidget *widget,
654 GdkDragContext *context,
655 gpointer data)
656 {
657 const GimpDndDataDef *dnd_data;
658 GimpDndType data_type;
659 GCallback get_data_func = NULL;
660 gpointer get_data_data = NULL;
661 GtkWidget *icon_widget;
662
663 data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
664 "gimp-dnd-get-data-type"));
665
666 GIMP_LOG (DND, "data type %d", data_type);
667
668 if (! data_type)
669 return;
670
671 dnd_data = dnd_data_defs + data_type;
672
673 if (dnd_data->get_data_func_name)
674 get_data_func = g_object_get_data (G_OBJECT (widget),
675 dnd_data->get_data_func_name);
676
677 if (dnd_data->get_data_data_name)
678 get_data_data = g_object_get_data (G_OBJECT (widget),
679 dnd_data->get_data_data_name);
680
681 if (! get_data_func)
682 return;
683
684 icon_widget = dnd_data->get_icon_func (widget,
685 context,
686 get_data_func,
687 get_data_data);
688
689 if (icon_widget)
690 {
691 GtkWidget *frame;
692 GtkWidget *window;
693
694 window = gtk_window_new (GTK_WINDOW_POPUP);
695 gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
696 gtk_window_set_screen (GTK_WINDOW (window),
697 gtk_widget_get_screen (widget));
698
699 gtk_widget_realize (window);
700
701 frame = gtk_frame_new (NULL);
702 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
703 gtk_container_add (GTK_CONTAINER (window), frame);
704 gtk_widget_show (frame);
705
706 gtk_container_add (GTK_CONTAINER (frame), icon_widget);
707 gtk_widget_show (icon_widget);
708
709 g_object_set_data_full (G_OBJECT (widget), "gimp-dnd-data-widget",
710 window, (GDestroyNotify) gtk_widget_destroy);
711
712 gtk_drag_set_icon_widget (context, window,
713 DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
714
715 /* remember for which drag context the widget was made */
716 g_object_set_data (G_OBJECT (window), "gimp-gdk-drag-context", context);
717 }
718 }
719
720 static void
gimp_dnd_data_drag_end(GtkWidget * widget,GdkDragContext * context)721 gimp_dnd_data_drag_end (GtkWidget *widget,
722 GdkDragContext *context)
723 {
724 GimpDndType data_type;
725 GtkWidget *icon_widget;
726
727 data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
728 "gimp-dnd-get-data-type"));
729
730 GIMP_LOG (DND, "data type %d", data_type);
731
732 icon_widget = g_object_get_data (G_OBJECT (widget), "gimp-dnd-data-widget");
733
734 if (icon_widget)
735 {
736 /* destroy the icon_widget only if it was made for this drag
737 * context. See bug #139337.
738 */
739 if (g_object_get_data (G_OBJECT (icon_widget),
740 "gimp-gdk-drag-context") ==
741 (gpointer) context)
742 {
743 g_object_set_data (G_OBJECT (widget), "gimp-dnd-data-widget", NULL);
744 }
745 }
746 }
747
748 static void
gimp_dnd_data_drag_handle(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint time,gpointer data)749 gimp_dnd_data_drag_handle (GtkWidget *widget,
750 GdkDragContext *context,
751 GtkSelectionData *selection_data,
752 guint info,
753 guint time,
754 gpointer data)
755 {
756 GCallback get_data_func = NULL;
757 gpointer get_data_data = NULL;
758 GimpDndType data_type;
759
760 GIMP_LOG (DND, "data type %d", info);
761
762 for (data_type = GIMP_DND_TYPE_NONE + 1;
763 data_type <= GIMP_DND_TYPE_LAST;
764 data_type++)
765 {
766 const GimpDndDataDef *dnd_data = dnd_data_defs + data_type;
767
768 if (dnd_data->target_entry.info == info)
769 {
770 GIMP_LOG (DND, "target %s", dnd_data->target_entry.target);
771
772 if (dnd_data->get_data_func_name)
773 get_data_func = g_object_get_data (G_OBJECT (widget),
774 dnd_data->get_data_func_name);
775
776 if (dnd_data->get_data_data_name)
777 get_data_data = g_object_get_data (G_OBJECT (widget),
778 dnd_data->get_data_data_name);
779
780 if (! get_data_func)
781 return;
782
783 dnd_data->get_data_func (widget,
784 context,
785 get_data_func,
786 get_data_data,
787 selection_data);
788
789 return;
790 }
791 }
792 }
793
794 static void
gimp_dnd_data_drop_handle(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint time,gpointer data)795 gimp_dnd_data_drop_handle (GtkWidget *widget,
796 GdkDragContext *context,
797 gint x,
798 gint y,
799 GtkSelectionData *selection_data,
800 guint info,
801 guint time,
802 gpointer data)
803 {
804 GimpDndType data_type;
805
806 GIMP_LOG (DND, "data type %d", info);
807
808 if (gtk_selection_data_get_length (selection_data) <= 0)
809 {
810 gtk_drag_finish (context, FALSE, FALSE, time);
811 return;
812 }
813
814 for (data_type = GIMP_DND_TYPE_NONE + 1;
815 data_type <= GIMP_DND_TYPE_LAST;
816 data_type++)
817 {
818 const GimpDndDataDef *dnd_data = dnd_data_defs + data_type;
819
820 if (dnd_data->target_entry.info == info)
821 {
822 GCallback set_data_func = NULL;
823 gpointer set_data_data = NULL;
824
825 GIMP_LOG (DND, "target %s", dnd_data->target_entry.target);
826
827 if (dnd_data->set_data_func_name)
828 set_data_func = g_object_get_data (G_OBJECT (widget),
829 dnd_data->set_data_func_name);
830
831 if (dnd_data->set_data_data_name)
832 set_data_data = g_object_get_data (G_OBJECT (widget),
833 dnd_data->set_data_data_name);
834
835 if (set_data_func &&
836 dnd_data->set_data_func (widget, x, y,
837 set_data_func,
838 set_data_data,
839 selection_data))
840 {
841 gtk_drag_finish (context, TRUE, FALSE, time);
842 return;
843 }
844
845 gtk_drag_finish (context, FALSE, FALSE, time);
846 return;
847 }
848 }
849 }
850
851 static void
gimp_dnd_data_source_add(GimpDndType data_type,GtkWidget * widget,GCallback get_data_func,gpointer get_data_data)852 gimp_dnd_data_source_add (GimpDndType data_type,
853 GtkWidget *widget,
854 GCallback get_data_func,
855 gpointer get_data_data)
856 {
857 const GimpDndDataDef *dnd_data;
858 gboolean drag_connected;
859
860 dnd_data = dnd_data_defs + data_type;
861
862 /* set a default drag source if not already done */
863 if (! g_object_get_data (G_OBJECT (widget), "gtk-site-data"))
864 gtk_drag_source_set (widget, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
865 NULL, 0,
866 GDK_ACTION_COPY | GDK_ACTION_MOVE);
867
868 drag_connected =
869 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
870 "gimp-dnd-drag-connected"));
871
872 if (! drag_connected)
873 {
874 g_signal_connect (widget, "drag-begin",
875 G_CALLBACK (gimp_dnd_data_drag_begin),
876 NULL);
877 g_signal_connect (widget, "drag-end",
878 G_CALLBACK (gimp_dnd_data_drag_end),
879 NULL);
880 g_signal_connect (widget, "drag-data-get",
881 G_CALLBACK (gimp_dnd_data_drag_handle),
882 NULL);
883
884 g_object_set_data (G_OBJECT (widget), "gimp-dnd-drag-connected",
885 GINT_TO_POINTER (TRUE));
886 }
887
888 g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name,
889 get_data_func);
890 g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name,
891 get_data_data);
892
893 /* remember the first set source type for drag view creation */
894 if (! g_object_get_data (G_OBJECT (widget), "gimp-dnd-get-data-type"))
895 g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type",
896 GINT_TO_POINTER (data_type));
897
898 if (dnd_data->target_entry.target)
899 {
900 GtkTargetList *target_list;
901
902 target_list = gtk_drag_source_get_target_list (widget);
903
904 if (target_list)
905 {
906 gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
907 }
908 else
909 {
910 target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
911
912 gtk_drag_source_set_target_list (widget, target_list);
913 gtk_target_list_unref (target_list);
914 }
915 }
916 }
917
918 static gboolean
gimp_dnd_data_source_remove(GimpDndType data_type,GtkWidget * widget)919 gimp_dnd_data_source_remove (GimpDndType data_type,
920 GtkWidget *widget)
921 {
922 const GimpDndDataDef *dnd_data;
923 gboolean drag_connected;
924 gboolean list_changed = FALSE;
925
926 drag_connected =
927 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
928 "gimp-dnd-drag-connected"));
929
930 if (! drag_connected)
931 return FALSE;
932
933 dnd_data = dnd_data_defs + data_type;
934
935 g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name, NULL);
936 g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name, NULL);
937
938 /* remove the dnd type remembered for the dnd icon */
939 if (data_type ==
940 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
941 "gimp-dnd-get-data-type")))
942 g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type", NULL);
943
944 if (dnd_data->target_entry.target)
945 {
946 /* Don't just remove the target from the existing list, create a
947 * new list without the target and replace the old list. The
948 * source's target list is part of a drag operation's state, but
949 * only by reference, it's not copied. So when we change the
950 * list, we would change the state of that ongoing drag, making
951 * it impossible to drop anything. See bug #676522.
952 */
953 GtkTargetList *target_list = gtk_drag_source_get_target_list (widget);
954
955 if (target_list)
956 {
957 GtkTargetList *new_list;
958 GtkTargetEntry *targets;
959 gint n_targets_old;
960 gint n_targets_new;
961 gint i;
962
963 targets = gtk_target_table_new_from_list (target_list, &n_targets_old);
964
965 new_list = gtk_target_list_new (NULL, 0);
966
967 for (i = 0; i < n_targets_old; i++)
968 {
969 if (targets[i].info != data_type)
970 {
971 gtk_target_list_add (new_list,
972 gdk_atom_intern (targets[i].target, FALSE),
973 targets[i].flags,
974 targets[i].info);
975 }
976 }
977
978 gtk_target_table_free (targets, n_targets_old);
979
980 targets = gtk_target_table_new_from_list (new_list, &n_targets_new);
981 gtk_target_table_free (targets, n_targets_new);
982
983 if (n_targets_old != n_targets_new)
984 {
985 list_changed = TRUE;
986
987 if (n_targets_new > 0)
988 gtk_drag_source_set_target_list (widget, new_list);
989 else
990 gtk_drag_source_set_target_list (widget, NULL);
991 }
992
993 gtk_target_list_unref (new_list);
994 }
995 }
996
997 return list_changed;
998 }
999
1000 static void
gimp_dnd_data_dest_add(GimpDndType data_type,GtkWidget * widget,gpointer set_data_func,gpointer set_data_data)1001 gimp_dnd_data_dest_add (GimpDndType data_type,
1002 GtkWidget *widget,
1003 gpointer set_data_func,
1004 gpointer set_data_data)
1005 {
1006 const GimpDndDataDef *dnd_data;
1007 gboolean drop_connected;
1008
1009 /* set a default drag dest if not already done */
1010 if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
1011 gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
1012
1013 drop_connected =
1014 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
1015 "gimp-dnd-drop-connected"));
1016
1017 if (set_data_func && ! drop_connected)
1018 {
1019 g_signal_connect (widget, "drag-data-received",
1020 G_CALLBACK (gimp_dnd_data_drop_handle),
1021 NULL);
1022
1023 g_object_set_data (G_OBJECT (widget), "gimp-dnd-drop-connected",
1024 GINT_TO_POINTER (TRUE));
1025 }
1026
1027 dnd_data = dnd_data_defs + data_type;
1028
1029 if (set_data_func)
1030 {
1031 g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name,
1032 set_data_func);
1033 g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name,
1034 set_data_data);
1035 }
1036
1037 if (dnd_data->target_entry.target)
1038 {
1039 GtkTargetList *target_list;
1040
1041 target_list = gtk_drag_dest_get_target_list (widget);
1042
1043 if (target_list)
1044 {
1045 gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
1046 }
1047 else
1048 {
1049 target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
1050
1051 gtk_drag_dest_set_target_list (widget, target_list);
1052 gtk_target_list_unref (target_list);
1053 }
1054 }
1055 }
1056
1057 static void
gimp_dnd_data_dest_remove(GimpDndType data_type,GtkWidget * widget)1058 gimp_dnd_data_dest_remove (GimpDndType data_type,
1059 GtkWidget *widget)
1060 {
1061 const GimpDndDataDef *dnd_data;
1062
1063 dnd_data = dnd_data_defs + data_type;
1064
1065 g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name, NULL);
1066 g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name, NULL);
1067
1068 if (dnd_data->target_entry.target)
1069 {
1070 GtkTargetList *target_list;
1071
1072 target_list = gtk_drag_dest_get_target_list (widget);
1073
1074 if (target_list)
1075 {
1076 GdkAtom atom = gdk_atom_intern (dnd_data->target_entry.target, TRUE);
1077
1078 if (atom != GDK_NONE)
1079 gtk_target_list_remove (target_list, atom);
1080 }
1081 }
1082 }
1083
1084
1085 /****************************/
1086 /* uri list dnd functions */
1087 /****************************/
1088
1089 static void
gimp_dnd_get_uri_list_data(GtkWidget * widget,GdkDragContext * context,GCallback get_uri_list_func,gpointer get_uri_list_data,GtkSelectionData * selection)1090 gimp_dnd_get_uri_list_data (GtkWidget *widget,
1091 GdkDragContext *context,
1092 GCallback get_uri_list_func,
1093 gpointer get_uri_list_data,
1094 GtkSelectionData *selection)
1095 {
1096 GList *uri_list;
1097
1098 uri_list = (* (GimpDndDragUriListFunc) get_uri_list_func) (widget,
1099 get_uri_list_data);
1100
1101 GIMP_LOG (DND, "uri_list %p", uri_list);
1102
1103 if (uri_list)
1104 {
1105 gimp_selection_data_set_uri_list (selection, uri_list);
1106
1107 g_list_free_full (uri_list, (GDestroyNotify) g_free);
1108 }
1109 }
1110
1111 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)1112 gimp_dnd_set_uri_list_data (GtkWidget *widget,
1113 gint x,
1114 gint y,
1115 GCallback set_uri_list_func,
1116 gpointer set_uri_list_data,
1117 GtkSelectionData *selection)
1118 {
1119 GList *uri_list = gimp_selection_data_get_uri_list (selection);
1120
1121 GIMP_LOG (DND, "uri_list %p", uri_list);
1122
1123 if (! uri_list)
1124 return FALSE;
1125
1126 (* (GimpDndDropUriListFunc) set_uri_list_func) (widget, x, y, uri_list,
1127 set_uri_list_data);
1128
1129 g_list_free_full (uri_list, (GDestroyNotify) g_free);
1130
1131 return TRUE;
1132 }
1133
1134 void
gimp_dnd_uri_list_source_add(GtkWidget * widget,GimpDndDragUriListFunc get_uri_list_func,gpointer data)1135 gimp_dnd_uri_list_source_add (GtkWidget *widget,
1136 GimpDndDragUriListFunc get_uri_list_func,
1137 gpointer data)
1138 {
1139 g_return_if_fail (GTK_IS_WIDGET (widget));
1140
1141 gimp_dnd_data_source_add (GIMP_DND_TYPE_URI_LIST, widget,
1142 G_CALLBACK (get_uri_list_func),
1143 data);
1144 }
1145
1146 void
gimp_dnd_uri_list_source_remove(GtkWidget * widget)1147 gimp_dnd_uri_list_source_remove (GtkWidget *widget)
1148 {
1149 g_return_if_fail (GTK_IS_WIDGET (widget));
1150
1151 gimp_dnd_data_source_remove (GIMP_DND_TYPE_URI_LIST, widget);
1152 }
1153
1154 void
gimp_dnd_uri_list_dest_add(GtkWidget * widget,GimpDndDropUriListFunc set_uri_list_func,gpointer data)1155 gimp_dnd_uri_list_dest_add (GtkWidget *widget,
1156 GimpDndDropUriListFunc set_uri_list_func,
1157 gpointer data)
1158 {
1159 g_return_if_fail (GTK_IS_WIDGET (widget));
1160
1161 /* Set a default drag dest if not already done. Explicitly set
1162 * COPY and MOVE for file drag destinations. Some file managers
1163 * such as Konqueror only offer MOVE by default.
1164 */
1165 if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
1166 gtk_drag_dest_set (widget,
1167 GTK_DEST_DEFAULT_ALL, NULL, 0,
1168 GDK_ACTION_COPY | GDK_ACTION_MOVE);
1169
1170 gimp_dnd_data_dest_add (GIMP_DND_TYPE_URI_LIST, widget,
1171 G_CALLBACK (set_uri_list_func),
1172 data);
1173 gimp_dnd_data_dest_add (GIMP_DND_TYPE_TEXT_PLAIN, widget,
1174 G_CALLBACK (set_uri_list_func),
1175 data);
1176 gimp_dnd_data_dest_add (GIMP_DND_TYPE_NETSCAPE_URL, widget,
1177 G_CALLBACK (set_uri_list_func),
1178 data);
1179 }
1180
1181 void
gimp_dnd_uri_list_dest_remove(GtkWidget * widget)1182 gimp_dnd_uri_list_dest_remove (GtkWidget *widget)
1183 {
1184 g_return_if_fail (GTK_IS_WIDGET (widget));
1185
1186 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_URI_LIST, widget);
1187 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_TEXT_PLAIN, widget);
1188 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_NETSCAPE_URL, widget);
1189 }
1190
1191
1192 /******************************/
1193 /* Direct Save Protocol (XDS) */
1194 /******************************/
1195
1196 static void
gimp_dnd_get_xds_data(GtkWidget * widget,GdkDragContext * context,GCallback get_image_func,gpointer get_image_data,GtkSelectionData * selection)1197 gimp_dnd_get_xds_data (GtkWidget *widget,
1198 GdkDragContext *context,
1199 GCallback get_image_func,
1200 gpointer get_image_data,
1201 GtkSelectionData *selection)
1202 {
1203 GimpImage *image;
1204 GimpContext *gimp_context;
1205
1206 image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
1207
1208 if (! image)
1209 image = (GimpImage *)
1210 (* (GimpDndDragViewableFunc) get_image_func) (widget, &gimp_context,
1211 get_image_data);
1212
1213 GIMP_LOG (DND, "image %p", image);
1214
1215 if (image)
1216 gimp_dnd_xds_save_image (context, image, selection);
1217 }
1218
1219 static void
gimp_dnd_xds_drag_begin(GtkWidget * widget,GdkDragContext * context)1220 gimp_dnd_xds_drag_begin (GtkWidget *widget,
1221 GdkDragContext *context)
1222 {
1223 const GimpDndDataDef *dnd_data = dnd_data_defs + GIMP_DND_TYPE_XDS;
1224 GCallback get_data_func;
1225 gpointer get_data_data;
1226
1227 get_data_func = g_object_get_data (G_OBJECT (widget),
1228 dnd_data->get_data_func_name);
1229 get_data_data = g_object_get_data (G_OBJECT (widget),
1230 dnd_data->get_data_data_name);
1231
1232 if (get_data_func)
1233 {
1234 GimpImage *image;
1235 GimpContext *gimp_context;
1236
1237 image = (GimpImage *)
1238 (* (GimpDndDragViewableFunc) get_data_func) (widget, &gimp_context,
1239 get_data_data);
1240
1241 GIMP_LOG (DND, "image %p", image);
1242
1243 gimp_dnd_xds_source_set (context, image);
1244 }
1245 }
1246
1247 static void
gimp_dnd_xds_drag_end(GtkWidget * widget,GdkDragContext * context)1248 gimp_dnd_xds_drag_end (GtkWidget *widget,
1249 GdkDragContext *context)
1250 {
1251 gimp_dnd_xds_source_set (context, NULL);
1252 }
1253
1254 void
gimp_dnd_xds_source_add(GtkWidget * widget,GimpDndDragViewableFunc get_image_func,gpointer data)1255 gimp_dnd_xds_source_add (GtkWidget *widget,
1256 GimpDndDragViewableFunc get_image_func,
1257 gpointer data)
1258 {
1259 gulong handler;
1260
1261 g_return_if_fail (GTK_IS_WIDGET (widget));
1262
1263 gimp_dnd_data_source_add (GIMP_DND_TYPE_XDS, widget,
1264 G_CALLBACK (get_image_func),
1265 data);
1266
1267 handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
1268 "gimp-dnd-xds-drag-begin"));
1269
1270 if (! handler)
1271 {
1272 handler = g_signal_connect (widget, "drag-begin",
1273 G_CALLBACK (gimp_dnd_xds_drag_begin),
1274 NULL);
1275 g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-begin",
1276 GUINT_TO_POINTER (handler));
1277 }
1278
1279 handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
1280 "gimp-dnd-xds-drag-end"));
1281
1282 if (! handler)
1283 {
1284 handler = g_signal_connect (widget, "drag-end",
1285 G_CALLBACK (gimp_dnd_xds_drag_end),
1286 NULL);
1287 g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-end",
1288 GUINT_TO_POINTER (handler));
1289 }
1290 }
1291
1292 void
gimp_dnd_xds_source_remove(GtkWidget * widget)1293 gimp_dnd_xds_source_remove (GtkWidget *widget)
1294 {
1295 gulong handler;
1296
1297 g_return_if_fail (GTK_IS_WIDGET (widget));
1298
1299 handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
1300 "gimp-dnd-xds-drag-begin"));
1301 if (handler)
1302 {
1303 g_signal_handler_disconnect (widget, handler);
1304 g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-begin", NULL);
1305 }
1306
1307 handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
1308 "gimp-dnd-xds-drag-end"));
1309 if (handler)
1310 {
1311 g_signal_handler_disconnect (widget, handler);
1312 g_object_set_data (G_OBJECT (widget), "gimp-dnd-xds-drag-end", NULL);
1313 }
1314
1315 gimp_dnd_data_source_remove (GIMP_DND_TYPE_XDS, widget);
1316 }
1317
1318
1319 /*************************/
1320 /* color dnd functions */
1321 /*************************/
1322
1323 static GtkWidget *
gimp_dnd_get_color_icon(GtkWidget * widget,GdkDragContext * context,GCallback get_color_func,gpointer get_color_data)1324 gimp_dnd_get_color_icon (GtkWidget *widget,
1325 GdkDragContext *context,
1326 GCallback get_color_func,
1327 gpointer get_color_data)
1328 {
1329 GtkWidget *color_area;
1330 GimpRGB color;
1331
1332 (* (GimpDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
1333
1334 GIMP_LOG (DND, "called");
1335
1336 g_object_set_data_full (G_OBJECT (context),
1337 "gimp-dnd-color", g_memdup (&color, sizeof (GimpRGB)),
1338 (GDestroyNotify) g_free);
1339
1340 color_area = gimp_color_area_new (&color, GIMP_COLOR_AREA_SMALL_CHECKS, 0);
1341 gimp_color_area_set_color_config (GIMP_COLOR_AREA (color_area),
1342 the_dnd_gimp->config->color_management);
1343 gtk_widget_set_size_request (color_area,
1344 DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);
1345
1346 return color_area;
1347 }
1348
1349 static void
gimp_dnd_get_color_data(GtkWidget * widget,GdkDragContext * context,GCallback get_color_func,gpointer get_color_data,GtkSelectionData * selection)1350 gimp_dnd_get_color_data (GtkWidget *widget,
1351 GdkDragContext *context,
1352 GCallback get_color_func,
1353 gpointer get_color_data,
1354 GtkSelectionData *selection)
1355 {
1356 GimpRGB *c;
1357 GimpRGB color;
1358
1359 c = g_object_get_data (G_OBJECT (context), "gimp-dnd-color");
1360
1361 if (c)
1362 color = *c;
1363 else
1364 (* (GimpDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
1365
1366 GIMP_LOG (DND, "called");
1367
1368 gimp_selection_data_set_color (selection, &color);
1369 }
1370
1371 static gboolean
gimp_dnd_set_color_data(GtkWidget * widget,gint x,gint y,GCallback set_color_func,gpointer set_color_data,GtkSelectionData * selection)1372 gimp_dnd_set_color_data (GtkWidget *widget,
1373 gint x,
1374 gint y,
1375 GCallback set_color_func,
1376 gpointer set_color_data,
1377 GtkSelectionData *selection)
1378 {
1379 GimpRGB color;
1380
1381 GIMP_LOG (DND, "called");
1382
1383 if (! gimp_selection_data_get_color (selection, &color))
1384 return FALSE;
1385
1386 (* (GimpDndDropColorFunc) set_color_func) (widget, x, y, &color,
1387 set_color_data);
1388
1389 return TRUE;
1390 }
1391
1392 void
gimp_dnd_color_source_add(GtkWidget * widget,GimpDndDragColorFunc get_color_func,gpointer data)1393 gimp_dnd_color_source_add (GtkWidget *widget,
1394 GimpDndDragColorFunc get_color_func,
1395 gpointer data)
1396 {
1397 g_return_if_fail (GTK_IS_WIDGET (widget));
1398
1399 gimp_dnd_data_source_add (GIMP_DND_TYPE_COLOR, widget,
1400 G_CALLBACK (get_color_func),
1401 data);
1402 }
1403
1404 void
gimp_dnd_color_source_remove(GtkWidget * widget)1405 gimp_dnd_color_source_remove (GtkWidget *widget)
1406 {
1407 g_return_if_fail (GTK_IS_WIDGET (widget));
1408
1409 gimp_dnd_data_source_remove (GIMP_DND_TYPE_COLOR, widget);
1410 }
1411
1412 void
gimp_dnd_color_dest_add(GtkWidget * widget,GimpDndDropColorFunc set_color_func,gpointer data)1413 gimp_dnd_color_dest_add (GtkWidget *widget,
1414 GimpDndDropColorFunc set_color_func,
1415 gpointer data)
1416 {
1417 g_return_if_fail (GTK_IS_WIDGET (widget));
1418
1419 gimp_dnd_data_dest_add (GIMP_DND_TYPE_COLOR, widget,
1420 G_CALLBACK (set_color_func),
1421 data);
1422 }
1423
1424 void
gimp_dnd_color_dest_remove(GtkWidget * widget)1425 gimp_dnd_color_dest_remove (GtkWidget *widget)
1426 {
1427 g_return_if_fail (GTK_IS_WIDGET (widget));
1428
1429 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_COLOR, widget);
1430 }
1431
1432
1433 /**************************/
1434 /* stream dnd functions */
1435 /**************************/
1436
1437 static void
gimp_dnd_get_stream_data(GtkWidget * widget,GdkDragContext * context,GCallback get_stream_func,gpointer get_stream_data,GtkSelectionData * selection)1438 gimp_dnd_get_stream_data (GtkWidget *widget,
1439 GdkDragContext *context,
1440 GCallback get_stream_func,
1441 gpointer get_stream_data,
1442 GtkSelectionData *selection)
1443 {
1444 guchar *stream;
1445 gsize stream_length;
1446
1447 stream = (* (GimpDndDragStreamFunc) get_stream_func) (widget, &stream_length,
1448 get_stream_data);
1449
1450 GIMP_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
1451
1452 if (stream)
1453 {
1454 gimp_selection_data_set_stream (selection, stream, stream_length);
1455 g_free (stream);
1456 }
1457 }
1458
1459 static gboolean
gimp_dnd_set_stream_data(GtkWidget * widget,gint x,gint y,GCallback set_stream_func,gpointer set_stream_data,GtkSelectionData * selection)1460 gimp_dnd_set_stream_data (GtkWidget *widget,
1461 gint x,
1462 gint y,
1463 GCallback set_stream_func,
1464 gpointer set_stream_data,
1465 GtkSelectionData *selection)
1466 {
1467 const guchar *stream;
1468 gsize stream_length;
1469
1470 stream = gimp_selection_data_get_stream (selection, &stream_length);
1471
1472 GIMP_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
1473
1474 if (! stream)
1475 return FALSE;
1476
1477 (* (GimpDndDropStreamFunc) set_stream_func) (widget, x, y,
1478 stream, stream_length,
1479 set_stream_data);
1480
1481 return TRUE;
1482 }
1483
1484 void
gimp_dnd_svg_source_add(GtkWidget * widget,GimpDndDragStreamFunc get_svg_func,gpointer data)1485 gimp_dnd_svg_source_add (GtkWidget *widget,
1486 GimpDndDragStreamFunc get_svg_func,
1487 gpointer data)
1488 {
1489 g_return_if_fail (GTK_IS_WIDGET (widget));
1490
1491 gimp_dnd_data_source_add (GIMP_DND_TYPE_SVG, widget,
1492 G_CALLBACK (get_svg_func),
1493 data);
1494 gimp_dnd_data_source_add (GIMP_DND_TYPE_SVG_XML, widget,
1495 G_CALLBACK (get_svg_func),
1496 data);
1497 }
1498
1499 void
gimp_dnd_svg_source_remove(GtkWidget * widget)1500 gimp_dnd_svg_source_remove (GtkWidget *widget)
1501 {
1502 g_return_if_fail (GTK_IS_WIDGET (widget));
1503
1504 gimp_dnd_data_source_remove (GIMP_DND_TYPE_SVG, widget);
1505 gimp_dnd_data_source_remove (GIMP_DND_TYPE_SVG_XML, widget);
1506 }
1507
1508 void
gimp_dnd_svg_dest_add(GtkWidget * widget,GimpDndDropStreamFunc set_svg_func,gpointer data)1509 gimp_dnd_svg_dest_add (GtkWidget *widget,
1510 GimpDndDropStreamFunc set_svg_func,
1511 gpointer data)
1512 {
1513 g_return_if_fail (GTK_IS_WIDGET (widget));
1514
1515 gimp_dnd_data_dest_add (GIMP_DND_TYPE_SVG, widget,
1516 G_CALLBACK (set_svg_func),
1517 data);
1518 gimp_dnd_data_dest_add (GIMP_DND_TYPE_SVG_XML, widget,
1519 G_CALLBACK (set_svg_func),
1520 data);
1521 }
1522
1523 void
gimp_dnd_svg_dest_remove(GtkWidget * widget)1524 gimp_dnd_svg_dest_remove (GtkWidget *widget)
1525 {
1526 g_return_if_fail (GTK_IS_WIDGET (widget));
1527
1528 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_SVG, widget);
1529 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_SVG_XML, widget);
1530 }
1531
1532
1533 /**************************/
1534 /* pixbuf dnd functions */
1535 /**************************/
1536
1537 static void
gimp_dnd_get_pixbuf_data(GtkWidget * widget,GdkDragContext * context,GCallback get_pixbuf_func,gpointer get_pixbuf_data,GtkSelectionData * selection)1538 gimp_dnd_get_pixbuf_data (GtkWidget *widget,
1539 GdkDragContext *context,
1540 GCallback get_pixbuf_func,
1541 gpointer get_pixbuf_data,
1542 GtkSelectionData *selection)
1543 {
1544 GdkPixbuf *pixbuf;
1545
1546 pixbuf = (* (GimpDndDragPixbufFunc) get_pixbuf_func) (widget,
1547 get_pixbuf_data);
1548
1549 GIMP_LOG (DND, "pixbuf %p", pixbuf);
1550
1551 if (pixbuf)
1552 {
1553 gimp_set_busy (the_dnd_gimp);
1554
1555 gtk_selection_data_set_pixbuf (selection, pixbuf);
1556 g_object_unref (pixbuf);
1557
1558 gimp_unset_busy (the_dnd_gimp);
1559 }
1560 }
1561
1562 static gboolean
gimp_dnd_set_pixbuf_data(GtkWidget * widget,gint x,gint y,GCallback set_pixbuf_func,gpointer set_pixbuf_data,GtkSelectionData * selection)1563 gimp_dnd_set_pixbuf_data (GtkWidget *widget,
1564 gint x,
1565 gint y,
1566 GCallback set_pixbuf_func,
1567 gpointer set_pixbuf_data,
1568 GtkSelectionData *selection)
1569 {
1570 GdkPixbuf *pixbuf;
1571
1572 gimp_set_busy (the_dnd_gimp);
1573
1574 pixbuf = gtk_selection_data_get_pixbuf (selection);
1575
1576 gimp_unset_busy (the_dnd_gimp);
1577
1578 GIMP_LOG (DND, "pixbuf %p", pixbuf);
1579
1580 if (! pixbuf)
1581 return FALSE;
1582
1583 (* (GimpDndDropPixbufFunc) set_pixbuf_func) (widget, x, y,
1584 pixbuf,
1585 set_pixbuf_data);
1586
1587 g_object_unref (pixbuf);
1588
1589 return TRUE;
1590 }
1591
1592 void
gimp_dnd_pixbuf_source_add(GtkWidget * widget,GimpDndDragPixbufFunc get_pixbuf_func,gpointer data)1593 gimp_dnd_pixbuf_source_add (GtkWidget *widget,
1594 GimpDndDragPixbufFunc get_pixbuf_func,
1595 gpointer data)
1596 {
1597 GtkTargetList *target_list;
1598
1599 g_return_if_fail (GTK_IS_WIDGET (widget));
1600
1601 gimp_dnd_data_source_add (GIMP_DND_TYPE_PIXBUF, widget,
1602 G_CALLBACK (get_pixbuf_func),
1603 data);
1604
1605 target_list = gtk_drag_source_get_target_list (widget);
1606
1607 if (target_list)
1608 gtk_target_list_ref (target_list);
1609 else
1610 target_list = gtk_target_list_new (NULL, 0);
1611
1612 gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, TRUE);
1613
1614 gtk_drag_source_set_target_list (widget, target_list);
1615 gtk_target_list_unref (target_list);
1616 }
1617
1618 void
gimp_dnd_pixbuf_source_remove(GtkWidget * widget)1619 gimp_dnd_pixbuf_source_remove (GtkWidget *widget)
1620 {
1621 GtkTargetList *target_list;
1622
1623 g_return_if_fail (GTK_IS_WIDGET (widget));
1624
1625 gimp_dnd_data_source_remove (GIMP_DND_TYPE_PIXBUF, widget);
1626
1627 target_list = gtk_drag_source_get_target_list (widget);
1628
1629 if (target_list)
1630 gimp_pixbuf_targets_remove (target_list);
1631 }
1632
1633 void
gimp_dnd_pixbuf_dest_add(GtkWidget * widget,GimpDndDropPixbufFunc set_pixbuf_func,gpointer data)1634 gimp_dnd_pixbuf_dest_add (GtkWidget *widget,
1635 GimpDndDropPixbufFunc set_pixbuf_func,
1636 gpointer data)
1637 {
1638 GtkTargetList *target_list;
1639
1640 g_return_if_fail (GTK_IS_WIDGET (widget));
1641
1642 gimp_dnd_data_dest_add (GIMP_DND_TYPE_PIXBUF, widget,
1643 G_CALLBACK (set_pixbuf_func),
1644 data);
1645
1646 target_list = gtk_drag_dest_get_target_list (widget);
1647
1648 if (target_list)
1649 gtk_target_list_ref (target_list);
1650 else
1651 target_list = gtk_target_list_new (NULL, 0);
1652
1653 gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, FALSE);
1654
1655 gtk_drag_dest_set_target_list (widget, target_list);
1656 gtk_target_list_unref (target_list);
1657 }
1658
1659 void
gimp_dnd_pixbuf_dest_remove(GtkWidget * widget)1660 gimp_dnd_pixbuf_dest_remove (GtkWidget *widget)
1661 {
1662 GtkTargetList *target_list;
1663
1664 g_return_if_fail (GTK_IS_WIDGET (widget));
1665
1666 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_PIXBUF, widget);
1667
1668 target_list = gtk_drag_dest_get_target_list (widget);
1669
1670 if (target_list)
1671 gimp_pixbuf_targets_remove (target_list);
1672 }
1673
1674
1675 /*****************************/
1676 /* component dnd functions */
1677 /*****************************/
1678
1679 static GtkWidget *
gimp_dnd_get_component_icon(GtkWidget * widget,GdkDragContext * context,GCallback get_comp_func,gpointer get_comp_data)1680 gimp_dnd_get_component_icon (GtkWidget *widget,
1681 GdkDragContext *context,
1682 GCallback get_comp_func,
1683 gpointer get_comp_data)
1684 {
1685 GtkWidget *view;
1686 GimpImage *image;
1687 GimpContext *gimp_context;
1688 GimpChannelType channel;
1689
1690 image = (* (GimpDndDragComponentFunc) get_comp_func) (widget, &gimp_context,
1691 &channel,
1692 get_comp_data);
1693
1694 GIMP_LOG (DND, "image %p, component %d", image, channel);
1695
1696 if (! image)
1697 return NULL;
1698
1699 g_object_set_data_full (G_OBJECT (context),
1700 "gimp-dnd-viewable", g_object_ref (image),
1701 (GDestroyNotify) g_object_unref);
1702 g_object_set_data (G_OBJECT (context),
1703 "gimp-dnd-component", GINT_TO_POINTER (channel));
1704
1705 view = gimp_view_new (gimp_context, GIMP_VIEWABLE (image),
1706 DRAG_PREVIEW_SIZE, 0, TRUE);
1707
1708 GIMP_VIEW_RENDERER_IMAGE (GIMP_VIEW (view)->renderer)->channel = channel;
1709
1710 return view;
1711 }
1712
1713 static void
gimp_dnd_get_component_data(GtkWidget * widget,GdkDragContext * context,GCallback get_comp_func,gpointer get_comp_data,GtkSelectionData * selection)1714 gimp_dnd_get_component_data (GtkWidget *widget,
1715 GdkDragContext *context,
1716 GCallback get_comp_func,
1717 gpointer get_comp_data,
1718 GtkSelectionData *selection)
1719 {
1720 GimpImage *image;
1721 GimpContext *gimp_context;
1722 GimpChannelType channel = 0;
1723
1724 image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
1725 channel = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
1726 "gimp-dnd-component"));
1727
1728 if (! image)
1729 image = (* (GimpDndDragComponentFunc) get_comp_func) (widget, &gimp_context,
1730 &channel,
1731 get_comp_data);
1732
1733 GIMP_LOG (DND, "image %p, component %d", image, channel);
1734
1735 if (image)
1736 gimp_selection_data_set_component (selection, image, channel);
1737 }
1738
1739 static gboolean
gimp_dnd_set_component_data(GtkWidget * widget,gint x,gint y,GCallback set_comp_func,gpointer set_comp_data,GtkSelectionData * selection)1740 gimp_dnd_set_component_data (GtkWidget *widget,
1741 gint x,
1742 gint y,
1743 GCallback set_comp_func,
1744 gpointer set_comp_data,
1745 GtkSelectionData *selection)
1746 {
1747 GimpImage *image;
1748 GimpChannelType channel = 0;
1749
1750 image = gimp_selection_data_get_component (selection, the_dnd_gimp,
1751 &channel);
1752
1753 GIMP_LOG (DND, "image %p, component %d", image, channel);
1754
1755 if (! image)
1756 return FALSE;
1757
1758 (* (GimpDndDropComponentFunc) set_comp_func) (widget, x, y,
1759 image, channel,
1760 set_comp_data);
1761
1762 return TRUE;
1763 }
1764
1765 void
gimp_dnd_component_source_add(GtkWidget * widget,GimpDndDragComponentFunc get_comp_func,gpointer data)1766 gimp_dnd_component_source_add (GtkWidget *widget,
1767 GimpDndDragComponentFunc get_comp_func,
1768 gpointer data)
1769 {
1770 g_return_if_fail (GTK_IS_WIDGET (widget));
1771
1772 gimp_dnd_data_source_add (GIMP_DND_TYPE_COMPONENT, widget,
1773 G_CALLBACK (get_comp_func),
1774 data);
1775 }
1776
1777 void
gimp_dnd_component_source_remove(GtkWidget * widget)1778 gimp_dnd_component_source_remove (GtkWidget *widget)
1779 {
1780 g_return_if_fail (GTK_IS_WIDGET (widget));
1781
1782 gimp_dnd_data_source_remove (GIMP_DND_TYPE_COMPONENT, widget);
1783 }
1784
1785 void
gimp_dnd_component_dest_add(GtkWidget * widget,GimpDndDropComponentFunc set_comp_func,gpointer data)1786 gimp_dnd_component_dest_add (GtkWidget *widget,
1787 GimpDndDropComponentFunc set_comp_func,
1788 gpointer data)
1789 {
1790 g_return_if_fail (GTK_IS_WIDGET (widget));
1791
1792 gimp_dnd_data_dest_add (GIMP_DND_TYPE_COMPONENT, widget,
1793 G_CALLBACK (set_comp_func),
1794 data);
1795 }
1796
1797 void
gimp_dnd_component_dest_remove(GtkWidget * widget)1798 gimp_dnd_component_dest_remove (GtkWidget *widget)
1799 {
1800 g_return_if_fail (GTK_IS_WIDGET (widget));
1801
1802 gimp_dnd_data_dest_remove (GIMP_DND_TYPE_COMPONENT, widget);
1803 }
1804
1805
1806 /*******************************************/
1807 /* GimpViewable (by GType) dnd functions */
1808 /*******************************************/
1809
1810 static GtkWidget *
gimp_dnd_get_viewable_icon(GtkWidget * widget,GdkDragContext * context,GCallback get_viewable_func,gpointer get_viewable_data)1811 gimp_dnd_get_viewable_icon (GtkWidget *widget,
1812 GdkDragContext *context,
1813 GCallback get_viewable_func,
1814 gpointer get_viewable_data)
1815 {
1816 GimpViewable *viewable;
1817 GimpContext *gimp_context;
1818 GtkWidget *view;
1819 gchar *desc;
1820
1821 viewable = (* (GimpDndDragViewableFunc) get_viewable_func) (widget,
1822 &gimp_context,
1823 get_viewable_data);
1824
1825 GIMP_LOG (DND, "viewable %p", viewable);
1826
1827 if (! viewable)
1828 return NULL;
1829
1830 g_object_set_data_full (G_OBJECT (context),
1831 "gimp-dnd-viewable", g_object_ref (viewable),
1832 (GDestroyNotify) g_object_unref);
1833
1834 view = gimp_view_new (gimp_context, viewable,
1835 DRAG_PREVIEW_SIZE, 0, TRUE);
1836
1837 desc = gimp_viewable_get_description (viewable, NULL);
1838
1839 if (desc)
1840 {
1841 GtkWidget *hbox;
1842 GtkWidget *label;
1843
1844 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
1845 gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
1846 gtk_box_pack_start (GTK_BOX (hbox), view, FALSE, FALSE, 0);
1847 gtk_widget_show (view);
1848
1849 label = g_object_new (GTK_TYPE_LABEL,
1850 "label", desc,
1851 "xpad", 3,
1852 "xalign", 0.0,
1853 "yalign", 0.5,
1854 "max-width-chars", 30,
1855 "ellipsize", PANGO_ELLIPSIZE_END,
1856 NULL);
1857
1858 g_free (desc);
1859
1860 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
1861 gtk_widget_show (label);
1862
1863 return hbox;
1864 }
1865
1866 return view;
1867 }
1868
1869 static GimpDndType
gimp_dnd_data_type_get_by_g_type(GType type)1870 gimp_dnd_data_type_get_by_g_type (GType type)
1871 {
1872 GimpDndType dnd_type = GIMP_DND_TYPE_NONE;
1873
1874 if (g_type_is_a (type, GIMP_TYPE_IMAGE))
1875 {
1876 dnd_type = GIMP_DND_TYPE_IMAGE;
1877 }
1878 else if (g_type_is_a (type, GIMP_TYPE_LAYER))
1879 {
1880 dnd_type = GIMP_DND_TYPE_LAYER;
1881 }
1882 else if (g_type_is_a (type, GIMP_TYPE_LAYER_MASK))
1883 {
1884 dnd_type = GIMP_DND_TYPE_LAYER_MASK;
1885 }
1886 else if (g_type_is_a (type, GIMP_TYPE_CHANNEL))
1887 {
1888 dnd_type = GIMP_DND_TYPE_CHANNEL;
1889 }
1890 else if (g_type_is_a (type, GIMP_TYPE_VECTORS))
1891 {
1892 dnd_type = GIMP_DND_TYPE_VECTORS;
1893 }
1894 else if (g_type_is_a (type, GIMP_TYPE_BRUSH))
1895 {
1896 dnd_type = GIMP_DND_TYPE_BRUSH;
1897 }
1898 else if (g_type_is_a (type, GIMP_TYPE_PATTERN))
1899 {
1900 dnd_type = GIMP_DND_TYPE_PATTERN;
1901 }
1902 else if (g_type_is_a (type, GIMP_TYPE_GRADIENT))
1903 {
1904 dnd_type = GIMP_DND_TYPE_GRADIENT;
1905 }
1906 else if (g_type_is_a (type, GIMP_TYPE_PALETTE))
1907 {
1908 dnd_type = GIMP_DND_TYPE_PALETTE;
1909 }
1910 else if (g_type_is_a (type, GIMP_TYPE_FONT))
1911 {
1912 dnd_type = GIMP_DND_TYPE_FONT;
1913 }
1914 else if (g_type_is_a (type, GIMP_TYPE_BUFFER))
1915 {
1916 dnd_type = GIMP_DND_TYPE_BUFFER;
1917 }
1918 else if (g_type_is_a (type, GIMP_TYPE_IMAGEFILE))
1919 {
1920 dnd_type = GIMP_DND_TYPE_IMAGEFILE;
1921 }
1922 else if (g_type_is_a (type, GIMP_TYPE_TEMPLATE))
1923 {
1924 dnd_type = GIMP_DND_TYPE_TEMPLATE;
1925 }
1926 else if (g_type_is_a (type, GIMP_TYPE_TOOL_ITEM))
1927 {
1928 dnd_type = GIMP_DND_TYPE_TOOL_ITEM;
1929 }
1930
1931 return dnd_type;
1932 }
1933
1934 gboolean
gimp_dnd_drag_source_set_by_type(GtkWidget * widget,GdkModifierType start_button_mask,GType type,GdkDragAction actions)1935 gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
1936 GdkModifierType start_button_mask,
1937 GType type,
1938 GdkDragAction actions)
1939 {
1940 GimpDndType dnd_type;
1941
1942 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1943
1944 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
1945
1946 if (dnd_type == GIMP_DND_TYPE_NONE)
1947 return FALSE;
1948
1949 gtk_drag_source_set (widget, start_button_mask,
1950 &dnd_data_defs[dnd_type].target_entry, 1,
1951 actions);
1952
1953 return TRUE;
1954 }
1955
1956 gboolean
gimp_dnd_drag_dest_set_by_type(GtkWidget * widget,GtkDestDefaults flags,GType type,GdkDragAction actions)1957 gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
1958 GtkDestDefaults flags,
1959 GType type,
1960 GdkDragAction actions)
1961 {
1962 GimpDndType dnd_type;
1963
1964 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1965
1966 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
1967
1968 if (dnd_type == GIMP_DND_TYPE_NONE)
1969 return FALSE;
1970
1971 gtk_drag_dest_set (widget, flags,
1972 &dnd_data_defs[dnd_type].target_entry, 1,
1973 actions);
1974
1975 return TRUE;
1976 }
1977
1978 gboolean
gimp_dnd_viewable_source_add(GtkWidget * widget,GType type,GimpDndDragViewableFunc get_viewable_func,gpointer data)1979 gimp_dnd_viewable_source_add (GtkWidget *widget,
1980 GType type,
1981 GimpDndDragViewableFunc get_viewable_func,
1982 gpointer data)
1983 {
1984 GimpDndType dnd_type;
1985
1986 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1987 g_return_val_if_fail (get_viewable_func != NULL, FALSE);
1988
1989 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
1990
1991 if (dnd_type == GIMP_DND_TYPE_NONE)
1992 return FALSE;
1993
1994 gimp_dnd_data_source_add (dnd_type, widget,
1995 G_CALLBACK (get_viewable_func),
1996 data);
1997
1998 return TRUE;
1999 }
2000
2001 gboolean
gimp_dnd_viewable_source_remove(GtkWidget * widget,GType type)2002 gimp_dnd_viewable_source_remove (GtkWidget *widget,
2003 GType type)
2004 {
2005 GimpDndType dnd_type;
2006
2007 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2008
2009 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
2010
2011 if (dnd_type == GIMP_DND_TYPE_NONE)
2012 return FALSE;
2013
2014 return gimp_dnd_data_source_remove (dnd_type, widget);
2015 }
2016
2017 gboolean
gimp_dnd_viewable_dest_add(GtkWidget * widget,GType type,GimpDndDropViewableFunc set_viewable_func,gpointer data)2018 gimp_dnd_viewable_dest_add (GtkWidget *widget,
2019 GType type,
2020 GimpDndDropViewableFunc set_viewable_func,
2021 gpointer data)
2022 {
2023 GimpDndType dnd_type;
2024
2025 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2026
2027 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
2028
2029 if (dnd_type == GIMP_DND_TYPE_NONE)
2030 return FALSE;
2031
2032 gimp_dnd_data_dest_add (dnd_type, widget,
2033 G_CALLBACK (set_viewable_func),
2034 data);
2035
2036 return TRUE;
2037 }
2038
2039 gboolean
gimp_dnd_viewable_dest_remove(GtkWidget * widget,GType type)2040 gimp_dnd_viewable_dest_remove (GtkWidget *widget,
2041 GType type)
2042 {
2043 GimpDndType dnd_type;
2044
2045 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2046
2047 dnd_type = gimp_dnd_data_type_get_by_g_type (type);
2048
2049 if (dnd_type == GIMP_DND_TYPE_NONE)
2050 return FALSE;
2051
2052 gimp_dnd_data_dest_remove (dnd_type, widget);
2053
2054 return TRUE;
2055 }
2056
2057 GimpViewable *
gimp_dnd_get_drag_data(GtkWidget * widget)2058 gimp_dnd_get_drag_data (GtkWidget *widget)
2059 {
2060 const GimpDndDataDef *dnd_data;
2061 GimpDndType data_type;
2062 GimpDndDragViewableFunc get_data_func = NULL;
2063 gpointer get_data_data = NULL;
2064 GimpContext *context;
2065
2066 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
2067
2068 data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
2069 "gimp-dnd-get-data-type"));
2070
2071 if (! data_type)
2072 return NULL;
2073
2074 dnd_data = dnd_data_defs + data_type;
2075
2076 if (dnd_data->get_data_func_name)
2077 get_data_func = g_object_get_data (G_OBJECT (widget),
2078 dnd_data->get_data_func_name);
2079
2080 if (dnd_data->get_data_data_name)
2081 get_data_data = g_object_get_data (G_OBJECT (widget),
2082 dnd_data->get_data_data_name);
2083
2084 if (! get_data_func)
2085 return NULL;
2086
2087 return (GimpViewable *) (* get_data_func) (widget, &context, get_data_data);
2088 }
2089
2090
2091 /*****************************/
2092 /* GimpImage dnd functions */
2093 /*****************************/
2094
2095 static void
gimp_dnd_get_image_data(GtkWidget * widget,GdkDragContext * context,GCallback get_image_func,gpointer get_image_data,GtkSelectionData * selection)2096 gimp_dnd_get_image_data (GtkWidget *widget,
2097 GdkDragContext *context,
2098 GCallback get_image_func,
2099 gpointer get_image_data,
2100 GtkSelectionData *selection)
2101 {
2102 GimpImage *image;
2103 GimpContext *gimp_context;
2104
2105 image = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
2106
2107 if (! image)
2108 image = (GimpImage *)
2109 (* (GimpDndDragViewableFunc) get_image_func) (widget, &gimp_context,
2110 get_image_data);
2111
2112 GIMP_LOG (DND, "image %p", image);
2113
2114 if (image)
2115 gimp_selection_data_set_image (selection, image);
2116 }
2117
2118 static gboolean
gimp_dnd_set_image_data(GtkWidget * widget,gint x,gint y,GCallback set_image_func,gpointer set_image_data,GtkSelectionData * selection)2119 gimp_dnd_set_image_data (GtkWidget *widget,
2120 gint x,
2121 gint y,
2122 GCallback set_image_func,
2123 gpointer set_image_data,
2124 GtkSelectionData *selection)
2125 {
2126 GimpImage *image = gimp_selection_data_get_image (selection, the_dnd_gimp);
2127
2128 GIMP_LOG (DND, "image %p", image);
2129
2130 if (! image)
2131 return FALSE;
2132
2133 (* (GimpDndDropViewableFunc) set_image_func) (widget, x, y,
2134 GIMP_VIEWABLE (image),
2135 set_image_data);
2136
2137 return TRUE;
2138 }
2139
2140
2141 /****************************/
2142 /* GimpItem dnd functions */
2143 /****************************/
2144
2145 static void
gimp_dnd_get_item_data(GtkWidget * widget,GdkDragContext * context,GCallback get_item_func,gpointer get_item_data,GtkSelectionData * selection)2146 gimp_dnd_get_item_data (GtkWidget *widget,
2147 GdkDragContext *context,
2148 GCallback get_item_func,
2149 gpointer get_item_data,
2150 GtkSelectionData *selection)
2151 {
2152 GimpItem *item;
2153 GimpContext *gimp_context;
2154
2155 item = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
2156
2157 if (! item)
2158 item = (GimpItem *)
2159 (* (GimpDndDragViewableFunc) get_item_func) (widget, &gimp_context,
2160 get_item_data);
2161
2162 GIMP_LOG (DND, "item %p", item);
2163
2164 if (item)
2165 gimp_selection_data_set_item (selection, item);
2166 }
2167
2168 static gboolean
gimp_dnd_set_item_data(GtkWidget * widget,gint x,gint y,GCallback set_item_func,gpointer set_item_data,GtkSelectionData * selection)2169 gimp_dnd_set_item_data (GtkWidget *widget,
2170 gint x,
2171 gint y,
2172 GCallback set_item_func,
2173 gpointer set_item_data,
2174 GtkSelectionData *selection)
2175 {
2176 GimpItem *item = gimp_selection_data_get_item (selection, the_dnd_gimp);
2177
2178 GIMP_LOG (DND, "item %p", item);
2179
2180 if (! item)
2181 return FALSE;
2182
2183 (* (GimpDndDropViewableFunc) set_item_func) (widget, x, y,
2184 GIMP_VIEWABLE (item),
2185 set_item_data);
2186
2187 return TRUE;
2188 }
2189
2190
2191 /******************************/
2192 /* GimpObject dnd functions */
2193 /******************************/
2194
2195 static void
gimp_dnd_get_object_data(GtkWidget * widget,GdkDragContext * context,GCallback get_object_func,gpointer get_object_data,GtkSelectionData * selection)2196 gimp_dnd_get_object_data (GtkWidget *widget,
2197 GdkDragContext *context,
2198 GCallback get_object_func,
2199 gpointer get_object_data,
2200 GtkSelectionData *selection)
2201 {
2202 GimpObject *object;
2203 GimpContext *gimp_context;
2204
2205 object = g_object_get_data (G_OBJECT (context), "gimp-dnd-viewable");
2206
2207 if (! object)
2208 object = (GimpObject *)
2209 (* (GimpDndDragViewableFunc) get_object_func) (widget, &gimp_context,
2210 get_object_data);
2211
2212 GIMP_LOG (DND, "object %p", object);
2213
2214 if (GIMP_IS_OBJECT (object))
2215 gimp_selection_data_set_object (selection, object);
2216 }
2217
2218
2219 /*****************************/
2220 /* GimpBrush dnd functions */
2221 /*****************************/
2222
2223 static gboolean
gimp_dnd_set_brush_data(GtkWidget * widget,gint x,gint y,GCallback set_brush_func,gpointer set_brush_data,GtkSelectionData * selection)2224 gimp_dnd_set_brush_data (GtkWidget *widget,
2225 gint x,
2226 gint y,
2227 GCallback set_brush_func,
2228 gpointer set_brush_data,
2229 GtkSelectionData *selection)
2230 {
2231 GimpBrush *brush = gimp_selection_data_get_brush (selection, the_dnd_gimp);
2232
2233 GIMP_LOG (DND, "brush %p", brush);
2234
2235 if (! brush)
2236 return FALSE;
2237
2238 (* (GimpDndDropViewableFunc) set_brush_func) (widget, x, y,
2239 GIMP_VIEWABLE (brush),
2240 set_brush_data);
2241
2242 return TRUE;
2243 }
2244
2245
2246 /*******************************/
2247 /* GimpPattern dnd functions */
2248 /*******************************/
2249
2250 static gboolean
gimp_dnd_set_pattern_data(GtkWidget * widget,gint x,gint y,GCallback set_pattern_func,gpointer set_pattern_data,GtkSelectionData * selection)2251 gimp_dnd_set_pattern_data (GtkWidget *widget,
2252 gint x,
2253 gint y,
2254 GCallback set_pattern_func,
2255 gpointer set_pattern_data,
2256 GtkSelectionData *selection)
2257 {
2258 GimpPattern *pattern = gimp_selection_data_get_pattern (selection,
2259 the_dnd_gimp);
2260
2261 GIMP_LOG (DND, "pattern %p", pattern);
2262
2263 if (! pattern)
2264 return FALSE;
2265
2266 (* (GimpDndDropViewableFunc) set_pattern_func) (widget, x, y,
2267 GIMP_VIEWABLE (pattern),
2268 set_pattern_data);
2269
2270 return TRUE;
2271 }
2272
2273
2274 /********************************/
2275 /* GimpGradient dnd functions */
2276 /********************************/
2277
2278 static gboolean
gimp_dnd_set_gradient_data(GtkWidget * widget,gint x,gint y,GCallback set_gradient_func,gpointer set_gradient_data,GtkSelectionData * selection)2279 gimp_dnd_set_gradient_data (GtkWidget *widget,
2280 gint x,
2281 gint y,
2282 GCallback set_gradient_func,
2283 gpointer set_gradient_data,
2284 GtkSelectionData *selection)
2285 {
2286 GimpGradient *gradient = gimp_selection_data_get_gradient (selection,
2287 the_dnd_gimp);
2288
2289 GIMP_LOG (DND, "gradient %p", gradient);
2290
2291 if (! gradient)
2292 return FALSE;
2293
2294 (* (GimpDndDropViewableFunc) set_gradient_func) (widget, x, y,
2295 GIMP_VIEWABLE (gradient),
2296 set_gradient_data);
2297
2298 return TRUE;
2299 }
2300
2301
2302 /*******************************/
2303 /* GimpPalette dnd functions */
2304 /*******************************/
2305
2306 static gboolean
gimp_dnd_set_palette_data(GtkWidget * widget,gint x,gint y,GCallback set_palette_func,gpointer set_palette_data,GtkSelectionData * selection)2307 gimp_dnd_set_palette_data (GtkWidget *widget,
2308 gint x,
2309 gint y,
2310 GCallback set_palette_func,
2311 gpointer set_palette_data,
2312 GtkSelectionData *selection)
2313 {
2314 GimpPalette *palette = gimp_selection_data_get_palette (selection,
2315 the_dnd_gimp);
2316
2317 GIMP_LOG (DND, "palette %p", palette);
2318
2319 if (! palette)
2320 return FALSE;
2321
2322 (* (GimpDndDropViewableFunc) set_palette_func) (widget, x, y,
2323 GIMP_VIEWABLE (palette),
2324 set_palette_data);
2325
2326 return TRUE;
2327 }
2328
2329
2330 /****************************/
2331 /* GimpFont dnd functions */
2332 /****************************/
2333
2334 static gboolean
gimp_dnd_set_font_data(GtkWidget * widget,gint x,gint y,GCallback set_font_func,gpointer set_font_data,GtkSelectionData * selection)2335 gimp_dnd_set_font_data (GtkWidget *widget,
2336 gint x,
2337 gint y,
2338 GCallback set_font_func,
2339 gpointer set_font_data,
2340 GtkSelectionData *selection)
2341 {
2342 GimpFont *font = gimp_selection_data_get_font (selection, the_dnd_gimp);
2343
2344 GIMP_LOG (DND, "font %p", font);
2345
2346 if (! font)
2347 return FALSE;
2348
2349 (* (GimpDndDropViewableFunc) set_font_func) (widget, x, y,
2350 GIMP_VIEWABLE (font),
2351 set_font_data);
2352
2353 return TRUE;
2354 }
2355
2356
2357 /******************************/
2358 /* GimpBuffer dnd functions */
2359 /******************************/
2360
2361 static gboolean
gimp_dnd_set_buffer_data(GtkWidget * widget,gint x,gint y,GCallback set_buffer_func,gpointer set_buffer_data,GtkSelectionData * selection)2362 gimp_dnd_set_buffer_data (GtkWidget *widget,
2363 gint x,
2364 gint y,
2365 GCallback set_buffer_func,
2366 gpointer set_buffer_data,
2367 GtkSelectionData *selection)
2368 {
2369 GimpBuffer *buffer = gimp_selection_data_get_buffer (selection, the_dnd_gimp);
2370
2371 GIMP_LOG (DND, "buffer %p", buffer);
2372
2373 if (! buffer)
2374 return FALSE;
2375
2376 (* (GimpDndDropViewableFunc) set_buffer_func) (widget, x, y,
2377 GIMP_VIEWABLE (buffer),
2378 set_buffer_data);
2379
2380 return TRUE;
2381 }
2382
2383
2384 /*********************************/
2385 /* GimpImagefile dnd functions */
2386 /*********************************/
2387
2388 static gboolean
gimp_dnd_set_imagefile_data(GtkWidget * widget,gint x,gint y,GCallback set_imagefile_func,gpointer set_imagefile_data,GtkSelectionData * selection)2389 gimp_dnd_set_imagefile_data (GtkWidget *widget,
2390 gint x,
2391 gint y,
2392 GCallback set_imagefile_func,
2393 gpointer set_imagefile_data,
2394 GtkSelectionData *selection)
2395 {
2396 GimpImagefile *imagefile = gimp_selection_data_get_imagefile (selection,
2397 the_dnd_gimp);
2398
2399 GIMP_LOG (DND, "imagefile %p", imagefile);
2400
2401 if (! imagefile)
2402 return FALSE;
2403
2404 (* (GimpDndDropViewableFunc) set_imagefile_func) (widget, x, y,
2405 GIMP_VIEWABLE (imagefile),
2406 set_imagefile_data);
2407
2408 return TRUE;
2409 }
2410
2411
2412 /********************************/
2413 /* GimpTemplate dnd functions */
2414 /********************************/
2415
2416 static gboolean
gimp_dnd_set_template_data(GtkWidget * widget,gint x,gint y,GCallback set_template_func,gpointer set_template_data,GtkSelectionData * selection)2417 gimp_dnd_set_template_data (GtkWidget *widget,
2418 gint x,
2419 gint y,
2420 GCallback set_template_func,
2421 gpointer set_template_data,
2422 GtkSelectionData *selection)
2423 {
2424 GimpTemplate *template = gimp_selection_data_get_template (selection,
2425 the_dnd_gimp);
2426
2427 GIMP_LOG (DND, "template %p", template);
2428
2429 if (! template)
2430 return FALSE;
2431
2432 (* (GimpDndDropViewableFunc) set_template_func) (widget, x, y,
2433 GIMP_VIEWABLE (template),
2434 set_template_data);
2435
2436 return TRUE;
2437 }
2438
2439
2440 /*********************************/
2441 /* GimpToolEntry dnd functions */
2442 /*********************************/
2443
2444 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)2445 gimp_dnd_set_tool_item_data (GtkWidget *widget,
2446 gint x,
2447 gint y,
2448 GCallback set_tool_item_func,
2449 gpointer set_tool_item_data,
2450 GtkSelectionData *selection)
2451 {
2452 GimpToolItem *tool_item = gimp_selection_data_get_tool_item (selection,
2453 the_dnd_gimp);
2454
2455 GIMP_LOG (DND, "tool_item %p", tool_item);
2456
2457 if (! tool_item)
2458 return FALSE;
2459
2460 (* (GimpDndDropViewableFunc) set_tool_item_func) (widget, x, y,
2461 GIMP_VIEWABLE (tool_item),
2462 set_tool_item_data);
2463
2464 return TRUE;
2465 }
2466