1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 /* This file implements most of the work of the ICCCM selection protocol.
21 * The code was written after an intensive study of the equivalent part
22 * of John Ousterhout's Tk toolkit, and does many things in much the
25 * The one thing in the ICCCM that isn't fully supported here (or in Tk)
26 * is side effects targets. For these to be handled properly, MULTIPLE
27 * targets need to be done in the order specified. This cannot be
28 * guaranteed with the way we do things, since if we are doing INCR
29 * transfers, the order will depend on the timing of the requestor.
31 * By Owen Taylor <owt1@cornell.edu> 8/16/97
34 /* Terminology note: when not otherwise specified, the term "incr" below
35 * refers to the _sending_ part of the INCR protocol. The receiving
36 * portion is referred to just as "retrieval". (Terminology borrowed
37 * from Tk, because there is no good opposite to "retrieval" in English.
38 * "send" can't be made into a noun gracefully and we're already using
39 * "emission" for something else ....)
42 /* The MOTIF entry widget seems to ask for the TARGETS target, then
43 (regardless of the reply) ask for the TEXT target. It's slightly
44 possible though that it somehow thinks we are responding negatively
45 to the TARGETS request, though I don't really think so ... */
48 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
49 * file for a list of people on the GTK+ Team. See the ChangeLog
50 * files for a list of changes. These files are distributed with
51 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
60 #include "gtkselection.h"
61 #include "gtktextbufferrichtext.h"
63 #include "gdk-pixbuf/gdk-pixbuf.h"
65 #ifdef GDK_WINDOWING_X11
69 #ifdef GDK_WINDOWING_WIN32
70 #include "win32/gdkwin32.h"
73 #undef DEBUG_SELECTION
75 /* Maximum size of a sent chunk, in bytes. Also the default size of
77 #ifdef GDK_WINDOWING_X11
78 #define GTK_SELECTION_MAX_SIZE(display) \
80 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
81 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
82 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
84 /* No chunks on Win32 */
85 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
88 #define IDLE_ABORT_TIME 30
99 typedef struct _GtkSelectionInfo GtkSelectionInfo;
100 typedef struct _GtkIncrConversion GtkIncrConversion;
101 typedef struct _GtkIncrInfo GtkIncrInfo;
102 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
104 struct _GtkSelectionInfo
107 GtkWidget *widget; /* widget that owns selection */
108 guint32 time; /* time used to acquire selection */
109 GdkDisplay *display; /* needed in gtk_selection_remove_all */
112 struct _GtkIncrConversion
114 GdkAtom target; /* Requested target */
115 GdkAtom property; /* Property to store in */
116 GtkSelectionData data; /* The data being supplied */
117 gint offset; /* Current offset in sent selection.
119 * -2 => Only the final (empty) portion
125 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
126 so we can receive events */
127 GdkAtom selection; /* Selection we're sending */
129 GtkIncrConversion *conversions; /* Information about requested conversions -
130 * With MULTIPLE requests (benighted 1980's
131 * hardware idea), there can be more than
133 gint num_conversions;
134 gint num_incrs; /* number of remaining INCR style transactions */
139 struct _GtkRetrievalInfo
142 GdkAtom selection; /* Selection being retrieved. */
143 GdkAtom target; /* Form of selection that we requested */
144 guint32 idle_time; /* Number of seconds since we last heard
145 from selection owner */
146 guchar *buffer; /* Buffer in which to accumulate results */
147 gint offset; /* Current offset in buffer, -1 indicates
149 guint32 notify_time; /* Timestamp from SelectionNotify */
152 /* Local Functions */
153 static void gtk_selection_init (void);
154 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
155 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
156 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
162 static void gtk_selection_invoke_handler (GtkWidget *widget,
163 GtkSelectionData *data,
165 static void gtk_selection_default_handler (GtkWidget *widget,
166 GtkSelectionData *data);
167 static int gtk_selection_bytes_per_item (gint format);
170 static gint initialize = TRUE;
171 static GList *current_retrievals = NULL;
172 static GList *current_incrs = NULL;
173 static GList *current_selections = NULL;
175 static GdkAtom gtk_selection_atoms[LAST_ATOM];
176 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
188 * gtk_target_list_new:
189 * @targets: Pointer to an array of #GtkTargetEntry
190 * @ntargets: number of entries in @targets.
192 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
194 * Return value: the new #GtkTargetList.
197 gtk_target_list_new (const GtkTargetEntry *targets,
200 GtkTargetList *result = g_slice_new (GtkTargetList);
202 result->ref_count = 1;
205 gtk_target_list_add_table (result, targets, ntargets);
211 * gtk_target_list_ref:
212 * @list: a #GtkTargetList
214 * Increases the reference count of a #GtkTargetList by one.
216 * Return value: the passed in #GtkTargetList.
219 gtk_target_list_ref (GtkTargetList *list)
221 g_return_val_if_fail (list != NULL, NULL);
229 * gtk_target_list_unref:
230 * @list: a #GtkTargetList
232 * Decreases the reference count of a #GtkTargetList by one.
233 * If the resulting reference count is zero, frees the list.
236 gtk_target_list_unref (GtkTargetList *list)
238 g_return_if_fail (list != NULL);
239 g_return_if_fail (list->ref_count > 0);
242 if (list->ref_count == 0)
244 GList *tmp_list = list->list;
247 GtkTargetPair *pair = tmp_list->data;
248 g_slice_free (GtkTargetPair, pair);
250 tmp_list = tmp_list->next;
253 g_list_free (list->list);
254 g_slice_free (GtkTargetList, list);
259 * gtk_target_list_add:
260 * @list: a #GtkTargetList
261 * @target: the interned atom representing the target
262 * @flags: the flags for this target
263 * @info: an ID that will be passed back to the application
265 * Appends another target to a #GtkTargetList.
268 gtk_target_list_add (GtkTargetList *list,
275 g_return_if_fail (list != NULL);
277 pair = g_slice_new (GtkTargetPair);
278 pair->target = target;
282 list->list = g_list_append (list->list, pair);
285 static GdkAtom utf8_atom;
286 static GdkAtom text_atom;
287 static GdkAtom ctext_atom;
288 static GdkAtom text_plain_atom;
289 static GdkAtom text_plain_utf8_atom;
290 static GdkAtom text_plain_locale_atom;
291 static GdkAtom text_uri_list_atom;
297 const gchar *charset;
301 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
302 text_atom = gdk_atom_intern_static_string ("TEXT");
303 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
304 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
305 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
306 g_get_charset (&charset);
307 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
308 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
311 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
316 * gtk_target_list_add_text_targets:
317 * @list: a #GtkTargetList
318 * @info: an ID that will be passed back to the application
320 * Appends the text targets supported by #GtkSelection to
321 * the target list. All targets are added with the same @info.
326 gtk_target_list_add_text_targets (GtkTargetList *list,
329 g_return_if_fail (list != NULL);
333 /* Keep in sync with gtk_selection_data_targets_include_text()
335 gtk_target_list_add (list, utf8_atom, 0, info);
336 gtk_target_list_add (list, ctext_atom, 0, info);
337 gtk_target_list_add (list, text_atom, 0, info);
338 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
339 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
340 if (!g_get_charset (NULL))
341 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
342 gtk_target_list_add (list, text_plain_atom, 0, info);
346 * gtk_target_list_add_rich_text_targets:
347 * @list: a #GtkTargetList
348 * @info: an ID that will be passed back to the application
349 * @deserializable: if %TRUE, then deserializable rich text formats
350 * will be added, serializable formats otherwise.
351 * @buffer: a #GtkTextBuffer.
353 * Appends the rich text targets registered with
354 * gtk_text_buffer_register_serialize_format() or
355 * gtk_text_buffer_register_deserialize_format() to the target list. All
356 * targets are added with the same @info.
361 gtk_target_list_add_rich_text_targets (GtkTargetList *list,
363 gboolean deserializable,
364 GtkTextBuffer *buffer)
370 g_return_if_fail (list != NULL);
371 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
374 atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
376 atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
378 for (i = 0; i < n_atoms; i++)
379 gtk_target_list_add (list, atoms[i], 0, info);
385 * gtk_target_list_add_image_targets:
386 * @list: a #GtkTargetList
387 * @info: an ID that will be passed back to the application
388 * @writable: whether to add only targets for which GTK+ knows
389 * how to convert a pixbuf into the format
391 * Appends the image targets supported by #GtkSelection to
392 * the target list. All targets are added with the same @info.
397 gtk_target_list_add_image_targets (GtkTargetList *list,
405 g_return_if_fail (list != NULL);
407 formats = gdk_pixbuf_get_formats ();
409 /* Make sure png comes first */
410 for (f = formats; f; f = f->next)
412 GdkPixbufFormat *fmt = f->data;
415 name = gdk_pixbuf_format_get_name (fmt);
416 if (strcmp (name, "png") == 0)
418 formats = g_slist_delete_link (formats, f);
419 formats = g_slist_prepend (formats, fmt);
429 for (f = formats; f; f = f->next)
431 GdkPixbufFormat *fmt = f->data;
433 if (writable && !gdk_pixbuf_format_is_writable (fmt))
436 mimes = gdk_pixbuf_format_get_mime_types (fmt);
437 for (m = mimes; *m; m++)
439 atom = gdk_atom_intern (*m, FALSE);
440 gtk_target_list_add (list, atom, 0, info);
445 g_slist_free (formats);
449 * gtk_target_list_add_uri_targets:
450 * @list: a #GtkTargetList
451 * @info: an ID that will be passed back to the application
453 * Appends the URI targets supported by #GtkSelection to
454 * the target list. All targets are added with the same @info.
459 gtk_target_list_add_uri_targets (GtkTargetList *list,
462 g_return_if_fail (list != NULL);
466 gtk_target_list_add (list, text_uri_list_atom, 0, info);
470 * gtk_target_list_add_table:
471 * @list: a #GtkTargetList
472 * @targets: the table of #GtkTargetEntry
473 * @ntargets: number of targets in the table
475 * Prepends a table of #GtkTargetEntry to a target list.
478 gtk_target_list_add_table (GtkTargetList *list,
479 const GtkTargetEntry *targets,
484 for (i=ntargets-1; i >= 0; i--)
486 GtkTargetPair *pair = g_slice_new (GtkTargetPair);
487 pair->target = gdk_atom_intern (targets[i].target, FALSE);
488 pair->flags = targets[i].flags;
489 pair->info = targets[i].info;
491 list->list = g_list_prepend (list->list, pair);
496 * gtk_target_list_remove:
497 * @list: a #GtkTargetList
498 * @target: the interned atom representing the target
500 * Removes a target from a target list.
503 gtk_target_list_remove (GtkTargetList *list,
508 g_return_if_fail (list != NULL);
510 tmp_list = list->list;
513 GtkTargetPair *pair = tmp_list->data;
515 if (pair->target == target)
517 g_slice_free (GtkTargetPair, pair);
519 list->list = g_list_remove_link (list->list, tmp_list);
520 g_list_free_1 (tmp_list);
525 tmp_list = tmp_list->next;
530 * gtk_target_list_find:
531 * @list: a #GtkTargetList
532 * @target: an interned atom representing the target to search for
533 * @info: a pointer to the location to store application info for target,
536 * Looks up a given target in a #GtkTargetList.
538 * Return value: %TRUE if the target was found, otherwise %FALSE
541 gtk_target_list_find (GtkTargetList *list,
547 g_return_val_if_fail (list != NULL, FALSE);
549 tmp_list = list->list;
552 GtkTargetPair *pair = tmp_list->data;
554 if (pair->target == target)
562 tmp_list = tmp_list->next;
569 * gtk_target_table_new_from_list:
570 * @list: a #GtkTargetList
571 * @n_targets: return location for the number ot targets in the table
573 * This function creates an #GtkTargetEntry array that contains the
574 * same targets as the passed %list. The returned table is newly
575 * allocated and should be freed using gtk_target_table_free() when no
578 * Return value: the new table.
583 gtk_target_table_new_from_list (GtkTargetList *list,
586 GtkTargetEntry *targets;
590 g_return_val_if_fail (list != NULL, NULL);
591 g_return_val_if_fail (n_targets != NULL, NULL);
593 *n_targets = g_list_length (list->list);
594 targets = g_new0 (GtkTargetEntry, *n_targets);
596 for (i = 0, tmp_list = list->list;
598 i++, tmp_list = g_list_next (tmp_list))
600 GtkTargetPair *pair = tmp_list->data;
602 targets[i].target = gdk_atom_name (pair->target);
603 targets[i].flags = pair->flags;
604 targets[i].info = pair->info;
611 * gtk_target_table_free:
612 * @targets: a #GtkTargetEntry array
613 * @n_targets: the number of entries in the array
615 * This function frees a target table as returned by
616 * gtk_target_table_new_from_list()
621 gtk_target_table_free (GtkTargetEntry *targets,
626 g_return_if_fail (targets == NULL || n_targets > 0);
628 for (i = 0; i < n_targets; i++)
629 g_free (targets[i].target);
635 * gtk_selection_owner_set_for_display:
636 * @display: the #Gdkdisplay where the selection is set
637 * @widget: (allow-none): new selection owner (a #GdkWidget), or %NULL.
638 * @selection: an interned atom representing the selection to claim.
639 * @time_: timestamp with which to claim the selection
641 * Claim ownership of a given selection for a particular widget, or,
642 * if @widget is %NULL, release ownership of the selection.
644 * Return value: TRUE if the operation succeeded
649 gtk_selection_owner_set_for_display (GdkDisplay *display,
655 GtkWidget *old_owner;
656 GtkSelectionInfo *selection_info = NULL;
659 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
660 g_return_val_if_fail (selection != GDK_NONE, FALSE);
661 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
662 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
667 window = gtk_widget_get_window (widget);
669 tmp_list = current_selections;
672 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
674 selection_info = tmp_list->data;
678 tmp_list = tmp_list->next;
681 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
689 old_owner = selection_info->widget;
690 current_selections = g_list_remove_link (current_selections,
692 g_list_free (tmp_list);
693 g_slice_free (GtkSelectionInfo, selection_info);
698 if (selection_info == NULL)
700 selection_info = g_slice_new (GtkSelectionInfo);
701 selection_info->selection = selection;
702 selection_info->widget = widget;
703 selection_info->time = time;
704 selection_info->display = display;
705 current_selections = g_list_prepend (current_selections,
710 old_owner = selection_info->widget;
711 selection_info->widget = widget;
712 selection_info->time = time;
713 selection_info->display = display;
716 /* If another widget in the application lost the selection,
717 * send it a GDK_SELECTION_CLEAR event.
719 if (old_owner && old_owner != widget)
721 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
723 event->selection.window = g_object_ref (gtk_widget_get_window (old_owner));
724 event->selection.selection = selection;
725 event->selection.time = time;
727 gtk_widget_event (old_owner, event);
729 gdk_event_free (event);
738 * gtk_selection_owner_set:
739 * @widget: (allow-none): a #GtkWidget, or %NULL.
740 * @selection: an interned atom representing the selection to claim
741 * @time_: timestamp with which to claim the selection
743 * Claims ownership of a given selection for a particular widget,
744 * or, if @widget is %NULL, release ownership of the selection.
746 * Return value: %TRUE if the operation succeeded
749 gtk_selection_owner_set (GtkWidget *widget,
755 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
756 g_return_val_if_fail (selection != GDK_NONE, FALSE);
759 display = gtk_widget_get_display (widget);
763 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
765 display = gdk_display_get_default ();
768 return gtk_selection_owner_set_for_display (display, widget,
772 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
774 struct _GtkSelectionTargetList {
779 static GtkTargetList *
780 gtk_selection_target_list_get (GtkWidget *widget,
783 GtkSelectionTargetList *sellist;
787 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
792 sellist = tmp_list->data;
793 if (sellist->selection == selection)
794 return sellist->list;
795 tmp_list = tmp_list->next;
798 sellist = g_slice_new (GtkSelectionTargetList);
799 sellist->selection = selection;
800 sellist->list = gtk_target_list_new (NULL, 0);
802 lists = g_list_prepend (lists, sellist);
803 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
805 return sellist->list;
809 gtk_selection_target_list_remove (GtkWidget *widget)
811 GtkSelectionTargetList *sellist;
815 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
820 sellist = tmp_list->data;
822 gtk_target_list_unref (sellist->list);
824 g_slice_free (GtkSelectionTargetList, sellist);
825 tmp_list = tmp_list->next;
829 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
833 * gtk_selection_clear_targets:
834 * @widget: a #GtkWidget
835 * @selection: an atom representing a selection
837 * Remove all targets registered for the given selection for the
841 gtk_selection_clear_targets (GtkWidget *widget,
844 GtkSelectionTargetList *sellist;
848 g_return_if_fail (GTK_IS_WIDGET (widget));
849 g_return_if_fail (selection != GDK_NONE);
851 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
856 sellist = tmp_list->data;
857 if (sellist->selection == selection)
859 lists = g_list_delete_link (lists, tmp_list);
860 gtk_target_list_unref (sellist->list);
861 g_slice_free (GtkSelectionTargetList, sellist);
866 tmp_list = tmp_list->next;
869 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
873 * gtk_selection_add_target:
874 * @widget: a #GtkTarget
875 * @selection: the selection
876 * @target: target to add.
877 * @info: A unsigned integer which will be passed back to the application.
879 * Appends a specified target to the list of supported targets for a
880 * given widget and selection.
883 gtk_selection_add_target (GtkWidget *widget,
890 g_return_if_fail (GTK_IS_WIDGET (widget));
891 g_return_if_fail (selection != GDK_NONE);
893 list = gtk_selection_target_list_get (widget, selection);
894 gtk_target_list_add (list, target, 0, info);
895 #ifdef GDK_WINDOWING_WIN32
896 gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target);
901 * gtk_selection_add_targets:
902 * @widget: a #GtkWidget
903 * @selection: the selection
904 * @targets: a table of targets to add
905 * @ntargets: number of entries in @targets
907 * Prepends a table of targets to the list of supported targets
908 * for a given widget and selection.
911 gtk_selection_add_targets (GtkWidget *widget,
913 const GtkTargetEntry *targets,
918 g_return_if_fail (GTK_IS_WIDGET (widget));
919 g_return_if_fail (selection != GDK_NONE);
920 g_return_if_fail (targets != NULL);
922 list = gtk_selection_target_list_get (widget, selection);
923 gtk_target_list_add_table (list, targets, ntargets);
925 #ifdef GDK_WINDOWING_WIN32
928 GdkAtom *atoms = g_new (GdkAtom, ntargets);
930 for (i = 0; i < ntargets; ++i)
931 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
932 gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, ntargets, atoms);
940 * gtk_selection_remove_all:
941 * @widget: a #GtkWidget
943 * Removes all handlers and unsets ownership of all
944 * selections for a widget. Called when widget is being
945 * destroyed. This function will not generally be
946 * called by applications.
949 gtk_selection_remove_all (GtkWidget *widget)
953 GtkSelectionInfo *selection_info;
955 g_return_if_fail (GTK_IS_WIDGET (widget));
957 /* Remove pending requests/incrs for this widget */
959 tmp_list = current_retrievals;
962 next = tmp_list->next;
963 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
965 current_retrievals = g_list_remove_link (current_retrievals,
967 /* structure will be freed in timeout */
968 g_list_free (tmp_list);
973 /* Disclaim ownership of any selections */
975 tmp_list = current_selections;
978 next = tmp_list->next;
979 selection_info = (GtkSelectionInfo *)tmp_list->data;
981 if (selection_info->widget == widget)
983 gdk_selection_owner_set_for_display (selection_info->display,
985 selection_info->selection,
986 GDK_CURRENT_TIME, FALSE);
987 current_selections = g_list_remove_link (current_selections,
989 g_list_free (tmp_list);
990 g_slice_free (GtkSelectionInfo, selection_info);
996 /* Remove all selection lists */
997 gtk_selection_target_list_remove (widget);
1002 * gtk_selection_convert:
1003 * @widget: The widget which acts as requestor
1004 * @selection: Which selection to get
1005 * @target: Form of information desired (e.g., STRING)
1006 * @time_: Time of request (usually of triggering event)
1007 In emergency, you could use #GDK_CURRENT_TIME
1009 * Requests the contents of a selection. When received,
1010 * a "selection-received" signal will be generated.
1012 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1013 * request. (e.g., there was already a request in process for
1017 gtk_selection_convert (GtkWidget *widget,
1022 GtkRetrievalInfo *info;
1024 GdkWindow *owner_window;
1025 GdkDisplay *display;
1027 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1028 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1031 gtk_selection_init ();
1033 if (!gtk_widget_get_realized (widget))
1034 gtk_widget_realize (widget);
1036 /* Check to see if there are already any retrievals in progress for
1037 this widget. If we changed GDK to use the selection for the
1038 window property in which to store the retrieved information, then
1039 we could support multiple retrievals for different selections.
1040 This might be useful for DND. */
1042 tmp_list = current_retrievals;
1045 info = (GtkRetrievalInfo *)tmp_list->data;
1046 if (info->widget == widget)
1048 tmp_list = tmp_list->next;
1051 info = g_slice_new (GtkRetrievalInfo);
1053 info->widget = widget;
1054 info->selection = selection;
1055 info->target = target;
1056 info->idle_time = 0;
1057 info->buffer = NULL;
1060 /* Check if this process has current owner. If so, call handler
1061 procedure directly to avoid deadlocks with INCR. */
1063 display = gtk_widget_get_display (widget);
1064 owner_window = gdk_selection_owner_get_for_display (display, selection);
1066 if (owner_window != NULL)
1068 GtkWidget *owner_widget;
1069 gpointer owner_widget_ptr;
1070 GtkSelectionData selection_data;
1072 selection_data.selection = selection;
1073 selection_data.target = target;
1074 selection_data.data = NULL;
1075 selection_data.length = -1;
1076 selection_data.display = display;
1078 gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1079 owner_widget = owner_widget_ptr;
1081 if (owner_widget != NULL)
1083 gtk_selection_invoke_handler (owner_widget,
1087 gtk_selection_retrieval_report (info,
1088 selection_data.type,
1089 selection_data.format,
1090 selection_data.data,
1091 selection_data.length,
1094 g_free (selection_data.data);
1095 selection_data.data = NULL;
1096 selection_data.length = -1;
1098 g_slice_free (GtkRetrievalInfo, info);
1103 /* Otherwise, we need to go through X */
1105 current_retrievals = g_list_append (current_retrievals, info);
1106 gdk_selection_convert (gtk_widget_get_window (widget), selection, target, time_);
1107 gdk_threads_add_timeout (1000,
1108 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1114 * gtk_selection_data_get_selection:
1115 * @selection_data: a pointer to a #GtkSelectionData structure.
1117 * Retrieves the selection #GdkAtom of the selection data.
1119 * Returns: the selection #GdkAtom of the selection data.
1124 gtk_selection_data_get_selection (GtkSelectionData *selection_data)
1126 g_return_val_if_fail (selection_data != NULL, 0);
1128 return selection_data->selection;
1132 * gtk_selection_data_get_target:
1133 * @selection_data: a pointer to a #GtkSelectionData structure.
1135 * Retrieves the target of the selection.
1137 * Returns: the target of the selection.
1142 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1144 g_return_val_if_fail (selection_data != NULL, 0);
1146 return selection_data->target;
1150 * gtk_selection_data_get_data_type:
1151 * @selection_data: a pointer to a #GtkSelectionData structure.
1153 * Retrieves the data type of the selection.
1155 * Returns: the data type of the selection.
1160 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1162 g_return_val_if_fail (selection_data != NULL, 0);
1164 return selection_data->type;
1168 * gtk_selection_data_get_format:
1169 * @selection_data: a pointer to a #GtkSelectionData structure.
1171 * Retrieves the format of the selection.
1173 * Returns: the format of the selection.
1178 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1180 g_return_val_if_fail (selection_data != NULL, 0);
1182 return selection_data->format;
1186 * gtk_selection_data_get_data:
1187 * @selection_data: a pointer to a #GtkSelectionData structure.
1189 * Retrieves the raw data of the selection.
1191 * Returns: the raw data of the selection.
1196 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1198 g_return_val_if_fail (selection_data != NULL, NULL);
1200 return selection_data->data;
1204 * gtk_selection_data_get_length:
1205 * @selection_data: a pointer to a #GtkSelectionData structure.
1207 * Retrieves the length of the raw data of the selection.
1209 * Returns: the length of the data of the selection.
1214 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1216 g_return_val_if_fail (selection_data != NULL, -1);
1218 return selection_data->length;
1222 * gtk_selection_data_get_display:
1223 * @selection_data: a pointer to a #GtkSelectionData structure.
1225 * Retrieves the display of the selection.
1227 * Returns: (transfer none): the display of the selection.
1232 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1234 g_return_val_if_fail (selection_data != NULL, NULL);
1236 return selection_data->display;
1240 * gtk_selection_data_set:
1241 * @selection_data: a pointer to a #GtkSelectionData structure.
1242 * @type: the type of selection data
1243 * @format: format (number of bits in a unit)
1244 * @data: pointer to the data (will be copied)
1245 * @length: length of the data
1247 * Stores new data into a #GtkSelectionData object. Should
1248 * <emphasis>only</emphasis> be called from a selection handler callback.
1249 * Zero-terminates the stored data.
1252 gtk_selection_data_set (GtkSelectionData *selection_data,
1258 g_return_if_fail (selection_data != NULL);
1260 g_free (selection_data->data);
1262 selection_data->type = type;
1263 selection_data->format = format;
1267 selection_data->data = g_new (guchar, length+1);
1268 memcpy (selection_data->data, data, length);
1269 selection_data->data[length] = 0;
1273 g_return_if_fail (length <= 0);
1276 selection_data->data = NULL;
1278 selection_data->data = (guchar *) g_strdup ("");
1281 selection_data->length = length;
1285 selection_set_string (GtkSelectionData *selection_data,
1289 gchar *tmp = g_strndup (str, len);
1290 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1295 gtk_selection_data_set (selection_data,
1296 GDK_SELECTION_TYPE_STRING,
1297 8, (guchar *) latin1, strlen (latin1));
1307 selection_set_compound_text (GtkSelectionData *selection_data,
1316 gboolean result = FALSE;
1318 tmp = g_strndup (str, len);
1319 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1320 &encoding, &format, &text, &new_length))
1322 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1323 gdk_free_compound_text (text);
1333 /* Normalize \r and \n into \r\n
1336 normalize_to_crlf (const gchar *str,
1339 GString *result = g_string_sized_new (len);
1340 const gchar *p = str;
1341 const gchar *end = str + len;
1346 g_string_append_c (result, '\r');
1350 g_string_append_c (result, *p);
1352 if (p == end || *p != '\n')
1353 g_string_append_c (result, '\n');
1358 g_string_append_c (result, *p);
1362 return g_string_free (result, FALSE);
1365 /* Normalize \r and \r\n into \n
1368 normalize_to_lf (gchar *str,
1371 GString *result = g_string_sized_new (len);
1372 const gchar *p = str;
1380 g_string_append_c (result, '\n');
1386 g_string_append_c (result, *p);
1390 return g_string_free (result, FALSE);
1394 selection_set_text_plain (GtkSelectionData *selection_data,
1398 const gchar *charset = NULL;
1400 GError *error = NULL;
1402 result = normalize_to_crlf (str, len);
1403 if (selection_data->target == text_plain_atom)
1405 else if (selection_data->target == text_plain_locale_atom)
1406 g_get_charset (&charset);
1410 gchar *tmp = result;
1411 result = g_convert_with_fallback (tmp, -1,
1413 NULL, NULL, NULL, &error);
1419 g_warning ("Error converting from %s to %s: %s",
1420 "UTF-8", charset, error->message);
1421 g_error_free (error);
1426 gtk_selection_data_set (selection_data,
1427 selection_data->target,
1428 8, (guchar *) result, strlen (result));
1435 selection_get_text_plain (GtkSelectionData *selection_data)
1437 const gchar *charset = NULL;
1438 gchar *str, *result;
1440 GError *error = NULL;
1442 str = g_strdup ((const gchar *) selection_data->data);
1443 len = selection_data->length;
1445 if (selection_data->type == text_plain_atom)
1446 charset = "ISO-8859-1";
1447 else if (selection_data->type == text_plain_locale_atom)
1448 g_get_charset (&charset);
1453 str = g_convert_with_fallback (tmp, len,
1455 NULL, NULL, &len, &error);
1460 g_warning ("Error converting from %s to %s: %s",
1461 charset, "UTF-8", error->message);
1462 g_error_free (error);
1467 else if (!g_utf8_validate (str, -1, NULL))
1469 g_warning ("Error converting from %s to %s: %s",
1470 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1476 result = normalize_to_lf (str, len);
1479 return (guchar *) result;
1483 * gtk_selection_data_set_text:
1484 * @selection_data: a #GtkSelectionData
1485 * @str: a UTF-8 string
1486 * @len: the length of @str, or -1 if @str is nul-terminated.
1488 * Sets the contents of the selection from a UTF-8 encoded string.
1489 * The string is converted to the form determined by
1490 * @selection_data->target.
1492 * Return value: %TRUE if the selection was successfully set,
1496 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1500 g_return_val_if_fail (selection_data != NULL, FALSE);
1507 if (selection_data->target == utf8_atom)
1509 gtk_selection_data_set (selection_data,
1511 8, (guchar *)str, len);
1514 else if (selection_data->target == GDK_TARGET_STRING)
1516 return selection_set_string (selection_data, str, len);
1518 else if (selection_data->target == ctext_atom ||
1519 selection_data->target == text_atom)
1521 if (selection_set_compound_text (selection_data, str, len))
1523 else if (selection_data->target == text_atom)
1524 return selection_set_string (selection_data, str, len);
1526 else if (selection_data->target == text_plain_atom ||
1527 selection_data->target == text_plain_utf8_atom ||
1528 selection_data->target == text_plain_locale_atom)
1530 return selection_set_text_plain (selection_data, str, len);
1537 * gtk_selection_data_get_text:
1538 * @selection_data: a #GtkSelectionData
1540 * Gets the contents of the selection data as a UTF-8 string.
1542 * Return value: if the selection data contained a recognized
1543 * text type and it could be converted to UTF-8, a newly allocated
1544 * string containing the converted text, otherwise %NULL.
1545 * If the result is non-%NULL it must be freed with g_free().
1548 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1550 guchar *result = NULL;
1552 g_return_val_if_fail (selection_data != NULL, NULL);
1556 if (selection_data->length >= 0 &&
1557 (selection_data->type == GDK_TARGET_STRING ||
1558 selection_data->type == ctext_atom ||
1559 selection_data->type == utf8_atom))
1563 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1564 selection_data->type,
1565 selection_data->format,
1566 selection_data->data,
1567 selection_data->length,
1570 result = (guchar *) list[0];
1572 for (i = 1; i < count; i++)
1576 else if (selection_data->length >= 0 &&
1577 (selection_data->type == text_plain_atom ||
1578 selection_data->type == text_plain_utf8_atom ||
1579 selection_data->type == text_plain_locale_atom))
1581 result = selection_get_text_plain (selection_data);
1588 * gtk_selection_data_set_pixbuf:
1589 * @selection_data: a #GtkSelectionData
1590 * @pixbuf: a #GdkPixbuf
1592 * Sets the contents of the selection from a #GdkPixbuf
1593 * The pixbuf is converted to the form determined by
1594 * @selection_data->target.
1596 * Return value: %TRUE if the selection was successfully set,
1602 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1605 GSList *formats, *f;
1612 g_return_val_if_fail (selection_data != NULL, FALSE);
1613 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1615 formats = gdk_pixbuf_get_formats ();
1617 for (f = formats; f; f = f->next)
1619 GdkPixbufFormat *fmt = f->data;
1621 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1622 for (m = mimes; *m; m++)
1624 atom = gdk_atom_intern (*m, FALSE);
1625 if (selection_data->target == atom)
1628 type = gdk_pixbuf_format_get_name (fmt);
1629 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1631 ((strcmp (type, "png") == 0) ?
1632 "compression" : NULL), "2",
1635 gtk_selection_data_set (selection_data,
1636 atom, 8, (guchar *)str, len);
1640 g_slist_free (formats);
1649 g_slist_free (formats);
1655 * gtk_selection_data_get_pixbuf:
1656 * @selection_data: a #GtkSelectionData
1658 * Gets the contents of the selection data as a #GdkPixbuf.
1660 * Return value: (transfer full): if the selection data contained a recognized
1661 * image type and it could be converted to a #GdkPixbuf, a
1662 * newly allocated pixbuf is returned, otherwise %NULL.
1663 * If the result is non-%NULL it must be freed with g_object_unref().
1668 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1670 GdkPixbufLoader *loader;
1671 GdkPixbuf *result = NULL;
1673 g_return_val_if_fail (selection_data != NULL, NULL);
1675 if (selection_data->length > 0)
1677 loader = gdk_pixbuf_loader_new ();
1679 gdk_pixbuf_loader_write (loader,
1680 selection_data->data,
1681 selection_data->length,
1683 gdk_pixbuf_loader_close (loader, NULL);
1684 result = gdk_pixbuf_loader_get_pixbuf (loader);
1687 g_object_ref (result);
1689 g_object_unref (loader);
1696 * gtk_selection_data_set_uris:
1697 * @selection_data: a #GtkSelectionData
1698 * @uris: a %NULL-terminated array of strings holding URIs
1700 * Sets the contents of the selection from a list of URIs.
1701 * The string is converted to the form determined by
1702 * @selection_data->target.
1704 * Return value: %TRUE if the selection was successfully set,
1710 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1713 g_return_val_if_fail (selection_data != NULL, FALSE);
1714 g_return_val_if_fail (uris != NULL, FALSE);
1718 if (selection_data->target == text_uri_list_atom)
1725 list = g_string_new (NULL);
1726 for (i = 0; uris[i]; i++)
1728 g_string_append (list, uris[i]);
1729 g_string_append (list, "\r\n");
1732 result = g_convert (list->str, list->len,
1734 NULL, &length, NULL);
1735 g_string_free (list, TRUE);
1739 gtk_selection_data_set (selection_data,
1741 8, (guchar *)result, length);
1753 * gtk_selection_data_get_uris:
1754 * @selection_data: a #GtkSelectionData
1756 * Gets the contents of the selection data as array of URIs.
1758 * Return value: (array zero-terminated=1) (element-type utf8) (transfer full): if
1759 * the selection data contains a list of
1760 * URIs, a newly allocated %NULL-terminated string array
1761 * containing the URIs, otherwise %NULL. If the result is
1762 * non-%NULL it must be freed with g_strfreev().
1767 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1769 gchar **result = NULL;
1771 g_return_val_if_fail (selection_data != NULL, NULL);
1775 if (selection_data->length >= 0 &&
1776 selection_data->type == text_uri_list_atom)
1779 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1781 selection_data->format,
1782 selection_data->data,
1783 selection_data->length,
1786 result = g_uri_list_extract_uris (list[0]);
1796 * gtk_selection_data_get_targets:
1797 * @selection_data: a #GtkSelectionData object
1798 * @targets: location to store an array of targets. The result
1799 * stored here must be freed with g_free().
1800 * @n_atoms: location to store number of items in @targets.
1802 * Gets the contents of @selection_data as an array of targets.
1803 * This can be used to interpret the results of getting
1804 * the standard TARGETS target that is always supplied for
1807 * Return value: %TRUE if @selection_data contains a valid
1808 * array of targets, otherwise %FALSE.
1811 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1815 g_return_val_if_fail (selection_data != NULL, FALSE);
1817 if (selection_data->length >= 0 &&
1818 selection_data->format == 32 &&
1819 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1822 *targets = g_memdup (selection_data->data, selection_data->length);
1824 *n_atoms = selection_data->length / sizeof (GdkAtom);
1840 * gtk_targets_include_text:
1841 * @targets: an array of #GdkAtom<!-- -->s
1842 * @n_targets: the length of @targets
1844 * Determines if any of the targets in @targets can be used to
1847 * Return value: %TRUE if @targets include a suitable target for text,
1853 gtk_targets_include_text (GdkAtom *targets,
1857 gboolean result = FALSE;
1859 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1861 /* Keep in sync with gtk_target_list_add_text_targets()
1866 for (i = 0; i < n_targets; i++)
1868 if (targets[i] == utf8_atom ||
1869 targets[i] == text_atom ||
1870 targets[i] == GDK_TARGET_STRING ||
1871 targets[i] == ctext_atom ||
1872 targets[i] == text_plain_atom ||
1873 targets[i] == text_plain_utf8_atom ||
1874 targets[i] == text_plain_locale_atom)
1885 * gtk_targets_include_rich_text:
1886 * @targets: an array of #GdkAtom<!-- -->s
1887 * @n_targets: the length of @targets
1888 * @buffer: a #GtkTextBuffer
1890 * Determines if any of the targets in @targets can be used to
1891 * provide rich text.
1893 * Return value: %TRUE if @targets include a suitable target for rich text,
1899 gtk_targets_include_rich_text (GdkAtom *targets,
1901 GtkTextBuffer *buffer)
1903 GdkAtom *rich_targets;
1904 gint n_rich_targets;
1906 gboolean result = FALSE;
1908 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1909 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1913 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1916 for (i = 0; i < n_targets; i++)
1918 for (j = 0; j < n_rich_targets; j++)
1920 if (targets[i] == rich_targets[j])
1929 g_free (rich_targets);
1935 * gtk_selection_data_targets_include_text:
1936 * @selection_data: a #GtkSelectionData object
1938 * Given a #GtkSelectionData object holding a list of targets,
1939 * determines if any of the targets in @targets can be used to
1942 * Return value: %TRUE if @selection_data holds a list of targets,
1943 * and a suitable target for text is included, otherwise %FALSE.
1946 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1950 gboolean result = FALSE;
1952 g_return_val_if_fail (selection_data != NULL, FALSE);
1956 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1958 result = gtk_targets_include_text (targets, n_targets);
1966 * gtk_selection_data_targets_include_rich_text:
1967 * @selection_data: a #GtkSelectionData object
1968 * @buffer: a #GtkTextBuffer
1970 * Given a #GtkSelectionData object holding a list of targets,
1971 * determines if any of the targets in @targets can be used to
1972 * provide rich text.
1974 * Return value: %TRUE if @selection_data holds a list of targets,
1975 * and a suitable target for rich text is included,
1981 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1982 GtkTextBuffer *buffer)
1986 gboolean result = FALSE;
1988 g_return_val_if_fail (selection_data != NULL, FALSE);
1989 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1993 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1995 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2003 * gtk_targets_include_image:
2004 * @targets: an array of #GdkAtom<!-- -->s
2005 * @n_targets: the length of @targets
2006 * @writable: whether to accept only targets for which GTK+ knows
2007 * how to convert a pixbuf into the format
2009 * Determines if any of the targets in @targets can be used to
2010 * provide a #GdkPixbuf.
2012 * Return value: %TRUE if @targets include a suitable target for images,
2018 gtk_targets_include_image (GdkAtom *targets,
2022 GtkTargetList *list;
2025 gboolean result = FALSE;
2027 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2029 list = gtk_target_list_new (NULL, 0);
2030 gtk_target_list_add_image_targets (list, 0, writable);
2031 for (i = 0; i < n_targets && !result; i++)
2033 for (l = list->list; l; l = l->next)
2035 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2036 if (pair->target == targets[i])
2043 gtk_target_list_unref (list);
2049 * gtk_selection_data_targets_include_image:
2050 * @selection_data: a #GtkSelectionData object
2051 * @writable: whether to accept only targets for which GTK+ knows
2052 * how to convert a pixbuf into the format
2054 * Given a #GtkSelectionData object holding a list of targets,
2055 * determines if any of the targets in @targets can be used to
2056 * provide a #GdkPixbuf.
2058 * Return value: %TRUE if @selection_data holds a list of targets,
2059 * and a suitable target for images is included, otherwise %FALSE.
2064 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2069 gboolean result = FALSE;
2071 g_return_val_if_fail (selection_data != NULL, FALSE);
2075 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2077 result = gtk_targets_include_image (targets, n_targets, writable);
2085 * gtk_targets_include_uri:
2086 * @targets: an array of #GdkAtom<!-- -->s
2087 * @n_targets: the length of @targets
2089 * Determines if any of the targets in @targets can be used to
2090 * provide an uri list.
2092 * Return value: %TRUE if @targets include a suitable target for uri lists,
2098 gtk_targets_include_uri (GdkAtom *targets,
2102 gboolean result = FALSE;
2104 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2106 /* Keep in sync with gtk_target_list_add_uri_targets()
2111 for (i = 0; i < n_targets; i++)
2113 if (targets[i] == text_uri_list_atom)
2124 * gtk_selection_data_targets_include_uri:
2125 * @selection_data: a #GtkSelectionData object
2127 * Given a #GtkSelectionData object holding a list of targets,
2128 * determines if any of the targets in @targets can be used to
2129 * provide a list or URIs.
2131 * Return value: %TRUE if @selection_data holds a list of targets,
2132 * and a suitable target for URI lists is included, otherwise %FALSE.
2137 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2141 gboolean result = FALSE;
2143 g_return_val_if_fail (selection_data != NULL, FALSE);
2147 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2149 result = gtk_targets_include_uri (targets, n_targets);
2157 /*************************************************************
2158 * gtk_selection_init:
2159 * Initialize local variables
2163 *************************************************************/
2166 gtk_selection_init (void)
2168 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2169 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2170 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2171 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2172 gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS");
2178 * _gtk_selection_clear:
2179 * @widget: a #GtkWidget
2182 * The default handler for the #GtkWidget::selection-clear-event
2185 * Return value: %TRUE if the event was handled, otherwise false
2188 _gtk_selection_clear (GtkWidget *widget,
2189 GdkEventSelection *event)
2191 /* Note that we filter clear events in gdkselection-x11.c, so
2192 * that we only will get here if the clear event actually
2193 * represents a change that we didn't do ourself.
2196 GtkSelectionInfo *selection_info = NULL;
2198 tmp_list = current_selections;
2201 selection_info = (GtkSelectionInfo *)tmp_list->data;
2203 if ((selection_info->selection == event->selection) &&
2204 (selection_info->widget == widget))
2207 tmp_list = tmp_list->next;
2212 current_selections = g_list_remove_link (current_selections, tmp_list);
2213 g_list_free (tmp_list);
2214 g_slice_free (GtkSelectionInfo, selection_info);
2221 /*************************************************************
2222 * _gtk_selection_request:
2223 * Handler for "selection_request_event"
2228 *************************************************************/
2231 _gtk_selection_request (GtkWidget *widget,
2232 GdkEventSelection *event)
2234 GdkDisplay *display = gtk_widget_get_display (widget);
2238 gulong selection_max_size;
2241 gtk_selection_init ();
2243 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2245 /* Check if we own selection */
2247 tmp_list = current_selections;
2250 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2252 if ((selection_info->selection == event->selection) &&
2253 (selection_info->widget == widget))
2256 tmp_list = tmp_list->next;
2259 if (tmp_list == NULL)
2262 info = g_slice_new (GtkIncrInfo);
2264 g_object_ref (widget);
2266 info->selection = event->selection;
2267 info->num_incrs = 0;
2269 /* Create GdkWindow structure for the requestor */
2271 info->requestor = gdk_window_lookup_for_display (display,
2273 if (!info->requestor)
2274 info->requestor = gdk_window_foreign_new_for_display (display,
2277 /* Determine conversions we need to perform */
2279 if (event->target == gtk_selection_atoms[MULTIPLE])
2288 gdk_error_trap_push ();
2289 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2290 0, selection_max_size, FALSE,
2291 &type, &format, &length, &mult_atoms))
2293 gdk_selection_send_notify_for_display (display,
2299 g_free (mult_atoms);
2300 g_slice_free (GtkIncrInfo, info);
2301 gdk_error_trap_pop_ignored ();
2304 gdk_error_trap_pop_ignored ();
2306 /* This is annoying; the ICCCM doesn't specify the property type
2307 * used for the property contents, so the autoconversion for
2308 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2310 #ifdef GDK_WINDOWING_X11
2311 if (type != GDK_SELECTION_TYPE_ATOM &&
2312 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2314 info->num_conversions = length / (2*sizeof (glong));
2315 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2317 for (i=0; i<info->num_conversions; i++)
2319 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2320 ((glong *)mult_atoms)[2*i]);
2321 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2322 ((glong *)mult_atoms)[2*i + 1]);
2325 g_free (mult_atoms);
2330 info->num_conversions = length / (2*sizeof (GdkAtom));
2331 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2333 for (i=0; i<info->num_conversions; i++)
2335 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2336 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2339 g_free (mult_atoms);
2342 else /* only a single conversion */
2344 info->conversions = g_new (GtkIncrConversion, 1);
2345 info->num_conversions = 1;
2346 info->conversions[0].target = event->target;
2347 info->conversions[0].property = event->property;
2350 /* Loop through conversions and determine which of these are big
2351 enough to require doing them via INCR */
2352 for (i=0; i<info->num_conversions; i++)
2354 GtkSelectionData data;
2357 data.selection = event->selection;
2358 data.target = info->conversions[i].target;
2361 data.display = gtk_widget_get_display (widget);
2363 #ifdef DEBUG_SELECTION
2364 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2366 info->conversions[i].target,
2367 gdk_atom_name (info->conversions[i].target),
2368 event->requestor, info->conversions[i].property);
2371 gtk_selection_invoke_handler (widget, &data, event->time);
2372 if (data.length < 0)
2374 info->conversions[i].property = GDK_NONE;
2378 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2380 items = data.length / gtk_selection_bytes_per_item (data.format);
2382 if (data.length > selection_max_size)
2384 /* Sending via INCR */
2385 #ifdef DEBUG_SELECTION
2386 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2387 data.length, selection_max_size);
2390 info->conversions[i].offset = 0;
2391 info->conversions[i].data = data;
2394 gdk_property_change (info->requestor,
2395 info->conversions[i].property,
2396 gtk_selection_atoms[INCR],
2398 GDK_PROP_MODE_REPLACE,
2399 (guchar *)&items, 1);
2403 info->conversions[i].offset = -1;
2405 gdk_property_change (info->requestor,
2406 info->conversions[i].property,
2409 GDK_PROP_MODE_REPLACE,
2416 /* If we have some INCR's, we need to send the rest of the data in
2419 if (info->num_incrs > 0)
2421 /* FIXME: this could be dangerous if window doesn't still
2424 #ifdef DEBUG_SELECTION
2425 g_message ("Starting INCR...");
2428 gdk_window_set_events (info->requestor,
2429 gdk_window_get_events (info->requestor) |
2430 GDK_PROPERTY_CHANGE_MASK);
2431 current_incrs = g_list_append (current_incrs, info);
2432 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2435 /* If it was a MULTIPLE request, set the property to indicate which
2436 conversions succeeded */
2437 if (event->target == gtk_selection_atoms[MULTIPLE])
2439 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2440 for (i = 0; i < info->num_conversions; i++)
2442 mult_atoms[2*i] = info->conversions[i].target;
2443 mult_atoms[2*i+1] = info->conversions[i].property;
2446 gdk_property_change (info->requestor, event->property,
2447 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2448 GDK_PROP_MODE_REPLACE,
2449 (guchar *)mult_atoms, 2*info->num_conversions);
2450 g_free (mult_atoms);
2453 if (info->num_conversions == 1 &&
2454 info->conversions[0].property == GDK_NONE)
2456 /* Reject the entire conversion */
2457 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2466 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2474 if (info->num_incrs == 0)
2476 g_free (info->conversions);
2477 g_slice_free (GtkIncrInfo, info);
2480 g_object_unref (widget);
2485 /*************************************************************
2486 * _gtk_selection_incr_event:
2487 * Called whenever an PropertyNotify event occurs for an
2488 * GdkWindow with user_data == NULL. These will be notifications
2489 * that a window we are sending the selection to via the
2490 * INCR protocol has deleted a property and is ready for
2494 * window: the requestor window
2495 * event: the property event structure
2498 *************************************************************/
2501 _gtk_selection_incr_event (GdkWindow *window,
2502 GdkEventProperty *event)
2505 GtkIncrInfo *info = NULL;
2508 gulong selection_max_size;
2512 if (event->state != GDK_PROPERTY_DELETE)
2515 #ifdef DEBUG_SELECTION
2516 g_message ("PropertyDelete, property %ld", event->atom);
2519 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2521 /* Now find the appropriate ongoing INCR */
2522 tmp_list = current_incrs;
2525 info = (GtkIncrInfo *)tmp_list->data;
2526 if (info->requestor == event->window)
2529 tmp_list = tmp_list->next;
2532 if (tmp_list == NULL)
2535 /* Find out which target this is for */
2536 for (i=0; i<info->num_conversions; i++)
2538 if (info->conversions[i].property == event->atom &&
2539 info->conversions[i].offset != -1)
2543 info->idle_time = 0;
2545 if (info->conversions[i].offset == -2) /* only the last 0-length
2553 num_bytes = info->conversions[i].data.length -
2554 info->conversions[i].offset;
2555 buffer = info->conversions[i].data.data +
2556 info->conversions[i].offset;
2558 if (num_bytes > selection_max_size)
2560 num_bytes = selection_max_size;
2561 info->conversions[i].offset += selection_max_size;
2564 info->conversions[i].offset = -2;
2566 #ifdef DEBUG_SELECTION
2567 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2568 num_bytes, info->conversions[i].offset,
2569 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2572 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2573 gdk_property_change (info->requestor, event->atom,
2574 info->conversions[i].data.type,
2575 info->conversions[i].data.format,
2576 GDK_PROP_MODE_REPLACE,
2578 num_bytes / bytes_per_item);
2580 if (info->conversions[i].offset == -2)
2582 g_free (info->conversions[i].data.data);
2583 info->conversions[i].data.data = NULL;
2589 info->conversions[i].offset = -1;
2594 /* Check if we're finished with all the targets */
2596 if (info->num_incrs == 0)
2598 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2599 g_list_free (tmp_list);
2600 /* Let the timeout free it */
2606 /*************************************************************
2607 * gtk_selection_incr_timeout:
2608 * Timeout callback for the sending portion of the INCR
2611 * info: Information about this incr
2613 *************************************************************/
2616 gtk_selection_incr_timeout (GtkIncrInfo *info)
2621 /* Determine if retrieval has finished by checking if it still in
2622 list of pending retrievals */
2624 tmp_list = current_incrs;
2627 if (info == (GtkIncrInfo *)tmp_list->data)
2629 tmp_list = tmp_list->next;
2632 /* If retrieval is finished */
2633 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2635 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2637 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2638 g_list_free (tmp_list);
2641 g_free (info->conversions);
2642 /* FIXME: we should check if requestor window is still in use,
2643 and if not, remove it? */
2645 g_slice_free (GtkIncrInfo, info);
2647 retval = FALSE; /* remove timeout */
2653 retval = TRUE; /* timeout will happen again */
2659 /*************************************************************
2660 * _gtk_selection_notify:
2661 * Handler for "selection-notify-event" signals on windows
2662 * where a retrieval is currently in process. The selection
2663 * owner has responded to our conversion request.
2665 * widget: Widget getting signal
2666 * event: Selection event structure
2667 * info: Information about this retrieval
2669 * was event handled?
2670 *************************************************************/
2673 _gtk_selection_notify (GtkWidget *widget,
2674 GdkEventSelection *event)
2677 GtkRetrievalInfo *info = NULL;
2679 guchar *buffer = NULL;
2684 #ifdef DEBUG_SELECTION
2685 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2686 event->selection, event->target, event->property);
2689 window = gtk_widget_get_window (widget);
2691 tmp_list = current_retrievals;
2694 info = (GtkRetrievalInfo *)tmp_list->data;
2695 if (info->widget == widget && info->selection == event->selection)
2697 tmp_list = tmp_list->next;
2700 if (!tmp_list) /* no retrieval in progress */
2703 if (event->property != GDK_NONE)
2704 length = gdk_selection_property_get (window, &buffer,
2707 length = 0; /* silence gcc */
2709 if (event->property == GDK_NONE || buffer == NULL)
2711 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2712 g_list_free (tmp_list);
2713 /* structure will be freed in timeout */
2714 gtk_selection_retrieval_report (info,
2715 GDK_NONE, 0, NULL, -1, event->time);
2720 if (type == gtk_selection_atoms[INCR])
2722 /* The remainder of the selection will come through PropertyNotify
2725 info->notify_time = event->time;
2726 info->idle_time = 0;
2727 info->offset = 0; /* Mark as OK to proceed */
2728 gdk_window_set_events (window,
2729 gdk_window_get_events (window)
2730 | GDK_PROPERTY_CHANGE_MASK);
2734 /* We don't delete the info structure - that will happen in timeout */
2735 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2736 g_list_free (tmp_list);
2738 info->offset = length;
2739 gtk_selection_retrieval_report (info,
2741 buffer, length, event->time);
2744 gdk_property_delete (window, event->property);
2751 /*************************************************************
2752 * _gtk_selection_property_notify:
2753 * Handler for "property-notify-event" signals on windows
2754 * where a retrieval is currently in process. The selection
2755 * owner has added more data.
2757 * widget: Widget getting signal
2758 * event: Property event structure
2759 * info: Information about this retrieval
2761 * was event handled?
2762 *************************************************************/
2765 _gtk_selection_property_notify (GtkWidget *widget,
2766 GdkEventProperty *event)
2769 GtkRetrievalInfo *info = NULL;
2776 g_return_val_if_fail (widget != NULL, FALSE);
2777 g_return_val_if_fail (event != NULL, FALSE);
2779 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2780 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2781 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2785 #ifdef DEBUG_SELECTION
2786 g_message ("PropertyNewValue, property %ld",
2790 tmp_list = current_retrievals;
2793 info = (GtkRetrievalInfo *)tmp_list->data;
2794 if (info->widget == widget)
2796 tmp_list = tmp_list->next;
2799 if (!tmp_list) /* No retrieval in progress */
2802 if (info->offset < 0) /* We haven't got the SelectionNotify
2803 for this retrieval yet */
2806 info->idle_time = 0;
2808 window = gtk_widget_get_window (widget);
2809 length = gdk_selection_property_get (window, &new_buffer,
2811 gdk_property_delete (window, event->atom);
2813 /* We could do a lot better efficiency-wise by paying attention to
2814 what length was sent in the initial INCR transaction, instead of
2815 doing memory allocation at every step. But its only guaranteed to
2816 be a _lower bound_ (pretty useless!) */
2818 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2820 /* Info structure will be freed in timeout */
2821 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2822 g_list_free (tmp_list);
2823 gtk_selection_retrieval_report (info,
2825 (type == GDK_NONE) ? NULL : info->buffer,
2826 (type == GDK_NONE) ? -1 : info->offset,
2829 else /* append on newly arrived data */
2833 #ifdef DEBUG_SELECTION
2834 g_message ("Start - Adding %d bytes at offset 0",
2837 info->buffer = new_buffer;
2838 info->offset = length;
2843 #ifdef DEBUG_SELECTION
2844 g_message ("Appending %d bytes at offset %d",
2845 length,info->offset);
2847 /* We copy length+1 bytes to preserve guaranteed null termination */
2848 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2849 memcpy (info->buffer + info->offset, new_buffer, length+1);
2850 info->offset += length;
2851 g_free (new_buffer);
2858 /*************************************************************
2859 * gtk_selection_retrieval_timeout:
2860 * Timeout callback while receiving a selection.
2862 * info: Information about this retrieval
2864 *************************************************************/
2867 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2872 /* Determine if retrieval has finished by checking if it still in
2873 list of pending retrievals */
2875 tmp_list = current_retrievals;
2878 if (info == (GtkRetrievalInfo *)tmp_list->data)
2880 tmp_list = tmp_list->next;
2883 /* If retrieval is finished */
2884 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2886 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2888 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2889 g_list_free (tmp_list);
2890 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2893 g_free (info->buffer);
2894 g_slice_free (GtkRetrievalInfo, info);
2896 retval = FALSE; /* remove timeout */
2902 retval = TRUE; /* timeout will happen again */
2908 /*************************************************************
2909 * gtk_selection_retrieval_report:
2910 * Emits a "selection-received" signal.
2912 * info: information about the retrieval that completed
2913 * buffer: buffer containing data (NULL => errror)
2914 * time: timestamp for data in buffer
2916 *************************************************************/
2919 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2920 GdkAtom type, gint format,
2921 guchar *buffer, gint length,
2924 GtkSelectionData data;
2926 data.selection = info->selection;
2927 data.target = info->target;
2929 data.format = format;
2931 data.length = length;
2933 data.display = gtk_widget_get_display (info->widget);
2935 g_signal_emit_by_name (info->widget,
2936 "selection-received",
2940 /*************************************************************
2941 * gtk_selection_invoke_handler:
2942 * Finds and invokes handler for specified
2943 * widget/selection/target combination, calls
2944 * gtk_selection_default_handler if none exists.
2947 * widget: selection owner
2948 * data: selection data [INOUT]
2949 * time: time from requeset
2952 * Number of bytes written to buffer, -1 if error
2953 *************************************************************/
2956 gtk_selection_invoke_handler (GtkWidget *widget,
2957 GtkSelectionData *data,
2960 GtkTargetList *target_list;
2964 g_return_if_fail (widget != NULL);
2966 target_list = gtk_selection_target_list_get (widget, data->selection);
2967 if (data->target != gtk_selection_atoms[SAVE_TARGETS] &&
2969 gtk_target_list_find (target_list, data->target, &info))
2971 g_signal_emit_by_name (widget,
2977 gtk_selection_default_handler (widget, data);
2980 /*************************************************************
2981 * gtk_selection_default_handler:
2982 * Handles some default targets that exist for any widget
2983 * If it can't fit results into buffer, returns -1. This
2984 * won't happen in any conceivable case, since it would
2985 * require 1000 selection targets!
2988 * widget: selection owner
2989 * data: selection data [INOUT]
2991 *************************************************************/
2994 gtk_selection_default_handler (GtkWidget *widget,
2995 GtkSelectionData *data)
2997 if (data->target == gtk_selection_atoms[TIMESTAMP])
2999 /* Time which was used to obtain selection */
3001 GtkSelectionInfo *selection_info;
3003 tmp_list = current_selections;
3006 selection_info = (GtkSelectionInfo *)tmp_list->data;
3007 if ((selection_info->widget == widget) &&
3008 (selection_info->selection == data->selection))
3010 gulong time = selection_info->time;
3012 gtk_selection_data_set (data,
3013 GDK_SELECTION_TYPE_INTEGER,
3020 tmp_list = tmp_list->next;
3025 else if (data->target == gtk_selection_atoms[TARGETS])
3027 /* List of all targets supported for this widget/selection pair */
3031 GtkTargetList *target_list;
3032 GtkTargetPair *pair;
3034 target_list = gtk_selection_target_list_get (widget,
3036 count = g_list_length (target_list->list) + 3;
3038 data->type = GDK_SELECTION_TYPE_ATOM;
3040 data->length = count * sizeof (GdkAtom);
3042 /* selection data is always terminated by a trailing \0
3044 p = g_malloc (data->length + 1);
3045 data->data = (guchar *)p;
3046 data->data[data->length] = '\0';
3048 *p++ = gtk_selection_atoms[TIMESTAMP];
3049 *p++ = gtk_selection_atoms[TARGETS];
3050 *p++ = gtk_selection_atoms[MULTIPLE];
3052 tmp_list = target_list->list;
3055 pair = (GtkTargetPair *)tmp_list->data;
3056 *p++ = pair->target;
3058 tmp_list = tmp_list->next;
3061 else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
3063 gtk_selection_data_set (data,
3064 gdk_atom_intern_static_string ("NULL"),
3075 * gtk_selection_data_copy:
3076 * @data: a pointer to a #GtkSelectionData structure.
3078 * Makes a copy of a #GtkSelectionData structure and its data.
3080 * Return value: a pointer to a copy of @data.
3083 gtk_selection_data_copy (GtkSelectionData *data)
3085 GtkSelectionData *new_data;
3087 g_return_val_if_fail (data != NULL, NULL);
3089 new_data = g_slice_new (GtkSelectionData);
3094 new_data->data = g_malloc (data->length + 1);
3095 memcpy (new_data->data, data->data, data->length + 1);
3102 * gtk_selection_data_free:
3103 * @data: a pointer to a #GtkSelectionData structure.
3105 * Frees a #GtkSelectionData structure returned from
3106 * gtk_selection_data_copy().
3109 gtk_selection_data_free (GtkSelectionData *data)
3111 g_return_if_fail (data != NULL);
3113 g_free (data->data);
3115 g_slice_free (GtkSelectionData, data);
3118 G_DEFINE_BOXED_TYPE (GtkSelectionData, gtk_selection_data,
3119 gtk_selection_data_copy,
3120 gtk_selection_data_free)
3122 G_DEFINE_BOXED_TYPE (GtkTargetList, gtk_target_list,
3123 gtk_target_list_ref,
3124 gtk_target_list_unref)
3127 gtk_selection_bytes_per_item (gint format)
3132 return sizeof (char);
3135 return sizeof (short);
3138 return sizeof (long);
3141 g_assert_not_reached();