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