1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 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 <string.h>
21
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24
25 #include "libgimpmath/gimpmath.h"
26
27 #include "widgets-types.h"
28
29 #include "core/gimp.h"
30 #include "core/gimpbuffer.h"
31 #include "core/gimpcurve.h"
32 #include "core/gimpimage.h"
33 #include "core/gimppickable.h"
34
35 #include "gimpclipboard.h"
36 #include "gimppixbuf.h"
37 #include "gimpselectiondata.h"
38
39 #include "gimp-intl.h"
40
41
42 #define GIMP_CLIPBOARD_KEY "gimp-clipboard"
43
44
45 typedef struct _GimpClipboard GimpClipboard;
46
47 struct _GimpClipboard
48 {
49 GSList *pixbuf_formats;
50
51 GtkTargetEntry *image_target_entries;
52 gint n_image_target_entries;
53
54 GtkTargetEntry *buffer_target_entries;
55 gint n_buffer_target_entries;
56
57 GtkTargetEntry *svg_target_entries;
58 gint n_svg_target_entries;
59
60 GtkTargetEntry *curve_target_entries;
61 gint n_curve_target_entries;
62
63 GimpImage *image;
64 GimpBuffer *buffer;
65 gchar *svg;
66 GimpCurve *curve;
67 };
68
69
70 static GimpClipboard * gimp_clipboard_get (Gimp *gimp);
71
72 static GimpClipboard * gimp_clipboard_new (gboolean verbose);
73 static void gimp_clipboard_free (GimpClipboard *gimp_clip);
74
75 static void gimp_clipboard_clear (GimpClipboard *gimp_clip);
76
77 static GdkAtom * gimp_clipboard_wait_for_targets (Gimp *gimp,
78 gint *n_targets);
79 static GdkAtom gimp_clipboard_wait_for_image (Gimp *gimp);
80 static GdkAtom gimp_clipboard_wait_for_buffer (Gimp *gimp);
81 static GdkAtom gimp_clipboard_wait_for_svg (Gimp *gimp);
82 static GdkAtom gimp_clipboard_wait_for_curve (Gimp *gimp);
83
84 static void gimp_clipboard_send_image (GtkClipboard *clipboard,
85 GtkSelectionData *data,
86 guint info,
87 Gimp *gimp);
88 static void gimp_clipboard_send_buffer (GtkClipboard *clipboard,
89 GtkSelectionData *data,
90 guint info,
91 Gimp *gimp);
92 static void gimp_clipboard_send_svg (GtkClipboard *clipboard,
93 GtkSelectionData *data,
94 guint info,
95 Gimp *gimp);
96 static void gimp_clipboard_send_curve (GtkClipboard *clipboard,
97 GtkSelectionData *data,
98 guint info,
99 Gimp *gimp);
100
101
102 /* public functions */
103
104 void
gimp_clipboard_init(Gimp * gimp)105 gimp_clipboard_init (Gimp *gimp)
106 {
107 GimpClipboard *gimp_clip;
108
109 g_return_if_fail (GIMP_IS_GIMP (gimp));
110
111 gimp_clip = gimp_clipboard_get (gimp);
112
113 g_return_if_fail (gimp_clip == NULL);
114
115 gimp_clip = gimp_clipboard_new (gimp->be_verbose);
116
117 g_object_set_data_full (G_OBJECT (gimp), GIMP_CLIPBOARD_KEY,
118 gimp_clip, (GDestroyNotify) gimp_clipboard_free);
119 }
120
121 void
gimp_clipboard_exit(Gimp * gimp)122 gimp_clipboard_exit (Gimp *gimp)
123 {
124 GtkClipboard *clipboard;
125
126 g_return_if_fail (GIMP_IS_GIMP (gimp));
127
128 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
129 GDK_SELECTION_CLIPBOARD);
130
131 if (clipboard &&
132 gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
133 {
134 gtk_clipboard_store (clipboard);
135 }
136
137 if (clipboard)
138 /* If we don't clear the clipboard, it keeps a reference on the object
139 * owner (i.e. Gimp object probably) which fails to finalize.
140 */
141 gtk_clipboard_clear (clipboard);
142
143 g_object_set_data (G_OBJECT (gimp), GIMP_CLIPBOARD_KEY, NULL);
144 }
145
146 /**
147 * gimp_clipboard_has_image:
148 * @gimp: pointer to #Gimp
149 *
150 * Tests if there's an image in the clipboard. If the global image cut
151 * buffer of @gimp is empty, this function returns %NULL.
152 *
153 * Return value: %TRUE if there's an image in the clipboard, %FALSE otherwise
154 **/
155 gboolean
gimp_clipboard_has_image(Gimp * gimp)156 gimp_clipboard_has_image (Gimp *gimp)
157 {
158 GimpClipboard *gimp_clip;
159 GtkClipboard *clipboard;
160
161 g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
162
163 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
164 GDK_SELECTION_CLIPBOARD);
165
166 if (clipboard &&
167 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
168 {
169 if (gimp_clipboard_wait_for_image (gimp) != GDK_NONE)
170 {
171 return TRUE;
172 }
173
174 return FALSE;
175 }
176
177 gimp_clip = gimp_clipboard_get (gimp);
178
179 return (gimp_clip->image != NULL);
180 }
181
182 /**
183 * gimp_clipboard_has_buffer:
184 * @gimp: pointer to #Gimp
185 *
186 * Tests if there's image data in the clipboard. If the global cut
187 * buffer of @gimp is empty, this function checks if there's image
188 * data in %GDK_SELECTION_CLIPBOARD. This is done in a main-loop
189 * similar to gtk_clipboard_wait_is_text_available(). The same caveats
190 * apply here.
191 *
192 * Return value: %TRUE if there's image data in the clipboard, %FALSE otherwise
193 **/
194 gboolean
gimp_clipboard_has_buffer(Gimp * gimp)195 gimp_clipboard_has_buffer (Gimp *gimp)
196 {
197 GimpClipboard *gimp_clip;
198 GtkClipboard *clipboard;
199
200 g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
201
202 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
203 GDK_SELECTION_CLIPBOARD);
204
205 if (clipboard &&
206 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
207 {
208 if (gimp_clipboard_wait_for_buffer (gimp) != GDK_NONE)
209 {
210 return TRUE;
211 }
212
213 return FALSE;
214 }
215
216 gimp_clip = gimp_clipboard_get (gimp);
217
218 return (gimp_clip->buffer != NULL);
219 }
220
221 /**
222 * gimp_clipboard_has_svg:
223 * @gimp: pointer to #Gimp
224 *
225 * Tests if there's SVG data in %GDK_SELECTION_CLIPBOARD.
226 * This is done in a main-loop similar to
227 * gtk_clipboard_wait_is_text_available(). The same caveats apply here.
228 *
229 * Return value: %TRUE if there's SVG data in the clipboard, %FALSE otherwise
230 **/
231 gboolean
gimp_clipboard_has_svg(Gimp * gimp)232 gimp_clipboard_has_svg (Gimp *gimp)
233 {
234 GimpClipboard *gimp_clip;
235 GtkClipboard *clipboard;
236
237 g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
238
239 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
240 GDK_SELECTION_CLIPBOARD);
241
242 if (clipboard &&
243 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
244 {
245 if (gimp_clipboard_wait_for_svg (gimp) != GDK_NONE)
246 {
247 return TRUE;
248 }
249
250 return FALSE;
251 }
252
253 gimp_clip = gimp_clipboard_get (gimp);
254
255 return (gimp_clip->svg != NULL);
256 }
257
258 /**
259 * gimp_clipboard_has_curve:
260 * @gimp: pointer to #Gimp
261 *
262 * Tests if there's curve data in %GDK_SELECTION_CLIPBOARD.
263 * This is done in a main-loop similar to
264 * gtk_clipboard_wait_is_text_available(). The same caveats apply here.
265 *
266 * Return value: %TRUE if there's curve data in the clipboard, %FALSE otherwise
267 **/
268 gboolean
gimp_clipboard_has_curve(Gimp * gimp)269 gimp_clipboard_has_curve (Gimp *gimp)
270 {
271 GimpClipboard *gimp_clip;
272 GtkClipboard *clipboard;
273
274 g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
275
276 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
277 GDK_SELECTION_CLIPBOARD);
278
279 if (clipboard &&
280 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
281 {
282 if (gimp_clipboard_wait_for_curve (gimp) != GDK_NONE)
283 {
284 return TRUE;
285 }
286
287 return FALSE;
288 }
289
290 gimp_clip = gimp_clipboard_get (gimp);
291
292 return (gimp_clip->curve != NULL);
293 }
294
295 /**
296 * gimp_clipboard_get_object:
297 * @gimp: pointer to #Gimp
298 *
299 * Retrieves either an image or a buffer from the global image cut
300 * buffer of @gimp.
301 *
302 * The returned #GimpObject needs to be unref'ed when it's no longer
303 * needed.
304 *
305 * Return value: a reference to a #GimpObject or %NULL if there's no
306 * image or buffer in the clipboard
307 **/
308 GimpObject *
gimp_clipboard_get_object(Gimp * gimp)309 gimp_clipboard_get_object (Gimp *gimp)
310 {
311 GimpObject *object;
312
313 g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
314
315 object = GIMP_OBJECT (gimp_clipboard_get_image (gimp));
316
317 if (! object)
318 object = GIMP_OBJECT (gimp_clipboard_get_buffer (gimp));
319
320 return object;
321 }
322
323 /**
324 * gimp_clipboard_get_image:
325 * @gimp: pointer to #Gimp
326 *
327 * Retrieves an image from the global image cut buffer of @gimp.
328 *
329 * The returned #GimpImage needs to be unref'ed when it's no longer
330 * needed.
331 *
332 * Return value: a reference to a #GimpImage or %NULL if there's no
333 * image in the clipboard
334 **/
335 GimpImage *
gimp_clipboard_get_image(Gimp * gimp)336 gimp_clipboard_get_image (Gimp *gimp)
337 {
338 GimpClipboard *gimp_clip;
339 GtkClipboard *clipboard;
340 GimpImage *image = NULL;
341
342 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
343
344 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
345 GDK_SELECTION_CLIPBOARD);
346
347 if (clipboard &&
348 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
349 {
350 GdkAtom atom = gimp_clipboard_wait_for_image (gimp);
351
352 if (atom != GDK_NONE)
353 {
354 GtkSelectionData *data;
355
356 gimp_set_busy (gimp);
357
358 data = gtk_clipboard_wait_for_contents (clipboard, atom);
359
360 if (data)
361 {
362 image = gimp_selection_data_get_xcf (data, gimp);
363
364 gtk_selection_data_free (data);
365 }
366
367 gimp_unset_busy (gimp);
368 }
369
370 return image;
371 }
372
373 gimp_clip = gimp_clipboard_get (gimp);
374
375 if (! image && gimp_clip->image)
376 image = g_object_ref (gimp_clip->image);
377
378 return image;
379 }
380
381 /**
382 * gimp_clipboard_get_buffer:
383 * @gimp: pointer to #Gimp
384 *
385 * Retrieves either image data from %GDK_SELECTION_CLIPBOARD or from
386 * the global cut buffer of @gimp.
387 *
388 * The returned #GimpBuffer needs to be unref'ed when it's no longer
389 * needed.
390 *
391 * Return value: a reference to a #GimpBuffer or %NULL if there's no
392 * image data
393 **/
394 GimpBuffer *
gimp_clipboard_get_buffer(Gimp * gimp)395 gimp_clipboard_get_buffer (Gimp *gimp)
396 {
397 GimpClipboard *gimp_clip;
398 GtkClipboard *clipboard;
399 GimpBuffer *buffer = NULL;
400
401 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
402
403 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
404 GDK_SELECTION_CLIPBOARD);
405
406 if (clipboard &&
407 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
408 {
409 GdkAtom atom = gimp_clipboard_wait_for_buffer (gimp);
410
411 if (atom != GDK_NONE)
412 {
413 GtkSelectionData *data;
414
415 gimp_set_busy (gimp);
416
417 data = gtk_clipboard_wait_for_contents (clipboard, atom);
418
419 if (data)
420 {
421 GdkPixbuf *pixbuf = gtk_selection_data_get_pixbuf (data);
422
423 gtk_selection_data_free (data);
424
425 if (pixbuf)
426 {
427 buffer = gimp_buffer_new_from_pixbuf (pixbuf, _("Clipboard"),
428 0, 0);
429 g_object_unref (pixbuf);
430 }
431 }
432
433 gimp_unset_busy (gimp);
434 }
435
436 return buffer;
437 }
438
439 gimp_clip = gimp_clipboard_get (gimp);
440
441 if (! buffer && gimp_clip->buffer)
442 buffer = g_object_ref (gimp_clip->buffer);
443
444 return buffer;
445 }
446
447 /**
448 * gimp_clipboard_get_svg:
449 * @gimp: pointer to #Gimp
450 * @svg_length: returns the size of the SVG stream in bytes
451 *
452 * Retrieves SVG data from %GDK_SELECTION_CLIPBOARD or from the global
453 * SVG buffer of @gimp.
454 *
455 * The returned data needs to be freed when it's no longer needed.
456 *
457 * Return value: a reference to a #GimpBuffer or %NULL if there's no
458 * image data
459 **/
460 gchar *
gimp_clipboard_get_svg(Gimp * gimp,gsize * svg_length)461 gimp_clipboard_get_svg (Gimp *gimp,
462 gsize *svg_length)
463 {
464 GimpClipboard *gimp_clip;
465 GtkClipboard *clipboard;
466 gchar *svg = NULL;
467
468 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
469 g_return_val_if_fail (svg_length != NULL, NULL);
470
471 *svg_length = 0;
472
473 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
474 GDK_SELECTION_CLIPBOARD);
475
476 if (clipboard &&
477 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
478 {
479 GdkAtom atom = gimp_clipboard_wait_for_svg (gimp);
480
481 if (atom != GDK_NONE)
482 {
483 GtkSelectionData *data;
484
485 gimp_set_busy (gimp);
486
487 data = gtk_clipboard_wait_for_contents (clipboard, atom);
488
489 if (data)
490 {
491 const guchar *stream;
492
493 stream = gimp_selection_data_get_stream (data, svg_length);
494
495 if (stream)
496 svg = g_memdup (stream, *svg_length);
497
498 gtk_selection_data_free (data);
499 }
500
501 gimp_unset_busy (gimp);
502 }
503
504 return svg;
505 }
506
507 gimp_clip = gimp_clipboard_get (gimp);
508
509 if (! svg && gimp_clip->svg)
510 {
511 svg = g_strdup (gimp_clip->svg);
512 *svg_length = strlen (svg);
513 }
514
515 return svg;
516 }
517
518 /**
519 * gimp_clipboard_get_curve:
520 * @gimp: pointer to #Gimp
521 *
522 * Retrieves curve data from %GDK_SELECTION_CLIPBOARD or from the global
523 * curve buffer of @gimp.
524 *
525 * The returned curve needs to be unref'ed when it's no longer needed.
526 *
527 * Return value: a reference to a #GimpCurve or %NULL if there's no
528 * curve data
529 **/
530 GimpCurve *
gimp_clipboard_get_curve(Gimp * gimp)531 gimp_clipboard_get_curve (Gimp *gimp)
532 {
533 GimpClipboard *gimp_clip;
534 GtkClipboard *clipboard;
535 GimpCurve *curve = NULL;
536
537 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
538
539 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
540 GDK_SELECTION_CLIPBOARD);
541
542 if (clipboard &&
543 gtk_clipboard_get_owner (clipboard) != G_OBJECT (gimp))
544 {
545 GdkAtom atom = gimp_clipboard_wait_for_curve (gimp);
546
547 if (atom != GDK_NONE)
548 {
549 GtkSelectionData *data;
550
551 gimp_set_busy (gimp);
552
553 data = gtk_clipboard_wait_for_contents (clipboard, atom);
554
555 if (data)
556 {
557 curve = gimp_selection_data_get_curve (data);
558
559 gtk_selection_data_free (data);
560 }
561
562 gimp_unset_busy (gimp);
563 }
564
565 return curve;
566 }
567
568 gimp_clip = gimp_clipboard_get (gimp);
569
570 if (! curve && gimp_clip->curve)
571 curve = g_object_ref (gimp_clip->curve);
572
573 return curve;
574 }
575
576 /**
577 * gimp_clipboard_set_image:
578 * @gimp: pointer to #Gimp
579 * @image: a #GimpImage, or %NULL.
580 *
581 * Offers the image in %GDK_SELECTION_CLIPBOARD.
582 **/
583 void
gimp_clipboard_set_image(Gimp * gimp,GimpImage * image)584 gimp_clipboard_set_image (Gimp *gimp,
585 GimpImage *image)
586 {
587 GimpClipboard *gimp_clip;
588 GtkClipboard *clipboard;
589
590 g_return_if_fail (GIMP_IS_GIMP (gimp));
591 g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
592
593 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
594 GDK_SELECTION_CLIPBOARD);
595 if (! clipboard)
596 return;
597
598 gimp_clip = gimp_clipboard_get (gimp);
599
600 gimp_clipboard_clear (gimp_clip);
601
602 if (image)
603 {
604 gimp_clip->image = g_object_ref (image);
605
606 gtk_clipboard_set_with_owner (clipboard,
607 gimp_clip->image_target_entries,
608 gimp_clip->n_image_target_entries,
609 (GtkClipboardGetFunc) gimp_clipboard_send_image,
610 (GtkClipboardClearFunc) NULL,
611 G_OBJECT (gimp));
612
613 /* mark the first two entries (image/x-xcf and image/png) as
614 * suitable for storing
615 */
616 gtk_clipboard_set_can_store (clipboard,
617 gimp_clip->image_target_entries,
618 MIN (2, gimp_clip->n_image_target_entries));
619 }
620 else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
621 {
622 gtk_clipboard_clear (clipboard);
623 }
624 }
625
626 /**
627 * gimp_clipboard_set_buffer:
628 * @gimp: pointer to #Gimp
629 * @buffer: a #GimpBuffer, or %NULL.
630 *
631 * Offers the buffer in %GDK_SELECTION_CLIPBOARD.
632 **/
633 void
gimp_clipboard_set_buffer(Gimp * gimp,GimpBuffer * buffer)634 gimp_clipboard_set_buffer (Gimp *gimp,
635 GimpBuffer *buffer)
636 {
637 GimpClipboard *gimp_clip;
638 GtkClipboard *clipboard;
639
640 g_return_if_fail (GIMP_IS_GIMP (gimp));
641 g_return_if_fail (buffer == NULL || GIMP_IS_BUFFER (buffer));
642
643 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
644 GDK_SELECTION_CLIPBOARD);
645 if (! clipboard)
646 return;
647
648 gimp_clip = gimp_clipboard_get (gimp);
649
650 gimp_clipboard_clear (gimp_clip);
651
652 if (buffer)
653 {
654 gimp_clip->buffer = g_object_ref (buffer);
655
656 gtk_clipboard_set_with_owner (clipboard,
657 gimp_clip->buffer_target_entries,
658 gimp_clip->n_buffer_target_entries,
659 (GtkClipboardGetFunc) gimp_clipboard_send_buffer,
660 (GtkClipboardClearFunc) NULL,
661 G_OBJECT (gimp));
662
663 /* mark the first entry (image/png) as suitable for storing */
664 if (gimp_clip->n_buffer_target_entries > 0)
665 gtk_clipboard_set_can_store (clipboard,
666 gimp_clip->buffer_target_entries, 1);
667 }
668 else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
669 {
670 gtk_clipboard_clear (clipboard);
671 }
672 }
673
674 /**
675 * gimp_clipboard_set_svg:
676 * @gimp: pointer to #Gimp
677 * @svg: a string containing the SVG data, or %NULL
678 *
679 * Offers SVG data in %GDK_SELECTION_CLIPBOARD.
680 **/
681 void
gimp_clipboard_set_svg(Gimp * gimp,const gchar * svg)682 gimp_clipboard_set_svg (Gimp *gimp,
683 const gchar *svg)
684 {
685 GimpClipboard *gimp_clip;
686 GtkClipboard *clipboard;
687
688 g_return_if_fail (GIMP_IS_GIMP (gimp));
689
690 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
691 GDK_SELECTION_CLIPBOARD);
692 if (! clipboard)
693 return;
694
695 gimp_clip = gimp_clipboard_get (gimp);
696
697 gimp_clipboard_clear (gimp_clip);
698
699 if (svg)
700 {
701 gimp_clip->svg = g_strdup (svg);
702
703 gtk_clipboard_set_with_owner (clipboard,
704 gimp_clip->svg_target_entries,
705 gimp_clip->n_svg_target_entries,
706 (GtkClipboardGetFunc) gimp_clipboard_send_svg,
707 (GtkClipboardClearFunc) NULL,
708 G_OBJECT (gimp));
709
710 /* mark the first entry (image/svg) as suitable for storing */
711 gtk_clipboard_set_can_store (clipboard,
712 gimp_clip->svg_target_entries, 1);
713 }
714 else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
715 {
716 gtk_clipboard_clear (clipboard);
717 }
718 }
719
720 /**
721 * gimp_clipboard_set_text:
722 * @gimp: pointer to #Gimp
723 * @text: a %NULL-terminated string in UTF-8 encoding
724 *
725 * Offers @text in %GDK_SELECTION_CLIPBOARD and %GDK_SELECTION_PRIMARY.
726 **/
727 void
gimp_clipboard_set_text(Gimp * gimp,const gchar * text)728 gimp_clipboard_set_text (Gimp *gimp,
729 const gchar *text)
730 {
731 GtkClipboard *clipboard;
732
733 g_return_if_fail (GIMP_IS_GIMP (gimp));
734 g_return_if_fail (text != NULL);
735
736 gimp_clipboard_clear (gimp_clipboard_get (gimp));
737
738 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
739 GDK_SELECTION_CLIPBOARD);
740 if (clipboard)
741 gtk_clipboard_set_text (clipboard, text, -1);
742
743 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
744 GDK_SELECTION_PRIMARY);
745 if (clipboard)
746 gtk_clipboard_set_text (clipboard, text, -1);
747 }
748
749 /**
750 * gimp_clipboard_set_curve:
751 * @gimp: pointer to #Gimp
752 * @curve: a #GimpCurve, or %NULL
753 *
754 * Offers curve data in %GDK_SELECTION_CLIPBOARD.
755 **/
756 void
gimp_clipboard_set_curve(Gimp * gimp,GimpCurve * curve)757 gimp_clipboard_set_curve (Gimp *gimp,
758 GimpCurve *curve)
759 {
760 GimpClipboard *gimp_clip;
761 GtkClipboard *clipboard;
762
763 g_return_if_fail (GIMP_IS_GIMP (gimp));
764 g_return_if_fail (curve == NULL || GIMP_IS_CURVE (curve));
765
766 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
767 GDK_SELECTION_CLIPBOARD);
768 if (! clipboard)
769 return;
770
771 gimp_clip = gimp_clipboard_get (gimp);
772
773 gimp_clipboard_clear (gimp_clip);
774
775 if (curve)
776 {
777 gimp_clip->curve = g_object_ref (curve);
778
779 gtk_clipboard_set_with_owner (clipboard,
780 gimp_clip->curve_target_entries,
781 gimp_clip->n_curve_target_entries,
782 (GtkClipboardGetFunc) gimp_clipboard_send_curve,
783 (GtkClipboardClearFunc) NULL,
784 G_OBJECT (gimp));
785
786 gtk_clipboard_set_can_store (clipboard,
787 gimp_clip->curve_target_entries, 1);
788 }
789 else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (gimp))
790 {
791 gtk_clipboard_clear (clipboard);
792 }
793 }
794
795
796 /* private functions */
797
798 static GimpClipboard *
gimp_clipboard_get(Gimp * gimp)799 gimp_clipboard_get (Gimp *gimp)
800 {
801 return g_object_get_data (G_OBJECT (gimp), GIMP_CLIPBOARD_KEY);
802 }
803
804 static GimpClipboard *
gimp_clipboard_new(gboolean verbose)805 gimp_clipboard_new (gboolean verbose)
806 {
807 GimpClipboard *gimp_clip = g_slice_new0 (GimpClipboard);
808 GSList *list;
809
810 gimp_clip->pixbuf_formats = gimp_pixbuf_get_formats ();
811
812 for (list = gimp_clip->pixbuf_formats; list; list = g_slist_next (list))
813 {
814 GdkPixbufFormat *format = list->data;
815
816 if (gdk_pixbuf_format_is_writable (format))
817 {
818 gchar **mime_types;
819 gchar **type;
820
821 mime_types = gdk_pixbuf_format_get_mime_types (format);
822
823 for (type = mime_types; *type; type++)
824 gimp_clip->n_buffer_target_entries++;
825
826 g_strfreev (mime_types);
827 }
828 }
829
830 /* the image_target_entries have the XCF target, and all pixbuf
831 * targets that are also in buffer_target_entries
832 */
833 gimp_clip->n_image_target_entries = gimp_clip->n_buffer_target_entries + 1;
834 gimp_clip->image_target_entries = g_new0 (GtkTargetEntry,
835 gimp_clip->n_image_target_entries);
836
837 gimp_clip->image_target_entries[0].target = g_strdup ("image/x-xcf");
838 gimp_clip->image_target_entries[0].flags = 0;
839 gimp_clip->image_target_entries[0].info = 0;
840
841 if (gimp_clip->n_buffer_target_entries > 0)
842 {
843 gint i = 0;
844
845 gimp_clip->buffer_target_entries = g_new0 (GtkTargetEntry,
846 gimp_clip->n_buffer_target_entries);
847
848 for (list = gimp_clip->pixbuf_formats; list; list = g_slist_next (list))
849 {
850 GdkPixbufFormat *format = list->data;
851
852 if (gdk_pixbuf_format_is_writable (format))
853 {
854 gchar *format_name;
855 gchar **mime_types;
856 gchar **type;
857
858 format_name = gdk_pixbuf_format_get_name (format);
859 mime_types = gdk_pixbuf_format_get_mime_types (format);
860
861 for (type = mime_types; *type; type++)
862 {
863 const gchar *mime_type = *type;
864
865 if (verbose)
866 g_printerr ("clipboard: writable pixbuf format: %s\n",
867 mime_type);
868
869 gimp_clip->image_target_entries[i + 1].target = g_strdup (mime_type);
870 gimp_clip->image_target_entries[i + 1].flags = 0;
871 gimp_clip->image_target_entries[i + 1].info = i + 1;
872
873 gimp_clip->buffer_target_entries[i].target = g_strdup (mime_type);
874 gimp_clip->buffer_target_entries[i].flags = 0;
875 gimp_clip->buffer_target_entries[i].info = i;
876
877 i++;
878 }
879
880 g_strfreev (mime_types);
881 g_free (format_name);
882 }
883 }
884 }
885
886 gimp_clip->n_svg_target_entries = 2;
887 gimp_clip->svg_target_entries = g_new0 (GtkTargetEntry, 2);
888
889 gimp_clip->svg_target_entries[0].target = g_strdup ("image/svg");
890 gimp_clip->svg_target_entries[0].flags = 0;
891 gimp_clip->svg_target_entries[0].info = 0;
892
893 gimp_clip->svg_target_entries[1].target = g_strdup ("image/svg+xml");
894 gimp_clip->svg_target_entries[1].flags = 0;
895 gimp_clip->svg_target_entries[1].info = 1;
896
897 gimp_clip->n_curve_target_entries = 1;
898 gimp_clip->curve_target_entries = g_new0 (GtkTargetEntry, 1);
899
900 gimp_clip->curve_target_entries[0].target = g_strdup ("application/x-gimp-curve");
901 gimp_clip->curve_target_entries[0].flags = 0;
902 gimp_clip->curve_target_entries[0].info = 0;
903
904 return gimp_clip;
905 }
906
907 static void
gimp_clipboard_free(GimpClipboard * gimp_clip)908 gimp_clipboard_free (GimpClipboard *gimp_clip)
909 {
910 gint i;
911
912 gimp_clipboard_clear (gimp_clip);
913
914 g_slist_free (gimp_clip->pixbuf_formats);
915
916 for (i = 0; i < gimp_clip->n_image_target_entries; i++)
917 g_free ((gchar *) gimp_clip->image_target_entries[i].target);
918
919 g_free (gimp_clip->image_target_entries);
920
921 for (i = 0; i < gimp_clip->n_buffer_target_entries; i++)
922 g_free ((gchar *) gimp_clip->buffer_target_entries[i].target);
923
924 g_free (gimp_clip->buffer_target_entries);
925
926 for (i = 0; i < gimp_clip->n_svg_target_entries; i++)
927 g_free ((gchar *) gimp_clip->svg_target_entries[i].target);
928
929 g_free (gimp_clip->svg_target_entries);
930
931 for (i = 0; i < gimp_clip->n_curve_target_entries; i++)
932 g_free ((gchar *) gimp_clip->curve_target_entries[i].target);
933
934 g_free (gimp_clip->curve_target_entries);
935
936 g_slice_free (GimpClipboard, gimp_clip);
937 }
938
939 static void
gimp_clipboard_clear(GimpClipboard * gimp_clip)940 gimp_clipboard_clear (GimpClipboard *gimp_clip)
941 {
942 g_clear_object (&gimp_clip->image);
943 g_clear_object (&gimp_clip->buffer);
944 g_clear_pointer (&gimp_clip->svg, g_free);
945 g_clear_object (&gimp_clip->curve);
946 }
947
948 static GdkAtom *
gimp_clipboard_wait_for_targets(Gimp * gimp,gint * n_targets)949 gimp_clipboard_wait_for_targets (Gimp *gimp,
950 gint *n_targets)
951 {
952 GtkClipboard *clipboard;
953
954 clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
955 GDK_SELECTION_CLIPBOARD);
956
957 if (clipboard)
958 {
959 GtkSelectionData *data;
960 GdkAtom atom = gdk_atom_intern_static_string ("TARGETS");
961
962 data = gtk_clipboard_wait_for_contents (clipboard, atom);
963
964 if (data)
965 {
966 GdkAtom *targets;
967 gboolean success;
968
969 success = gtk_selection_data_get_targets (data, &targets, n_targets);
970
971 gtk_selection_data_free (data);
972
973 if (success)
974 {
975 if (gimp->be_verbose)
976 {
977 gint i;
978
979 for (i = 0; i < *n_targets; i++)
980 g_printerr ("clipboard: offered type: %s\n",
981 gdk_atom_name (targets[i]));
982
983 g_printerr ("\n");
984 }
985
986 return targets;
987 }
988 }
989 }
990
991 return NULL;
992 }
993
994 static GdkAtom
gimp_clipboard_wait_for_image(Gimp * gimp)995 gimp_clipboard_wait_for_image (Gimp *gimp)
996 {
997 GdkAtom *targets;
998 gint n_targets;
999 GdkAtom result = GDK_NONE;
1000
1001 targets = gimp_clipboard_wait_for_targets (gimp, &n_targets);
1002
1003 if (targets)
1004 {
1005 GdkAtom image_atom = gdk_atom_intern_static_string ("image/x-xcf");
1006 gint i;
1007
1008 for (i = 0; i < n_targets; i++)
1009 {
1010 if (targets[i] == image_atom)
1011 {
1012 result = image_atom;
1013 break;
1014 }
1015 }
1016
1017 g_free (targets);
1018 }
1019
1020 return result;
1021 }
1022
1023 static GdkAtom
gimp_clipboard_wait_for_buffer(Gimp * gimp)1024 gimp_clipboard_wait_for_buffer (Gimp *gimp)
1025 {
1026 GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
1027 GdkAtom *targets;
1028 gint n_targets;
1029 GdkAtom result = GDK_NONE;
1030
1031 targets = gimp_clipboard_wait_for_targets (gimp, &n_targets);
1032
1033 if (targets)
1034 {
1035 GSList *list;
1036
1037 for (list = gimp_clip->pixbuf_formats; list; list = g_slist_next (list))
1038 {
1039 GdkPixbufFormat *format = list->data;
1040 gchar **mime_types;
1041 gchar **type;
1042
1043 if (gimp->be_verbose)
1044 g_printerr ("clipboard: checking pixbuf format '%s'\n",
1045 gdk_pixbuf_format_get_name (format));
1046
1047 mime_types = gdk_pixbuf_format_get_mime_types (format);
1048
1049 for (type = mime_types; *type; type++)
1050 {
1051 gchar *mime_type = *type;
1052 GdkAtom atom = gdk_atom_intern (mime_type, FALSE);
1053 gint i;
1054
1055 if (gimp->be_verbose)
1056 g_printerr (" - checking mime type '%s'\n", mime_type);
1057
1058 for (i = 0; i < n_targets; i++)
1059 {
1060 if (targets[i] == atom)
1061 {
1062 result = atom;
1063 break;
1064 }
1065 }
1066
1067 if (result != GDK_NONE)
1068 break;
1069 }
1070
1071 g_strfreev (mime_types);
1072
1073 if (result != GDK_NONE)
1074 break;
1075 }
1076
1077 g_free (targets);
1078 }
1079
1080 return result;
1081 }
1082
1083 static GdkAtom
gimp_clipboard_wait_for_svg(Gimp * gimp)1084 gimp_clipboard_wait_for_svg (Gimp *gimp)
1085 {
1086 GdkAtom *targets;
1087 gint n_targets;
1088 GdkAtom result = GDK_NONE;
1089
1090 targets = gimp_clipboard_wait_for_targets (gimp, &n_targets);
1091
1092 if (targets)
1093 {
1094 GdkAtom svg_atom = gdk_atom_intern_static_string ("image/svg");
1095 GdkAtom svg_xml_atom = gdk_atom_intern_static_string ("image/svg+xml");
1096 gint i;
1097
1098 for (i = 0; i < n_targets; i++)
1099 {
1100 if (targets[i] == svg_atom)
1101 {
1102 result = svg_atom;
1103 break;
1104 }
1105 else if (targets[i] == svg_xml_atom)
1106 {
1107 result = svg_xml_atom;
1108 break;
1109 }
1110 }
1111
1112 g_free (targets);
1113 }
1114
1115 return result;
1116 }
1117
1118 static GdkAtom
gimp_clipboard_wait_for_curve(Gimp * gimp)1119 gimp_clipboard_wait_for_curve (Gimp *gimp)
1120 {
1121 GdkAtom *targets;
1122 gint n_targets;
1123 GdkAtom result = GDK_NONE;
1124
1125 targets = gimp_clipboard_wait_for_targets (gimp, &n_targets);
1126
1127 if (targets)
1128 {
1129 GdkAtom curve_atom = gdk_atom_intern_static_string ("application/x-gimp-curve");
1130 gint i;
1131
1132 for (i = 0; i < n_targets; i++)
1133 {
1134 if (targets[i] == curve_atom)
1135 {
1136 result = curve_atom;
1137 break;
1138 }
1139 }
1140
1141 g_free (targets);
1142 }
1143
1144 return result;
1145 }
1146
1147 static void
gimp_clipboard_send_image(GtkClipboard * clipboard,GtkSelectionData * data,guint info,Gimp * gimp)1148 gimp_clipboard_send_image (GtkClipboard *clipboard,
1149 GtkSelectionData *data,
1150 guint info,
1151 Gimp *gimp)
1152 {
1153 GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
1154
1155 gimp_set_busy (gimp);
1156
1157 if (info == 0)
1158 {
1159 if (gimp->be_verbose)
1160 g_printerr ("clipboard: sending image data as '%s'\n",
1161 gimp_clip->image_target_entries[info].target);
1162
1163 gimp_selection_data_set_xcf (data, gimp_clip->image);
1164 }
1165 else
1166 {
1167 GdkPixbuf *pixbuf;
1168
1169 gimp_pickable_flush (GIMP_PICKABLE (gimp_clip->image));
1170
1171 pixbuf = gimp_viewable_get_pixbuf (GIMP_VIEWABLE (gimp_clip->image),
1172 gimp_get_user_context (gimp),
1173 gimp_image_get_width (gimp_clip->image),
1174 gimp_image_get_height (gimp_clip->image));
1175
1176 if (pixbuf)
1177 {
1178 gdouble res_x;
1179 gdouble res_y;
1180 gchar str[16];
1181
1182 gimp_image_get_resolution (gimp_clip->image, &res_x, &res_y);
1183
1184 g_snprintf (str, sizeof (str), "%d", ROUND (res_x));
1185 gdk_pixbuf_set_option (pixbuf, "x-dpi", str);
1186
1187 g_snprintf (str, sizeof (str), "%d", ROUND (res_y));
1188 gdk_pixbuf_set_option (pixbuf, "y-dpi", str);
1189
1190 if (gimp->be_verbose)
1191 g_printerr ("clipboard: sending image data as '%s'\n",
1192 gimp_clip->image_target_entries[info].target);
1193
1194 gtk_selection_data_set_pixbuf (data, pixbuf);
1195 }
1196 else
1197 {
1198 g_warning ("%s: gimp_viewable_get_pixbuf() failed", G_STRFUNC);
1199 }
1200 }
1201
1202 gimp_unset_busy (gimp);
1203 }
1204
1205 static void
gimp_clipboard_send_buffer(GtkClipboard * clipboard,GtkSelectionData * data,guint info,Gimp * gimp)1206 gimp_clipboard_send_buffer (GtkClipboard *clipboard,
1207 GtkSelectionData *data,
1208 guint info,
1209 Gimp *gimp)
1210 {
1211 GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
1212 GdkPixbuf *pixbuf;
1213
1214 gimp_set_busy (gimp);
1215
1216 pixbuf = gimp_viewable_get_pixbuf (GIMP_VIEWABLE (gimp_clip->buffer),
1217 gimp_get_user_context (gimp),
1218 gimp_buffer_get_width (gimp_clip->buffer),
1219 gimp_buffer_get_height (gimp_clip->buffer));
1220
1221 if (pixbuf)
1222 {
1223 gdouble res_x;
1224 gdouble res_y;
1225 gchar str[16];
1226
1227 gimp_buffer_get_resolution (gimp_clip->buffer, &res_x, &res_y);
1228
1229 g_snprintf (str, sizeof (str), "%d", ROUND (res_x));
1230 gdk_pixbuf_set_option (pixbuf, "x-dpi", str);
1231
1232 g_snprintf (str, sizeof (str), "%d", ROUND (res_y));
1233 gdk_pixbuf_set_option (pixbuf, "y-dpi", str);
1234
1235 if (gimp->be_verbose)
1236 g_printerr ("clipboard: sending pixbuf data as '%s'\n",
1237 gimp_clip->buffer_target_entries[info].target);
1238
1239 gtk_selection_data_set_pixbuf (data, pixbuf);
1240 }
1241 else
1242 {
1243 g_warning ("%s: gimp_viewable_get_pixbuf() failed", G_STRFUNC);
1244 }
1245
1246 gimp_unset_busy (gimp);
1247 }
1248
1249 static void
gimp_clipboard_send_svg(GtkClipboard * clipboard,GtkSelectionData * data,guint info,Gimp * gimp)1250 gimp_clipboard_send_svg (GtkClipboard *clipboard,
1251 GtkSelectionData *data,
1252 guint info,
1253 Gimp *gimp)
1254 {
1255 GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
1256
1257 gimp_set_busy (gimp);
1258
1259 if (gimp_clip->svg)
1260 {
1261 if (gimp->be_verbose)
1262 g_printerr ("clipboard: sending SVG data as '%s'\n",
1263 gimp_clip->svg_target_entries[info].target);
1264
1265 gimp_selection_data_set_stream (data,
1266 (const guchar *) gimp_clip->svg,
1267 strlen (gimp_clip->svg));
1268 }
1269
1270 gimp_unset_busy (gimp);
1271 }
1272
1273 static void
gimp_clipboard_send_curve(GtkClipboard * clipboard,GtkSelectionData * data,guint info,Gimp * gimp)1274 gimp_clipboard_send_curve (GtkClipboard *clipboard,
1275 GtkSelectionData *data,
1276 guint info,
1277 Gimp *gimp)
1278 {
1279 GimpClipboard *gimp_clip = gimp_clipboard_get (gimp);
1280
1281 gimp_set_busy (gimp);
1282
1283 if (gimp_clip->curve)
1284 {
1285 if (gimp->be_verbose)
1286 g_printerr ("clipboard: sending curve data as '%s'\n",
1287 gimp_clip->curve_target_entries[info].target);
1288
1289 gimp_selection_data_set_curve (data, gimp_clip->curve);
1290 }
1291
1292 gimp_unset_busy (gimp);
1293 }
1294