]> Pileus Git - ~andy/gtk/blob - gtk/gtkclipboard-wayland.c
649acbd202bef78a1262a624fec3a822df8dfadc
[~andy/gtk] / gtk / gtkclipboard-wayland.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  * Copyright (C) 2004 Nokia Corporation
4  * Copyright (C) 2006-2008 Imendio AB
5  * Copyright (C) 2011-2012 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23
24 #include "config.h"
25 #include <string.h>
26
27 #include "gtkclipboard.h"
28 #include "gtkinvisible.h"
29 #include "gtkmain.h"
30 #include "gtkmarshalers.h"
31 #include "gtkintl.h"
32 #include "gtktextbuffer.h"
33 #include "gtkselectionprivate.h"
34
35 #include "../gdk/gdk.h"
36 #include "../gdk/wayland/gdkwayland.h"
37
38 enum {
39     OWNER_CHANGE,
40     LAST_SIGNAL
41 };
42
43 typedef struct _GtkClipboardClass GtkClipboardClass;
44
45 typedef struct _SetContentClosure SetContentClosure;
46 struct _GtkClipboard
47 {
48   GObject parent_instance;
49
50   GObject *owner;
51   GdkDisplay *display;
52
53   SetContentClosure *last_closure;
54 };
55
56 struct _GtkClipboardClass
57 {
58   GObjectClass parent_class;
59
60   void (*owner_change) (GtkClipboard        *clipboard,
61                         GdkEventOwnerChange *event);
62 };
63
64 static void gtk_clipboard_class_init   (GtkClipboardClass   *class);
65 static void gtk_clipboard_finalize     (GObject             *object);
66 static void gtk_clipboard_owner_change (GtkClipboard        *clipboard,
67                                         GdkEventOwnerChange *event);
68
69 static GObjectClass *parent_class;
70 static guint         clipboard_signals[LAST_SIGNAL] = { 0 };
71
72 GType
73 gtk_clipboard_get_type (void)
74 {
75   static GType clipboard_type = 0;
76
77   if (!clipboard_type)
78     {
79       const GTypeInfo clipboard_info =
80         {
81           sizeof (GtkClipboardClass),
82           NULL,           /* base_init */
83           NULL,           /* base_finalize */
84           (GClassInitFunc) gtk_clipboard_class_init,
85           NULL,           /* class_finalize */
86           NULL,           /* class_data */
87           sizeof (GtkClipboard),
88           0,              /* n_preallocs */
89           (GInstanceInitFunc) NULL,
90         };
91
92       clipboard_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkClipboard"),
93                                                &clipboard_info, 0);
94     }
95
96   return clipboard_type;
97 }
98
99 static void
100 gtk_clipboard_class_init (GtkClipboardClass *class)
101 {
102   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
103
104   parent_class = g_type_class_peek_parent (class);
105
106   gobject_class->finalize = gtk_clipboard_finalize;
107
108   class->owner_change = gtk_clipboard_owner_change;
109
110   clipboard_signals[OWNER_CHANGE] =
111     g_signal_new (I_("owner-change"),
112                   G_TYPE_FROM_CLASS (gobject_class),
113                   G_SIGNAL_RUN_FIRST,
114                   G_STRUCT_OFFSET (GtkClipboardClass, owner_change),
115                   NULL, NULL,
116                   _gtk_marshal_VOID__BOXED,
117                   G_TYPE_NONE, 1,
118                   GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
119 }
120
121 static void
122 gtk_clipboard_finalize (GObject *object)
123 {
124   G_OBJECT_CLASS (parent_class)->finalize (object);
125 }
126
127 GtkClipboard *
128 gtk_clipboard_get_for_display (GdkDisplay *display,
129                                GdkAtom     selection)
130 {
131   GtkClipboard *clipboard;
132
133   if (selection == GDK_NONE)
134     selection = GDK_SELECTION_CLIPBOARD;
135
136   if (selection != GDK_SELECTION_CLIPBOARD)
137     {
138       g_warning (G_STRLOC ": Only able to create clipboard for CLIPBOARD");
139     }
140
141   selection = GDK_SELECTION_CLIPBOARD;
142
143   clipboard = g_object_get_data (G_OBJECT (display), "gtk-clipboard");
144
145   if (clipboard)
146     return clipboard;
147
148   clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
149   clipboard->display = display;
150
151   g_object_set_data (G_OBJECT (display), "gtk-clipboard", clipboard);
152
153   /* TODO: Need to connect to display closed to free this */
154   return clipboard;
155 }
156
157 GtkClipboard *
158 gtk_clipboard_get (GdkAtom selection)
159 {
160   return gtk_clipboard_get_for_display (gdk_display_get_default (), selection);
161 }
162
163
164 struct _SetContentClosure {
165     GtkClipboard *clipboard;
166     GtkClipboardGetFunc get_func;
167     GtkClipboardClearFunc clear_func;
168     guint info;
169     gpointer userdata;
170     GtkTargetPair *targets;
171     gint n_targets;
172 };
173
174 static gchar *
175 _offer_cb (GdkDevice   *device,
176            const gchar *mime_type,
177            gssize      *len,
178            gpointer     userdata)
179 {
180   SetContentClosure *closure = (SetContentClosure *)userdata;
181   GtkSelectionData selection_data = { 0, };
182   guint info = 0;
183   gint i;
184
185   selection_data.target = gdk_atom_intern (mime_type, FALSE);
186
187   for (i = 0; i < closure->n_targets; i++)
188     {
189       if (closure->targets[i].target == selection_data.target)
190         {
191           info = closure->targets[i].info;
192           break;
193         }
194     }
195
196   closure->get_func (closure->clipboard,
197                      &selection_data,
198                      info,
199                      closure->userdata);
200
201   *len = gtk_selection_data_get_length (&selection_data);
202
203   /* The caller of this callback will free this data - the GtkClipboardGetFunc
204    * uses gtk_selection_data_set which copies*/
205   return (gchar *)selection_data.data;
206 }
207
208 static gboolean
209 gtk_clipboard_set_contents (GtkClipboard         *clipboard,
210                             const GtkTargetEntry *targets,
211                             guint                 n_targets,
212                             GtkClipboardGetFunc   get_func,
213                             GtkClipboardClearFunc clear_func,
214                             gpointer              user_data,
215                             gboolean              have_owner)
216 {
217   GdkDeviceManager *device_manager;
218   GdkDevice *device;
219   gint i;
220   gchar **mimetypes;
221   SetContentClosure *closure;
222
223   gtk_clipboard_clear (clipboard);
224
225   device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
226   device = gdk_device_manager_get_client_pointer (device_manager);
227
228   closure = g_new0 (SetContentClosure, 1);
229   closure->clipboard = clipboard;
230   closure->get_func = get_func;
231   closure->clear_func = clear_func;
232   closure->userdata = user_data;
233   closure->targets = g_new0 (GtkTargetPair, n_targets);
234   closure->n_targets = n_targets;
235
236   mimetypes = g_new (gchar *, n_targets);
237
238   for (i = 0; i < n_targets; i++)
239     {
240       mimetypes[i] = targets[i].target;
241       closure->targets[i].target = gdk_atom_intern (targets[i].target, FALSE);
242       closure->targets[i].flags = targets[i].flags;
243       closure->targets[i].info = targets[i].info;
244     }
245
246   gdk_wayland_device_offer_selection_content (device,
247                                               (const gchar **)mimetypes,
248                                               n_targets,
249                                               _offer_cb,
250                                               closure);
251   clipboard->last_closure = closure;
252
253   g_free (mimetypes);
254   return TRUE;
255 }
256
257 gboolean
258 gtk_clipboard_set_with_data (GtkClipboard          *clipboard,
259                              const GtkTargetEntry  *targets,
260                              guint                  n_targets,
261                              GtkClipboardGetFunc    get_func,
262                              GtkClipboardClearFunc  clear_func,
263                              gpointer               user_data)
264 {
265   g_return_val_if_fail (clipboard != NULL, FALSE);
266   g_return_val_if_fail (targets != NULL, FALSE);
267   g_return_val_if_fail (get_func != NULL, FALSE);
268
269   return gtk_clipboard_set_contents (clipboard, targets, n_targets,
270                                      get_func, clear_func, user_data,
271                                      FALSE);
272 }
273
274 gboolean
275 gtk_clipboard_set_with_owner (GtkClipboard          *clipboard,
276                               const GtkTargetEntry  *targets,
277                               guint                  n_targets,
278                               GtkClipboardGetFunc    get_func,
279                               GtkClipboardClearFunc  clear_func,
280                               GObject               *owner)
281 {
282   g_return_val_if_fail (clipboard != NULL, FALSE);
283   g_return_val_if_fail (targets != NULL, FALSE);
284   g_return_val_if_fail (get_func != NULL, FALSE);
285   g_return_val_if_fail (G_IS_OBJECT (owner), FALSE);
286
287   return gtk_clipboard_set_contents (clipboard, targets, n_targets,
288                                      get_func, clear_func, owner,
289                                      TRUE);
290 }
291
292 GObject *
293 gtk_clipboard_get_owner (GtkClipboard *clipboard)
294 {
295   g_return_val_if_fail (clipboard != NULL, NULL);
296
297   if (clipboard->owner)
298     return clipboard->owner;
299   else
300     return NULL;
301 }
302
303 void
304 gtk_clipboard_clear (GtkClipboard *clipboard)
305 {
306   GdkDeviceManager *device_manager;
307   GdkDevice *device;
308
309   if (!clipboard->last_closure)
310     return;
311
312   device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
313   device = gdk_device_manager_get_client_pointer (device_manager);
314
315   gdk_wayland_device_clear_selection_content (device);
316
317   if (clipboard->last_closure->clear_func)
318     {
319       clipboard->last_closure->clear_func (clipboard,
320                                            clipboard->last_closure->userdata);
321     }
322
323   /* TODO: Free last closure */
324   clipboard->last_closure = NULL;
325 }
326
327 static void 
328 text_get_func (GtkClipboard     *clipboard,
329                GtkSelectionData *selection_data,
330                guint             info,
331                gpointer          data)
332 {
333   gtk_selection_data_set_text (selection_data, data, -1);
334 }
335
336 static void 
337 text_clear_func (GtkClipboard *clipboard,
338                  gpointer      data)
339 {
340   g_free (data);
341 }
342
343 void
344 gtk_clipboard_set_text (GtkClipboard *clipboard,
345                         const gchar  *text,
346                         gint          len)
347 {
348   GtkTargetEntry target = { "text/plain;charset=utf-8", 0, 0 };
349
350   g_return_if_fail (clipboard != NULL);
351   g_return_if_fail (text != NULL);
352
353   if (len < 0)
354     len = strlen (text);
355
356   gtk_clipboard_set_with_data (clipboard, 
357                                &target, 1,
358                                text_get_func, text_clear_func,
359                                g_strndup (text, len));
360   gtk_clipboard_set_can_store (clipboard, NULL, 0);
361 }
362
363
364 static void
365 pixbuf_get_func (GtkClipboard     *clipboard,
366                  GtkSelectionData *selection_data,
367                  guint             info,
368                  gpointer          data)
369 {
370   gtk_selection_data_set_pixbuf (selection_data, data);
371 }
372
373 static void 
374 pixbuf_clear_func (GtkClipboard *clipboard,
375                    gpointer      data)
376 {
377   g_object_unref (data);
378 }
379
380 void
381 gtk_clipboard_set_image (GtkClipboard *clipboard,
382                          GdkPixbuf    *pixbuf)
383 {
384   GtkTargetList *list;
385   GList *l;
386   GtkTargetEntry *targets;
387   gint n_targets, i;
388
389   g_return_if_fail (clipboard != NULL);
390   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
391
392   list = gtk_target_list_new (NULL, 0);
393   gtk_target_list_add_image_targets (list, 0, TRUE);
394
395   n_targets = g_list_length (list->list);
396   targets = g_new0 (GtkTargetEntry, n_targets);
397   for (l = list->list, i = 0; l; l = l->next, i++)
398     {
399       GtkTargetPair *pair = (GtkTargetPair *)l->data;
400       targets[i].target = gdk_atom_name (pair->target);
401     }
402
403   gtk_clipboard_set_with_data (clipboard, 
404                                targets, n_targets,
405                                pixbuf_get_func, pixbuf_clear_func,
406                                g_object_ref (pixbuf));
407   gtk_clipboard_set_can_store (clipboard, NULL, 0);
408
409   for (i = 0; i < n_targets; i++)
410     g_free (targets[i].target);
411   g_free (targets);
412   gtk_target_list_unref (list);
413 }
414
415 typedef struct {
416     GtkClipboard *clipboard;
417     GCallback cb;
418     gpointer userdata;
419     GdkAtom target;
420 } ClipboardRequestClosure;
421
422 static void
423 _request_generic_cb (GdkDevice   *device,
424                      const gchar *data,
425                      gsize        len,
426                      gpointer     userdata)
427 {
428   ClipboardRequestClosure *closure = (ClipboardRequestClosure *)userdata;
429   GtkClipboardReceivedFunc cb = (GtkClipboardReceivedFunc)closure->cb;
430   GtkSelectionData selection_data;
431
432   selection_data.selection = GDK_SELECTION_CLIPBOARD;
433   selection_data.target = closure->target;
434   selection_data.length = len;
435   selection_data.data = (guchar *)data;
436
437   cb (closure->clipboard, &selection_data, closure->userdata);
438
439   g_free (closure);
440 }
441
442 void
443 gtk_clipboard_request_contents (GtkClipboard            *clipboard,
444                                 GdkAtom                  target,
445                                 GtkClipboardReceivedFunc callback,
446                                 gpointer                 user_data)
447 {
448   GdkDeviceManager *device_manager;
449   GdkDevice *device;
450   ClipboardRequestClosure *closure;
451
452   device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
453   device = gdk_device_manager_get_client_pointer (device_manager);
454
455   closure = g_new0 (ClipboardRequestClosure, 1);
456   closure->clipboard = clipboard;
457   closure->cb = (GCallback)callback;
458   closure->userdata = user_data;
459   closure->target = target;
460
461   /* TODO: Do we need to check that target is valid ? */
462   gdk_wayland_device_request_selection_content (device,
463                                                 gdk_atom_name (target),
464                                                 _request_generic_cb,
465                                                 closure);
466 }
467
468 static void
469 _request_text_cb (GdkDevice   *device,
470                   const gchar *data,
471                   gsize        len,
472                   gpointer     userdata)
473 {
474   ClipboardRequestClosure *closure = (ClipboardRequestClosure *)userdata;
475   GtkClipboardTextReceivedFunc cb = (GtkClipboardTextReceivedFunc)closure->cb;
476
477   cb (closure->clipboard, data, closure->userdata);
478
479   g_free (closure);
480 }
481
482 void
483 gtk_clipboard_request_text (GtkClipboard                *clipboard,
484                             GtkClipboardTextReceivedFunc callback,
485                             gpointer                     user_data)
486 {
487   GdkDeviceManager *device_manager;
488   GdkDevice *device;
489
490   ClipboardRequestClosure *closure;
491
492   device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
493   device = gdk_device_manager_get_client_pointer (device_manager);
494
495   closure = g_new0 (ClipboardRequestClosure, 1);
496   closure->clipboard = clipboard;
497   closure->cb = (GCallback)callback;
498   closure->userdata = user_data;
499   gdk_wayland_device_request_selection_content (device,
500                                                 "text/plain;charset=utf-8",
501                                                 _request_text_cb,
502                                                 closure);
503 }
504
505 void
506 gtk_clipboard_request_rich_text (GtkClipboard                    *clipboard,
507                                  GtkTextBuffer                   *buffer,
508                                  GtkClipboardRichTextReceivedFunc callback,
509                                  gpointer                         user_data)
510 {
511   /* FIXME: Implement */
512 }
513
514 void
515 gtk_clipboard_request_image (GtkClipboard                  *clipboard,
516                              GtkClipboardImageReceivedFunc  callback,
517                              gpointer                       user_data)
518 {
519   /* FIXME: Implement */
520 }
521
522 void
523 gtk_clipboard_request_uris (GtkClipboard                *clipboard,
524                             GtkClipboardURIReceivedFunc  callback,
525                             gpointer                     user_data)
526 {
527   /* FIXME: Implement */
528 }
529
530 void
531 gtk_clipboard_request_targets (GtkClipboard                    *clipboard,
532                                GtkClipboardTargetsReceivedFunc  callback,
533                                gpointer                         user_data)
534 {
535   GdkAtom *targets;
536   gint n_targets;
537
538   gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets);
539
540   callback (clipboard, targets, n_targets, user_data);
541
542   g_free (targets);
543 }
544
545 typedef struct {
546     GMainLoop *loop;
547     GtkSelectionData *selection_data;
548 } WaitClosure;
549
550 static void
551 _wait_for_contents_cb (GtkClipboard     *clipboard,
552                        GtkSelectionData *selection_data,
553                        gpointer          userdata)
554 {
555   WaitClosure *closure = (WaitClosure *)userdata;
556
557   if (gtk_selection_data_get_length (selection_data) != -1)
558     closure->selection_data = gtk_selection_data_copy (selection_data);
559
560   g_main_loop_quit (closure->loop);
561 }
562
563 GtkSelectionData *
564 gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
565                                  GdkAtom       target)
566 {
567   GdkDeviceManager *device_manager;
568   GdkDevice *device;
569   WaitClosure *closure;
570   GtkSelectionData *selection_data = NULL;
571
572   g_return_val_if_fail (clipboard != NULL, NULL);
573   g_return_val_if_fail (target != GDK_NONE, NULL);
574
575   device_manager = gdk_display_get_device_manager (clipboard->display);
576   device = gdk_device_manager_get_client_pointer (device_manager);
577
578   if (target == gdk_atom_intern_static_string ("TARGETS")) 
579     {
580       GdkAtom *atoms;
581       gint nr_atoms;
582
583       selection_data = g_slice_new0 (GtkSelectionData);
584       selection_data->selection = GDK_SELECTION_CLIPBOARD;
585       selection_data->target = target;
586
587       nr_atoms = gdk_wayland_device_get_selection_type_atoms (device, &atoms);
588       gtk_selection_data_set (selection_data,
589                               GDK_SELECTION_TYPE_ATOM, 32,
590                               (guchar *)atoms,
591                               32 * nr_atoms);
592
593       g_free (atoms);
594
595       return selection_data;
596     }
597
598   closure = g_new0 (WaitClosure, 1);
599   closure->selection_data = NULL;
600   closure->loop = g_main_loop_new (NULL, TRUE);
601
602   gtk_clipboard_request_contents (clipboard,
603                                   target,
604                                   _wait_for_contents_cb,
605                                   closure);
606
607   if (g_main_loop_is_running (closure->loop))
608     {
609       GDK_THREADS_LEAVE ();
610       g_main_loop_run (closure->loop);
611       GDK_THREADS_ENTER ();
612     }
613
614   g_main_loop_unref (closure->loop);
615
616   selection_data = closure->selection_data;
617
618   g_free (closure);
619
620   return selection_data;
621 }
622
623 gchar *
624 gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
625 {
626   GtkSelectionData *data;
627   gchar *result;
628
629   data =
630     gtk_clipboard_wait_for_contents (clipboard,
631                                      gdk_atom_intern_static_string ("text/plain;charset=utf-8"));
632
633   result = (gchar *)gtk_selection_data_get_text (data);
634
635   gtk_selection_data_free (data);
636
637   return result;
638 }
639
640 GdkPixbuf *
641 gtk_clipboard_wait_for_image (GtkClipboard *clipboard)
642 {
643   const gchar *priority[] = { "image/png",
644       "image/tiff",
645       "image/jpeg",
646       "image/gif",
647       "image/bmp" };
648   int i;
649   GtkSelectionData *data;
650
651   for (i = 0; i < G_N_ELEMENTS (priority); i++) 
652     {
653       data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string (priority[i]));
654
655       if (data)
656         {
657           GdkPixbuf *pixbuf = gtk_selection_data_get_pixbuf (data);
658
659           gtk_selection_data_free (data);
660
661           return pixbuf;
662         }
663     }
664
665   return NULL;
666 }
667
668 guint8 *
669 gtk_clipboard_wait_for_rich_text (GtkClipboard  *clipboard,
670                                   GtkTextBuffer *buffer,
671                                   GdkAtom       *format,
672                                   gsize         *length)
673 {
674   /* FIXME: Implement */
675   return NULL;
676 }
677
678 gchar **
679 gtk_clipboard_wait_for_uris (GtkClipboard *clipboard)
680 {
681   GtkSelectionData *data;
682
683   data =
684     gtk_clipboard_wait_for_contents (clipboard,
685                                      gdk_atom_intern_static_string ("text/uri-list"));
686   if (data)
687     {
688       gchar **uris;
689
690       uris = gtk_selection_data_get_uris (data);
691       gtk_selection_data_free (data);
692
693       return uris;
694     }  
695
696   return NULL;
697 }
698
699 GdkDisplay *
700 gtk_clipboard_get_display (GtkClipboard *clipboard)
701 {
702   g_return_val_if_fail (clipboard != NULL, NULL);
703
704   return clipboard->display;
705 }
706
707 gboolean
708 gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
709 {
710   GtkSelectionData *data;
711   gboolean result = FALSE;
712
713   data =
714     gtk_clipboard_wait_for_contents (clipboard,
715                                      gdk_atom_intern_static_string ("TARGETS"));
716   if (data)
717     {
718       result = gtk_selection_data_targets_include_text (data);
719       gtk_selection_data_free (data);
720     }
721
722   return result;
723 }
724
725 gboolean
726 gtk_clipboard_wait_is_rich_text_available (GtkClipboard  *clipboard,
727                                            GtkTextBuffer *buffer)
728 {
729   GtkSelectionData *data;
730   gboolean result = FALSE;
731
732   g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
733   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
734
735   data =
736     gtk_clipboard_wait_for_contents (clipboard,
737                                      gdk_atom_intern_static_string ("TARGETS"));
738   if (data)
739     {
740       result = gtk_selection_data_targets_include_rich_text (data, buffer);
741       gtk_selection_data_free (data);
742     }
743
744   return result;
745 }
746
747 gboolean
748 gtk_clipboard_wait_is_image_available (GtkClipboard *clipboard)
749 {
750   GtkSelectionData *data;
751   gboolean result = FALSE;
752
753   data =
754     gtk_clipboard_wait_for_contents (clipboard, 
755                                      gdk_atom_intern_static_string ("TARGETS"));
756   if (data)
757     {
758       result = gtk_selection_data_targets_include_image (data, FALSE);
759       gtk_selection_data_free (data);
760     }
761
762   return result;
763 }
764
765 gboolean
766 gtk_clipboard_wait_is_uris_available (GtkClipboard *clipboard)
767 {
768   GtkSelectionData *data;
769   gboolean result = FALSE;
770
771   data =
772     gtk_clipboard_wait_for_contents (clipboard, 
773                                      gdk_atom_intern_static_string ("TARGETS"));
774   if (data)
775     {
776       result = gtk_selection_data_targets_include_uri (data);
777       gtk_selection_data_free (data);
778     }
779
780   return result;
781 }
782
783 gboolean
784 gtk_clipboard_wait_for_targets (GtkClipboard  *clipboard,
785                                 GdkAtom      **targets,
786                                 gint          *n_targets)
787 {
788   GtkSelectionData *data;
789   gboolean result = FALSE;
790
791   g_return_val_if_fail (clipboard != NULL, FALSE);
792
793   data =
794     gtk_clipboard_wait_for_contents (clipboard,
795                                      gdk_atom_intern_static_string ("TARGETS"));
796
797   if (data)
798     {
799       GdkAtom *tmp_targets;
800       gint tmp_n_targets;
801
802       result = gtk_selection_data_get_targets (data,
803                                                &tmp_targets,
804                                                &tmp_n_targets);
805
806       if (n_targets)
807         *n_targets = tmp_n_targets;
808
809       if (targets)
810         *targets = tmp_targets;
811       else
812         g_free (tmp_targets);
813
814       gtk_selection_data_free (data);
815     }
816
817   return result;
818 }
819
820 static void
821 gtk_clipboard_owner_change (GtkClipboard        *clipboard,
822                             GdkEventOwnerChange *event)
823 {
824
825 }
826
827 gboolean
828 gtk_clipboard_wait_is_target_available (GtkClipboard *clipboard,
829                                         GdkAtom       target)
830 {
831   GdkAtom *targets;
832   gint i, n_targets;
833   gboolean retval = FALSE;
834
835   g_return_val_if_fail (clipboard != NULL, FALSE);
836
837   if (!gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets))
838     return FALSE;
839
840   for (i = 0; i < n_targets; i++)
841     {
842       if (targets[i] == target)
843         {
844           retval = TRUE;
845           break;
846         }
847     }
848
849   g_free (targets);
850
851   return retval;
852 }
853
854 void
855 _gtk_clipboard_handle_event (GdkEventOwnerChange *event)
856 {
857 }
858
859 void
860 gtk_clipboard_set_can_store (GtkClipboard         *clipboard,
861                              const GtkTargetEntry *targets,
862                              gint                  n_targets)
863 {
864   /* FIXME: Implement */
865 }
866
867 void
868 gtk_clipboard_store (GtkClipboard *clipboard)
869 {
870   /* FIXME: Implement */
871 }
872
873 void
874 _gtk_clipboard_store_all (void)
875 {
876   /* FIXME: Implement */
877 }