1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  * Copyright (C) 2004 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Global clipboard abstraction.
19  */
20 
21 #include "config.h"
22 #include <string.h>
23 
24 #include "gtkclipboard.h"
25 #include "gtkclipboardprivate.h"
26 #include "gtkinvisible.h"
27 #include "gtkmain.h"
28 #include "gtkmarshalers.h"
29 #include "gtktextbufferrichtext.h"
30 #include "gtkintl.h"
31 
32 #ifdef GDK_WINDOWING_X11
33 #include "x11/gdkx.h"
34 #endif
35 
36 #ifdef GDK_WINDOWING_BROADWAY
37 #include "broadway/gdkbroadway.h"
38 #endif
39 
40 #ifdef GDK_WINDOWING_WIN32
41 #include "win32/gdkwin32.h"
42 #endif
43 
44 
45 /**
46  * SECTION:gtkclipboard
47  * @Short_description: Storing data on clipboards
48  * @Title: Clipboards
49  * @See_also: #GtkSelectionData
50  *
51  * The #GtkClipboard object represents a clipboard of data shared
52  * between different processes or between different widgets in
53  * the same process. Each clipboard is identified by a name encoded as a
54  * #GdkAtom. (Conversion to and from strings can be done with
55  * gdk_atom_intern() and gdk_atom_name().) The default clipboard
56  * corresponds to the “CLIPBOARD” atom; another commonly used clipboard
57  * is the “PRIMARY” clipboard, which, in X, traditionally contains
58  * the currently selected text.
59  *
60  * To support having a number of different formats on the clipboard
61  * at the same time, the clipboard mechanism allows providing
62  * callbacks instead of the actual data.  When you set the contents
63  * of the clipboard, you can either supply the data directly (via
64  * functions like gtk_clipboard_set_text()), or you can supply a
65  * callback to be called at a later time when the data is needed (via
66  * gtk_clipboard_set_with_data() or gtk_clipboard_set_with_owner().)
67  * Providing a callback also avoids having to make copies of the data
68  * when it is not needed.
69  *
70  * gtk_clipboard_set_with_data() and gtk_clipboard_set_with_owner()
71  * are quite similar; the choice between the two depends mostly on
72  * which is more convenient in a particular situation.
73  * The former is most useful when you want to have a blob of data
74  * with callbacks to convert it into the various data types that you
75  * advertise. When the @clear_func you provided is called, you
76  * simply free the data blob. The latter is more useful when the
77  * contents of clipboard reflect the internal state of a #GObject
78  * (As an example, for the PRIMARY clipboard, when an entry widget
79  * provides the clipboard’s contents the contents are simply the
80  * text within the selected region.) If the contents change, the
81  * entry widget can call gtk_clipboard_set_with_owner() to update
82  * the timestamp for clipboard ownership, without having to worry
83  * about @clear_func being called.
84  *
85  * Requesting the data from the clipboard is essentially
86  * asynchronous. If the contents of the clipboard are provided within
87  * the same process, then a direct function call will be made to
88  * retrieve the data, but if they are provided by another process,
89  * then the data needs to be retrieved from the other process, which
90  * may take some time. To avoid blocking the user interface, the call
91  * to request the selection, gtk_clipboard_request_contents() takes a
92  * callback that will be called when the contents are received (or
93  * when the request fails.) If you don’t want to deal with providing
94  * a separate callback, you can also use gtk_clipboard_wait_for_contents().
95  * What this does is run the GLib main loop recursively waiting for
96  * the contents. This can simplify the code flow, but you still have
97  * to be aware that other callbacks in your program can be called
98  * while this recursive mainloop is running.
99  *
100  * Along with the functions to get the clipboard contents as an
101  * arbitrary data chunk, there are also functions to retrieve
102  * it as text, gtk_clipboard_request_text() and
103  * gtk_clipboard_wait_for_text(). These functions take care of
104  * determining which formats are advertised by the clipboard
105  * provider, asking for the clipboard in the best available format
106  * and converting the results into the UTF-8 encoding. (The standard
107  * form for representing strings in GTK+.)
108  */
109 
110 
111 enum {
112   OWNER_CHANGE,
113   LAST_SIGNAL
114 };
115 
116 typedef struct _RequestContentsInfo RequestContentsInfo;
117 typedef struct _RequestTextInfo RequestTextInfo;
118 typedef struct _RequestRichTextInfo RequestRichTextInfo;
119 typedef struct _RequestImageInfo RequestImageInfo;
120 typedef struct _RequestURIInfo RequestURIInfo;
121 typedef struct _RequestTargetsInfo RequestTargetsInfo;
122 
123 struct _RequestContentsInfo
124 {
125   GtkClipboardReceivedFunc callback;
126   gpointer user_data;
127 };
128 
129 struct _RequestTextInfo
130 {
131   GtkClipboardTextReceivedFunc callback;
132   gpointer user_data;
133 };
134 
135 struct _RequestRichTextInfo
136 {
137   GtkClipboardRichTextReceivedFunc callback;
138   GdkAtom *atoms;
139   gint     n_atoms;
140   gint     current_atom;
141   gpointer user_data;
142 };
143 
144 struct _RequestImageInfo
145 {
146   GtkClipboardImageReceivedFunc callback;
147   gpointer user_data;
148 };
149 
150 struct _RequestURIInfo
151 {
152   GtkClipboardURIReceivedFunc callback;
153   gpointer user_data;
154 };
155 
156 struct _RequestTargetsInfo
157 {
158   GtkClipboardTargetsReceivedFunc callback;
159   gpointer user_data;
160 };
161 
162 static void gtk_clipboard_class_init   (GtkClipboardClass   *class);
163 static void gtk_clipboard_finalize     (GObject             *object);
164 static void gtk_clipboard_owner_change (GtkClipboard        *clipboard,
165 					GdkEventOwnerChange *event);
166 static gboolean gtk_clipboard_set_contents      (GtkClipboard                   *clipboard,
167                                                  const GtkTargetEntry           *targets,
168                                                  guint                           n_targets,
169                                                  GtkClipboardGetFunc             get_func,
170                                                  GtkClipboardClearFunc           clear_func,
171                                                  gpointer                        user_data,
172                                                  gboolean                        have_owner);
173 static void gtk_clipboard_real_clear            (GtkClipboard                   *clipboard);
174 static void gtk_clipboard_real_request_contents (GtkClipboard                   *clipboard,
175                                                  GdkAtom                         target,
176                                                  GtkClipboardReceivedFunc        callback,
177                                                  gpointer                        user_data);
178 static void gtk_clipboard_real_set_can_store    (GtkClipboard                   *clipboard,
179                                                  const GtkTargetEntry           *targets,
180                                                  gint                            n_targets);
181 static void gtk_clipboard_real_store            (GtkClipboard                   *clipboard);
182 
183 
184 static void          clipboard_unset      (GtkClipboard     *clipboard);
185 static void          selection_received   (GtkWidget        *widget,
186 					   GtkSelectionData *selection_data,
187 					   guint             time);
188 static GtkClipboard *clipboard_peek       (GdkDisplay       *display,
189 					   GdkAtom           selection,
190 					   gboolean          only_if_exists);
191 static GtkWidget *   get_clipboard_widget (GdkDisplay       *display);
192 
193 
194 enum {
195   TARGET_STRING,
196   TARGET_TEXT,
197   TARGET_COMPOUND_TEXT,
198   TARGET_UTF8_STRING,
199   TARGET_SAVE_TARGETS
200 };
201 
202 static const gchar request_contents_key[] = "gtk-request-contents";
203 static GQuark request_contents_key_id = 0;
204 
205 static const gchar clipboards_owned_key[] = "gtk-clipboards-owned";
206 static GQuark clipboards_owned_key_id = 0;
207 
208 static guint         clipboard_signals[LAST_SIGNAL] = { 0 };
209 
G_DEFINE_TYPE(GtkClipboard,gtk_clipboard,G_TYPE_OBJECT)210 G_DEFINE_TYPE (GtkClipboard, gtk_clipboard, G_TYPE_OBJECT)
211 
212 static void
213 gtk_clipboard_init (GtkClipboard *object)
214 {
215 }
216 
217 static void
gtk_clipboard_class_init(GtkClipboardClass * class)218 gtk_clipboard_class_init (GtkClipboardClass *class)
219 {
220   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
221 
222   gobject_class->finalize = gtk_clipboard_finalize;
223 
224   class->set_contents = gtk_clipboard_set_contents;
225   class->clear = gtk_clipboard_real_clear;
226   class->request_contents = gtk_clipboard_real_request_contents;
227   class->set_can_store = gtk_clipboard_real_set_can_store;
228   class->store = gtk_clipboard_real_store;
229   class->owner_change = gtk_clipboard_owner_change;
230 
231   /**
232    * GtkClipboard::owner-change:
233    * @clipboard: the #GtkClipboard on which the signal is emitted
234    * @event: (type Gdk.EventOwnerChange): the @GdkEventOwnerChange event
235    *
236    * The ::owner-change signal is emitted when GTK+ receives an
237    * event that indicates that the ownership of the selection
238    * associated with @clipboard has changed.
239    *
240    * Since: 2.6
241    */
242   clipboard_signals[OWNER_CHANGE] =
243     g_signal_new (I_("owner-change"),
244 		  G_TYPE_FROM_CLASS (gobject_class),
245 		  G_SIGNAL_RUN_FIRST,
246 		  G_STRUCT_OFFSET (GtkClipboardClass, owner_change),
247 		  NULL, NULL,
248 		  NULL,
249 		  G_TYPE_NONE, 1,
250 		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
251 }
252 
253 static void
gtk_clipboard_finalize(GObject * object)254 gtk_clipboard_finalize (GObject *object)
255 {
256   GtkClipboard *clipboard;
257   GtkWidget *clipboard_widget = NULL;
258   GSList *clipboards = NULL;
259 
260   clipboard = GTK_CLIPBOARD (object);
261 
262   if (clipboard->display)
263     {
264       clipboards = g_object_get_data (G_OBJECT (clipboard->display), "gtk-clipboard-list");
265 
266       if (g_slist_index (clipboards, clipboard) >= 0)
267         g_warning ("GtkClipboard prematurely finalized");
268 
269       clipboards = g_slist_remove (clipboards, clipboard);
270 
271       g_object_set_data (G_OBJECT (clipboard->display), "gtk-clipboard-list",
272                          clipboards);
273 
274       /* don't use get_clipboard_widget() here because it would create the
275        * widget if it doesn't exist.
276        */
277       clipboard_widget = g_object_get_data (G_OBJECT (clipboard->display),
278                                             "gtk-clipboard-widget");
279     }
280 
281   clipboard_unset (clipboard);
282 
283   if (clipboard->store_loop && g_main_loop_is_running (clipboard->store_loop))
284     g_main_loop_quit (clipboard->store_loop);
285 
286   if (clipboard->store_timeout != 0)
287     g_source_remove (clipboard->store_timeout);
288 
289   if (clipboard_widget != NULL && clipboard->notify_signal_id != 0)
290     g_signal_handler_disconnect (clipboard_widget, clipboard->notify_signal_id);
291 
292   g_free (clipboard->storable_targets);
293   g_free (clipboard->cached_targets);
294 
295   G_OBJECT_CLASS (gtk_clipboard_parent_class)->finalize (object);
296 }
297 
298 static void
clipboard_display_closed(GdkDisplay * display,gboolean is_error,GtkClipboard * clipboard)299 clipboard_display_closed (GdkDisplay   *display,
300 			  gboolean      is_error,
301 			  GtkClipboard *clipboard)
302 {
303   GSList *clipboards;
304 
305   clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
306   g_object_run_dispose (G_OBJECT (clipboard));
307   clipboards = g_slist_remove (clipboards, clipboard);
308   g_object_set_data (G_OBJECT (display), I_("gtk-clipboard-list"), clipboards);
309   g_object_unref (clipboard);
310 }
311 
312 /**
313  * gtk_clipboard_get_for_display:
314  * @display: the #GdkDisplay for which the clipboard is to be retrieved or created.
315  * @selection: a #GdkAtom which identifies the clipboard to use.
316  *
317  * Returns the clipboard object for the given selection.
318  * Cut/copy/paste menu items and keyboard shortcuts should use
319  * the default clipboard, returned by passing %GDK_SELECTION_CLIPBOARD for @selection.
320  * (%GDK_NONE is supported as a synonym for GDK_SELECTION_CLIPBOARD
321  * for backwards compatibility reasons.)
322  * The currently-selected object or text should be provided on the clipboard
323  * identified by #GDK_SELECTION_PRIMARY. Cut/copy/paste menu items
324  * conceptually copy the contents of the #GDK_SELECTION_PRIMARY clipboard
325  * to the default clipboard, i.e. they copy the selection to what the
326  * user sees as the clipboard.
327  *
328  * (Passing #GDK_NONE is the same as using `gdk_atom_intern
329  * ("CLIPBOARD", FALSE)`.
330  *
331  * See the
332  * [FreeDesktop Clipboard Specification](http://www.freedesktop.org/Standards/clipboards-spec)
333  * for a detailed discussion of the “CLIPBOARD” vs. “PRIMARY”
334  * selections under the X window system. On Win32 the
335  * #GDK_SELECTION_PRIMARY clipboard is essentially ignored.)
336  *
337  * It’s possible to have arbitrary named clipboards; if you do invent
338  * new clipboards, you should prefix the selection name with an
339  * underscore (because the ICCCM requires that nonstandard atoms are
340  * underscore-prefixed), and namespace it as well. For example,
341  * if your application called “Foo” has a special-purpose
342  * clipboard, you might call it “_FOO_SPECIAL_CLIPBOARD”.
343  *
344  * Returns: (transfer none): the appropriate clipboard object. If no
345  *   clipboard already exists, a new one will be created. Once a clipboard
346  *   object has been created, it is persistent and, since it is owned by
347  *   GTK+, must not be freed or unrefd.
348  *
349  * Since: 2.2
350  **/
351 GtkClipboard *
gtk_clipboard_get_for_display(GdkDisplay * display,GdkAtom selection)352 gtk_clipboard_get_for_display (GdkDisplay *display,
353 			       GdkAtom     selection)
354 {
355   g_return_val_if_fail (display != NULL, NULL); /* See bgo#463773; this is needed because Flash Player sucks */
356   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
357   g_return_val_if_fail (!gdk_display_is_closed (display), NULL);
358 
359   return clipboard_peek (display, selection, FALSE);
360 }
361 
362 
363 /**
364  * gtk_clipboard_get:
365  * @selection: a #GdkAtom which identifies the clipboard to use
366  *
367  * Returns the clipboard object for the given selection.
368  * See gtk_clipboard_get_for_display() for complete details.
369  *
370  * Returns: (transfer none): the appropriate clipboard object. If no clipboard
371  *     already exists, a new one will be created. Once a clipboard
372  *     object has been created, it is persistent and, since it is
373  *     owned by GTK+, must not be freed or unreffed.
374  */
375 GtkClipboard *
gtk_clipboard_get(GdkAtom selection)376 gtk_clipboard_get (GdkAtom selection)
377 {
378   return gtk_clipboard_get_for_display (gdk_display_get_default (), selection);
379 }
380 
381 /**
382  * gtk_clipboard_get_default:
383  * @display: the #GdkDisplay for which the clipboard is to be retrieved.
384  *
385  * Returns the default clipboard object for use with cut/copy/paste menu items
386  * and keyboard shortcuts.
387  *
388  * Return value: (transfer none): the default clipboard object.
389  *
390  * Since: 3.16
391  **/
392 GtkClipboard *
gtk_clipboard_get_default(GdkDisplay * display)393 gtk_clipboard_get_default (GdkDisplay *display)
394 {
395   g_return_val_if_fail (display != NULL, NULL);
396   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
397 
398   return gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
399 }
400 
401 static void
selection_get_cb(GtkWidget * widget,GtkSelectionData * selection_data,guint info,guint time)402 selection_get_cb (GtkWidget          *widget,
403 		  GtkSelectionData   *selection_data,
404 		  guint               info,
405 		  guint               time)
406 {
407   GtkClipboard *clipboard;
408 
409   clipboard = gtk_widget_get_clipboard (widget,
410                                         gtk_selection_data_get_selection (selection_data));
411 
412   if (clipboard && clipboard->get_func)
413     clipboard->get_func (clipboard, selection_data, info, clipboard->user_data);
414 }
415 
416 static gboolean
selection_clear_event_cb(GtkWidget * widget,GdkEventSelection * event)417 selection_clear_event_cb (GtkWidget	    *widget,
418 			  GdkEventSelection *event)
419 {
420   GtkClipboard *clipboard = gtk_widget_get_clipboard (widget, event->selection);
421 
422   if (clipboard)
423     {
424       clipboard_unset (clipboard);
425 
426       return TRUE;
427     }
428 
429   return FALSE;
430 }
431 
432 static GtkWidget *
make_clipboard_widget(GdkDisplay * display,gboolean provider)433 make_clipboard_widget (GdkDisplay *display,
434 		       gboolean    provider)
435 {
436   GtkWidget *widget = gtk_invisible_new_for_screen (gdk_display_get_default_screen (display));
437 
438   g_signal_connect (widget, "selection-received",
439 		    G_CALLBACK (selection_received), NULL);
440 
441   if (provider)
442     {
443       /* We need this for gdk_x11_get_server_time() */
444       gtk_widget_add_events (widget, GDK_PROPERTY_CHANGE_MASK);
445 
446       g_signal_connect (widget, "selection-get",
447 			G_CALLBACK (selection_get_cb), NULL);
448       g_signal_connect (widget, "selection-clear-event",
449 			G_CALLBACK (selection_clear_event_cb), NULL);
450     }
451 
452   return widget;
453 }
454 
455 static GtkWidget *
get_clipboard_widget(GdkDisplay * display)456 get_clipboard_widget (GdkDisplay *display)
457 {
458   GtkWidget *clip_widget = g_object_get_data (G_OBJECT (display), "gtk-clipboard-widget");
459   if (!clip_widget)
460     {
461       clip_widget = make_clipboard_widget (display, TRUE);
462       g_object_set_data (G_OBJECT (display), I_("gtk-clipboard-widget"), clip_widget);
463     }
464 
465   return clip_widget;
466 }
467 
468 /* This function makes a very good guess at what the correct
469  * timestamp for a selection request should be. If there is
470  * a currently processed event, it uses the timestamp for that
471  * event, otherwise it uses the current server time. However,
472  * if the time resulting from that is older than the time used
473  * last time, it uses the time used last time instead.
474  *
475  * In order implement this correctly, we never use CurrentTime,
476  * but actually retrieve the actual timestamp from the server.
477  * This is a little slower but allows us to make the guarantee
478  * that the times used by this application will always ascend
479  * and we won’t get selections being rejected just because
480  * we are using a correct timestamp from an event, but used
481  * CurrentTime previously.
482  */
483 static guint32
clipboard_get_timestamp(GtkClipboard * clipboard)484 clipboard_get_timestamp (GtkClipboard *clipboard)
485 {
486   GtkWidget *clipboard_widget = get_clipboard_widget (clipboard->display);
487   guint32 timestamp = gtk_get_current_event_time ();
488   GdkWindow *window;
489 
490   if (timestamp == GDK_CURRENT_TIME)
491     {
492       window = gtk_widget_get_window (clipboard_widget);
493 #ifdef GDK_WINDOWING_X11
494       if (GDK_IS_X11_WINDOW (window))
495 	{
496 	  timestamp = gdk_x11_get_server_time (gtk_widget_get_window (clipboard_widget));
497 	}
498       else
499 #endif
500 #if defined GDK_WINDOWING_WIN32
501       if (GDK_IS_WIN32_WINDOW (window))
502 	{
503 	  timestamp = GetMessageTime ();
504 	}
505       else
506 #endif
507 #if defined GDK_WINDOWING_BROADWAY
508       if (GDK_IS_BROADWAY_WINDOW (window))
509 	{
510 	  timestamp = gdk_broadway_get_last_seen_time (window);
511 	}
512       else
513 #endif
514 	{
515 	  /* No implementation */
516 	}
517     }
518   else
519     {
520       if (clipboard->timestamp != GDK_CURRENT_TIME)
521 	{
522 	  /* Check to see if clipboard->timestamp is newer than
523 	   * timestamp, accounting for wraparound.
524 	   */
525 
526 	  guint32 max = timestamp + 0x80000000;
527 
528 	  if ((max > timestamp &&
529 	       (clipboard->timestamp > timestamp &&
530 		clipboard->timestamp <= max)) ||
531 	      (max <= timestamp &&
532 	       (clipboard->timestamp > timestamp ||
533 		clipboard->timestamp <= max)))
534 	    {
535 	      timestamp = clipboard->timestamp;
536 	    }
537 	}
538     }
539 
540   clipboard->timestamp = timestamp;
541 
542   return timestamp;
543 }
544 
545 static void
clipboard_owner_destroyed(gpointer data)546 clipboard_owner_destroyed (gpointer data)
547 {
548   GSList *clipboards = data;
549   GSList *tmp_list;
550 
551   tmp_list = clipboards;
552   while (tmp_list)
553     {
554       GtkClipboard *clipboard = tmp_list->data;
555 
556       clipboard->get_func = NULL;
557       clipboard->clear_func = NULL;
558       clipboard->user_data = NULL;
559       clipboard->have_owner = FALSE;
560 
561       gtk_clipboard_clear (clipboard);
562 
563       tmp_list = tmp_list->next;
564     }
565 
566   g_slist_free (clipboards);
567 }
568 
569 static void
clipboard_add_owner_notify(GtkClipboard * clipboard)570 clipboard_add_owner_notify (GtkClipboard *clipboard)
571 {
572   if (!clipboards_owned_key_id)
573     clipboards_owned_key_id = g_quark_from_static_string (clipboards_owned_key);
574 
575   if (clipboard->have_owner)
576     g_object_set_qdata_full (clipboard->user_data, clipboards_owned_key_id,
577 			     g_slist_prepend (g_object_steal_qdata (clipboard->user_data,
578 								    clipboards_owned_key_id),
579 					      clipboard),
580 			     clipboard_owner_destroyed);
581 }
582 
583 static void
clipboard_remove_owner_notify(GtkClipboard * clipboard)584 clipboard_remove_owner_notify (GtkClipboard *clipboard)
585 {
586   if (clipboard->have_owner)
587      g_object_set_qdata_full (clipboard->user_data, clipboards_owned_key_id,
588 			      g_slist_remove (g_object_steal_qdata (clipboard->user_data,
589 								    clipboards_owned_key_id),
590 					      clipboard),
591 			      clipboard_owner_destroyed);
592 }
593 
594 static gboolean
gtk_clipboard_set_contents(GtkClipboard * clipboard,const GtkTargetEntry * targets,guint n_targets,GtkClipboardGetFunc get_func,GtkClipboardClearFunc clear_func,gpointer user_data,gboolean have_owner)595 gtk_clipboard_set_contents (GtkClipboard         *clipboard,
596 			    const GtkTargetEntry *targets,
597 			    guint                 n_targets,
598 			    GtkClipboardGetFunc   get_func,
599 			    GtkClipboardClearFunc clear_func,
600 			    gpointer              user_data,
601 			    gboolean              have_owner)
602 {
603   GtkWidget *clipboard_widget = get_clipboard_widget (clipboard->display);
604 
605   if (gtk_selection_owner_set_for_display (clipboard->display,
606 					   clipboard_widget,
607 					   clipboard->selection,
608 					   clipboard_get_timestamp (clipboard)))
609     {
610       clipboard->have_selection = TRUE;
611 
612       if (clipboard->n_cached_targets != -1)
613         {
614           g_free (clipboard->cached_targets);
615 	  clipboard->cached_targets = NULL;
616           clipboard->n_cached_targets = -1;
617         }
618 
619       if (!(clipboard->have_owner && have_owner) ||
620 	  clipboard->user_data != user_data)
621 	{
622 	  clipboard_unset (clipboard);
623 
624 	  clipboard->user_data = user_data;
625 	  clipboard->have_owner = have_owner;
626 	  if (have_owner)
627 	      clipboard_add_owner_notify (clipboard);
628  	}
629 
630       clipboard->get_func = get_func;
631       clipboard->clear_func = clear_func;
632 
633       gtk_selection_clear_targets (clipboard_widget, clipboard->selection);
634       gtk_selection_add_targets (clipboard_widget, clipboard->selection,
635 				 targets, n_targets);
636 
637       return TRUE;
638     }
639   else
640     return FALSE;
641 }
642 
643 /**
644  * gtk_clipboard_set_with_data: (skip)
645  * @clipboard: a #GtkClipboard
646  * @targets: (array length=n_targets): array containing information
647  *     about the available forms for the clipboard data
648  * @n_targets: number of elements in @targets
649  * @get_func: (scope async): function to call to get the actual clipboard data
650  * @clear_func: (scope async): when the clipboard contents are set again,
651  *     this function will be called, and @get_func will not be subsequently
652  *     called.
653  * @user_data: user data to pass to @get_func and @clear_func.
654  *
655  * Virtually sets the contents of the specified clipboard by providing
656  * a list of supported formats for the clipboard data and a function
657  * to call to get the actual data when it is requested.
658  *
659  * Returns: %TRUE if setting the clipboard data succeeded.
660  *    If setting the clipboard data failed the provided callback
661  *    functions will be ignored.
662  **/
663 gboolean
gtk_clipboard_set_with_data(GtkClipboard * clipboard,const GtkTargetEntry * targets,guint n_targets,GtkClipboardGetFunc get_func,GtkClipboardClearFunc clear_func,gpointer user_data)664 gtk_clipboard_set_with_data (GtkClipboard          *clipboard,
665 			     const GtkTargetEntry  *targets,
666 			     guint                  n_targets,
667 			     GtkClipboardGetFunc    get_func,
668 			     GtkClipboardClearFunc  clear_func,
669 			     gpointer               user_data)
670 {
671   g_return_val_if_fail (clipboard != NULL, FALSE);
672   g_return_val_if_fail (targets != NULL, FALSE);
673   g_return_val_if_fail (get_func != NULL, FALSE);
674 
675   return GTK_CLIPBOARD_GET_CLASS (clipboard)->set_contents (clipboard,
676                                                             targets,
677                                                             n_targets,
678 				                            get_func,
679                                                             clear_func,
680                                                             user_data,
681 				                            FALSE);
682 }
683 
684 /**
685  * gtk_clipboard_set_with_owner: (skip)
686  * @clipboard: a #GtkClipboard
687  * @targets: (array length=n_targets): array containing information
688  *     about the available forms for the clipboard data
689  * @n_targets: number of elements in @targets
690  * @get_func: (scope async): function to call to get the actual clipboard data
691  * @clear_func: (scope async): when the clipboard contents are set again,
692  *     this function will be called, and @get_func will not be subsequently
693  *     called
694  * @owner: an object that “owns” the data. This object will be passed
695  *     to the callbacks when called
696  *
697  * Virtually sets the contents of the specified clipboard by providing
698  * a list of supported formats for the clipboard data and a function
699  * to call to get the actual data when it is requested.
700  *
701  * The difference between this function and gtk_clipboard_set_with_data()
702  * is that instead of an generic @user_data pointer, a #GObject is passed
703  * in.
704  *
705  * Returns: %TRUE if setting the clipboard data succeeded.
706  *     If setting the clipboard data failed the provided callback
707  *     functions will be ignored.
708  **/
709 gboolean
gtk_clipboard_set_with_owner(GtkClipboard * clipboard,const GtkTargetEntry * targets,guint n_targets,GtkClipboardGetFunc get_func,GtkClipboardClearFunc clear_func,GObject * owner)710 gtk_clipboard_set_with_owner (GtkClipboard          *clipboard,
711 			      const GtkTargetEntry  *targets,
712 			      guint                  n_targets,
713 			      GtkClipboardGetFunc    get_func,
714 			      GtkClipboardClearFunc  clear_func,
715 			      GObject               *owner)
716 {
717   g_return_val_if_fail (clipboard != NULL, FALSE);
718   g_return_val_if_fail (targets != NULL, FALSE);
719   g_return_val_if_fail (get_func != NULL, FALSE);
720   g_return_val_if_fail (G_IS_OBJECT (owner), FALSE);
721 
722   return GTK_CLIPBOARD_GET_CLASS (clipboard)->set_contents (clipboard,
723                                                             targets,
724                                                             n_targets,
725 				                            get_func,
726                                                             clear_func,
727                                                             owner,
728 				                            TRUE);
729 }
730 
731 /**
732  * gtk_clipboard_get_owner:
733  * @clipboard: a #GtkClipboard
734  *
735  * If the clipboard contents callbacks were set with
736  * gtk_clipboard_set_with_owner(), and the gtk_clipboard_set_with_data() or
737  * gtk_clipboard_clear() has not subsequently called, returns the owner set
738  * by gtk_clipboard_set_with_owner().
739  *
740  * Returns: (nullable) (transfer none): the owner of the clipboard, if any;
741  *     otherwise %NULL.
742  **/
743 GObject *
gtk_clipboard_get_owner(GtkClipboard * clipboard)744 gtk_clipboard_get_owner (GtkClipboard *clipboard)
745 {
746   g_return_val_if_fail (clipboard != NULL, NULL);
747 
748   if (clipboard->have_owner)
749     return clipboard->user_data;
750   else
751     return NULL;
752 }
753 
754 static void
clipboard_unset(GtkClipboard * clipboard)755 clipboard_unset (GtkClipboard *clipboard)
756 {
757   GtkClipboardClearFunc old_clear_func;
758   gpointer old_data;
759   gboolean old_have_owner;
760   gint old_n_storable_targets;
761 
762   old_clear_func = clipboard->clear_func;
763   old_data = clipboard->user_data;
764   old_have_owner = clipboard->have_owner;
765   old_n_storable_targets = clipboard->n_storable_targets;
766 
767   if (old_have_owner)
768     {
769       clipboard_remove_owner_notify (clipboard);
770       clipboard->have_owner = FALSE;
771     }
772 
773   clipboard->n_storable_targets = -1;
774   g_free (clipboard->storable_targets);
775   clipboard->storable_targets = NULL;
776 
777   clipboard->get_func = NULL;
778   clipboard->clear_func = NULL;
779   clipboard->user_data = NULL;
780 
781   if (old_clear_func)
782     old_clear_func (clipboard, old_data);
783 
784   /* If we've transferred the clipboard data to the manager,
785    * unref the owner
786    */
787   if (old_have_owner &&
788       old_n_storable_targets != -1)
789     g_object_unref (old_data);
790 }
791 
792 /**
793  * gtk_clipboard_clear:
794  * @clipboard:  a #GtkClipboard
795  *
796  * Clears the contents of the clipboard. Generally this should only
797  * be called between the time you call gtk_clipboard_set_with_owner()
798  * or gtk_clipboard_set_with_data(),
799  * and when the @clear_func you supplied is called. Otherwise, the
800  * clipboard may be owned by someone else.
801  **/
802 void
gtk_clipboard_clear(GtkClipboard * clipboard)803 gtk_clipboard_clear (GtkClipboard *clipboard)
804 {
805   g_return_if_fail (clipboard != NULL);
806 
807   GTK_CLIPBOARD_GET_CLASS (clipboard)->clear (clipboard);
808 }
809 
810 static void
gtk_clipboard_real_clear(GtkClipboard * clipboard)811 gtk_clipboard_real_clear (GtkClipboard *clipboard)
812 {
813   if (clipboard->have_selection)
814     gtk_selection_owner_set_for_display (clipboard->display,
815 					 NULL,
816 					 clipboard->selection,
817 					 clipboard_get_timestamp (clipboard));
818 }
819 
820 static void
text_get_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,guint info,gpointer data)821 text_get_func (GtkClipboard     *clipboard,
822 	       GtkSelectionData *selection_data,
823 	       guint             info,
824 	       gpointer          data)
825 {
826   gtk_selection_data_set_text (selection_data, data, -1);
827 }
828 
829 static void
text_clear_func(GtkClipboard * clipboard,gpointer data)830 text_clear_func (GtkClipboard *clipboard,
831 		 gpointer      data)
832 {
833   g_free (data);
834 }
835 
836 
837 /**
838  * gtk_clipboard_set_text:
839  * @clipboard: a #GtkClipboard object
840  * @text:      a UTF-8 string.
841  * @len:       length of @text, in bytes, or -1, in which case
842  *             the length will be determined with strlen().
843  *
844  * Sets the contents of the clipboard to the given UTF-8 string. GTK+ will
845  * make a copy of the text and take responsibility for responding
846  * for requests for the text, and for converting the text into
847  * the requested format.
848  **/
849 void
gtk_clipboard_set_text(GtkClipboard * clipboard,const gchar * text,gint len)850 gtk_clipboard_set_text (GtkClipboard *clipboard,
851 			const gchar  *text,
852 			gint          len)
853 {
854   GtkTargetList *list;
855   GtkTargetEntry *targets;
856   gint n_targets;
857 
858   g_return_if_fail (clipboard != NULL);
859   g_return_if_fail (text != NULL);
860 
861   list = gtk_target_list_new (NULL, 0);
862   gtk_target_list_add_text_targets (list, 0);
863 
864   targets = gtk_target_table_new_from_list (list, &n_targets);
865 
866   if (len < 0)
867     len = strlen (text);
868 
869   gtk_clipboard_set_with_data (clipboard,
870 			       targets, n_targets,
871 			       text_get_func, text_clear_func,
872 			       g_strndup (text, len));
873   gtk_clipboard_set_can_store (clipboard, NULL, 0);
874 
875   gtk_target_table_free (targets, n_targets);
876   gtk_target_list_unref (list);
877 }
878 
879 static void
pixbuf_get_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,guint info,gpointer data)880 pixbuf_get_func (GtkClipboard     *clipboard,
881 		 GtkSelectionData *selection_data,
882 		 guint             info,
883 		 gpointer          data)
884 {
885   gtk_selection_data_set_pixbuf (selection_data, data);
886 }
887 
888 static void
pixbuf_clear_func(GtkClipboard * clipboard,gpointer data)889 pixbuf_clear_func (GtkClipboard *clipboard,
890 		   gpointer      data)
891 {
892   g_object_unref (data);
893 }
894 
895 /**
896  * gtk_clipboard_set_image:
897  * @clipboard: a #GtkClipboard object
898  * @pixbuf:    a #GdkPixbuf
899  *
900  * Sets the contents of the clipboard to the given #GdkPixbuf.
901  * GTK+ will take responsibility for responding for requests
902  * for the image, and for converting the image into the
903  * requested format.
904  *
905  * Since: 2.6
906  **/
907 void
gtk_clipboard_set_image(GtkClipboard * clipboard,GdkPixbuf * pixbuf)908 gtk_clipboard_set_image (GtkClipboard *clipboard,
909 			  GdkPixbuf    *pixbuf)
910 {
911   GtkTargetList *list;
912   GtkTargetEntry *targets;
913   gint n_targets;
914 
915   g_return_if_fail (clipboard != NULL);
916   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
917 
918   list = gtk_target_list_new (NULL, 0);
919   gtk_target_list_add_image_targets (list, 0, TRUE);
920 
921   targets = gtk_target_table_new_from_list (list, &n_targets);
922 
923   gtk_clipboard_set_with_data (clipboard,
924 			       targets, n_targets,
925 			       pixbuf_get_func, pixbuf_clear_func,
926 			       g_object_ref (pixbuf));
927   gtk_clipboard_set_can_store (clipboard, NULL, 0);
928 
929   gtk_target_table_free (targets, n_targets);
930   gtk_target_list_unref (list);
931 }
932 
933 static void
set_request_contents_info(GtkWidget * widget,RequestContentsInfo * info)934 set_request_contents_info (GtkWidget           *widget,
935 			   RequestContentsInfo *info)
936 {
937   if (!request_contents_key_id)
938     request_contents_key_id = g_quark_from_static_string (request_contents_key);
939 
940   g_object_set_qdata (G_OBJECT (widget), request_contents_key_id, info);
941 }
942 
943 static RequestContentsInfo *
get_request_contents_info(GtkWidget * widget)944 get_request_contents_info (GtkWidget *widget)
945 {
946   if (!request_contents_key_id)
947     return NULL;
948   else
949     return g_object_get_qdata (G_OBJECT (widget), request_contents_key_id);
950 }
951 
952 static void
selection_received(GtkWidget * widget,GtkSelectionData * selection_data,guint time)953 selection_received (GtkWidget            *widget,
954 		    GtkSelectionData     *selection_data,
955 		    guint                 time)
956 {
957   RequestContentsInfo *request_info = get_request_contents_info (widget);
958   set_request_contents_info (widget, NULL);
959 
960   request_info->callback (gtk_widget_get_clipboard (widget, gtk_selection_data_get_selection (selection_data)),
961 			  selection_data,
962 			  request_info->user_data);
963 
964   g_free (request_info);
965 
966   if (widget != get_clipboard_widget (gtk_widget_get_display (widget)))
967     gtk_widget_destroy (widget);
968 }
969 
970 /**
971  * gtk_clipboard_request_contents:
972  * @clipboard: a #GtkClipboard
973  * @target: an atom representing the form into which the clipboard
974  *     owner should convert the selection.
975  * @callback: (scope async): A function to call when the results are received
976  *     (or the retrieval fails). If the retrieval fails the length field of
977  *     @selection_data will be negative.
978  * @user_data: user data to pass to @callback
979  *
980  * Requests the contents of clipboard as the given target.
981  * When the results of the result are later received the supplied callback
982  * will be called.
983  **/
984 void
gtk_clipboard_request_contents(GtkClipboard * clipboard,GdkAtom target,GtkClipboardReceivedFunc callback,gpointer user_data)985 gtk_clipboard_request_contents (GtkClipboard            *clipboard,
986 				GdkAtom                  target,
987 				GtkClipboardReceivedFunc callback,
988 				gpointer                 user_data)
989 {
990   g_return_if_fail (clipboard != NULL);
991   g_return_if_fail (target != GDK_NONE);
992   g_return_if_fail (callback != NULL);
993 
994   GTK_CLIPBOARD_GET_CLASS (clipboard)->request_contents (clipboard,
995                                                          target,
996                                                          callback,
997                                                          user_data);
998 }
999 
1000 static void
gtk_clipboard_real_request_contents(GtkClipboard * clipboard,GdkAtom target,GtkClipboardReceivedFunc callback,gpointer user_data)1001 gtk_clipboard_real_request_contents (GtkClipboard            *clipboard,
1002                                      GdkAtom                  target,
1003                                      GtkClipboardReceivedFunc callback,
1004                                      gpointer                 user_data)
1005 {
1006   RequestContentsInfo *info;
1007   GtkWidget *widget;
1008   GtkWidget *clipboard_widget;
1009 
1010   clipboard_widget = get_clipboard_widget (clipboard->display);
1011 
1012   if (get_request_contents_info (clipboard_widget))
1013     widget = make_clipboard_widget (clipboard->display, FALSE);
1014   else
1015     widget = clipboard_widget;
1016 
1017   info = g_new (RequestContentsInfo, 1);
1018   info->callback = callback;
1019   info->user_data = user_data;
1020 
1021   set_request_contents_info (widget, info);
1022 
1023   gtk_selection_convert (widget, clipboard->selection, target,
1024 			 clipboard_get_timestamp (clipboard));
1025 }
1026 
1027 static void
request_text_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1028 request_text_received_func (GtkClipboard     *clipboard,
1029 			    GtkSelectionData *selection_data,
1030 			    gpointer          data)
1031 {
1032   RequestTextInfo *info = data;
1033   gchar *result = NULL;
1034 
1035   result = (gchar *) gtk_selection_data_get_text (selection_data);
1036 
1037   if (!result)
1038     {
1039       /* If we asked for UTF8 and didn't get it, try compound_text;
1040        * if we asked for compound_text and didn't get it, try string;
1041        * If we asked for anything else and didn't get it, give up.
1042        */
1043       GdkAtom target = gtk_selection_data_get_target (selection_data);
1044 
1045       if (target == gdk_atom_intern_static_string ("text/plain;charset=utf-8"))
1046         {
1047           gtk_clipboard_request_contents (clipboard,
1048                                           gdk_atom_intern_static_string ("UTF8_STRING"),
1049                                           request_text_received_func, info);
1050           return;
1051         }
1052       else if (target == gdk_atom_intern_static_string ("UTF8_STRING"))
1053 	{
1054 	  gtk_clipboard_request_contents (clipboard,
1055 					  gdk_atom_intern_static_string ("COMPOUND_TEXT"),
1056 					  request_text_received_func, info);
1057 	  return;
1058 	}
1059       else if (target == gdk_atom_intern_static_string ("COMPOUND_TEXT"))
1060 	{
1061 	  gtk_clipboard_request_contents (clipboard,
1062 					  GDK_TARGET_STRING,
1063 					  request_text_received_func, info);
1064 	  return;
1065 	}
1066     }
1067 
1068   info->callback (clipboard, result, info->user_data);
1069   g_free (info);
1070   g_free (result);
1071 }
1072 
1073 /**
1074  * gtk_clipboard_request_text:
1075  * @clipboard: a #GtkClipboard
1076  * @callback: (scope async): a function to call when the text is received,
1077  *     or the retrieval fails. (It will always be called one way or the other.)
1078  * @user_data: user data to pass to @callback.
1079  *
1080  * Requests the contents of the clipboard as text. When the text is
1081  * later received, it will be converted to UTF-8 if necessary, and
1082  * @callback will be called.
1083  *
1084  * The @text parameter to @callback will contain the resulting text if
1085  * the request succeeded, or %NULL if it failed. This could happen for
1086  * various reasons, in particular if the clipboard was empty or if the
1087  * contents of the clipboard could not be converted into text form.
1088  **/
1089 void
gtk_clipboard_request_text(GtkClipboard * clipboard,GtkClipboardTextReceivedFunc callback,gpointer user_data)1090 gtk_clipboard_request_text (GtkClipboard                *clipboard,
1091 			    GtkClipboardTextReceivedFunc callback,
1092 			    gpointer                     user_data)
1093 {
1094   RequestTextInfo *info;
1095 
1096   g_return_if_fail (clipboard != NULL);
1097   g_return_if_fail (callback != NULL);
1098 
1099   info = g_new (RequestTextInfo, 1);
1100   info->callback = callback;
1101   info->user_data = user_data;
1102 
1103   gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("text/plain;charset=utf-8"),
1104 				  request_text_received_func,
1105 				  info);
1106 }
1107 
1108 static void
request_rich_text_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1109 request_rich_text_received_func (GtkClipboard     *clipboard,
1110                                  GtkSelectionData *selection_data,
1111                                  gpointer          data)
1112 {
1113   RequestRichTextInfo *info = data;
1114   guint8 *result = NULL;
1115   gsize length = 0;
1116 
1117   result = (guint8 *) gtk_selection_data_get_data (selection_data);
1118   length = gtk_selection_data_get_length (selection_data);
1119 
1120   info->current_atom++;
1121 
1122   if ((!result || length < 1) && (info->current_atom < info->n_atoms))
1123     {
1124       gtk_clipboard_request_contents (clipboard, info->atoms[info->current_atom],
1125                                       request_rich_text_received_func,
1126                                       info);
1127       return;
1128     }
1129 
1130   info->callback (clipboard, gtk_selection_data_get_target (selection_data),
1131                   result, length,
1132                   info->user_data);
1133   g_free (info->atoms);
1134   g_free (info);
1135 }
1136 
1137 /**
1138  * gtk_clipboard_request_rich_text:
1139  * @clipboard: a #GtkClipboard
1140  * @buffer: a #GtkTextBuffer
1141  * @callback: (scope async): a function to call when the text is received,
1142  *     or the retrieval fails. (It will always be called one way or the other.)
1143  * @user_data: user data to pass to @callback.
1144  *
1145  * Requests the contents of the clipboard as rich text. When the rich
1146  * text is later received, @callback will be called.
1147  *
1148  * The @text parameter to @callback will contain the resulting rich
1149  * text if the request succeeded, or %NULL if it failed. The @length
1150  * parameter will contain @text’s length. This function can fail for
1151  * various reasons, in particular if the clipboard was empty or if the
1152  * contents of the clipboard could not be converted into rich text form.
1153  *
1154  * Since: 2.10
1155  **/
1156 void
gtk_clipboard_request_rich_text(GtkClipboard * clipboard,GtkTextBuffer * buffer,GtkClipboardRichTextReceivedFunc callback,gpointer user_data)1157 gtk_clipboard_request_rich_text (GtkClipboard                    *clipboard,
1158                                  GtkTextBuffer                   *buffer,
1159                                  GtkClipboardRichTextReceivedFunc callback,
1160                                  gpointer                         user_data)
1161 {
1162   RequestRichTextInfo *info;
1163 
1164   g_return_if_fail (clipboard != NULL);
1165   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1166   g_return_if_fail (callback != NULL);
1167 
1168   info = g_new (RequestRichTextInfo, 1);
1169   info->callback = callback;
1170   info->atoms = NULL;
1171   info->n_atoms = 0;
1172   info->current_atom = 0;
1173   info->user_data = user_data;
1174 
1175   info->atoms = gtk_text_buffer_get_deserialize_formats (buffer, &info->n_atoms);
1176 
1177   gtk_clipboard_request_contents (clipboard, info->atoms[info->current_atom],
1178 				  request_rich_text_received_func,
1179 				  info);
1180 }
1181 
1182 static void
request_image_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1183 request_image_received_func (GtkClipboard     *clipboard,
1184 			     GtkSelectionData *selection_data,
1185 			     gpointer          data)
1186 {
1187   RequestImageInfo *info = data;
1188   GdkPixbuf *result = NULL;
1189 
1190   result = gtk_selection_data_get_pixbuf (selection_data);
1191 
1192   if (!result)
1193     {
1194       /* If we asked for image/png and didn't get it, try image/jpeg;
1195        * if we asked for image/jpeg and didn't get it, try image/gif;
1196        * if we asked for image/gif and didn't get it, try image/bmp;
1197        * If we asked for anything else and didn't get it, give up.
1198        */
1199       GdkAtom target = gtk_selection_data_get_target (selection_data);
1200 
1201       if (target == gdk_atom_intern_static_string ("image/png"))
1202 	{
1203 	  gtk_clipboard_request_contents (clipboard,
1204 					  gdk_atom_intern_static_string ("image/jpeg"),
1205 					  request_image_received_func, info);
1206 	  return;
1207 	}
1208       else if (target == gdk_atom_intern_static_string ("image/jpeg"))
1209 	{
1210 	  gtk_clipboard_request_contents (clipboard,
1211 					  gdk_atom_intern_static_string ("image/gif"),
1212 					  request_image_received_func, info);
1213 	  return;
1214 	}
1215       else if (target == gdk_atom_intern_static_string ("image/gif"))
1216 	{
1217 	  gtk_clipboard_request_contents (clipboard,
1218 					  gdk_atom_intern_static_string ("image/bmp"),
1219 					  request_image_received_func, info);
1220 	  return;
1221 	}
1222     }
1223 
1224   info->callback (clipboard, result, info->user_data);
1225   g_free (info);
1226 
1227   if (result)
1228     g_object_unref (result);
1229 }
1230 
1231 /**
1232  * gtk_clipboard_request_image:
1233  * @clipboard: a #GtkClipboard
1234  * @callback: (scope async): a function to call when the image is received,
1235  *     or the retrieval fails. (It will always be called one way or the other.)
1236  * @user_data: user data to pass to @callback.
1237  *
1238  * Requests the contents of the clipboard as image. When the image is
1239  * later received, it will be converted to a #GdkPixbuf, and
1240  * @callback will be called.
1241  *
1242  * The @pixbuf parameter to @callback will contain the resulting
1243  * #GdkPixbuf if the request succeeded, or %NULL if it failed. This
1244  * could happen for various reasons, in particular if the clipboard
1245  * was empty or if the contents of the clipboard could not be
1246  * converted into an image.
1247  *
1248  * Since: 2.6
1249  **/
1250 void
gtk_clipboard_request_image(GtkClipboard * clipboard,GtkClipboardImageReceivedFunc callback,gpointer user_data)1251 gtk_clipboard_request_image (GtkClipboard                  *clipboard,
1252 			     GtkClipboardImageReceivedFunc  callback,
1253 			     gpointer                       user_data)
1254 {
1255   RequestImageInfo *info;
1256 
1257   g_return_if_fail (clipboard != NULL);
1258   g_return_if_fail (callback != NULL);
1259 
1260   info = g_new (RequestImageInfo, 1);
1261   info->callback = callback;
1262   info->user_data = user_data;
1263 
1264   gtk_clipboard_request_contents (clipboard,
1265 				  gdk_atom_intern_static_string ("image/png"),
1266 				  request_image_received_func,
1267 				  info);
1268 }
1269 
1270 static void
request_uris_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1271 request_uris_received_func (GtkClipboard     *clipboard,
1272 			    GtkSelectionData *selection_data,
1273 			    gpointer          data)
1274 {
1275   RequestURIInfo *info = data;
1276   gchar **uris;
1277 
1278   uris = gtk_selection_data_get_uris (selection_data);
1279   info->callback (clipboard, uris, info->user_data);
1280   g_strfreev (uris);
1281 
1282   g_slice_free (RequestURIInfo, info);
1283 }
1284 
1285 /**
1286  * gtk_clipboard_request_uris:
1287  * @clipboard: a #GtkClipboard
1288  * @callback: (scope async): a function to call when the URIs are received,
1289  *     or the retrieval fails. (It will always be called one way or the other.)
1290  * @user_data: user data to pass to @callback.
1291  *
1292  * Requests the contents of the clipboard as URIs. When the URIs are
1293  * later received @callback will be called.
1294  *
1295  * The @uris parameter to @callback will contain the resulting array of
1296  * URIs if the request succeeded, or %NULL if it failed. This could happen
1297  * for various reasons, in particular if the clipboard was empty or if the
1298  * contents of the clipboard could not be converted into URI form.
1299  *
1300  * Since: 2.14
1301  **/
1302 void
gtk_clipboard_request_uris(GtkClipboard * clipboard,GtkClipboardURIReceivedFunc callback,gpointer user_data)1303 gtk_clipboard_request_uris (GtkClipboard                *clipboard,
1304 			    GtkClipboardURIReceivedFunc  callback,
1305 			    gpointer                     user_data)
1306 {
1307   RequestURIInfo *info;
1308 
1309   g_return_if_fail (clipboard != NULL);
1310   g_return_if_fail (callback != NULL);
1311 
1312   info = g_slice_new (RequestURIInfo);
1313   info->callback = callback;
1314   info->user_data = user_data;
1315 
1316   gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("text/uri-list"),
1317 				  request_uris_received_func,
1318 				  info);
1319 }
1320 
1321 static void
request_targets_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1322 request_targets_received_func (GtkClipboard     *clipboard,
1323 			       GtkSelectionData *selection_data,
1324 			       gpointer          data)
1325 {
1326   RequestTargetsInfo *info = data;
1327   GdkAtom *targets = NULL;
1328   gint n_targets = 0;
1329 
1330   gtk_selection_data_get_targets (selection_data, &targets, &n_targets);
1331 
1332   info->callback (clipboard, targets, n_targets, info->user_data);
1333 
1334   g_free (info);
1335   g_free (targets);
1336 }
1337 
1338 /**
1339  * gtk_clipboard_request_targets:
1340  * @clipboard: a #GtkClipboard
1341  * @callback: (scope async): a function to call when the targets are
1342  *     received, or the retrieval fails. (It will always be called
1343  *     one way or the other.)
1344  * @user_data: user data to pass to @callback.
1345  *
1346  * Requests the contents of the clipboard as list of supported targets.
1347  * When the list is later received, @callback will be called.
1348  *
1349  * The @targets parameter to @callback will contain the resulting targets if
1350  * the request succeeded, or %NULL if it failed.
1351  *
1352  * Since: 2.4
1353  **/
1354 void
gtk_clipboard_request_targets(GtkClipboard * clipboard,GtkClipboardTargetsReceivedFunc callback,gpointer user_data)1355 gtk_clipboard_request_targets (GtkClipboard                *clipboard,
1356 			       GtkClipboardTargetsReceivedFunc callback,
1357 			       gpointer                     user_data)
1358 {
1359   RequestTargetsInfo *info;
1360 
1361   g_return_if_fail (clipboard != NULL);
1362   g_return_if_fail (callback != NULL);
1363 
1364   /* If the display supports change notification we cache targets */
1365   if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)) &&
1366       clipboard->n_cached_targets != -1)
1367     {
1368       (* callback) (clipboard, clipboard->cached_targets, clipboard->n_cached_targets, user_data);
1369       return;
1370     }
1371 
1372   info = g_new (RequestTargetsInfo, 1);
1373   info->callback = callback;
1374   info->user_data = user_data;
1375 
1376   gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"),
1377 				  request_targets_received_func,
1378 				  info);
1379 }
1380 
1381 typedef struct
1382 {
1383   GMainLoop *loop;
1384   gpointer data;
1385   GdkAtom format; /* used by rich text */
1386   gsize length; /* used by rich text */
1387 } WaitResults;
1388 
1389 static void
clipboard_received_func(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)1390 clipboard_received_func (GtkClipboard     *clipboard,
1391 			 GtkSelectionData *selection_data,
1392 			 gpointer          data)
1393 {
1394   WaitResults *results = data;
1395 
1396   if (gtk_selection_data_get_length (selection_data) >= 0)
1397     results->data = gtk_selection_data_copy (selection_data);
1398 
1399   g_main_loop_quit (results->loop);
1400 }
1401 
1402 /**
1403  * gtk_clipboard_wait_for_contents:
1404  * @clipboard: a #GtkClipboard
1405  * @target: an atom representing the form into which the clipboard
1406  *          owner should convert the selection.
1407  *
1408  * Requests the contents of the clipboard using the given target.
1409  * This function waits for the data to be received using the main
1410  * loop, so events, timeouts, etc, may be dispatched during the wait.
1411  *
1412  * Returns: (nullable): a newly-allocated #GtkSelectionData object or %NULL
1413  *               if retrieving the given target failed. If non-%NULL,
1414  *               this value must be freed with gtk_selection_data_free()
1415  *               when you are finished with it.
1416  **/
1417 GtkSelectionData *
gtk_clipboard_wait_for_contents(GtkClipboard * clipboard,GdkAtom target)1418 gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
1419 				 GdkAtom       target)
1420 {
1421   WaitResults results;
1422 
1423   g_return_val_if_fail (clipboard != NULL, NULL);
1424   g_return_val_if_fail (target != GDK_NONE, NULL);
1425 
1426   results.data = NULL;
1427   results.loop = g_main_loop_new (NULL, TRUE);
1428 
1429   gtk_clipboard_request_contents (clipboard, target,
1430 				  clipboard_received_func,
1431 				  &results);
1432 
1433   if (g_main_loop_is_running (results.loop))
1434     {
1435       gdk_threads_leave ();
1436       g_main_loop_run (results.loop);
1437       gdk_threads_enter ();
1438     }
1439 
1440   g_main_loop_unref (results.loop);
1441 
1442   return results.data;
1443 }
1444 
1445 static void
clipboard_text_received_func(GtkClipboard * clipboard,const gchar * text,gpointer data)1446 clipboard_text_received_func (GtkClipboard *clipboard,
1447 			      const gchar  *text,
1448 			      gpointer      data)
1449 {
1450   WaitResults *results = data;
1451 
1452   results->data = g_strdup (text);
1453   g_main_loop_quit (results->loop);
1454 }
1455 
1456 /**
1457  * gtk_clipboard_wait_for_text:
1458  * @clipboard: a #GtkClipboard
1459  *
1460  * Requests the contents of the clipboard as text and converts
1461  * the result to UTF-8 if necessary. This function waits for
1462  * the data to be received using the main loop, so events,
1463  * timeouts, etc, may be dispatched during the wait.
1464  *
1465  * Returns: (nullable): a newly-allocated UTF-8 string which must
1466  *               be freed with g_free(), or %NULL if retrieving
1467  *               the selection data failed. (This could happen
1468  *               for various reasons, in particular if the
1469  *               clipboard was empty or if the contents of the
1470  *               clipboard could not be converted into text form.)
1471  **/
1472 gchar *
gtk_clipboard_wait_for_text(GtkClipboard * clipboard)1473 gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
1474 {
1475   WaitResults results;
1476 
1477   g_return_val_if_fail (clipboard != NULL, NULL);
1478 
1479   results.data = NULL;
1480   results.loop = g_main_loop_new (NULL, TRUE);
1481 
1482   gtk_clipboard_request_text (clipboard,
1483 			      clipboard_text_received_func,
1484 			      &results);
1485 
1486   if (g_main_loop_is_running (results.loop))
1487     {
1488       gdk_threads_leave ();
1489       g_main_loop_run (results.loop);
1490       gdk_threads_enter ();
1491     }
1492 
1493   g_main_loop_unref (results.loop);
1494 
1495   return results.data;
1496 }
1497 
1498 static void
clipboard_rich_text_received_func(GtkClipboard * clipboard,GdkAtom format,const guint8 * text,gsize length,gpointer data)1499 clipboard_rich_text_received_func (GtkClipboard *clipboard,
1500                                    GdkAtom       format,
1501                                    const guint8 *text,
1502                                    gsize         length,
1503                                    gpointer      data)
1504 {
1505   WaitResults *results = data;
1506 
1507   results->data = g_memdup (text, length);
1508   results->format = format;
1509   results->length = length;
1510   g_main_loop_quit (results->loop);
1511 }
1512 
1513 /**
1514  * gtk_clipboard_wait_for_rich_text:
1515  * @clipboard: a #GtkClipboard
1516  * @buffer: a #GtkTextBuffer
1517  * @format: (out): return location for the format of the returned data
1518  * @length: (out): return location for the length of the returned data
1519  *
1520  * Requests the contents of the clipboard as rich text.  This function
1521  * waits for the data to be received using the main loop, so events,
1522  * timeouts, etc, may be dispatched during the wait.
1523  *
1524  * Returns: (nullable) (array length=length) (transfer full): a
1525  *               newly-allocated binary block of data which must be
1526  *               freed with g_free(), or %NULL if retrieving the
1527  *               selection data failed. (This could happen for various
1528  *               reasons, in particular if the clipboard was empty or
1529  *               if the contents of the clipboard could not be
1530  *               converted into text form.)
1531  *
1532  * Since: 2.10
1533  **/
1534 guint8 *
gtk_clipboard_wait_for_rich_text(GtkClipboard * clipboard,GtkTextBuffer * buffer,GdkAtom * format,gsize * length)1535 gtk_clipboard_wait_for_rich_text (GtkClipboard  *clipboard,
1536                                   GtkTextBuffer *buffer,
1537                                   GdkAtom       *format,
1538                                   gsize         *length)
1539 {
1540   WaitResults results;
1541 
1542   g_return_val_if_fail (clipboard != NULL, NULL);
1543   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1544   g_return_val_if_fail (format != NULL, NULL);
1545   g_return_val_if_fail (length != NULL, NULL);
1546 
1547   results.data = NULL;
1548   results.loop = g_main_loop_new (NULL, TRUE);
1549 
1550   gtk_clipboard_request_rich_text (clipboard, buffer,
1551                                    clipboard_rich_text_received_func,
1552                                    &results);
1553 
1554   if (g_main_loop_is_running (results.loop))
1555     {
1556       gdk_threads_leave ();
1557       g_main_loop_run (results.loop);
1558       gdk_threads_enter ();
1559     }
1560 
1561   g_main_loop_unref (results.loop);
1562 
1563   *format = results.format;
1564   *length = results.length;
1565 
1566   return results.data;
1567 }
1568 
1569 static void
clipboard_image_received_func(GtkClipboard * clipboard,GdkPixbuf * pixbuf,gpointer data)1570 clipboard_image_received_func (GtkClipboard *clipboard,
1571 			       GdkPixbuf    *pixbuf,
1572 			       gpointer      data)
1573 {
1574   WaitResults *results = data;
1575 
1576   if (pixbuf)
1577     results->data = g_object_ref (pixbuf);
1578 
1579   g_main_loop_quit (results->loop);
1580 }
1581 
1582 /**
1583  * gtk_clipboard_wait_for_image:
1584  * @clipboard: a #GtkClipboard
1585  *
1586  * Requests the contents of the clipboard as image and converts
1587  * the result to a #GdkPixbuf. This function waits for
1588  * the data to be received using the main loop, so events,
1589  * timeouts, etc, may be dispatched during the wait.
1590  *
1591  * Returns: (nullable) (transfer full): a newly-allocated #GdkPixbuf
1592  *     object which must be disposed with g_object_unref(), or
1593  *     %NULL if retrieving the selection data failed. (This could
1594  *     happen for various reasons, in particular if the clipboard
1595  *     was empty or if the contents of the clipboard could not be
1596  *     converted into an image.)
1597  *
1598  * Since: 2.6
1599  **/
1600 GdkPixbuf *
gtk_clipboard_wait_for_image(GtkClipboard * clipboard)1601 gtk_clipboard_wait_for_image (GtkClipboard *clipboard)
1602 {
1603   WaitResults results;
1604 
1605   g_return_val_if_fail (clipboard != NULL, NULL);
1606 
1607   results.data = NULL;
1608   results.loop = g_main_loop_new (NULL, TRUE);
1609 
1610   gtk_clipboard_request_image (clipboard,
1611 			       clipboard_image_received_func,
1612 			       &results);
1613 
1614   if (g_main_loop_is_running (results.loop))
1615     {
1616       gdk_threads_leave ();
1617       g_main_loop_run (results.loop);
1618       gdk_threads_enter ();
1619     }
1620 
1621   g_main_loop_unref (results.loop);
1622 
1623   return results.data;
1624 }
1625 
1626 static void
clipboard_uris_received_func(GtkClipboard * clipboard,gchar ** uris,gpointer data)1627 clipboard_uris_received_func (GtkClipboard *clipboard,
1628 			      gchar       **uris,
1629 			      gpointer      data)
1630 {
1631   WaitResults *results = data;
1632 
1633   results->data = g_strdupv (uris);
1634   g_main_loop_quit (results->loop);
1635 }
1636 
1637 /**
1638  * gtk_clipboard_wait_for_uris:
1639  * @clipboard: a #GtkClipboard
1640  *
1641  * Requests the contents of the clipboard as URIs. This function waits
1642  * for the data to be received using the main loop, so events,
1643  * timeouts, etc, may be dispatched during the wait.
1644  *
1645  * Returns: (nullable) (array zero-terminated=1) (element-type utf8) (transfer full):
1646  *     a newly-allocated %NULL-terminated array of strings which must
1647  *     be freed with g_strfreev(), or %NULL if retrieving the
1648  *     selection data failed. (This could happen for various reasons,
1649  *     in particular if the clipboard was empty or if the contents of
1650  *     the clipboard could not be converted into URI form.)
1651  *
1652  * Since: 2.14
1653  **/
1654 gchar **
gtk_clipboard_wait_for_uris(GtkClipboard * clipboard)1655 gtk_clipboard_wait_for_uris (GtkClipboard *clipboard)
1656 {
1657   WaitResults results;
1658 
1659   g_return_val_if_fail (clipboard != NULL, NULL);
1660 
1661   results.data = NULL;
1662   results.loop = g_main_loop_new (NULL, TRUE);
1663 
1664   gtk_clipboard_request_uris (clipboard,
1665 			      clipboard_uris_received_func,
1666 			      &results);
1667 
1668   if (g_main_loop_is_running (results.loop))
1669     {
1670       gdk_threads_leave ();
1671       g_main_loop_run (results.loop);
1672       gdk_threads_enter ();
1673     }
1674 
1675   g_main_loop_unref (results.loop);
1676 
1677   return results.data;
1678 }
1679 
1680 /**
1681  * gtk_clipboard_get_display:
1682  * @clipboard: a #GtkClipboard
1683  *
1684  * Gets the #GdkDisplay associated with @clipboard
1685  *
1686  * Returns: (transfer none): the #GdkDisplay associated with @clipboard
1687  *
1688  * Since: 2.2
1689  **/
1690 GdkDisplay *
gtk_clipboard_get_display(GtkClipboard * clipboard)1691 gtk_clipboard_get_display (GtkClipboard *clipboard)
1692 {
1693   g_return_val_if_fail (clipboard != NULL, NULL);
1694 
1695   return clipboard->display;
1696 }
1697 
1698 /**
1699  * gtk_clipboard_wait_is_text_available:
1700  * @clipboard: a #GtkClipboard
1701  *
1702  * Test to see if there is text available to be pasted
1703  * This is done by requesting the TARGETS atom and checking
1704  * if it contains any of the supported text targets. This function
1705  * waits for the data to be received using the main loop, so events,
1706  * timeouts, etc, may be dispatched during the wait.
1707  *
1708  * This function is a little faster than calling
1709  * gtk_clipboard_wait_for_text() since it doesn’t need to retrieve
1710  * the actual text.
1711  *
1712  * Returns: %TRUE is there is text available, %FALSE otherwise.
1713  **/
1714 gboolean
gtk_clipboard_wait_is_text_available(GtkClipboard * clipboard)1715 gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
1716 {
1717   GtkSelectionData *data;
1718   gboolean result = FALSE;
1719 
1720   data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"));
1721   if (data)
1722     {
1723       result = gtk_selection_data_targets_include_text (data);
1724       gtk_selection_data_free (data);
1725     }
1726 
1727   return result;
1728 }
1729 
1730 /**
1731  * gtk_clipboard_wait_is_rich_text_available:
1732  * @clipboard: a #GtkClipboard
1733  * @buffer: a #GtkTextBuffer
1734  *
1735  * Test to see if there is rich text available to be pasted
1736  * This is done by requesting the TARGETS atom and checking
1737  * if it contains any of the supported rich text targets. This function
1738  * waits for the data to be received using the main loop, so events,
1739  * timeouts, etc, may be dispatched during the wait.
1740  *
1741  * This function is a little faster than calling
1742  * gtk_clipboard_wait_for_rich_text() since it doesn’t need to retrieve
1743  * the actual text.
1744  *
1745  * Returns: %TRUE is there is rich text available, %FALSE otherwise.
1746  *
1747  * Since: 2.10
1748  **/
1749 gboolean
gtk_clipboard_wait_is_rich_text_available(GtkClipboard * clipboard,GtkTextBuffer * buffer)1750 gtk_clipboard_wait_is_rich_text_available (GtkClipboard  *clipboard,
1751                                            GtkTextBuffer *buffer)
1752 {
1753   GtkSelectionData *data;
1754   gboolean result = FALSE;
1755 
1756   g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
1757   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1758 
1759   data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"));
1760   if (data)
1761     {
1762       result = gtk_selection_data_targets_include_rich_text (data, buffer);
1763       gtk_selection_data_free (data);
1764     }
1765 
1766   return result;
1767 }
1768 
1769 /**
1770  * gtk_clipboard_wait_is_image_available:
1771  * @clipboard: a #GtkClipboard
1772  *
1773  * Test to see if there is an image available to be pasted
1774  * This is done by requesting the TARGETS atom and checking
1775  * if it contains any of the supported image targets. This function
1776  * waits for the data to be received using the main loop, so events,
1777  * timeouts, etc, may be dispatched during the wait.
1778  *
1779  * This function is a little faster than calling
1780  * gtk_clipboard_wait_for_image() since it doesn’t need to retrieve
1781  * the actual image data.
1782  *
1783  * Returns: %TRUE is there is an image available, %FALSE otherwise.
1784  *
1785  * Since: 2.6
1786  **/
1787 gboolean
gtk_clipboard_wait_is_image_available(GtkClipboard * clipboard)1788 gtk_clipboard_wait_is_image_available (GtkClipboard *clipboard)
1789 {
1790   GtkSelectionData *data;
1791   gboolean result = FALSE;
1792 
1793   data = gtk_clipboard_wait_for_contents (clipboard,
1794 					  gdk_atom_intern_static_string ("TARGETS"));
1795   if (data)
1796     {
1797       result = gtk_selection_data_targets_include_image (data, FALSE);
1798       gtk_selection_data_free (data);
1799     }
1800 
1801   return result;
1802 }
1803 
1804 /**
1805  * gtk_clipboard_wait_is_uris_available:
1806  * @clipboard: a #GtkClipboard
1807  *
1808  * Test to see if there is a list of URIs available to be pasted
1809  * This is done by requesting the TARGETS atom and checking
1810  * if it contains the URI targets. This function
1811  * waits for the data to be received using the main loop, so events,
1812  * timeouts, etc, may be dispatched during the wait.
1813  *
1814  * This function is a little faster than calling
1815  * gtk_clipboard_wait_for_uris() since it doesn’t need to retrieve
1816  * the actual URI data.
1817  *
1818  * Returns: %TRUE is there is an URI list available, %FALSE otherwise.
1819  *
1820  * Since: 2.14
1821  **/
1822 gboolean
gtk_clipboard_wait_is_uris_available(GtkClipboard * clipboard)1823 gtk_clipboard_wait_is_uris_available (GtkClipboard *clipboard)
1824 {
1825   GtkSelectionData *data;
1826   gboolean result = FALSE;
1827 
1828   data = gtk_clipboard_wait_for_contents (clipboard,
1829 					  gdk_atom_intern_static_string ("TARGETS"));
1830   if (data)
1831     {
1832       result = gtk_selection_data_targets_include_uri (data);
1833       gtk_selection_data_free (data);
1834     }
1835 
1836   return result;
1837 }
1838 
1839 /**
1840  * gtk_clipboard_wait_for_targets:
1841  * @clipboard: a #GtkClipboard
1842  * @targets: (out) (array length=n_targets) (transfer container): location
1843  *           to store an array of targets. The result stored here must
1844  *           be freed with g_free().
1845  * @n_targets: (out): location to store number of items in @targets.
1846  *
1847  * Returns a list of targets that are present on the clipboard, or %NULL
1848  * if there aren’t any targets available. The returned list must be
1849  * freed with g_free().
1850  * This function waits for the data to be received using the main
1851  * loop, so events, timeouts, etc, may be dispatched during the wait.
1852  *
1853  * Returns: %TRUE if any targets are present on the clipboard,
1854  *               otherwise %FALSE.
1855  *
1856  * Since: 2.4
1857  */
1858 gboolean
gtk_clipboard_wait_for_targets(GtkClipboard * clipboard,GdkAtom ** targets,gint * n_targets)1859 gtk_clipboard_wait_for_targets (GtkClipboard  *clipboard,
1860 				GdkAtom      **targets,
1861 				gint          *n_targets)
1862 {
1863   GtkSelectionData *data;
1864   gboolean result = FALSE;
1865 
1866   g_return_val_if_fail (clipboard != NULL, FALSE);
1867 
1868   /* If the display supports change notification we cache targets */
1869   if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)) &&
1870       clipboard->n_cached_targets != -1)
1871     {
1872       if (n_targets)
1873  	*n_targets = clipboard->n_cached_targets;
1874 
1875       if (targets)
1876  	*targets = g_memdup (clipboard->cached_targets,
1877  			     clipboard->n_cached_targets * sizeof (GdkAtom));
1878 
1879        return TRUE;
1880     }
1881 
1882   if (n_targets)
1883     *n_targets = 0;
1884 
1885   if (targets)
1886     *targets = NULL;
1887 
1888   data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"));
1889 
1890   if (data)
1891     {
1892       GdkAtom *tmp_targets;
1893       gint tmp_n_targets;
1894 
1895       result = gtk_selection_data_get_targets (data, &tmp_targets, &tmp_n_targets);
1896 
1897       if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)))
1898  	{
1899  	  clipboard->n_cached_targets = tmp_n_targets;
1900  	  clipboard->cached_targets = g_memdup (tmp_targets,
1901  						tmp_n_targets * sizeof (GdkAtom));
1902  	}
1903 
1904       if (n_targets)
1905  	*n_targets = tmp_n_targets;
1906 
1907       if (targets)
1908  	*targets = tmp_targets;
1909       else
1910  	g_free (tmp_targets);
1911 
1912       gtk_selection_data_free (data);
1913     }
1914 
1915   return result;
1916 }
1917 
1918 static GtkClipboard *
clipboard_peek(GdkDisplay * display,GdkAtom selection,gboolean only_if_exists)1919 clipboard_peek (GdkDisplay *display,
1920 		GdkAtom     selection,
1921 		gboolean    only_if_exists)
1922 {
1923   GtkClipboard *clipboard = NULL;
1924   GSList *clipboards;
1925   GSList *tmp_list;
1926 
1927   if (selection == GDK_NONE)
1928     selection = GDK_SELECTION_CLIPBOARD;
1929 
1930   clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
1931 
1932   tmp_list = clipboards;
1933   while (tmp_list)
1934     {
1935       clipboard = tmp_list->data;
1936       if (clipboard->selection == selection)
1937 	break;
1938 
1939       tmp_list = tmp_list->next;
1940     }
1941 
1942   if (!tmp_list && !only_if_exists)
1943     {
1944       clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
1945 
1946       clipboard->selection = selection;
1947       clipboard->display = display;
1948       clipboard->n_cached_targets = -1;
1949       clipboard->n_storable_targets = -1;
1950       clipboards = g_slist_prepend (clipboards, clipboard);
1951       g_object_set_data (G_OBJECT (display), I_("gtk-clipboard-list"), clipboards);
1952       g_signal_connect (display, "closed",
1953 			G_CALLBACK (clipboard_display_closed), clipboard);
1954       gdk_display_request_selection_notification (display, selection);
1955     }
1956 
1957   return clipboard;
1958 }
1959 
1960 static void
gtk_clipboard_owner_change(GtkClipboard * clipboard,GdkEventOwnerChange * event)1961 gtk_clipboard_owner_change (GtkClipboard        *clipboard,
1962 			    GdkEventOwnerChange *event)
1963 {
1964   if (clipboard->n_cached_targets != -1)
1965     {
1966       g_free (clipboard->cached_targets);
1967       clipboard->cached_targets = NULL;
1968       clipboard->n_cached_targets = -1;
1969     }
1970 }
1971 
1972 /**
1973  * gtk_clipboard_wait_is_target_available:
1974  * @clipboard: a #GtkClipboard
1975  * @target:    A #GdkAtom indicating which target to look for.
1976  *
1977  * Checks if a clipboard supports pasting data of a given type. This
1978  * function can be used to determine if a “Paste” menu item should be
1979  * insensitive or not.
1980  *
1981  * If you want to see if there’s text available on the clipboard, use
1982  * gtk_clipboard_wait_is_text_available () instead.
1983  *
1984  * Returns: %TRUE if the target is available, %FALSE otherwise.
1985  *
1986  * Since: 2.6
1987  */
1988 gboolean
gtk_clipboard_wait_is_target_available(GtkClipboard * clipboard,GdkAtom target)1989 gtk_clipboard_wait_is_target_available (GtkClipboard *clipboard,
1990 					GdkAtom       target)
1991 {
1992   GdkAtom *targets;
1993   gint i, n_targets;
1994   gboolean retval = FALSE;
1995 
1996   if (!gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets))
1997     return FALSE;
1998 
1999   for (i = 0; i < n_targets; i++)
2000     {
2001       if (targets[i] == target)
2002 	{
2003 	  retval = TRUE;
2004 	  break;
2005 	}
2006     }
2007 
2008   g_free (targets);
2009 
2010   return retval;
2011 }
2012 
2013 /**
2014  * _gtk_clipboard_handle_event:
2015  * @event: a owner change event
2016  *
2017  * Emits the #GtkClipboard::owner-change signal on the appropriate @clipboard.
2018  *
2019  * Since: 2.6
2020  **/
2021 void
_gtk_clipboard_handle_event(GdkEventOwnerChange * event)2022 _gtk_clipboard_handle_event (GdkEventOwnerChange *event)
2023 {
2024   GdkDisplay *display;
2025   GtkClipboard *clipboard;
2026 
2027   display = gdk_window_get_display (event->window);
2028   clipboard = clipboard_peek (display, event->selection, TRUE);
2029 
2030   if (clipboard)
2031     g_signal_emit (clipboard,
2032 		   clipboard_signals[OWNER_CHANGE], 0, event, NULL);
2033 }
2034 
2035 static gboolean
gtk_clipboard_store_timeout(GtkClipboard * clipboard)2036 gtk_clipboard_store_timeout (GtkClipboard *clipboard)
2037 {
2038   g_main_loop_quit (clipboard->store_loop);
2039   clipboard->store_timeout = 0;
2040 
2041   return G_SOURCE_REMOVE;
2042 }
2043 
2044 /**
2045  * gtk_clipboard_set_can_store:
2046  * @clipboard: a #GtkClipboard
2047  * @targets: (allow-none) (array length=n_targets): array containing
2048  *           information about which forms should be stored or %NULL
2049  *           to indicate that all forms should be stored.
2050  * @n_targets: number of elements in @targets
2051  *
2052  * Hints that the clipboard data should be stored somewhere when the
2053  * application exits or when gtk_clipboard_store () is called.
2054  *
2055  * This value is reset when the clipboard owner changes.
2056  * Where the clipboard data is stored is platform dependent,
2057  * see gdk_display_store_clipboard () for more information.
2058  *
2059  * Since: 2.6
2060  */
2061 void
gtk_clipboard_set_can_store(GtkClipboard * clipboard,const GtkTargetEntry * targets,gint n_targets)2062 gtk_clipboard_set_can_store (GtkClipboard         *clipboard,
2063  			     const GtkTargetEntry *targets,
2064  			     gint                  n_targets)
2065 {
2066   g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
2067   g_return_if_fail (n_targets >= 0);
2068 
2069   GTK_CLIPBOARD_GET_CLASS (clipboard)->set_can_store (clipboard,
2070                                                       targets,
2071                                                       n_targets);
2072 }
2073 
2074 static void
gtk_clipboard_real_set_can_store(GtkClipboard * clipboard,const GtkTargetEntry * targets,gint n_targets)2075 gtk_clipboard_real_set_can_store (GtkClipboard         *clipboard,
2076                                   const GtkTargetEntry *targets,
2077                                   gint                  n_targets)
2078 {
2079   GtkWidget *clipboard_widget;
2080   int i;
2081   static const GtkTargetEntry save_targets[] = {
2082     { "SAVE_TARGETS", 0, TARGET_SAVE_TARGETS }
2083   };
2084 
2085   if (clipboard->selection != GDK_SELECTION_CLIPBOARD)
2086     return;
2087 
2088   g_free (clipboard->storable_targets);
2089 
2090   clipboard_widget = get_clipboard_widget (clipboard->display);
2091 
2092   /* n_storable_targets being -1 means that
2093    * gtk_clipboard_set_can_store hasn't been called since the
2094    * clipboard owner changed. We only want to add SAVE_TARGETS and
2095    * ref the owner once , so we do that here
2096    */
2097   if (clipboard->n_storable_targets == -1)
2098     {
2099       gtk_selection_add_targets (clipboard_widget, clipboard->selection,
2100 				 save_targets, 1);
2101 
2102       /* Ref the owner so it won't go away */
2103       if (clipboard->have_owner)
2104 	g_object_ref (clipboard->user_data);
2105     }
2106 
2107   clipboard->n_storable_targets = n_targets;
2108   clipboard->storable_targets = g_new (GdkAtom, n_targets);
2109   for (i = 0; i < n_targets; i++)
2110     clipboard->storable_targets[i] = gdk_atom_intern (targets[i].target, FALSE);
2111 }
2112 
2113 static gboolean
gtk_clipboard_selection_notify(GtkWidget * widget,GdkEventSelection * event,GtkClipboard * clipboard)2114 gtk_clipboard_selection_notify (GtkWidget         *widget,
2115 				GdkEventSelection *event,
2116 				GtkClipboard      *clipboard)
2117 {
2118   if (event->selection == gdk_atom_intern_static_string ("CLIPBOARD_MANAGER") &&
2119       clipboard->storing_selection)
2120     g_main_loop_quit (clipboard->store_loop);
2121 
2122   return FALSE;
2123 }
2124 
2125 /**
2126  * gtk_clipboard_store:
2127  * @clipboard: a #GtkClipboard
2128  *
2129  * Stores the current clipboard data somewhere so that it will stay
2130  * around after the application has quit.
2131  *
2132  * Since: 2.6
2133  */
2134 void
gtk_clipboard_store(GtkClipboard * clipboard)2135 gtk_clipboard_store (GtkClipboard *clipboard)
2136 {
2137   g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
2138 
2139   GTK_CLIPBOARD_GET_CLASS (clipboard)->store (clipboard);
2140 }
2141 
2142 static void
gtk_clipboard_real_store(GtkClipboard * clipboard)2143 gtk_clipboard_real_store (GtkClipboard *clipboard)
2144 {
2145   GtkWidget *clipboard_widget;
2146 
2147   if (clipboard->n_storable_targets < 0)
2148     return;
2149 
2150   if (!gdk_display_supports_clipboard_persistence (clipboard->display))
2151     return;
2152 
2153   g_object_ref (clipboard);
2154 
2155   clipboard_widget = get_clipboard_widget (clipboard->display);
2156   clipboard->notify_signal_id = g_signal_connect (clipboard_widget,
2157 						  "selection-notify-event",
2158 						  G_CALLBACK (gtk_clipboard_selection_notify),
2159 						  clipboard);
2160 
2161   gdk_display_store_clipboard (clipboard->display,
2162                                gtk_widget_get_window (clipboard_widget),
2163 			       clipboard_get_timestamp (clipboard),
2164 			       clipboard->storable_targets,
2165 			       clipboard->n_storable_targets);
2166 
2167   clipboard->storing_selection = TRUE;
2168 
2169   clipboard->store_loop = g_main_loop_new (NULL, TRUE);
2170   clipboard->store_timeout = g_timeout_add_seconds (10, (GSourceFunc) gtk_clipboard_store_timeout, clipboard);
2171   g_source_set_name_by_id (clipboard->store_timeout, "[gtk+] gtk_clipboard_store_timeout");
2172 
2173   if (g_main_loop_is_running (clipboard->store_loop))
2174     {
2175       gdk_threads_leave ();
2176       g_main_loop_run (clipboard->store_loop);
2177       gdk_threads_enter ();
2178     }
2179 
2180   g_main_loop_unref (clipboard->store_loop);
2181   clipboard->store_loop = NULL;
2182 
2183   if (clipboard->store_timeout != 0)
2184     {
2185       g_source_remove (clipboard->store_timeout);
2186       clipboard->store_timeout = 0;
2187     }
2188 
2189   g_signal_handler_disconnect (clipboard_widget, clipboard->notify_signal_id);
2190   clipboard->notify_signal_id = 0;
2191 
2192   clipboard->storing_selection = FALSE;
2193 
2194   g_object_unref (clipboard);
2195 }
2196 
2197 /* Stores all clipboard selections on all displays, called from
2198  * gtk_main_quit ().
2199  */
2200 void
_gtk_clipboard_store_all(void)2201 _gtk_clipboard_store_all (void)
2202 {
2203   GtkClipboard *clipboard;
2204   GSList *displays, *list;
2205 
2206   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
2207 
2208   list = displays;
2209   while (list)
2210     {
2211       GdkDisplay *display = list->data;
2212 
2213       clipboard = clipboard_peek (display, GDK_SELECTION_CLIPBOARD, TRUE);
2214 
2215       if (clipboard)
2216 	gtk_clipboard_store (clipboard);
2217 
2218       list = list->next;
2219     }
2220   g_slist_free (displays);
2221 
2222 }
2223 
2224 /**
2225  * gtk_clipboard_get_selection:
2226  * @clipboard: a #GtkClipboard
2227  *
2228  * Gets the selection that this clipboard is for.
2229  *
2230  * Returns: the selection
2231  *
2232  * Since: 3.22
2233  */
2234 GdkAtom
gtk_clipboard_get_selection(GtkClipboard * clipboard)2235 gtk_clipboard_get_selection (GtkClipboard *clipboard)
2236 {
2237   g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), GDK_NONE);
2238 
2239   return clipboard->selection;
2240 }
2241