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