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