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
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.
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.
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.
27 #include "gtkclipboard.h"
28 #include "gtkinvisible.h"
30 #include "gtkmarshalers.h"
32 #include "gtktextbuffer.h"
33 #include "gtkselectionprivate.h"
35 #include "../gdk/gdk.h"
36 #include "../gdk/wayland/gdkwayland.h"
43 typedef struct _GtkClipboardClass GtkClipboardClass;
45 typedef struct _SetContentClosure SetContentClosure;
48 GObject parent_instance;
53 SetContentClosure *last_closure;
56 struct _GtkClipboardClass
58 GObjectClass parent_class;
60 void (*owner_change) (GtkClipboard *clipboard,
61 GdkEventOwnerChange *event);
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);
69 static GObjectClass *parent_class;
70 static guint clipboard_signals[LAST_SIGNAL] = { 0 };
73 gtk_clipboard_get_type (void)
75 static GType clipboard_type = 0;
79 const GTypeInfo clipboard_info =
81 sizeof (GtkClipboardClass),
83 NULL, /* base_finalize */
84 (GClassInitFunc) gtk_clipboard_class_init,
85 NULL, /* class_finalize */
86 NULL, /* class_data */
87 sizeof (GtkClipboard),
89 (GInstanceInitFunc) NULL,
92 clipboard_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkClipboard"),
96 return clipboard_type;
100 gtk_clipboard_class_init (GtkClipboardClass *class)
102 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
104 parent_class = g_type_class_peek_parent (class);
106 gobject_class->finalize = gtk_clipboard_finalize;
108 class->owner_change = gtk_clipboard_owner_change;
110 clipboard_signals[OWNER_CHANGE] =
111 g_signal_new (I_("owner-change"),
112 G_TYPE_FROM_CLASS (gobject_class),
114 G_STRUCT_OFFSET (GtkClipboardClass, owner_change),
116 _gtk_marshal_VOID__BOXED,
118 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
122 gtk_clipboard_finalize (GObject *object)
124 G_OBJECT_CLASS (parent_class)->finalize (object);
128 gtk_clipboard_get_for_display (GdkDisplay *display,
131 GtkClipboard *clipboard;
133 if (selection == GDK_NONE)
134 selection = GDK_SELECTION_CLIPBOARD;
136 if (selection != GDK_SELECTION_CLIPBOARD)
138 g_warning (G_STRLOC ": Only able to create clipboard for CLIPBOARD");
141 selection = GDK_SELECTION_CLIPBOARD;
143 clipboard = g_object_get_data (G_OBJECT (display), "gtk-clipboard");
148 clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
149 clipboard->display = display;
151 g_object_set_data (G_OBJECT (display), "gtk-clipboard", clipboard);
153 /* TODO: Need to connect to display closed to free this */
158 gtk_clipboard_get (GdkAtom selection)
160 return gtk_clipboard_get_for_display (gdk_display_get_default (), selection);
164 struct _SetContentClosure {
165 GtkClipboard *clipboard;
166 GtkClipboardGetFunc get_func;
167 GtkClipboardClearFunc clear_func;
170 GtkTargetPair *targets;
175 _offer_cb (GdkDevice *device,
176 const gchar *mime_type,
180 SetContentClosure *closure = (SetContentClosure *)userdata;
181 GtkSelectionData selection_data = { 0, };
185 selection_data.target = gdk_atom_intern (mime_type, FALSE);
187 for (i = 0; i < closure->n_targets; i++)
189 if (closure->targets[i].target == selection_data.target)
191 info = closure->targets[i].info;
196 closure->get_func (closure->clipboard,
201 *len = gtk_selection_data_get_length (&selection_data);
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;
209 gtk_clipboard_set_contents (GtkClipboard *clipboard,
210 const GtkTargetEntry *targets,
212 GtkClipboardGetFunc get_func,
213 GtkClipboardClearFunc clear_func,
217 GdkDeviceManager *device_manager;
221 SetContentClosure *closure;
223 gtk_clipboard_clear (clipboard);
225 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
226 device = gdk_device_manager_get_client_pointer (device_manager);
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;
236 mimetypes = g_new (gchar *, n_targets);
238 for (i = 0; i < n_targets; i++)
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;
246 gdk_wayland_device_offer_selection_content (device,
247 (const gchar **)mimetypes,
251 clipboard->last_closure = closure;
258 gtk_clipboard_set_with_data (GtkClipboard *clipboard,
259 const GtkTargetEntry *targets,
261 GtkClipboardGetFunc get_func,
262 GtkClipboardClearFunc clear_func,
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);
269 return gtk_clipboard_set_contents (clipboard, targets, n_targets,
270 get_func, clear_func, user_data,
275 gtk_clipboard_set_with_owner (GtkClipboard *clipboard,
276 const GtkTargetEntry *targets,
278 GtkClipboardGetFunc get_func,
279 GtkClipboardClearFunc clear_func,
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);
287 return gtk_clipboard_set_contents (clipboard, targets, n_targets,
288 get_func, clear_func, owner,
293 gtk_clipboard_get_owner (GtkClipboard *clipboard)
295 g_return_val_if_fail (clipboard != NULL, NULL);
297 if (clipboard->owner)
298 return clipboard->owner;
304 gtk_clipboard_clear (GtkClipboard *clipboard)
306 GdkDeviceManager *device_manager;
309 if (!clipboard->last_closure)
312 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
313 device = gdk_device_manager_get_client_pointer (device_manager);
315 gdk_wayland_device_clear_selection_content (device);
317 if (clipboard->last_closure->clear_func)
319 clipboard->last_closure->clear_func (clipboard,
320 clipboard->last_closure->userdata);
323 /* TODO: Free last closure */
324 clipboard->last_closure = NULL;
328 text_get_func (GtkClipboard *clipboard,
329 GtkSelectionData *selection_data,
333 gtk_selection_data_set_text (selection_data, data, -1);
337 text_clear_func (GtkClipboard *clipboard,
344 gtk_clipboard_set_text (GtkClipboard *clipboard,
348 GtkTargetEntry target = { "text/plain;charset=utf-8", 0, 0 };
350 g_return_if_fail (clipboard != NULL);
351 g_return_if_fail (text != NULL);
356 gtk_clipboard_set_with_data (clipboard,
358 text_get_func, text_clear_func,
359 g_strndup (text, len));
360 gtk_clipboard_set_can_store (clipboard, NULL, 0);
365 pixbuf_get_func (GtkClipboard *clipboard,
366 GtkSelectionData *selection_data,
370 gtk_selection_data_set_pixbuf (selection_data, data);
374 pixbuf_clear_func (GtkClipboard *clipboard,
377 g_object_unref (data);
381 gtk_clipboard_set_image (GtkClipboard *clipboard,
386 GtkTargetEntry *targets;
389 g_return_if_fail (clipboard != NULL);
390 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
392 list = gtk_target_list_new (NULL, 0);
393 gtk_target_list_add_image_targets (list, 0, TRUE);
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++)
399 GtkTargetPair *pair = (GtkTargetPair *)l->data;
400 targets[i].target = gdk_atom_name (pair->target);
403 gtk_clipboard_set_with_data (clipboard,
405 pixbuf_get_func, pixbuf_clear_func,
406 g_object_ref (pixbuf));
407 gtk_clipboard_set_can_store (clipboard, NULL, 0);
409 for (i = 0; i < n_targets; i++)
410 g_free (targets[i].target);
412 gtk_target_list_unref (list);
416 GtkClipboard *clipboard;
420 } ClipboardRequestClosure;
423 _request_generic_cb (GdkDevice *device,
428 ClipboardRequestClosure *closure = (ClipboardRequestClosure *)userdata;
429 GtkClipboardReceivedFunc cb = (GtkClipboardReceivedFunc)closure->cb;
430 GtkSelectionData selection_data;
432 selection_data.selection = GDK_SELECTION_CLIPBOARD;
433 selection_data.target = closure->target;
434 selection_data.length = len;
435 selection_data.data = (guchar *)data;
437 cb (closure->clipboard, &selection_data, closure->userdata);
443 gtk_clipboard_request_contents (GtkClipboard *clipboard,
445 GtkClipboardReceivedFunc callback,
448 GdkDeviceManager *device_manager;
450 ClipboardRequestClosure *closure;
452 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
453 device = gdk_device_manager_get_client_pointer (device_manager);
455 closure = g_new0 (ClipboardRequestClosure, 1);
456 closure->clipboard = clipboard;
457 closure->cb = (GCallback)callback;
458 closure->userdata = user_data;
459 closure->target = target;
461 /* TODO: Do we need to check that target is valid ? */
462 gdk_wayland_device_request_selection_content (device,
463 gdk_atom_name (target),
469 _request_text_cb (GdkDevice *device,
474 ClipboardRequestClosure *closure = (ClipboardRequestClosure *)userdata;
475 GtkClipboardTextReceivedFunc cb = (GtkClipboardTextReceivedFunc)closure->cb;
477 cb (closure->clipboard, data, closure->userdata);
483 gtk_clipboard_request_text (GtkClipboard *clipboard,
484 GtkClipboardTextReceivedFunc callback,
487 GdkDeviceManager *device_manager;
490 ClipboardRequestClosure *closure;
492 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
493 device = gdk_device_manager_get_client_pointer (device_manager);
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",
506 gtk_clipboard_request_rich_text (GtkClipboard *clipboard,
507 GtkTextBuffer *buffer,
508 GtkClipboardRichTextReceivedFunc callback,
511 /* FIXME: Implement */
515 gtk_clipboard_request_image (GtkClipboard *clipboard,
516 GtkClipboardImageReceivedFunc callback,
519 /* FIXME: Implement */
523 gtk_clipboard_request_uris (GtkClipboard *clipboard,
524 GtkClipboardURIReceivedFunc callback,
527 /* FIXME: Implement */
531 gtk_clipboard_request_targets (GtkClipboard *clipboard,
532 GtkClipboardTargetsReceivedFunc callback,
538 gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets);
540 callback (clipboard, targets, n_targets, user_data);
547 GtkSelectionData *selection_data;
551 _wait_for_contents_cb (GtkClipboard *clipboard,
552 GtkSelectionData *selection_data,
555 WaitClosure *closure = (WaitClosure *)userdata;
557 if (gtk_selection_data_get_length (selection_data) != -1)
558 closure->selection_data = gtk_selection_data_copy (selection_data);
560 g_main_loop_quit (closure->loop);
564 gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
567 GdkDeviceManager *device_manager;
569 WaitClosure *closure;
570 GtkSelectionData *selection_data = NULL;
572 g_return_val_if_fail (clipboard != NULL, NULL);
573 g_return_val_if_fail (target != GDK_NONE, NULL);
575 device_manager = gdk_display_get_device_manager (clipboard->display);
576 device = gdk_device_manager_get_client_pointer (device_manager);
578 if (target == gdk_atom_intern_static_string ("TARGETS"))
583 selection_data = g_slice_new0 (GtkSelectionData);
584 selection_data->selection = GDK_SELECTION_CLIPBOARD;
585 selection_data->target = target;
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,
595 return selection_data;
598 closure = g_new0 (WaitClosure, 1);
599 closure->selection_data = NULL;
600 closure->loop = g_main_loop_new (NULL, TRUE);
602 gtk_clipboard_request_contents (clipboard,
604 _wait_for_contents_cb,
607 if (g_main_loop_is_running (closure->loop))
609 GDK_THREADS_LEAVE ();
610 g_main_loop_run (closure->loop);
611 GDK_THREADS_ENTER ();
614 g_main_loop_unref (closure->loop);
616 selection_data = closure->selection_data;
620 return selection_data;
624 gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
626 GtkSelectionData *data;
630 gtk_clipboard_wait_for_contents (clipboard,
631 gdk_atom_intern_static_string ("text/plain;charset=utf-8"));
633 result = (gchar *)gtk_selection_data_get_text (data);
635 gtk_selection_data_free (data);
641 gtk_clipboard_wait_for_image (GtkClipboard *clipboard)
643 const gchar *priority[] = { "image/png",
649 GtkSelectionData *data;
651 for (i = 0; i < G_N_ELEMENTS (priority); i++)
653 data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string (priority[i]));
657 GdkPixbuf *pixbuf = gtk_selection_data_get_pixbuf (data);
659 gtk_selection_data_free (data);
669 gtk_clipboard_wait_for_rich_text (GtkClipboard *clipboard,
670 GtkTextBuffer *buffer,
674 /* FIXME: Implement */
679 gtk_clipboard_wait_for_uris (GtkClipboard *clipboard)
681 GtkSelectionData *data;
684 gtk_clipboard_wait_for_contents (clipboard,
685 gdk_atom_intern_static_string ("text/uri-list"));
690 uris = gtk_selection_data_get_uris (data);
691 gtk_selection_data_free (data);
700 gtk_clipboard_get_display (GtkClipboard *clipboard)
702 g_return_val_if_fail (clipboard != NULL, NULL);
704 return clipboard->display;
708 gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
710 GtkSelectionData *data;
711 gboolean result = FALSE;
714 gtk_clipboard_wait_for_contents (clipboard,
715 gdk_atom_intern_static_string ("TARGETS"));
718 result = gtk_selection_data_targets_include_text (data);
719 gtk_selection_data_free (data);
726 gtk_clipboard_wait_is_rich_text_available (GtkClipboard *clipboard,
727 GtkTextBuffer *buffer)
729 GtkSelectionData *data;
730 gboolean result = FALSE;
732 g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
733 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
736 gtk_clipboard_wait_for_contents (clipboard,
737 gdk_atom_intern_static_string ("TARGETS"));
740 result = gtk_selection_data_targets_include_rich_text (data, buffer);
741 gtk_selection_data_free (data);
748 gtk_clipboard_wait_is_image_available (GtkClipboard *clipboard)
750 GtkSelectionData *data;
751 gboolean result = FALSE;
754 gtk_clipboard_wait_for_contents (clipboard,
755 gdk_atom_intern_static_string ("TARGETS"));
758 result = gtk_selection_data_targets_include_image (data, FALSE);
759 gtk_selection_data_free (data);
766 gtk_clipboard_wait_is_uris_available (GtkClipboard *clipboard)
768 GtkSelectionData *data;
769 gboolean result = FALSE;
772 gtk_clipboard_wait_for_contents (clipboard,
773 gdk_atom_intern_static_string ("TARGETS"));
776 result = gtk_selection_data_targets_include_uri (data);
777 gtk_selection_data_free (data);
784 gtk_clipboard_wait_for_targets (GtkClipboard *clipboard,
788 GtkSelectionData *data;
789 gboolean result = FALSE;
791 g_return_val_if_fail (clipboard != NULL, FALSE);
794 gtk_clipboard_wait_for_contents (clipboard,
795 gdk_atom_intern_static_string ("TARGETS"));
799 GdkAtom *tmp_targets;
802 result = gtk_selection_data_get_targets (data,
807 *n_targets = tmp_n_targets;
810 *targets = tmp_targets;
812 g_free (tmp_targets);
814 gtk_selection_data_free (data);
821 gtk_clipboard_owner_change (GtkClipboard *clipboard,
822 GdkEventOwnerChange *event)
828 gtk_clipboard_wait_is_target_available (GtkClipboard *clipboard,
833 gboolean retval = FALSE;
835 g_return_val_if_fail (clipboard != NULL, FALSE);
837 if (!gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets))
840 for (i = 0; i < n_targets; i++)
842 if (targets[i] == target)
855 _gtk_clipboard_handle_event (GdkEventOwnerChange *event)
860 gtk_clipboard_set_can_store (GtkClipboard *clipboard,
861 const GtkTargetEntry *targets,
864 /* FIXME: Implement */
868 gtk_clipboard_store (GtkClipboard *clipboard)
870 /* FIXME: Implement */
874 _gtk_clipboard_store_all (void)
876 /* FIXME: Implement */