]> Pileus Git - ~andy/gtk/blob - gtk/gtkclipboard.c
Intern type names in code generated by glib-mkenums, too.
[~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, g_intern_static_string ("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   for (i = 0; i < n_targets; i++)
769     g_free (targets[i].target);
770   g_free (targets);
771   gtk_target_list_unref (list);
772 }
773
774 static void 
775 pixbuf_get_func (GtkClipboard     *clipboard,
776                  GtkSelectionData *selection_data,
777                  guint             info,
778                  gpointer          data)
779 {
780   gtk_selection_data_set_pixbuf (selection_data, data);
781 }
782
783 static void 
784 pixbuf_clear_func (GtkClipboard *clipboard,
785                    gpointer      data)
786 {
787   g_object_unref (data);
788 }
789
790 /**
791  * gtk_clipboard_set_image:
792  * @clipboard: a #GtkClipboard object
793  * @pixbuf:    a #GdkPixbuf 
794  * 
795  * Sets the contents of the clipboard to the given #GdkPixbuf. 
796  * GTK+ will take responsibility for responding for requests 
797  * for the image, and for converting the image into the 
798  * requested format.
799  * 
800  * Since: 2.6
801  **/
802 void
803 gtk_clipboard_set_image (GtkClipboard *clipboard,
804                           GdkPixbuf    *pixbuf)
805 {
806   GtkTargetList *list;
807   GList *l;
808   GtkTargetEntry *targets;
809   gint n_targets, i;
810
811   g_return_if_fail (clipboard != NULL);
812   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
813
814   list = gtk_target_list_new (NULL, 0);
815   gtk_target_list_add_image_targets (list, 0, TRUE);
816
817   n_targets = g_list_length (list->list);
818   targets = g_new0 (GtkTargetEntry, n_targets);
819   for (l = list->list, i = 0; l; l = l->next, i++)
820     {
821       GtkTargetPair *pair = (GtkTargetPair *)l->data;
822       targets[i].target = gdk_atom_name (pair->target);
823     }
824
825   gtk_clipboard_set_with_data (clipboard, 
826                                targets, n_targets,
827                                pixbuf_get_func, pixbuf_clear_func,
828                                g_object_ref (pixbuf));
829   gtk_clipboard_set_can_store (clipboard, NULL, 0);
830
831   for (i = 0; i < n_targets; i++)
832     g_free (targets[i].target);
833   g_free (targets);
834   gtk_target_list_unref (list);
835 }
836
837 static void
838 set_request_contents_info (GtkWidget           *widget,
839                            RequestContentsInfo *info)
840 {
841   if (!request_contents_key_id)
842     request_contents_key_id = g_quark_from_static_string (request_contents_key);
843
844   g_object_set_qdata (G_OBJECT (widget), request_contents_key_id, info);
845 }
846
847 static RequestContentsInfo *
848 get_request_contents_info (GtkWidget *widget)
849 {
850   if (!request_contents_key_id)
851     return NULL;
852   else
853     return g_object_get_qdata (G_OBJECT (widget), request_contents_key_id);
854 }
855
856 static void 
857 selection_received (GtkWidget            *widget,
858                     GtkSelectionData     *selection_data,
859                     guint                 time)
860 {
861   RequestContentsInfo *request_info = get_request_contents_info (widget);
862   set_request_contents_info (widget, NULL);
863   
864   request_info->callback (gtk_widget_get_clipboard (widget, selection_data->selection), 
865                           selection_data,
866                           request_info->user_data);
867
868   g_free (request_info);
869
870   if (widget != get_clipboard_widget (gtk_widget_get_display (widget)))
871     gtk_widget_destroy (widget);
872 }
873
874 /**
875  * gtk_clipboard_request_contents:
876  * @clipboard: a #GtkClipboard
877  * @target:    an atom representing the form into which the clipboard
878  *             owner should convert the selection.
879  * @callback:  A function to call when the results are received
880  *             (or the retrieval fails). If the retrieval fails
881  *             the length field of @selection_data will be
882  *             negative.
883  * @user_data: user data to pass to @callback
884  * 
885  * Requests the contents of clipboard as the given target.
886  * When the results of the result are later received the supplied callback
887  * will be called.
888  **/
889 void 
890 gtk_clipboard_request_contents (GtkClipboard            *clipboard,
891                                 GdkAtom                  target,
892                                 GtkClipboardReceivedFunc callback,
893                                 gpointer                 user_data)
894 {
895   RequestContentsInfo *info;
896   GtkWidget *widget;
897   GtkWidget *clipboard_widget;
898
899   g_return_if_fail (clipboard != NULL);
900   g_return_if_fail (target != GDK_NONE);
901   g_return_if_fail (callback != NULL);
902   
903   clipboard_widget = get_clipboard_widget (clipboard->display);
904
905   if (get_request_contents_info (clipboard_widget))
906     widget = make_clipboard_widget (clipboard->display, FALSE);
907   else
908     widget = clipboard_widget;
909
910   info = g_new (RequestContentsInfo, 1);
911   info->callback = callback;
912   info->user_data = user_data;
913
914   set_request_contents_info (widget, info);
915
916   gtk_selection_convert (widget, clipboard->selection, target,
917                          clipboard_get_timestamp (clipboard));
918 }
919
920 static void 
921 request_text_received_func (GtkClipboard     *clipboard,
922                             GtkSelectionData *selection_data,
923                             gpointer          data)
924 {
925   RequestTextInfo *info = data;
926   gchar *result = NULL;
927
928   result = gtk_selection_data_get_text (selection_data);
929
930   if (!result)
931     {
932       /* If we asked for UTF8 and didn't get it, try compound_text;
933        * if we asked for compound_text and didn't get it, try string;
934        * If we asked for anything else and didn't get it, give up.
935        */
936       if (selection_data->target == gdk_atom_intern ("UTF8_STRING", FALSE))
937         {
938           gtk_clipboard_request_contents (clipboard,
939                                           gdk_atom_intern ("COMPOUND_TEXT", FALSE), 
940                                           request_text_received_func, info);
941           return;
942         }
943       else if (selection_data->target == gdk_atom_intern ("COMPOUND_TEXT", FALSE))
944         {
945           gtk_clipboard_request_contents (clipboard,
946                                           GDK_TARGET_STRING, 
947                                           request_text_received_func, info);
948           return;
949         }
950     }
951
952   info->callback (clipboard, result, info->user_data);
953   g_free (info);
954   g_free (result);
955 }
956
957 /**
958  * gtk_clipboard_request_text:
959  * @clipboard: a #GtkClipboard
960  * @callback:  a function to call when the text is received,
961  *             or the retrieval fails. (It will always be called
962  *             one way or the other.)
963  * @user_data: user data to pass to @callback.
964  * 
965  * Requests the contents of the clipboard as text. When the text is
966  * later received, it will be converted to UTF-8 if necessary, and
967  * @callback will be called. 
968  *
969  * The @text parameter to @callback will contain the resulting text if
970  * the request succeeded, or %NULL if it failed. This could happen for
971  * various reasons, in particular if the clipboard was empty or if the
972  * contents of the clipboard could not be converted into text form.
973  **/
974 void 
975 gtk_clipboard_request_text (GtkClipboard                *clipboard,
976                             GtkClipboardTextReceivedFunc callback,
977                             gpointer                     user_data)
978 {
979   RequestTextInfo *info;
980   
981   g_return_if_fail (clipboard != NULL);
982   g_return_if_fail (callback != NULL);
983   
984   info = g_new (RequestTextInfo, 1);
985   info->callback = callback;
986   info->user_data = user_data;
987
988   gtk_clipboard_request_contents (clipboard, gdk_atom_intern ("UTF8_STRING", FALSE),
989                                   request_text_received_func,
990                                   info);
991 }
992
993 static void 
994 request_image_received_func (GtkClipboard     *clipboard,
995                              GtkSelectionData *selection_data,
996                              gpointer          data)
997 {
998   RequestImageInfo *info = data;
999   GdkPixbuf *result = NULL;
1000
1001   result = gtk_selection_data_get_pixbuf (selection_data);
1002
1003   if (!result)
1004     {
1005       /* If we asked for image/png and didn't get it, try image/jpeg;
1006        * if we asked for image/jpeg and didn't get it, try image/gif;
1007        * if we asked for image/gif and didn't get it, try image/bmp;
1008        * If we asked for anything else and didn't get it, give up.
1009        */
1010       if (selection_data->target == gdk_atom_intern ("image/png", FALSE))
1011         {
1012           gtk_clipboard_request_contents (clipboard,
1013                                           gdk_atom_intern ("image/jpeg", FALSE), 
1014                                           request_image_received_func, info);
1015           return;
1016         }
1017       else if (selection_data->target == gdk_atom_intern ("image/jpeg", FALSE))
1018         {
1019           gtk_clipboard_request_contents (clipboard,
1020                                           gdk_atom_intern ("image/gif", FALSE), 
1021                                           request_image_received_func, info);
1022           return;
1023         }
1024       else if (selection_data->target == gdk_atom_intern ("image/gif", FALSE))
1025         {
1026           gtk_clipboard_request_contents (clipboard,
1027                                           gdk_atom_intern ("image/bmp", FALSE), 
1028                                           request_image_received_func, info);
1029           return;
1030         }
1031     }
1032
1033   info->callback (clipboard, result, info->user_data);
1034   g_free (info);
1035   g_object_unref (result);
1036 }
1037
1038 /**
1039  * gtk_clipboard_request_image:
1040  * @clipboard: a #GtkClipboard
1041  * @callback:  a function to call when the image is received,
1042  *             or the retrieval fails. (It will always be called
1043  *             one way or the other.)
1044  * @user_data: user data to pass to @callback.
1045  * 
1046  * Requests the contents of the clipboard as image. When the image is
1047  * later received, it will be converted to a #GdkPixbuf, and
1048  * @callback will be called. 
1049  *
1050  * The @pixbuf parameter to @callback will contain the resulting 
1051  * #GdkPixbuf if the request succeeded, or %NULL if it failed. This 
1052  * could happen for various reasons, in particular if the clipboard 
1053  * was empty or if the contents of the clipboard could not be 
1054  * converted into an image.
1055  *
1056  * Since: 2.6
1057  **/
1058 void 
1059 gtk_clipboard_request_image (GtkClipboard                  *clipboard,
1060                              GtkClipboardImageReceivedFunc  callback,
1061                              gpointer                       user_data)
1062 {
1063   RequestImageInfo *info;
1064   
1065   g_return_if_fail (clipboard != NULL);
1066   g_return_if_fail (callback != NULL);
1067   
1068   info = g_new (RequestImageInfo, 1);
1069   info->callback = callback;
1070   info->user_data = user_data;
1071
1072   gtk_clipboard_request_contents (clipboard, 
1073                                   gdk_atom_intern ("image/png", FALSE),
1074                                   request_image_received_func,
1075                                   info);
1076 }
1077
1078 static void 
1079 request_targets_received_func (GtkClipboard     *clipboard,
1080                                GtkSelectionData *selection_data,
1081                                gpointer          data)
1082 {
1083   RequestTargetsInfo *info = data;
1084   GdkAtom *targets = NULL;
1085   gint n_targets = 0;
1086
1087   gtk_selection_data_get_targets (selection_data, &targets, &n_targets);
1088
1089   info->callback (clipboard, targets, n_targets, info->user_data);
1090
1091   g_free (info);
1092   g_free (targets);
1093 }
1094
1095 /**
1096  * gtk_clipboard_request_targets:
1097  * @clipboard: a #GtkClipboard
1098  * @callback:  a function to call when the targets are received,
1099  *             or the retrieval fails. (It will always be called
1100  *             one way or the other.)
1101  * @user_data: user data to pass to @callback.
1102  * 
1103  * Requests the contents of the clipboard as list of supported targets. 
1104  * When the list is later received, @callback will be called. 
1105  *
1106  * The @targets parameter to @callback will contain the resulting targets if
1107  * the request succeeded, or %NULL if it failed.
1108  *
1109  * Since: 2.4
1110  **/
1111 void 
1112 gtk_clipboard_request_targets (GtkClipboard                *clipboard,
1113                                GtkClipboardTargetsReceivedFunc callback,
1114                                gpointer                     user_data)
1115 {
1116   RequestTargetsInfo *info;
1117   
1118   g_return_if_fail (clipboard != NULL);
1119   g_return_if_fail (callback != NULL);
1120
1121   /* If the display supports change notification we cache targets */
1122   if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)) &&
1123       clipboard->n_cached_targets != -1)
1124     {
1125       (* callback) (clipboard, clipboard->cached_targets, clipboard->n_cached_targets, user_data);
1126       return;
1127     }
1128   
1129   info = g_new (RequestTargetsInfo, 1);
1130   info->callback = callback;
1131   info->user_data = user_data;
1132
1133   gtk_clipboard_request_contents (clipboard, gdk_atom_intern ("TARGETS", FALSE),
1134                                   request_targets_received_func,
1135                                   info);
1136 }
1137
1138 typedef struct
1139 {
1140   GMainLoop *loop;
1141   gpointer data;
1142 } WaitResults;
1143
1144 static void 
1145 clipboard_received_func (GtkClipboard     *clipboard,
1146                          GtkSelectionData *selection_data,
1147                          gpointer          data)
1148 {
1149   WaitResults *results = data;
1150
1151   if (selection_data->length >= 0)
1152     results->data = gtk_selection_data_copy (selection_data);
1153   
1154   g_main_loop_quit (results->loop);
1155 }
1156
1157 /**
1158  * gtk_clipboard_wait_for_contents:
1159  * @clipboard: a #GtkClipboard
1160  * @target: an atom representing the form into which the clipboard
1161  *          owner should convert the selection.
1162  * 
1163  * Requests the contents of the clipboard using the given target.
1164  * This function waits for the data to be received using the main 
1165  * loop, so events, timeouts, etc, may be dispatched during the wait.
1166  * 
1167  * Return value: a newly-allocated #GtkSelectionData object or %NULL
1168  *               if retrieving the given target failed. If non-%NULL,
1169  *               this value must be freed with gtk_selection_data_free() 
1170  *               when you are finished with it.
1171  **/
1172 GtkSelectionData *
1173 gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
1174                                  GdkAtom       target)
1175 {
1176   WaitResults results;
1177
1178   g_return_val_if_fail (clipboard != NULL, NULL);
1179   g_return_val_if_fail (target != GDK_NONE, NULL);
1180   
1181   results.data = NULL;
1182   results.loop = g_main_loop_new (NULL, TRUE);
1183
1184   gtk_clipboard_request_contents (clipboard, target, 
1185                                   clipboard_received_func,
1186                                   &results);
1187
1188   if (g_main_loop_is_running (results.loop))
1189     {
1190       GDK_THREADS_LEAVE ();
1191       g_main_loop_run (results.loop);
1192       GDK_THREADS_ENTER ();
1193     }
1194
1195   g_main_loop_unref (results.loop);
1196
1197   return results.data;
1198 }
1199
1200 static void 
1201 clipboard_text_received_func (GtkClipboard *clipboard,
1202                               const gchar  *text,
1203                               gpointer      data)
1204 {
1205   WaitResults *results = data;
1206
1207   results->data = g_strdup (text);
1208   g_main_loop_quit (results->loop);
1209 }
1210
1211 /**
1212  * gtk_clipboard_wait_for_text:
1213  * @clipboard: a #GtkClipboard
1214  * 
1215  * Requests the contents of the clipboard as text and converts
1216  * the result to UTF-8 if necessary. This function waits for
1217  * the data to be received using the main loop, so events,
1218  * timeouts, etc, may be dispatched during the wait.
1219  * 
1220  * Return value: a newly-allocated UTF-8 string which must
1221  *               be freed with g_free(), or %NULL if retrieving
1222  *               the selection data failed. (This could happen
1223  *               for various reasons, in particular if the
1224  *               clipboard was empty or if the contents of the
1225  *               clipboard could not be converted into text form.)
1226  **/
1227 gchar *
1228 gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
1229 {
1230   WaitResults results;
1231
1232   g_return_val_if_fail (clipboard != NULL, NULL);
1233   
1234   results.data = NULL;
1235   results.loop = g_main_loop_new (NULL, TRUE);
1236
1237   gtk_clipboard_request_text (clipboard,
1238                               clipboard_text_received_func,
1239                               &results);
1240
1241   if (g_main_loop_is_running (results.loop))
1242     {
1243       GDK_THREADS_LEAVE ();
1244       g_main_loop_run (results.loop);
1245       GDK_THREADS_ENTER ();
1246     }
1247
1248   g_main_loop_unref (results.loop);
1249
1250   return results.data;
1251 }
1252
1253 static void 
1254 clipboard_image_received_func (GtkClipboard *clipboard,
1255                                GdkPixbuf    *pixbuf,
1256                                gpointer      data)
1257 {
1258   WaitResults *results = data;
1259
1260   if (pixbuf)
1261     results->data = g_object_ref (pixbuf);
1262
1263   g_main_loop_quit (results->loop);
1264 }
1265
1266 /**
1267  * gtk_clipboard_wait_for_image:
1268  * @clipboard: a #GtkClipboard
1269  * 
1270  * Requests the contents of the clipboard as image and converts
1271  * the result to a #GdkPixbuf. This function waits for
1272  * the data to be received using the main loop, so events,
1273  * timeouts, etc, may be dispatched during the wait.
1274  * 
1275  * Return value: a newly-allocated #GdkPixbuf object which must
1276  *               be disposed with g_object_unref(), or %NULL if 
1277  *               retrieving the selection data failed. (This 
1278  *               could happen for various reasons, in particular 
1279  *               if the clipboard was empty or if the contents of 
1280  *               the clipboard could not be converted into an image.)
1281  *
1282  * Since: 2.6
1283  **/
1284 GdkPixbuf *
1285 gtk_clipboard_wait_for_image (GtkClipboard *clipboard)
1286 {
1287   WaitResults results;
1288
1289   g_return_val_if_fail (clipboard != NULL, NULL);
1290   
1291   results.data = NULL;
1292   results.loop = g_main_loop_new (NULL, TRUE);
1293
1294   gtk_clipboard_request_image (clipboard,
1295                                clipboard_image_received_func,
1296                                &results);
1297
1298   if (g_main_loop_is_running (results.loop))
1299     {
1300       GDK_THREADS_LEAVE ();
1301       g_main_loop_run (results.loop);
1302       GDK_THREADS_ENTER ();
1303     }
1304
1305   g_main_loop_unref (results.loop);
1306
1307   return results.data;
1308 }
1309
1310 /**
1311  * gtk_clipboard_get_display:
1312  * @clipboard: a #GtkClipboard
1313  *
1314  * Gets the #GdkDisplay associated with @clipboard
1315  *
1316  * Return value: the #GdkDisplay associated with @clipboard
1317  *
1318  * Since: 2.2
1319  **/
1320 GdkDisplay *
1321 gtk_clipboard_get_display (GtkClipboard *clipboard)
1322 {
1323   g_return_val_if_fail (clipboard != NULL, NULL);
1324
1325   return clipboard->display;
1326 }
1327
1328 /**
1329  * gtk_clipboard_wait_is_text_available:
1330  * @clipboard: a #GtkClipboard
1331  * 
1332  * Test to see if there is text available to be pasted
1333  * This is done by requesting the TARGETS atom and checking
1334  * if it contains any of the supported text targets. This function 
1335  * waits for the data to be received using the main loop, so events, 
1336  * timeouts, etc, may be dispatched during the wait.
1337  *
1338  * This function is a little faster than calling
1339  * gtk_clipboard_wait_for_text() since it doesn't need to retrieve
1340  * the actual text.
1341  * 
1342  * Return value: %TRUE is there is text available, %FALSE otherwise.
1343  **/
1344 gboolean
1345 gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
1346 {
1347   GtkSelectionData *data;
1348   gboolean result = FALSE;
1349
1350   data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern ("TARGETS", FALSE));
1351   if (data)
1352     {
1353       result = gtk_selection_data_targets_include_text (data);
1354       gtk_selection_data_free (data);
1355     }
1356
1357   return result;
1358 }
1359
1360 /**
1361  * gtk_clipboard_wait_is_image_available:
1362  * @clipboard: a #GtkClipboard
1363  * 
1364  * Test to see if there is an image available to be pasted
1365  * This is done by requesting the TARGETS atom and checking
1366  * if it contains any of the supported image targets. This function 
1367  * waits for the data to be received using the main loop, so events, 
1368  * timeouts, etc, may be dispatched during the wait.
1369  *
1370  * This function is a little faster than calling
1371  * gtk_clipboard_wait_for_image() since it doesn't need to retrieve
1372  * the actual image data.
1373  * 
1374  * Return value: %TRUE is there is an image available, %FALSE otherwise.
1375  *
1376  * Since: 2.6
1377  **/
1378 gboolean
1379 gtk_clipboard_wait_is_image_available (GtkClipboard *clipboard)
1380 {
1381   GtkSelectionData *data;
1382   gboolean result = FALSE;
1383
1384   data = gtk_clipboard_wait_for_contents (clipboard, 
1385                                           gdk_atom_intern ("TARGETS", FALSE));
1386   if (data)
1387     {
1388       result = gtk_selection_data_targets_include_image (data, FALSE);
1389       gtk_selection_data_free (data);
1390     }
1391
1392   return result;
1393 }
1394
1395 /**
1396  * gtk_clipboard_wait_for_targets
1397  * @clipboard: a #GtkClipboard
1398  * @targets: location to store an array of targets. The result
1399  *           stored here must be freed with g_free().
1400  * @n_targets: location to store number of items in @targets.
1401  *
1402  * Returns a list of targets that are present on the clipboard, or %NULL
1403  * if there aren't any targets available. The returned list must be 
1404  * freed with g_free().
1405  * This function waits for the data to be received using the main 
1406  * loop, so events, timeouts, etc, may be dispatched during the wait.
1407  *
1408  * Return value: %TRUE if any targets are present on the clipboard,
1409  *               otherwise %FALSE.
1410  *
1411  * Since: 2.4
1412  */
1413 gboolean
1414 gtk_clipboard_wait_for_targets (GtkClipboard  *clipboard, 
1415                                 GdkAtom      **targets,
1416                                 gint          *n_targets)
1417 {
1418   GtkSelectionData *data;
1419   gboolean result = FALSE;
1420   
1421   g_return_val_if_fail (clipboard != NULL, FALSE);
1422
1423   /* If the display supports change notification we cache targets */
1424   if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)) &&
1425       clipboard->n_cached_targets != -1)
1426     {
1427       if (n_targets)
1428         *n_targets = clipboard->n_cached_targets;
1429  
1430       if (targets)
1431         *targets = g_memdup (clipboard->cached_targets,
1432                              clipboard->n_cached_targets * sizeof (GdkAtom));
1433
1434        return TRUE;
1435     }
1436   
1437   if (n_targets)
1438     *n_targets = 0;
1439       
1440   if (targets)
1441     *targets = NULL;      
1442
1443   data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern ("TARGETS", FALSE));
1444
1445   if (data)
1446     {
1447       GdkAtom *tmp_targets;
1448       gint tmp_n_targets;
1449        
1450       result = gtk_selection_data_get_targets (data, &tmp_targets, &tmp_n_targets);
1451  
1452       if (gdk_display_supports_selection_notification (gtk_clipboard_get_display (clipboard)))
1453         {
1454           clipboard->n_cached_targets = tmp_n_targets;
1455           clipboard->cached_targets = g_memdup (tmp_targets,
1456                                                 tmp_n_targets * sizeof (GdkAtom));
1457         }
1458  
1459       if (n_targets)
1460         *n_targets = tmp_n_targets;
1461  
1462       if (targets)
1463         *targets = tmp_targets;
1464       else
1465         g_free (tmp_targets);
1466       
1467       gtk_selection_data_free (data);
1468     }
1469
1470   return result;
1471 }
1472
1473 static GtkClipboard *
1474 clipboard_peek (GdkDisplay *display, 
1475                 GdkAtom     selection,
1476                 gboolean    only_if_exists)
1477 {
1478   GtkClipboard *clipboard = NULL;
1479   GSList *clipboards;
1480   GSList *tmp_list;
1481
1482   if (selection == GDK_NONE)
1483     selection = GDK_SELECTION_CLIPBOARD;
1484
1485   clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
1486
1487   tmp_list = clipboards;
1488   while (tmp_list)
1489     {
1490       clipboard = tmp_list->data;
1491       if (clipboard->selection == selection)
1492         break;
1493
1494       tmp_list = tmp_list->next;
1495     }
1496
1497   if (!tmp_list && !only_if_exists)
1498     {
1499       clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
1500       clipboard->selection = selection;
1501       clipboard->display = display;
1502       clipboard->n_cached_targets = -1;
1503       clipboard->n_storable_targets = -1;
1504       clipboards = g_slist_prepend (clipboards, clipboard);
1505       g_object_set_data (G_OBJECT (display), "gtk-clipboard-list", clipboards);
1506       g_signal_connect (display, "closed",
1507                         G_CALLBACK (clipboard_display_closed), clipboard);
1508       gdk_display_request_selection_notification (display, selection);
1509     }
1510   
1511   return clipboard;
1512 }
1513
1514 static void
1515 gtk_clipboard_owner_change (GtkClipboard        *clipboard,
1516                             GdkEventOwnerChange *event)
1517 {
1518   if (clipboard->n_cached_targets != -1)
1519     {
1520       clipboard->n_cached_targets = -1;
1521       g_free (clipboard->cached_targets);
1522     }
1523 }
1524
1525 /**
1526  * gtk_clipboard_wait_is_target_available:
1527  * @clipboard: a #GtkClipboard
1528  * @target:    A #GdkAtom indicating which target to look for.
1529  *
1530  * Checks if a clipboard supports pasting data of a given type. This
1531  * function can be used to determine if a "Paste" menu item should be
1532  * insensitive or not.
1533  *
1534  * If you want to see if there's text available on the clipboard, use
1535  * gtk_clipboard_wait_is_text_available () instead.
1536  *
1537  * Return value: %TRUE if the target is available, %FALSE otherwise.
1538  *
1539  * Since: 2.6
1540  */
1541 gboolean
1542 gtk_clipboard_wait_is_target_available (GtkClipboard *clipboard,
1543                                         GdkAtom       target)
1544 {
1545   GdkAtom *targets;
1546   gint i, n_targets;
1547   gboolean retval = FALSE;
1548     
1549   if (!gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets))
1550     return FALSE;
1551
1552   for (i = 0; i < n_targets; i++)
1553     {
1554       if (targets[i] == target)
1555         {
1556           retval = TRUE;
1557           break;
1558         }
1559     }
1560
1561   g_free (targets);
1562   
1563   return retval;
1564 }
1565
1566 /**
1567  * _gtk_clipboard_handle_event:
1568  * @event: a owner change event
1569  * 
1570  * Emits the ::owner_change signal on the appropriate @clipboard.
1571  *
1572  * Since: 2.6
1573  **/
1574 void 
1575 _gtk_clipboard_handle_event (GdkEventOwnerChange *event)
1576 {
1577   GdkDisplay *display;
1578   GtkClipboard *clipboard;
1579   
1580   display = gdk_drawable_get_display (event->window);
1581   clipboard = clipboard_peek (display, event->selection, TRUE);
1582       
1583   if (clipboard)
1584     g_signal_emit (clipboard, 
1585                    clipboard_signals[OWNER_CHANGE], 0, event, NULL);
1586 }
1587
1588 static gboolean
1589 gtk_clipboard_store_timeout (GtkClipboard *clipboard)
1590 {
1591   g_main_loop_quit (clipboard->store_loop);
1592   
1593   return FALSE;
1594 }
1595
1596 /**
1597  * gtk_clipboard_set_can_store:
1598  * @clipboard: a #GtkClipboard
1599  * @targets: array containing information about which forms should be stored
1600  *           or %NULL to indicate that all forms should be stored.
1601  * @n_targets: number of elements in @targets
1602  *
1603  * Hints that the clipboard data should be stored somewhere when the
1604  * application exits or when gtk_clipboard_store () is called.
1605  *
1606  * This value is reset when the clipboard owner changes.
1607  * Where the clipboard data is stored is platform dependent,
1608  * see gdk_display_store_clipboard () for more information.
1609  * 
1610  * Since: 2.6
1611  */
1612 void
1613 gtk_clipboard_set_can_store (GtkClipboard         *clipboard,
1614                              const GtkTargetEntry *targets,
1615                              gint                  n_targets)
1616 {
1617   GtkWidget *clipboard_widget;
1618   int i;
1619   static const GtkTargetEntry save_targets[] = {
1620     { "SAVE_TARGETS", 0, TARGET_SAVE_TARGETS }
1621   };
1622   
1623   g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
1624   g_return_if_fail (n_targets >= 0);
1625
1626   if (clipboard->selection != GDK_SELECTION_CLIPBOARD)
1627     return;
1628   
1629   g_free (clipboard->storable_targets);
1630   
1631   clipboard_widget = get_clipboard_widget (clipboard->display);
1632
1633   /* n_storable_targets being -1 means that
1634    * gtk_clipboard_set_can_store hasn't been called since the
1635    * clipboard owner changed. We only want to add SAVE_TARGETS and 
1636    * ref the owner once , so we do that here
1637    */  
1638   if (clipboard->n_storable_targets == -1)
1639     {
1640       gtk_selection_add_targets (clipboard_widget, clipboard->selection,
1641                                  save_targets, 1);
1642
1643       /* Ref the owner so it won't go away */
1644       if (clipboard->have_owner)
1645         g_object_ref (clipboard->user_data);
1646     }
1647   
1648   clipboard->n_storable_targets = n_targets;
1649   clipboard->storable_targets = g_new (GdkAtom, n_targets);
1650   for (i = 0; i < n_targets; i++)
1651     clipboard->storable_targets[i] = gdk_atom_intern (targets[i].target, FALSE);
1652 }
1653
1654 static gboolean
1655 gtk_clipboard_selection_notify (GtkWidget         *widget,
1656                                 GdkEventSelection *event,
1657                                 GtkClipboard      *clipboard)
1658 {
1659   if (event->selection == gdk_atom_intern ("CLIPBOARD_MANAGER", FALSE) &&
1660       clipboard->storing_selection)
1661     g_main_loop_quit (clipboard->store_loop);
1662
1663   return FALSE;
1664 }
1665
1666 /**
1667  * gtk_clipboard_store:
1668  * @clipboard: a #GtkClipboard
1669  *
1670  * Stores the current clipboard data somewhere so that it will stay
1671  * around after the application has quit.
1672  *
1673  * Since: 2.6
1674  */
1675 void
1676 gtk_clipboard_store (GtkClipboard *clipboard)
1677 {
1678   GtkWidget *clipboard_widget;
1679
1680   g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
1681
1682   if (clipboard->n_storable_targets < 0)
1683     return;
1684   
1685   if (!gdk_display_supports_clipboard_persistence (clipboard->display))
1686     return;
1687
1688   clipboard_widget = get_clipboard_widget (clipboard->display);
1689   clipboard->notify_signal_id = g_signal_connect (clipboard_widget, "selection_notify_event",
1690                                                   G_CALLBACK (gtk_clipboard_selection_notify), clipboard);
1691   
1692   gdk_display_store_clipboard (clipboard->display,
1693                                clipboard_widget->window,
1694                                clipboard_get_timestamp (clipboard),
1695                                clipboard->storable_targets,
1696                                clipboard->n_storable_targets);
1697
1698   clipboard->storing_selection = TRUE;
1699
1700   clipboard->store_loop = g_main_loop_new (NULL, TRUE);
1701   clipboard->store_timeout = g_timeout_add (10000, (GSourceFunc) gtk_clipboard_store_timeout, clipboard);
1702
1703   if (g_main_loop_is_running (clipboard->store_loop))
1704     {
1705       GDK_THREADS_LEAVE ();
1706       g_main_loop_run (clipboard->store_loop);
1707       GDK_THREADS_ENTER ();
1708     }
1709   
1710   g_main_loop_unref (clipboard->store_loop);
1711   clipboard->store_loop = NULL;
1712   
1713   g_source_remove (clipboard->store_timeout);
1714   clipboard->store_timeout = 0;
1715   g_signal_handler_disconnect (clipboard_widget, clipboard->notify_signal_id);
1716   clipboard->notify_signal_id = 0;
1717   
1718   clipboard->storing_selection = FALSE;
1719 }
1720
1721 /* Stores all clipboard selections on all displays, called from
1722  * gtk_main_quit ().
1723  */
1724 void
1725 _gtk_clipboard_store_all (void)
1726 {
1727   GtkClipboard *clipboard;
1728   GSList *displays, *list;
1729   
1730   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
1731
1732   list = displays;
1733   while (list)
1734     {
1735       GdkDisplay *display = list->data;
1736
1737       clipboard = clipboard_peek (display, GDK_SELECTION_CLIPBOARD, TRUE);
1738
1739       if (clipboard)
1740         gtk_clipboard_store (clipboard);
1741       
1742       list = list->next;
1743     }
1744   g_slist_free (displays);
1745   
1746 }
1747
1748 #define __GTK_CLIPBOARD_C__
1749 #include "gtkaliasdef.c"