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