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"
75 #undef DEBUG_SELECTION
77 /* Maximum size of a sent chunk, in bytes. Also the default size of
79 #ifdef GDK_WINDOWING_X11
80 #define GTK_SELECTION_MAX_SIZE(display) \
82 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
83 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
84 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
86 /* No chunks on Win32 */
87 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
90 #define IDLE_ABORT_TIME 30
101 typedef struct _GtkSelectionInfo GtkSelectionInfo;
102 typedef struct _GtkIncrConversion GtkIncrConversion;
103 typedef struct _GtkIncrInfo GtkIncrInfo;
104 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
106 struct _GtkSelectionInfo
109 GtkWidget *widget; /* widget that owns selection */
110 guint32 time; /* time used to acquire selection */
111 GdkDisplay *display; /* needed in gtk_selection_remove_all */
114 struct _GtkIncrConversion
116 GdkAtom target; /* Requested target */
117 GdkAtom property; /* Property to store in */
118 GtkSelectionData data; /* The data being supplied */
119 gint offset; /* Current offset in sent selection.
121 * -2 => Only the final (empty) portion
127 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
128 so we can receive events */
129 GdkAtom selection; /* Selection we're sending */
131 GtkIncrConversion *conversions; /* Information about requested conversions -
132 * With MULTIPLE requests (benighted 1980's
133 * hardware idea), there can be more than
135 gint num_conversions;
136 gint num_incrs; /* number of remaining INCR style transactions */
141 struct _GtkRetrievalInfo
144 GdkAtom selection; /* Selection being retrieved. */
145 GdkAtom target; /* Form of selection that we requested */
146 guint32 idle_time; /* Number of seconds since we last heard
147 from selection owner */
148 guchar *buffer; /* Buffer in which to accumulate results */
149 gint offset; /* Current offset in buffer, -1 indicates
151 guint32 notify_time; /* Timestamp from SelectionNotify */
154 /* Local Functions */
155 static void gtk_selection_init (void);
156 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
157 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
158 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
164 static void gtk_selection_invoke_handler (GtkWidget *widget,
165 GtkSelectionData *data,
167 static void gtk_selection_default_handler (GtkWidget *widget,
168 GtkSelectionData *data);
169 static int gtk_selection_bytes_per_item (gint format);
172 static gint initialize = TRUE;
173 static GList *current_retrievals = NULL;
174 static GList *current_incrs = NULL;
175 static GList *current_selections = NULL;
177 static GdkAtom gtk_selection_atoms[LAST_ATOM];
178 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
190 * gtk_target_list_new:
191 * @targets: Pointer to an array of #GtkTargetEntry
192 * @ntargets: number of entries in @targets.
194 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
196 * Return value: the new #GtkTargetList.
199 gtk_target_list_new (const GtkTargetEntry *targets,
202 GtkTargetList *result = g_slice_new (GtkTargetList);
204 result->ref_count = 1;
207 gtk_target_list_add_table (result, targets, ntargets);
213 * gtk_target_list_ref:
214 * @list: a #GtkTargetList
216 * Increases the reference count of a #GtkTargetList by one.
218 * Return value: the passed in #GtkTargetList.
221 gtk_target_list_ref (GtkTargetList *list)
223 g_return_val_if_fail (list != NULL, NULL);
231 * gtk_target_list_unref:
232 * @list: a #GtkTargetList
234 * Decreases the reference count of a #GtkTargetList by one.
235 * If the resulting reference count is zero, frees the list.
238 gtk_target_list_unref (GtkTargetList *list)
240 g_return_if_fail (list != NULL);
241 g_return_if_fail (list->ref_count > 0);
244 if (list->ref_count == 0)
246 GList *tmp_list = list->list;
249 GtkTargetPair *pair = tmp_list->data;
250 g_slice_free (GtkTargetPair, pair);
252 tmp_list = tmp_list->next;
255 g_list_free (list->list);
256 g_slice_free (GtkTargetList, list);
261 * gtk_target_list_add:
262 * @list: a #GtkTargetList
263 * @target: the interned atom representing the target
264 * @flags: the flags for this target
265 * @info: an ID that will be passed back to the application
267 * Appends another target to a #GtkTargetList.
270 gtk_target_list_add (GtkTargetList *list,
277 g_return_if_fail (list != NULL);
279 pair = g_slice_new (GtkTargetPair);
280 pair->target = target;
284 list->list = g_list_append (list->list, pair);
287 static GdkAtom utf8_atom;
288 static GdkAtom text_atom;
289 static GdkAtom ctext_atom;
290 static GdkAtom text_plain_atom;
291 static GdkAtom text_plain_utf8_atom;
292 static GdkAtom text_plain_locale_atom;
293 static GdkAtom text_uri_list_atom;
299 const gchar *charset;
303 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
304 text_atom = gdk_atom_intern_static_string ("TEXT");
305 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
306 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
307 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
308 g_get_charset (&charset);
309 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
310 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
313 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
318 * gtk_target_list_add_text_targets:
319 * @list: a #GtkTargetList
320 * @info: an ID that will be passed back to the application
322 * Appends the text targets supported by #GtkSelection to
323 * the target list. All targets are added with the same @info.
328 gtk_target_list_add_text_targets (GtkTargetList *list,
331 g_return_if_fail (list != NULL);
335 /* Keep in sync with gtk_selection_data_targets_include_text()
337 gtk_target_list_add (list, utf8_atom, 0, info);
338 gtk_target_list_add (list, ctext_atom, 0, info);
339 gtk_target_list_add (list, text_atom, 0, info);
340 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
341 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
342 if (!g_get_charset (NULL))
343 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
344 gtk_target_list_add (list, text_plain_atom, 0, info);
348 * gtk_target_list_add_rich_text_targets:
349 * @list: a #GtkTargetList
350 * @info: an ID that will be passed back to the application
351 * @deserializable: if %TRUE, then deserializable rich text formats
352 * will be added, serializable formats otherwise.
353 * @buffer: a #GtkTextBuffer.
355 * Appends the rich text targets registered with
356 * gtk_text_buffer_register_serialize_format() or
357 * gtk_text_buffer_register_deserialize_format() to the target list. All
358 * targets are added with the same @info.
363 gtk_target_list_add_rich_text_targets (GtkTargetList *list,
365 gboolean deserializable,
366 GtkTextBuffer *buffer)
372 g_return_if_fail (list != NULL);
373 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
376 atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
378 atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
380 for (i = 0; i < n_atoms; i++)
381 gtk_target_list_add (list, atoms[i], 0, info);
387 * gtk_target_list_add_image_targets:
388 * @list: a #GtkTargetList
389 * @info: an ID that will be passed back to the application
390 * @writable: whether to add only targets for which GTK+ knows
391 * how to convert a pixbuf into the format
393 * Appends the image targets supported by #GtkSelection to
394 * the target list. All targets are added with the same @info.
399 gtk_target_list_add_image_targets (GtkTargetList *list,
407 g_return_if_fail (list != NULL);
409 formats = gdk_pixbuf_get_formats ();
411 /* Make sure png comes first */
412 for (f = formats; f; f = f->next)
414 GdkPixbufFormat *fmt = f->data;
417 name = gdk_pixbuf_format_get_name (fmt);
418 if (strcmp (name, "png") == 0)
420 formats = g_slist_delete_link (formats, f);
421 formats = g_slist_prepend (formats, fmt);
431 for (f = formats; f; f = f->next)
433 GdkPixbufFormat *fmt = f->data;
435 if (writable && !gdk_pixbuf_format_is_writable (fmt))
438 mimes = gdk_pixbuf_format_get_mime_types (fmt);
439 for (m = mimes; *m; m++)
441 atom = gdk_atom_intern (*m, FALSE);
442 gtk_target_list_add (list, atom, 0, info);
447 g_slist_free (formats);
451 * gtk_target_list_add_uri_targets:
452 * @list: a #GtkTargetList
453 * @info: an ID that will be passed back to the application
455 * Appends the URI targets supported by #GtkSelection to
456 * the target list. All targets are added with the same @info.
461 gtk_target_list_add_uri_targets (GtkTargetList *list,
464 g_return_if_fail (list != NULL);
468 gtk_target_list_add (list, text_uri_list_atom, 0, info);
472 * gtk_target_list_add_table:
473 * @list: a #GtkTargetList
474 * @targets: the table of #GtkTargetEntry
475 * @ntargets: number of targets in the table
477 * Prepends a table of #GtkTargetEntry to a target list.
480 gtk_target_list_add_table (GtkTargetList *list,
481 const GtkTargetEntry *targets,
486 for (i=ntargets-1; i >= 0; i--)
488 GtkTargetPair *pair = g_slice_new (GtkTargetPair);
489 pair->target = gdk_atom_intern (targets[i].target, FALSE);
490 pair->flags = targets[i].flags;
491 pair->info = targets[i].info;
493 list->list = g_list_prepend (list->list, pair);
498 * gtk_target_list_remove:
499 * @list: a #GtkTargetList
500 * @target: the interned atom representing the target
502 * Removes a target from a target list.
505 gtk_target_list_remove (GtkTargetList *list,
510 g_return_if_fail (list != NULL);
512 tmp_list = list->list;
515 GtkTargetPair *pair = tmp_list->data;
517 if (pair->target == target)
519 g_slice_free (GtkTargetPair, pair);
521 list->list = g_list_remove_link (list->list, tmp_list);
522 g_list_free_1 (tmp_list);
527 tmp_list = tmp_list->next;
532 * gtk_target_list_find:
533 * @list: a #GtkTargetList
534 * @target: an interned atom representing the target to search for
535 * @info: a pointer to the location to store application info for target,
538 * Looks up a given target in a #GtkTargetList.
540 * Return value: %TRUE if the target was found, otherwise %FALSE
543 gtk_target_list_find (GtkTargetList *list,
549 g_return_val_if_fail (list != NULL, FALSE);
551 tmp_list = list->list;
554 GtkTargetPair *pair = tmp_list->data;
556 if (pair->target == target)
564 tmp_list = tmp_list->next;
571 * gtk_target_table_new_from_list:
572 * @list: a #GtkTargetList
573 * @n_targets: return location for the number ot targets in the table
575 * This function creates an #GtkTargetEntry array that contains the
576 * same targets as the passed %list. The returned table is newly
577 * allocated and should be freed using gtk_target_table_free() when no
580 * Return value: the new table.
585 gtk_target_table_new_from_list (GtkTargetList *list,
588 GtkTargetEntry *targets;
592 g_return_val_if_fail (list != NULL, NULL);
593 g_return_val_if_fail (n_targets != NULL, NULL);
595 *n_targets = g_list_length (list->list);
596 targets = g_new0 (GtkTargetEntry, *n_targets);
598 for (i = 0, tmp_list = list->list;
600 i++, tmp_list = g_list_next (tmp_list))
602 GtkTargetPair *pair = tmp_list->data;
604 targets[i].target = gdk_atom_name (pair->target);
605 targets[i].flags = pair->flags;
606 targets[i].info = pair->info;
613 * gtk_target_table_free:
614 * @targets: a #GtkTargetEntry array
615 * @n_targets: the number of entries in the array
617 * This function frees a target table as returned by
618 * gtk_target_table_new_from_list()
623 gtk_target_table_free (GtkTargetEntry *targets,
628 g_return_if_fail (targets == NULL || n_targets > 0);
630 for (i = 0; i < n_targets; i++)
631 g_free (targets[i].target);
637 * gtk_selection_owner_set_for_display:
638 * @display: the #Gdkdisplay where the selection is set
639 * @widget: new selection owner (a #GdkWidget), or %NULL.
640 * @selection: an interned atom representing the selection to claim.
641 * @time_: timestamp with which to claim the selection
643 * Claim ownership of a given selection for a particular widget, or,
644 * if @widget is %NULL, release ownership of the selection.
646 * Return value: TRUE if the operation succeeded
651 gtk_selection_owner_set_for_display (GdkDisplay *display,
657 GtkWidget *old_owner;
658 GtkSelectionInfo *selection_info = NULL;
661 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
662 g_return_val_if_fail (selection != GDK_NONE, FALSE);
663 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
664 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
669 window = widget->window;
671 tmp_list = current_selections;
674 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
676 selection_info = tmp_list->data;
680 tmp_list = tmp_list->next;
683 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
691 old_owner = selection_info->widget;
692 current_selections = g_list_remove_link (current_selections,
694 g_list_free (tmp_list);
695 g_slice_free (GtkSelectionInfo, selection_info);
700 if (selection_info == NULL)
702 selection_info = g_slice_new (GtkSelectionInfo);
703 selection_info->selection = selection;
704 selection_info->widget = widget;
705 selection_info->time = time;
706 selection_info->display = display;
707 current_selections = g_list_prepend (current_selections,
712 old_owner = selection_info->widget;
713 selection_info->widget = widget;
714 selection_info->time = time;
715 selection_info->display = display;
718 /* If another widget in the application lost the selection,
719 * send it a GDK_SELECTION_CLEAR event.
721 if (old_owner && old_owner != widget)
723 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
725 event->selection.window = g_object_ref (old_owner->window);
726 event->selection.selection = selection;
727 event->selection.time = time;
729 gtk_widget_event (old_owner, event);
731 gdk_event_free (event);
740 * gtk_selection_owner_set:
741 * @widget: a #GtkWidget, or %NULL.
742 * @selection: an interned atom representing the selection to claim
743 * @time_: timestamp with which to claim the selection
745 * Claims ownership of a given selection for a particular widget,
746 * or, if @widget is %NULL, release ownership of the selection.
748 * Return value: %TRUE if the operation succeeded
751 gtk_selection_owner_set (GtkWidget *widget,
757 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
758 g_return_val_if_fail (selection != GDK_NONE, FALSE);
761 display = gtk_widget_get_display (widget);
765 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
767 display = gdk_display_get_default ();
770 return gtk_selection_owner_set_for_display (display, widget,
774 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
776 struct _GtkSelectionTargetList {
781 static GtkTargetList *
782 gtk_selection_target_list_get (GtkWidget *widget,
785 GtkSelectionTargetList *sellist;
789 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
794 sellist = tmp_list->data;
795 if (sellist->selection == selection)
796 return sellist->list;
797 tmp_list = tmp_list->next;
800 sellist = g_slice_new (GtkSelectionTargetList);
801 sellist->selection = selection;
802 sellist->list = gtk_target_list_new (NULL, 0);
804 lists = g_list_prepend (lists, sellist);
805 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
807 return sellist->list;
811 gtk_selection_target_list_remove (GtkWidget *widget)
813 GtkSelectionTargetList *sellist;
817 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
822 sellist = tmp_list->data;
824 gtk_target_list_unref (sellist->list);
826 g_slice_free (GtkSelectionTargetList, sellist);
827 tmp_list = tmp_list->next;
831 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
835 * gtk_selection_clear_targets:
836 * @widget: a #GtkWidget
837 * @selection: an atom representing a selection
839 * Remove all targets registered for the given selection for the
843 gtk_selection_clear_targets (GtkWidget *widget,
846 GtkSelectionTargetList *sellist;
850 g_return_if_fail (GTK_IS_WIDGET (widget));
851 g_return_if_fail (selection != GDK_NONE);
853 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
858 sellist = tmp_list->data;
859 if (sellist->selection == selection)
861 lists = g_list_delete_link (lists, tmp_list);
862 gtk_target_list_unref (sellist->list);
863 g_slice_free (GtkSelectionTargetList, sellist);
868 tmp_list = tmp_list->next;
871 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
875 * gtk_selection_add_target:
876 * @widget: a #GtkTarget
877 * @selection: the selection
878 * @target: target to add.
879 * @info: A unsigned integer which will be passed back to the application.
881 * Appends a specified target to the list of supported targets for a
882 * given widget and selection.
885 gtk_selection_add_target (GtkWidget *widget,
892 g_return_if_fail (GTK_IS_WIDGET (widget));
893 g_return_if_fail (selection != GDK_NONE);
895 list = gtk_selection_target_list_get (widget, selection);
896 gtk_target_list_add (list, target, 0, info);
897 #ifdef GDK_WINDOWING_WIN32
898 gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
903 * gtk_selection_add_targets:
904 * @widget: a #GtkWidget
905 * @selection: the selection
906 * @targets: a table of targets to add
907 * @ntargets: number of entries in @targets
909 * Prepends a table of targets to the list of supported targets
910 * for a given widget and selection.
913 gtk_selection_add_targets (GtkWidget *widget,
915 const GtkTargetEntry *targets,
920 g_return_if_fail (GTK_IS_WIDGET (widget));
921 g_return_if_fail (selection != GDK_NONE);
922 g_return_if_fail (targets != NULL);
924 list = gtk_selection_target_list_get (widget, selection);
925 gtk_target_list_add_table (list, targets, ntargets);
927 #ifdef GDK_WINDOWING_WIN32
930 GdkAtom *atoms = g_new (GdkAtom, ntargets);
932 for (i = 0; i < ntargets; ++i)
933 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
934 gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
942 * gtk_selection_remove_all:
943 * @widget: a #GtkWidget
945 * Removes all handlers and unsets ownership of all
946 * selections for a widget. Called when widget is being
947 * destroyed. This function will not generally be
948 * called by applications.
951 gtk_selection_remove_all (GtkWidget *widget)
955 GtkSelectionInfo *selection_info;
957 g_return_if_fail (GTK_IS_WIDGET (widget));
959 /* Remove pending requests/incrs for this widget */
961 tmp_list = current_retrievals;
964 next = tmp_list->next;
965 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
967 current_retrievals = g_list_remove_link (current_retrievals,
969 /* structure will be freed in timeout */
970 g_list_free (tmp_list);
975 /* Disclaim ownership of any selections */
977 tmp_list = current_selections;
980 next = tmp_list->next;
981 selection_info = (GtkSelectionInfo *)tmp_list->data;
983 if (selection_info->widget == widget)
985 gdk_selection_owner_set_for_display (selection_info->display,
987 selection_info->selection,
988 GDK_CURRENT_TIME, FALSE);
989 current_selections = g_list_remove_link (current_selections,
991 g_list_free (tmp_list);
992 g_slice_free (GtkSelectionInfo, selection_info);
998 /* Remove all selection lists */
999 gtk_selection_target_list_remove (widget);
1004 * gtk_selection_convert:
1005 * @widget: The widget which acts as requestor
1006 * @selection: Which selection to get
1007 * @target: Form of information desired (e.g., STRING)
1008 * @time_: Time of request (usually of triggering event)
1009 In emergency, you could use #GDK_CURRENT_TIME
1011 * Requests the contents of a selection. When received,
1012 * a "selection-received" signal will be generated.
1014 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1015 * request. (e.g., there was already a request in process for
1019 gtk_selection_convert (GtkWidget *widget,
1024 GtkRetrievalInfo *info;
1026 GdkWindow *owner_window;
1027 GdkDisplay *display;
1029 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1030 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1033 gtk_selection_init ();
1035 if (!GTK_WIDGET_REALIZED (widget))
1036 gtk_widget_realize (widget);
1038 /* Check to see if there are already any retrievals in progress for
1039 this widget. If we changed GDK to use the selection for the
1040 window property in which to store the retrieved information, then
1041 we could support multiple retrievals for different selections.
1042 This might be useful for DND. */
1044 tmp_list = current_retrievals;
1047 info = (GtkRetrievalInfo *)tmp_list->data;
1048 if (info->widget == widget)
1050 tmp_list = tmp_list->next;
1053 info = g_slice_new (GtkRetrievalInfo);
1055 info->widget = widget;
1056 info->selection = selection;
1057 info->target = target;
1058 info->idle_time = 0;
1059 info->buffer = NULL;
1062 /* Check if this process has current owner. If so, call handler
1063 procedure directly to avoid deadlocks with INCR. */
1065 display = gtk_widget_get_display (widget);
1066 owner_window = gdk_selection_owner_get_for_display (display, selection);
1068 if (owner_window != NULL)
1070 GtkWidget *owner_widget;
1071 gpointer owner_widget_ptr;
1072 GtkSelectionData selection_data;
1074 selection_data.selection = selection;
1075 selection_data.target = target;
1076 selection_data.data = NULL;
1077 selection_data.length = -1;
1078 selection_data.display = display;
1080 gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1081 owner_widget = owner_widget_ptr;
1083 if (owner_widget != NULL)
1085 gtk_selection_invoke_handler (owner_widget,
1089 gtk_selection_retrieval_report (info,
1090 selection_data.type,
1091 selection_data.format,
1092 selection_data.data,
1093 selection_data.length,
1096 g_free (selection_data.data);
1097 selection_data.data = NULL;
1098 selection_data.length = -1;
1100 g_slice_free (GtkRetrievalInfo, info);
1105 /* Otherwise, we need to go through X */
1107 current_retrievals = g_list_append (current_retrievals, info);
1108 gdk_selection_convert (widget->window, selection, target, time_);
1109 gdk_threads_add_timeout (1000,
1110 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1116 * gtk_selection_data_get_selection:
1117 * @selection_data: a pointer to a #GtkSelectionData structure.
1119 * Retrieves the selection #GdkAtom of the selection data.
1121 * Returns: the selection #GdkAtom of the selection data.
1126 gtk_selection_data_get_selection (GtkSelectionData *selection_data)
1128 g_return_val_if_fail (selection_data != NULL, 0);
1130 return selection_data->selection;
1134 * gtk_selection_data_get_target:
1135 * @selection_data: a pointer to a #GtkSelectionData structure.
1137 * Retrieves the target of the selection.
1139 * Returns: the target of the selection.
1144 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1146 g_return_val_if_fail (selection_data != NULL, 0);
1148 return selection_data->target;
1152 * gtk_selection_data_get_data_type:
1153 * @selection_data: a pointer to a #GtkSelectionData structure.
1155 * Retrieves the data type of the selection.
1157 * Returns: the data type of the selection.
1162 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1164 g_return_val_if_fail (selection_data != NULL, 0);
1166 return selection_data->type;
1170 * gtk_selection_data_get_format:
1171 * @selection_data: a pointer to a #GtkSelectionData structure.
1173 * Retrieves the format of the selection.
1175 * Returns: the format of the selection.
1180 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1182 g_return_val_if_fail (selection_data != NULL, 0);
1184 return selection_data->format;
1188 * gtk_selection_data_get_data:
1189 * @selection_data: a pointer to a #GtkSelectionData structure.
1191 * Retrieves the raw data of the selection.
1193 * Returns: the raw data of the selection.
1198 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1200 g_return_val_if_fail (selection_data != NULL, NULL);
1202 return selection_data->data;
1206 * gtk_selection_data_get_length:
1207 * @selection_data: a pointer to a #GtkSelectionData structure.
1209 * Retrieves the length of the raw data of the selection.
1211 * Returns: the length of the data of the selection.
1216 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1218 g_return_val_if_fail (selection_data != NULL, -1);
1220 return selection_data->length;
1224 * gtk_selection_data_get_display:
1225 * @selection_data: a pointer to a #GtkSelectionData structure.
1227 * Retrieves the display of the selection.
1229 * Returns: the display of the selection.
1234 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1236 g_return_val_if_fail (selection_data != NULL, NULL);
1238 return selection_data->display;
1242 * gtk_selection_data_set:
1243 * @selection_data: a pointer to a #GtkSelectionData structure.
1244 * @type: the type of selection data
1245 * @format: format (number of bits in a unit)
1246 * @data: pointer to the data (will be copied)
1247 * @length: length of the data
1249 * Stores new data into a #GtkSelectionData object. Should
1250 * <emphasis>only</emphasis> be called from a selection handler callback.
1251 * Zero-terminates the stored data.
1254 gtk_selection_data_set (GtkSelectionData *selection_data,
1260 g_return_if_fail (selection_data != NULL);
1262 g_free (selection_data->data);
1264 selection_data->type = type;
1265 selection_data->format = format;
1269 selection_data->data = g_new (guchar, length+1);
1270 memcpy (selection_data->data, data, length);
1271 selection_data->data[length] = 0;
1275 g_return_if_fail (length <= 0);
1278 selection_data->data = NULL;
1280 selection_data->data = (guchar *) g_strdup ("");
1283 selection_data->length = length;
1287 selection_set_string (GtkSelectionData *selection_data,
1291 gchar *tmp = g_strndup (str, len);
1292 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1297 gtk_selection_data_set (selection_data,
1298 GDK_SELECTION_TYPE_STRING,
1299 8, (guchar *) latin1, strlen (latin1));
1309 selection_set_compound_text (GtkSelectionData *selection_data,
1318 gboolean result = FALSE;
1320 tmp = g_strndup (str, len);
1321 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1322 &encoding, &format, &text, &new_length))
1324 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1325 gdk_free_compound_text (text);
1335 /* Normalize \r and \n into \r\n
1338 normalize_to_crlf (const gchar *str,
1341 GString *result = g_string_sized_new (len);
1342 const gchar *p = str;
1343 const gchar *end = str + len;
1348 g_string_append_c (result, '\r');
1352 g_string_append_c (result, *p);
1354 if (p == end || *p != '\n')
1355 g_string_append_c (result, '\n');
1360 g_string_append_c (result, *p);
1364 return g_string_free (result, FALSE);
1367 /* Normalize \r and \r\n into \n
1370 normalize_to_lf (gchar *str,
1373 GString *result = g_string_sized_new (len);
1374 const gchar *p = str;
1382 g_string_append_c (result, '\n');
1388 g_string_append_c (result, *p);
1392 return g_string_free (result, FALSE);
1396 selection_set_text_plain (GtkSelectionData *selection_data,
1400 const gchar *charset = NULL;
1402 GError *error = NULL;
1404 result = normalize_to_crlf (str, len);
1405 if (selection_data->target == text_plain_atom)
1407 else if (selection_data->target == text_plain_locale_atom)
1408 g_get_charset (&charset);
1412 gchar *tmp = result;
1413 result = g_convert_with_fallback (tmp, -1,
1415 NULL, NULL, NULL, &error);
1421 g_warning ("Error converting from %s to %s: %s",
1422 "UTF-8", charset, error->message);
1423 g_error_free (error);
1428 gtk_selection_data_set (selection_data,
1429 selection_data->target,
1430 8, (guchar *) result, strlen (result));
1437 selection_get_text_plain (GtkSelectionData *selection_data)
1439 const gchar *charset = NULL;
1440 gchar *str, *result;
1442 GError *error = NULL;
1444 str = g_strdup ((const gchar *) selection_data->data);
1445 len = selection_data->length;
1447 if (selection_data->type == text_plain_atom)
1448 charset = "ISO-8859-1";
1449 else if (selection_data->type == text_plain_locale_atom)
1450 g_get_charset (&charset);
1455 str = g_convert_with_fallback (tmp, len,
1457 NULL, NULL, &len, &error);
1462 g_warning ("Error converting from %s to %s: %s",
1463 charset, "UTF-8", error->message);
1464 g_error_free (error);
1469 else if (!g_utf8_validate (str, -1, NULL))
1471 g_warning ("Error converting from %s to %s: %s",
1472 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1478 result = normalize_to_lf (str, len);
1481 return (guchar *) result;
1485 * gtk_selection_data_set_text:
1486 * @selection_data: a #GtkSelectionData
1487 * @str: a UTF-8 string
1488 * @len: the length of @str, or -1 if @str is nul-terminated.
1490 * Sets the contents of the selection from a UTF-8 encoded string.
1491 * The string is converted to the form determined by
1492 * @selection_data->target.
1494 * Return value: %TRUE if the selection was successfully set,
1498 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1502 g_return_val_if_fail (selection_data != NULL, FALSE);
1509 if (selection_data->target == utf8_atom)
1511 gtk_selection_data_set (selection_data,
1513 8, (guchar *)str, len);
1516 else if (selection_data->target == GDK_TARGET_STRING)
1518 return selection_set_string (selection_data, str, len);
1520 else if (selection_data->target == ctext_atom ||
1521 selection_data->target == text_atom)
1523 if (selection_set_compound_text (selection_data, str, len))
1525 else if (selection_data->target == text_atom)
1526 return selection_set_string (selection_data, str, len);
1528 else if (selection_data->target == text_plain_atom ||
1529 selection_data->target == text_plain_utf8_atom ||
1530 selection_data->target == text_plain_locale_atom)
1532 return selection_set_text_plain (selection_data, str, len);
1539 * gtk_selection_data_get_text:
1540 * @selection_data: a #GtkSelectionData
1542 * Gets the contents of the selection data as a UTF-8 string.
1544 * Return value: if the selection data contained a recognized
1545 * text type and it could be converted to UTF-8, a newly allocated
1546 * string containing the converted text, otherwise %NULL.
1547 * If the result is non-%NULL it must be freed with g_free().
1550 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1552 guchar *result = NULL;
1554 g_return_val_if_fail (selection_data != NULL, NULL);
1558 if (selection_data->length >= 0 &&
1559 (selection_data->type == GDK_TARGET_STRING ||
1560 selection_data->type == ctext_atom ||
1561 selection_data->type == utf8_atom))
1565 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1566 selection_data->type,
1567 selection_data->format,
1568 selection_data->data,
1569 selection_data->length,
1572 result = (guchar *) list[0];
1574 for (i = 1; i < count; i++)
1578 else if (selection_data->length >= 0 &&
1579 (selection_data->type == text_plain_atom ||
1580 selection_data->type == text_plain_utf8_atom ||
1581 selection_data->type == text_plain_locale_atom))
1583 result = selection_get_text_plain (selection_data);
1590 * gtk_selection_data_set_pixbuf:
1591 * @selection_data: a #GtkSelectionData
1592 * @pixbuf: a #GdkPixbuf
1594 * Sets the contents of the selection from a #GdkPixbuf
1595 * The pixbuf is converted to the form determined by
1596 * @selection_data->target.
1598 * Return value: %TRUE if the selection was successfully set,
1604 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1607 GSList *formats, *f;
1614 g_return_val_if_fail (selection_data != NULL, FALSE);
1615 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1617 formats = gdk_pixbuf_get_formats ();
1619 for (f = formats; f; f = f->next)
1621 GdkPixbufFormat *fmt = f->data;
1623 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1624 for (m = mimes; *m; m++)
1626 atom = gdk_atom_intern (*m, FALSE);
1627 if (selection_data->target == atom)
1630 type = gdk_pixbuf_format_get_name (fmt);
1631 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1633 ((strcmp (type, "png") == 0) ?
1634 "compression" : NULL), "2",
1637 gtk_selection_data_set (selection_data,
1638 atom, 8, (guchar *)str, len);
1642 g_slist_free (formats);
1651 g_slist_free (formats);
1657 * gtk_selection_data_get_pixbuf:
1658 * @selection_data: a #GtkSelectionData
1660 * Gets the contents of the selection data as a #GdkPixbuf.
1662 * Return value: if the selection data contained a recognized
1663 * image type and it could be converted to a #GdkPixbuf, a
1664 * newly allocated pixbuf is returned, otherwise %NULL.
1665 * If the result is non-%NULL it must be freed with g_object_unref().
1670 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1672 GdkPixbufLoader *loader;
1673 GdkPixbuf *result = NULL;
1675 g_return_val_if_fail (selection_data != NULL, NULL);
1677 if (selection_data->length > 0)
1679 loader = gdk_pixbuf_loader_new ();
1681 gdk_pixbuf_loader_write (loader,
1682 selection_data->data,
1683 selection_data->length,
1685 gdk_pixbuf_loader_close (loader, NULL);
1686 result = gdk_pixbuf_loader_get_pixbuf (loader);
1689 g_object_ref (result);
1691 g_object_unref (loader);
1698 * gtk_selection_data_set_uris:
1699 * @selection_data: a #GtkSelectionData
1700 * @uris: a %NULL-terminated array of strings holding URIs
1702 * Sets the contents of the selection from a list of URIs.
1703 * The string is converted to the form determined by
1704 * @selection_data->target.
1706 * Return value: %TRUE if the selection was successfully set,
1712 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1715 g_return_val_if_fail (selection_data != NULL, FALSE);
1716 g_return_val_if_fail (uris != NULL, FALSE);
1720 if (selection_data->target == text_uri_list_atom)
1727 list = g_string_new (NULL);
1728 for (i = 0; uris[i]; i++)
1730 g_string_append (list, uris[i]);
1731 g_string_append (list, "\r\n");
1734 result = g_convert (list->str, list->len,
1736 NULL, &length, NULL);
1737 g_string_free (list, TRUE);
1741 gtk_selection_data_set (selection_data,
1743 8, (guchar *)result, length);
1755 * gtk_selection_data_get_uris:
1756 * @selection_data: a #GtkSelectionData
1758 * Gets the contents of the selection data as array of URIs.
1760 * Return value: if the selection data contains a list of
1761 * URIs, a newly allocated %NULL-terminated string array
1762 * containing the URIs, otherwise %NULL. If the result is
1763 * non-%NULL it must be freed with g_strfreev().
1768 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1770 gchar **result = NULL;
1772 g_return_val_if_fail (selection_data != NULL, NULL);
1776 if (selection_data->length >= 0 &&
1777 selection_data->type == text_uri_list_atom)
1780 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1782 selection_data->format,
1783 selection_data->data,
1784 selection_data->length,
1787 result = g_uri_list_extract_uris (list[0]);
1797 * gtk_selection_data_get_targets:
1798 * @selection_data: a #GtkSelectionData object
1799 * @targets: location to store an array of targets. The result
1800 * stored here must be freed with g_free().
1801 * @n_atoms: location to store number of items in @targets.
1803 * Gets the contents of @selection_data as an array of targets.
1804 * This can be used to interpret the results of getting
1805 * the standard TARGETS target that is always supplied for
1808 * Return value: %TRUE if @selection_data contains a valid
1809 * array of targets, otherwise %FALSE.
1812 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1816 g_return_val_if_fail (selection_data != NULL, FALSE);
1818 /* As usual, java gets it wrong and sets the type to TARGETS, not ATOM
1820 if (selection_data->length >= 0 &&
1821 selection_data->format == 32 &&
1822 (selection_data->type == GDK_SELECTION_TYPE_ATOM ||
1823 selection_data->type == gtk_selection_atoms[TARGETS]))
1826 *targets = g_memdup (selection_data->data, selection_data->length);
1828 *n_atoms = selection_data->length / sizeof (GdkAtom);
1844 * gtk_targets_include_text:
1845 * @targets: an array of #GdkAtom<!-- -->s
1846 * @n_targets: the length of @targets
1848 * Determines if any of the targets in @targets can be used to
1851 * Return value: %TRUE if @targets include a suitable target for text,
1857 gtk_targets_include_text (GdkAtom *targets,
1861 gboolean result = FALSE;
1863 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1865 /* Keep in sync with gtk_target_list_add_text_targets()
1870 for (i = 0; i < n_targets; i++)
1872 if (targets[i] == utf8_atom ||
1873 targets[i] == text_atom ||
1874 targets[i] == GDK_TARGET_STRING ||
1875 targets[i] == ctext_atom ||
1876 targets[i] == text_plain_atom ||
1877 targets[i] == text_plain_utf8_atom ||
1878 targets[i] == text_plain_locale_atom)
1889 * gtk_targets_include_rich_text:
1890 * @targets: an array of #GdkAtom<!-- -->s
1891 * @n_targets: the length of @targets
1892 * @buffer: a #GtkTextBuffer
1894 * Determines if any of the targets in @targets can be used to
1895 * provide rich text.
1897 * Return value: %TRUE if @targets include a suitable target for rich text,
1903 gtk_targets_include_rich_text (GdkAtom *targets,
1905 GtkTextBuffer *buffer)
1907 GdkAtom *rich_targets;
1908 gint n_rich_targets;
1910 gboolean result = FALSE;
1912 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1913 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1917 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1920 for (i = 0; i < n_targets; i++)
1922 for (j = 0; j < n_rich_targets; j++)
1924 if (targets[i] == rich_targets[j])
1933 g_free (rich_targets);
1939 * gtk_selection_data_targets_include_text:
1940 * @selection_data: a #GtkSelectionData object
1942 * Given a #GtkSelectionData object holding a list of targets,
1943 * determines if any of the targets in @targets can be used to
1946 * Return value: %TRUE if @selection_data holds a list of targets,
1947 * and a suitable target for text is included, otherwise %FALSE.
1950 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1954 gboolean result = FALSE;
1956 g_return_val_if_fail (selection_data != NULL, FALSE);
1960 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1962 result = gtk_targets_include_text (targets, n_targets);
1970 * gtk_selection_data_targets_include_rich_text:
1971 * @selection_data: a #GtkSelectionData object
1972 * @buffer: a #GtkTextBuffer
1974 * Given a #GtkSelectionData object holding a list of targets,
1975 * determines if any of the targets in @targets can be used to
1976 * provide rich text.
1978 * Return value: %TRUE if @selection_data holds a list of targets,
1979 * and a suitable target for rich text is included,
1985 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1986 GtkTextBuffer *buffer)
1990 gboolean result = FALSE;
1992 g_return_val_if_fail (selection_data != NULL, FALSE);
1993 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1997 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1999 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2007 * gtk_targets_include_image:
2008 * @targets: an array of #GdkAtom<!-- -->s
2009 * @n_targets: the length of @targets
2010 * @writable: whether to accept only targets for which GTK+ knows
2011 * how to convert a pixbuf into the format
2013 * Determines if any of the targets in @targets can be used to
2014 * provide a #GdkPixbuf.
2016 * Return value: %TRUE if @targets include a suitable target for images,
2022 gtk_targets_include_image (GdkAtom *targets,
2026 GtkTargetList *list;
2029 gboolean result = FALSE;
2031 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2033 list = gtk_target_list_new (NULL, 0);
2034 gtk_target_list_add_image_targets (list, 0, writable);
2035 for (i = 0; i < n_targets && !result; i++)
2037 for (l = list->list; l; l = l->next)
2039 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2040 if (pair->target == targets[i])
2047 gtk_target_list_unref (list);
2053 * gtk_selection_data_targets_include_image:
2054 * @selection_data: a #GtkSelectionData object
2055 * @writable: whether to accept only targets for which GTK+ knows
2056 * how to convert a pixbuf into the format
2058 * Given a #GtkSelectionData object holding a list of targets,
2059 * determines if any of the targets in @targets can be used to
2060 * provide a #GdkPixbuf.
2062 * Return value: %TRUE if @selection_data holds a list of targets,
2063 * and a suitable target for images is included, otherwise %FALSE.
2068 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2073 gboolean result = FALSE;
2075 g_return_val_if_fail (selection_data != NULL, FALSE);
2079 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2081 result = gtk_targets_include_image (targets, n_targets, writable);
2089 * gtk_targets_include_uri:
2090 * @targets: an array of #GdkAtom<!-- -->s
2091 * @n_targets: the length of @targets
2093 * Determines if any of the targets in @targets can be used to
2094 * provide an uri list.
2096 * Return value: %TRUE if @targets include a suitable target for uri lists,
2102 gtk_targets_include_uri (GdkAtom *targets,
2106 gboolean result = FALSE;
2108 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2110 /* Keep in sync with gtk_target_list_add_uri_targets()
2115 for (i = 0; i < n_targets; i++)
2117 if (targets[i] == text_uri_list_atom)
2128 * gtk_selection_data_targets_include_uri:
2129 * @selection_data: a #GtkSelectionData object
2131 * Given a #GtkSelectionData object holding a list of targets,
2132 * determines if any of the targets in @targets can be used to
2133 * provide a list or URIs.
2135 * Return value: %TRUE if @selection_data holds a list of targets,
2136 * and a suitable target for URI lists is included, otherwise %FALSE.
2141 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2145 gboolean result = FALSE;
2147 g_return_val_if_fail (selection_data != NULL, FALSE);
2151 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2153 result = gtk_targets_include_uri (targets, n_targets);
2161 /*************************************************************
2162 * gtk_selection_init:
2163 * Initialize local variables
2167 *************************************************************/
2170 gtk_selection_init (void)
2172 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2173 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2174 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2175 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2176 gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS");
2182 * gtk_selection_clear:
2183 * @widget: a #GtkWidget
2186 * The default handler for the #GtkWidget::selection-clear-event
2189 * Return value: %TRUE if the event was handled, otherwise false
2193 * Deprecated: 2.4: Instead of calling this function, chain up from
2194 * your selection-clear-event handler. Calling this function
2195 * from any other context is illegal.
2198 gtk_selection_clear (GtkWidget *widget,
2199 GdkEventSelection *event)
2201 /* Note that we filter clear events in gdkselection-x11.c, so
2202 * that we only will get here if the clear event actually
2203 * represents a change that we didn't do ourself.
2206 GtkSelectionInfo *selection_info = NULL;
2208 tmp_list = current_selections;
2211 selection_info = (GtkSelectionInfo *)tmp_list->data;
2213 if ((selection_info->selection == event->selection) &&
2214 (selection_info->widget == widget))
2217 tmp_list = tmp_list->next;
2222 current_selections = g_list_remove_link (current_selections, tmp_list);
2223 g_list_free (tmp_list);
2224 g_slice_free (GtkSelectionInfo, selection_info);
2231 /*************************************************************
2232 * _gtk_selection_request:
2233 * Handler for "selection_request_event"
2238 *************************************************************/
2241 _gtk_selection_request (GtkWidget *widget,
2242 GdkEventSelection *event)
2244 GdkDisplay *display = gtk_widget_get_display (widget);
2248 gulong selection_max_size;
2251 gtk_selection_init ();
2253 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2255 /* Check if we own selection */
2257 tmp_list = current_selections;
2260 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2262 if ((selection_info->selection == event->selection) &&
2263 (selection_info->widget == widget))
2266 tmp_list = tmp_list->next;
2269 if (tmp_list == NULL)
2272 info = g_slice_new (GtkIncrInfo);
2274 g_object_ref (widget);
2276 info->selection = event->selection;
2277 info->num_incrs = 0;
2279 /* Create GdkWindow structure for the requestor */
2281 info->requestor = gdk_window_lookup_for_display (display,
2283 if (!info->requestor)
2284 info->requestor = gdk_window_foreign_new_for_display (display,
2287 /* Determine conversions we need to perform */
2289 if (event->target == gtk_selection_atoms[MULTIPLE])
2298 gdk_error_trap_push ();
2299 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2300 0, selection_max_size, FALSE,
2301 &type, &format, &length, &mult_atoms))
2303 gdk_selection_send_notify_for_display (display,
2309 g_free (mult_atoms);
2310 g_slice_free (GtkIncrInfo, info);
2311 gdk_error_trap_pop ();
2314 gdk_error_trap_pop ();
2316 /* This is annoying; the ICCCM doesn't specify the property type
2317 * used for the property contents, so the autoconversion for
2318 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2320 #ifdef GDK_WINDOWING_X11
2321 if (type != GDK_SELECTION_TYPE_ATOM &&
2322 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2324 info->num_conversions = length / (2*sizeof (glong));
2325 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2327 for (i=0; i<info->num_conversions; i++)
2329 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2330 ((glong *)mult_atoms)[2*i]);
2331 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2332 ((glong *)mult_atoms)[2*i + 1]);
2335 g_free (mult_atoms);
2340 info->num_conversions = length / (2*sizeof (GdkAtom));
2341 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2343 for (i=0; i<info->num_conversions; i++)
2345 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2346 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2349 g_free (mult_atoms);
2352 else /* only a single conversion */
2354 info->conversions = g_new (GtkIncrConversion, 1);
2355 info->num_conversions = 1;
2356 info->conversions[0].target = event->target;
2357 info->conversions[0].property = event->property;
2360 /* Loop through conversions and determine which of these are big
2361 enough to require doing them via INCR */
2362 for (i=0; i<info->num_conversions; i++)
2364 GtkSelectionData data;
2367 data.selection = event->selection;
2368 data.target = info->conversions[i].target;
2371 data.display = gtk_widget_get_display (widget);
2373 #ifdef DEBUG_SELECTION
2374 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2376 info->conversions[i].target,
2377 gdk_atom_name (info->conversions[i].target),
2378 event->requestor, info->conversions[i].property);
2381 gtk_selection_invoke_handler (widget, &data, event->time);
2382 if (data.length < 0)
2384 info->conversions[i].property = GDK_NONE;
2388 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2390 items = data.length / gtk_selection_bytes_per_item (data.format);
2392 if (data.length > selection_max_size)
2394 /* Sending via INCR */
2395 #ifdef DEBUG_SELECTION
2396 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2397 data.length, selection_max_size);
2400 info->conversions[i].offset = 0;
2401 info->conversions[i].data = data;
2404 gdk_property_change (info->requestor,
2405 info->conversions[i].property,
2406 gtk_selection_atoms[INCR],
2408 GDK_PROP_MODE_REPLACE,
2409 (guchar *)&items, 1);
2413 info->conversions[i].offset = -1;
2415 gdk_property_change (info->requestor,
2416 info->conversions[i].property,
2419 GDK_PROP_MODE_REPLACE,
2426 /* If we have some INCR's, we need to send the rest of the data in
2429 if (info->num_incrs > 0)
2431 /* FIXME: this could be dangerous if window doesn't still
2434 #ifdef DEBUG_SELECTION
2435 g_message ("Starting INCR...");
2438 gdk_window_set_events (info->requestor,
2439 gdk_window_get_events (info->requestor) |
2440 GDK_PROPERTY_CHANGE_MASK);
2441 current_incrs = g_list_append (current_incrs, info);
2442 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2445 /* If it was a MULTIPLE request, set the property to indicate which
2446 conversions succeeded */
2447 if (event->target == gtk_selection_atoms[MULTIPLE])
2449 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2450 for (i = 0; i < info->num_conversions; i++)
2452 mult_atoms[2*i] = info->conversions[i].target;
2453 mult_atoms[2*i+1] = info->conversions[i].property;
2456 gdk_property_change (info->requestor, event->property,
2457 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2458 GDK_PROP_MODE_REPLACE,
2459 (guchar *)mult_atoms, 2*info->num_conversions);
2460 g_free (mult_atoms);
2463 if (info->num_conversions == 1 &&
2464 info->conversions[0].property == GDK_NONE)
2466 /* Reject the entire conversion */
2467 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2476 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2484 if (info->num_incrs == 0)
2486 g_free (info->conversions);
2487 g_slice_free (GtkIncrInfo, info);
2490 g_object_unref (widget);
2495 /*************************************************************
2496 * _gtk_selection_incr_event:
2497 * Called whenever an PropertyNotify event occurs for an
2498 * GdkWindow with user_data == NULL. These will be notifications
2499 * that a window we are sending the selection to via the
2500 * INCR protocol has deleted a property and is ready for
2504 * window: the requestor window
2505 * event: the property event structure
2508 *************************************************************/
2511 _gtk_selection_incr_event (GdkWindow *window,
2512 GdkEventProperty *event)
2515 GtkIncrInfo *info = NULL;
2518 gulong selection_max_size;
2522 if (event->state != GDK_PROPERTY_DELETE)
2525 #ifdef DEBUG_SELECTION
2526 g_message ("PropertyDelete, property %ld", event->atom);
2529 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2531 /* Now find the appropriate ongoing INCR */
2532 tmp_list = current_incrs;
2535 info = (GtkIncrInfo *)tmp_list->data;
2536 if (info->requestor == event->window)
2539 tmp_list = tmp_list->next;
2542 if (tmp_list == NULL)
2545 /* Find out which target this is for */
2546 for (i=0; i<info->num_conversions; i++)
2548 if (info->conversions[i].property == event->atom &&
2549 info->conversions[i].offset != -1)
2553 info->idle_time = 0;
2555 if (info->conversions[i].offset == -2) /* only the last 0-length
2563 num_bytes = info->conversions[i].data.length -
2564 info->conversions[i].offset;
2565 buffer = info->conversions[i].data.data +
2566 info->conversions[i].offset;
2568 if (num_bytes > selection_max_size)
2570 num_bytes = selection_max_size;
2571 info->conversions[i].offset += selection_max_size;
2574 info->conversions[i].offset = -2;
2576 #ifdef DEBUG_SELECTION
2577 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2578 num_bytes, info->conversions[i].offset,
2579 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2582 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2583 gdk_property_change (info->requestor, event->atom,
2584 info->conversions[i].data.type,
2585 info->conversions[i].data.format,
2586 GDK_PROP_MODE_REPLACE,
2588 num_bytes / bytes_per_item);
2590 if (info->conversions[i].offset == -2)
2592 g_free (info->conversions[i].data.data);
2593 info->conversions[i].data.data = NULL;
2599 info->conversions[i].offset = -1;
2604 /* Check if we're finished with all the targets */
2606 if (info->num_incrs == 0)
2608 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2609 g_list_free (tmp_list);
2610 /* Let the timeout free it */
2616 /*************************************************************
2617 * gtk_selection_incr_timeout:
2618 * Timeout callback for the sending portion of the INCR
2621 * info: Information about this incr
2623 *************************************************************/
2626 gtk_selection_incr_timeout (GtkIncrInfo *info)
2631 /* Determine if retrieval has finished by checking if it still in
2632 list of pending retrievals */
2634 tmp_list = current_incrs;
2637 if (info == (GtkIncrInfo *)tmp_list->data)
2639 tmp_list = tmp_list->next;
2642 /* If retrieval is finished */
2643 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2645 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2647 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2648 g_list_free (tmp_list);
2651 g_free (info->conversions);
2652 /* FIXME: we should check if requestor window is still in use,
2653 and if not, remove it? */
2655 g_slice_free (GtkIncrInfo, info);
2657 retval = FALSE; /* remove timeout */
2663 retval = TRUE; /* timeout will happen again */
2669 /*************************************************************
2670 * _gtk_selection_notify:
2671 * Handler for "selection-notify-event" signals on windows
2672 * where a retrieval is currently in process. The selection
2673 * owner has responded to our conversion request.
2675 * widget: Widget getting signal
2676 * event: Selection event structure
2677 * info: Information about this retrieval
2679 * was event handled?
2680 *************************************************************/
2683 _gtk_selection_notify (GtkWidget *widget,
2684 GdkEventSelection *event)
2687 GtkRetrievalInfo *info = NULL;
2688 guchar *buffer = NULL;
2693 #ifdef DEBUG_SELECTION
2694 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2695 event->selection, event->target, event->property);
2698 tmp_list = current_retrievals;
2701 info = (GtkRetrievalInfo *)tmp_list->data;
2702 if (info->widget == widget && info->selection == event->selection)
2704 tmp_list = tmp_list->next;
2707 if (!tmp_list) /* no retrieval in progress */
2710 if (event->property != GDK_NONE)
2711 length = gdk_selection_property_get (widget->window, &buffer,
2714 length = 0; /* silence gcc */
2716 if (event->property == GDK_NONE || buffer == NULL)
2718 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2719 g_list_free (tmp_list);
2720 /* structure will be freed in timeout */
2721 gtk_selection_retrieval_report (info,
2722 GDK_NONE, 0, NULL, -1, event->time);
2727 if (type == gtk_selection_atoms[INCR])
2729 /* The remainder of the selection will come through PropertyNotify
2732 info->notify_time = event->time;
2733 info->idle_time = 0;
2734 info->offset = 0; /* Mark as OK to proceed */
2735 gdk_window_set_events (widget->window,
2736 gdk_window_get_events (widget->window)
2737 | GDK_PROPERTY_CHANGE_MASK);
2741 /* We don't delete the info structure - that will happen in timeout */
2742 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2743 g_list_free (tmp_list);
2745 info->offset = length;
2746 gtk_selection_retrieval_report (info,
2748 buffer, length, event->time);
2751 gdk_property_delete (widget->window, event->property);
2758 /*************************************************************
2759 * _gtk_selection_property_notify:
2760 * Handler for "property-notify-event" signals on windows
2761 * where a retrieval is currently in process. The selection
2762 * owner has added more data.
2764 * widget: Widget getting signal
2765 * event: Property event structure
2766 * info: Information about this retrieval
2768 * was event handled?
2769 *************************************************************/
2772 _gtk_selection_property_notify (GtkWidget *widget,
2773 GdkEventProperty *event)
2776 GtkRetrievalInfo *info = NULL;
2782 g_return_val_if_fail (widget != NULL, FALSE);
2783 g_return_val_if_fail (event != NULL, FALSE);
2785 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2786 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2787 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2791 #ifdef DEBUG_SELECTION
2792 g_message ("PropertyNewValue, property %ld",
2796 tmp_list = current_retrievals;
2799 info = (GtkRetrievalInfo *)tmp_list->data;
2800 if (info->widget == widget)
2802 tmp_list = tmp_list->next;
2805 if (!tmp_list) /* No retrieval in progress */
2808 if (info->offset < 0) /* We haven't got the SelectionNotify
2809 for this retrieval yet */
2812 info->idle_time = 0;
2814 length = gdk_selection_property_get (widget->window, &new_buffer,
2816 gdk_property_delete (widget->window, event->atom);
2818 /* We could do a lot better efficiency-wise by paying attention to
2819 what length was sent in the initial INCR transaction, instead of
2820 doing memory allocation at every step. But its only guaranteed to
2821 be a _lower bound_ (pretty useless!) */
2823 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2825 /* Info structure will be freed in timeout */
2826 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2827 g_list_free (tmp_list);
2828 gtk_selection_retrieval_report (info,
2830 (type == GDK_NONE) ? NULL : info->buffer,
2831 (type == GDK_NONE) ? -1 : info->offset,
2834 else /* append on newly arrived data */
2838 #ifdef DEBUG_SELECTION
2839 g_message ("Start - Adding %d bytes at offset 0",
2842 info->buffer = new_buffer;
2843 info->offset = length;
2848 #ifdef DEBUG_SELECTION
2849 g_message ("Appending %d bytes at offset %d",
2850 length,info->offset);
2852 /* We copy length+1 bytes to preserve guaranteed null termination */
2853 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2854 memcpy (info->buffer + info->offset, new_buffer, length+1);
2855 info->offset += length;
2856 g_free (new_buffer);
2863 /*************************************************************
2864 * gtk_selection_retrieval_timeout:
2865 * Timeout callback while receiving a selection.
2867 * info: Information about this retrieval
2869 *************************************************************/
2872 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2877 /* Determine if retrieval has finished by checking if it still in
2878 list of pending retrievals */
2880 tmp_list = current_retrievals;
2883 if (info == (GtkRetrievalInfo *)tmp_list->data)
2885 tmp_list = tmp_list->next;
2888 /* If retrieval is finished */
2889 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2891 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2893 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2894 g_list_free (tmp_list);
2895 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2898 g_free (info->buffer);
2899 g_slice_free (GtkRetrievalInfo, info);
2901 retval = FALSE; /* remove timeout */
2907 retval = TRUE; /* timeout will happen again */
2913 /*************************************************************
2914 * gtk_selection_retrieval_report:
2915 * Emits a "selection-received" signal.
2917 * info: information about the retrieval that completed
2918 * buffer: buffer containing data (NULL => errror)
2919 * time: timestamp for data in buffer
2921 *************************************************************/
2924 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2925 GdkAtom type, gint format,
2926 guchar *buffer, gint length,
2929 GtkSelectionData data;
2931 data.selection = info->selection;
2932 data.target = info->target;
2934 data.format = format;
2936 data.length = length;
2938 data.display = gtk_widget_get_display (info->widget);
2940 g_signal_emit_by_name (info->widget,
2941 "selection-received",
2945 /*************************************************************
2946 * gtk_selection_invoke_handler:
2947 * Finds and invokes handler for specified
2948 * widget/selection/target combination, calls
2949 * gtk_selection_default_handler if none exists.
2952 * widget: selection owner
2953 * data: selection data [INOUT]
2954 * time: time from requeset
2957 * Number of bytes written to buffer, -1 if error
2958 *************************************************************/
2961 gtk_selection_invoke_handler (GtkWidget *widget,
2962 GtkSelectionData *data,
2965 GtkTargetList *target_list;
2969 g_return_if_fail (widget != NULL);
2971 target_list = gtk_selection_target_list_get (widget, data->selection);
2972 if (data->target != gtk_selection_atoms[SAVE_TARGETS] &&
2974 gtk_target_list_find (target_list, data->target, &info))
2976 g_signal_emit_by_name (widget,
2982 gtk_selection_default_handler (widget, data);
2985 /*************************************************************
2986 * gtk_selection_default_handler:
2987 * Handles some default targets that exist for any widget
2988 * If it can't fit results into buffer, returns -1. This
2989 * won't happen in any conceivable case, since it would
2990 * require 1000 selection targets!
2993 * widget: selection owner
2994 * data: selection data [INOUT]
2996 *************************************************************/
2999 gtk_selection_default_handler (GtkWidget *widget,
3000 GtkSelectionData *data)
3002 if (data->target == gtk_selection_atoms[TIMESTAMP])
3004 /* Time which was used to obtain selection */
3006 GtkSelectionInfo *selection_info;
3008 tmp_list = current_selections;
3011 selection_info = (GtkSelectionInfo *)tmp_list->data;
3012 if ((selection_info->widget == widget) &&
3013 (selection_info->selection == data->selection))
3015 gulong time = selection_info->time;
3017 gtk_selection_data_set (data,
3018 GDK_SELECTION_TYPE_INTEGER,
3025 tmp_list = tmp_list->next;
3030 else if (data->target == gtk_selection_atoms[TARGETS])
3032 /* List of all targets supported for this widget/selection pair */
3036 GtkTargetList *target_list;
3037 GtkTargetPair *pair;
3039 target_list = gtk_selection_target_list_get (widget,
3041 count = g_list_length (target_list->list) + 3;
3043 data->type = GDK_SELECTION_TYPE_ATOM;
3045 data->length = count * sizeof (GdkAtom);
3047 /* selection data is always terminated by a trailing \0
3049 p = g_malloc (data->length + 1);
3050 data->data = (guchar *)p;
3051 data->data[data->length] = '\0';
3053 *p++ = gtk_selection_atoms[TIMESTAMP];
3054 *p++ = gtk_selection_atoms[TARGETS];
3055 *p++ = gtk_selection_atoms[MULTIPLE];
3057 tmp_list = target_list->list;
3060 pair = (GtkTargetPair *)tmp_list->data;
3061 *p++ = pair->target;
3063 tmp_list = tmp_list->next;
3066 else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
3068 gtk_selection_data_set (data,
3069 gdk_atom_intern_static_string ("NULL"),
3080 * gtk_selection_data_copy:
3081 * @data: a pointer to a #GtkSelectionData structure.
3083 * Makes a copy of a #GtkSelectionData structure and its data.
3085 * Return value: a pointer to a copy of @data.
3088 gtk_selection_data_copy (GtkSelectionData *data)
3090 GtkSelectionData *new_data;
3092 g_return_val_if_fail (data != NULL, NULL);
3094 new_data = g_slice_new (GtkSelectionData);
3099 new_data->data = g_malloc (data->length + 1);
3100 memcpy (new_data->data, data->data, data->length + 1);
3107 * gtk_selection_data_free:
3108 * @data: a pointer to a #GtkSelectionData structure.
3110 * Frees a #GtkSelectionData structure returned from
3111 * gtk_selection_data_copy().
3114 gtk_selection_data_free (GtkSelectionData *data)
3116 g_return_if_fail (data != NULL);
3118 g_free (data->data);
3120 g_slice_free (GtkSelectionData, data);
3124 gtk_selection_data_get_type (void)
3126 static GType our_type = 0;
3129 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3130 (GBoxedCopyFunc) gtk_selection_data_copy,
3131 (GBoxedFreeFunc) gtk_selection_data_free);
3137 gtk_target_list_get_type (void)
3139 static GType our_type = 0;
3142 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3143 (GBoxedCopyFunc) gtk_target_list_ref,
3144 (GBoxedFreeFunc) gtk_target_list_unref);
3150 gtk_selection_bytes_per_item (gint format)
3155 return sizeof (char);
3158 return sizeof (short);
3161 return sizeof (long);
3164 g_assert_not_reached();
3169 #define __GTK_SELECTION_C__
3170 #include "gtkaliasdef.c"