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
100 typedef struct _GtkSelectionInfo GtkSelectionInfo;
101 typedef struct _GtkIncrConversion GtkIncrConversion;
102 typedef struct _GtkIncrInfo GtkIncrInfo;
103 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
105 struct _GtkSelectionInfo
108 GtkWidget *widget; /* widget that owns selection */
109 guint32 time; /* time used to acquire selection */
110 GdkDisplay *display; /* needed in gtk_selection_remove_all */
113 struct _GtkIncrConversion
115 GdkAtom target; /* Requested target */
116 GdkAtom property; /* Property to store in */
117 GtkSelectionData data; /* The data being supplied */
118 gint offset; /* Current offset in sent selection.
120 * -2 => Only the final (empty) portion
126 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
127 so we can receive events */
128 GdkAtom selection; /* Selection we're sending */
130 GtkIncrConversion *conversions; /* Information about requested conversions -
131 * With MULTIPLE requests (benighted 1980's
132 * hardware idea), there can be more than
134 gint num_conversions;
135 gint num_incrs; /* number of remaining INCR style transactions */
140 struct _GtkRetrievalInfo
143 GdkAtom selection; /* Selection being retrieved. */
144 GdkAtom target; /* Form of selection that we requested */
145 guint32 idle_time; /* Number of seconds since we last heard
146 from selection owner */
147 guchar *buffer; /* Buffer in which to accumulate results */
148 gint offset; /* Current offset in buffer, -1 indicates
150 guint32 notify_time; /* Timestamp from SelectionNotify */
153 /* Local Functions */
154 static void gtk_selection_init (void);
155 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
156 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
157 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
163 static void gtk_selection_invoke_handler (GtkWidget *widget,
164 GtkSelectionData *data,
166 static void gtk_selection_default_handler (GtkWidget *widget,
167 GtkSelectionData *data);
168 static int gtk_selection_bytes_per_item (gint format);
171 static gint initialize = TRUE;
172 static GList *current_retrievals = NULL;
173 static GList *current_incrs = NULL;
174 static GList *current_selections = NULL;
176 static GdkAtom gtk_selection_atoms[LAST_ATOM];
177 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
189 * gtk_target_list_new:
190 * @targets: Pointer to an array of #GtkTargetEntry
191 * @ntargets: number of entries in @targets.
193 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
195 * Return value: the new #GtkTargetList.
198 gtk_target_list_new (const GtkTargetEntry *targets,
201 GtkTargetList *result = g_new (GtkTargetList, 1);
203 result->ref_count = 1;
206 gtk_target_list_add_table (result, targets, ntargets);
212 * gtk_target_list_ref:
213 * @list: a #GtkTargetList
215 * Increases the reference count of a #GtkTargetList by one.
217 * Return value: the passed in #GtkTargetList.
220 gtk_target_list_ref (GtkTargetList *list)
222 g_return_val_if_fail (list != NULL, NULL);
230 * gtk_target_list_unref:
231 * @list: a #GtkTargetList
233 * Decreases the reference count of a #GtkTargetList by one.
234 * If the resulting reference count is zero, frees the list.
237 gtk_target_list_unref (GtkTargetList *list)
239 g_return_if_fail (list != NULL);
240 g_return_if_fail (list->ref_count > 0);
243 if (list->ref_count == 0)
245 GList *tmp_list = list->list;
248 GtkTargetPair *pair = tmp_list->data;
251 tmp_list = tmp_list->next;
254 g_list_free (list->list);
260 * gtk_target_list_add:
261 * @list: a #GtkTargetList
262 * @target: the interned atom representing the target
263 * @flags: the flags for this target
264 * @info: an ID that will be passed back to the application
266 * Appends another target to a #GtkTargetList.
269 gtk_target_list_add (GtkTargetList *list,
276 g_return_if_fail (list != NULL);
278 pair = g_new (GtkTargetPair, 1);
279 pair->target = target;
283 list->list = g_list_append (list->list, pair);
286 static GdkAtom utf8_atom;
287 static GdkAtom text_atom;
288 static GdkAtom ctext_atom;
289 static GdkAtom text_plain_atom;
290 static GdkAtom text_plain_utf8_atom;
291 static GdkAtom text_plain_locale_atom;
292 static GdkAtom text_uri_list_atom;
298 const gchar *charset;
302 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
303 text_atom = gdk_atom_intern_static_string ("TEXT");
304 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
305 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
306 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
307 g_get_charset (&charset);
308 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
309 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
312 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
317 * gtk_target_list_add_text_targets:
318 * @list: a #GtkTargetList
319 * @info: an ID that will be passed back to the application
321 * Appends the text targets supported by #GtkSelection to
322 * the target list. All targets are added with the same @info.
327 gtk_target_list_add_text_targets (GtkTargetList *list,
330 g_return_if_fail (list != NULL);
334 /* Keep in sync with gtk_selection_data_targets_include_text()
336 gtk_target_list_add (list, utf8_atom, 0, info);
337 gtk_target_list_add (list, ctext_atom, 0, info);
338 gtk_target_list_add (list, text_atom, 0, info);
339 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
340 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
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_new (GtkTargetPair, 1);
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)
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: 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_REALIZED (widget), FALSE);
662 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
667 window = widget->window;
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_free (selection_info);
698 if (selection_info == NULL)
700 selection_info = g_new (GtkSelectionInfo, 1);
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 (old_owner->window);
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: 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_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_new (GtkSelectionTargetList, 1);
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);
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);
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 (widget->window, 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 (widget->window, 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 /* Remove pending requests/incrs for this widget */
957 tmp_list = current_retrievals;
960 next = tmp_list->next;
961 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
963 current_retrievals = g_list_remove_link (current_retrievals,
965 /* structure will be freed in timeout */
966 g_list_free (tmp_list);
971 /* Disclaim ownership of any selections */
973 tmp_list = current_selections;
976 next = tmp_list->next;
977 selection_info = (GtkSelectionInfo *)tmp_list->data;
979 if (selection_info->widget == widget)
981 gdk_selection_owner_set_for_display (selection_info->display,
983 selection_info->selection,
984 GDK_CURRENT_TIME, FALSE);
985 current_selections = g_list_remove_link (current_selections,
987 g_list_free (tmp_list);
988 g_free (selection_info);
994 /* Remove all selection lists */
995 gtk_selection_target_list_remove (widget);
1000 * gtk_selection_convert:
1001 * @widget: The widget which acts as requestor
1002 * @selection: Which selection to get
1003 * @target: Form of information desired (e.g., STRING)
1004 * @time_: Time of request (usually of triggering event)
1005 In emergency, you could use #GDK_CURRENT_TIME
1007 * Requests the contents of a selection. When received,
1008 * a "selection_received" signal will be generated.
1010 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1011 * request. (e.g., there was already a request in process for
1015 gtk_selection_convert (GtkWidget *widget,
1020 GtkRetrievalInfo *info;
1022 GdkWindow *owner_window;
1023 GdkDisplay *display;
1025 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1026 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1029 gtk_selection_init ();
1031 if (!GTK_WIDGET_REALIZED (widget))
1032 gtk_widget_realize (widget);
1034 /* Check to see if there are already any retrievals in progress for
1035 this widget. If we changed GDK to use the selection for the
1036 window property in which to store the retrieved information, then
1037 we could support multiple retrievals for different selections.
1038 This might be useful for DND. */
1040 tmp_list = current_retrievals;
1043 info = (GtkRetrievalInfo *)tmp_list->data;
1044 if (info->widget == widget)
1046 tmp_list = tmp_list->next;
1049 info = g_new (GtkRetrievalInfo, 1);
1051 info->widget = widget;
1052 info->selection = selection;
1053 info->target = target;
1054 info->idle_time = 0;
1055 info->buffer = NULL;
1058 /* Check if this process has current owner. If so, call handler
1059 procedure directly to avoid deadlocks with INCR. */
1061 display = gtk_widget_get_display (widget);
1062 owner_window = gdk_selection_owner_get_for_display (display, selection);
1064 if (owner_window != NULL)
1066 GtkWidget *owner_widget;
1067 GtkSelectionData selection_data;
1069 selection_data.selection = selection;
1070 selection_data.target = target;
1071 selection_data.data = NULL;
1072 selection_data.length = -1;
1073 selection_data.display = display;
1075 gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget);
1077 if (owner_widget != NULL)
1079 gtk_selection_invoke_handler (owner_widget,
1083 gtk_selection_retrieval_report (info,
1084 selection_data.type,
1085 selection_data.format,
1086 selection_data.data,
1087 selection_data.length,
1090 g_free (selection_data.data);
1097 /* Otherwise, we need to go through X */
1099 current_retrievals = g_list_append (current_retrievals, info);
1100 gdk_selection_convert (widget->window, selection, target, time_);
1101 gdk_threads_add_timeout (1000,
1102 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1109 * gtk_selection_data_set:
1110 * @selection_data: a pointer to a #GtkSelectionData structure.
1111 * @type: the type of selection data
1112 * @format: format (number of bits in a unit)
1113 * @data: pointer to the data (will be copied)
1114 * @length: length of the data
1116 * Stores new data into a #GtkSelectionData object. Should
1117 * <emphasis>only</emphasis> be called from a selection handler callback.
1118 * Zero-terminates the stored data.
1121 gtk_selection_data_set (GtkSelectionData *selection_data,
1127 g_free (selection_data->data);
1129 selection_data->type = type;
1130 selection_data->format = format;
1134 selection_data->data = g_new (guchar, length+1);
1135 memcpy (selection_data->data, data, length);
1136 selection_data->data[length] = 0;
1140 g_return_if_fail (length <= 0);
1143 selection_data->data = NULL;
1145 selection_data->data = g_strdup("");
1148 selection_data->length = length;
1152 selection_set_string (GtkSelectionData *selection_data,
1156 gchar *tmp = g_strndup (str, len);
1157 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1162 gtk_selection_data_set (selection_data,
1163 GDK_SELECTION_TYPE_STRING,
1164 8, latin1, strlen (latin1));
1174 selection_set_compound_text (GtkSelectionData *selection_data,
1183 gboolean result = FALSE;
1185 tmp = g_strndup (str, len);
1186 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1187 &encoding, &format, &text, &new_length))
1189 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1190 gdk_free_compound_text (text);
1200 /* Normalize \r and \n into \r\n
1203 normalize_to_crlf (const gchar *str,
1206 GString *result = g_string_sized_new (len);
1207 const gchar *p = str;
1208 const gchar *end = str + len;
1213 g_string_append_c (result, '\r');
1217 g_string_append_c (result, *p);
1219 if (p == end || *p != '\n')
1220 g_string_append_c (result, '\n');
1225 g_string_append_c (result, *p);
1229 return g_string_free (result, FALSE);
1232 /* Normalize \r and \r\n into \n
1235 normalize_to_lf (gchar *str,
1238 GString *result = g_string_sized_new (len);
1239 const gchar *p = str;
1247 g_string_append_c (result, '\n');
1253 g_string_append_c (result, *p);
1257 return g_string_free (result, FALSE);
1261 selection_set_text_plain (GtkSelectionData *selection_data,
1265 const gchar *charset = NULL;
1267 GError *error = NULL;
1269 result = normalize_to_crlf (str, len);
1270 if (selection_data->target == text_plain_atom)
1272 else if (selection_data->target == text_plain_locale_atom)
1273 g_get_charset (&charset);
1277 gchar *tmp = result;
1278 result = g_convert_with_fallback (tmp, -1,
1280 NULL, NULL, NULL, &error);
1286 g_warning ("Error converting from %s to %s: %s",
1287 "UTF-8", charset, error->message);
1288 g_error_free (error);
1293 gtk_selection_data_set (selection_data,
1294 selection_data->target,
1295 8, result, strlen (result));
1302 selection_get_text_plain (GtkSelectionData *selection_data)
1304 const gchar *charset = NULL;
1305 gchar *str, *result;
1307 GError *error = NULL;
1309 str = g_strdup (selection_data->data);
1310 len = selection_data->length;
1312 if (selection_data->type == text_plain_atom)
1313 charset = "ISO-8859-1";
1314 else if (selection_data->type == text_plain_locale_atom)
1315 g_get_charset (&charset);
1320 str = g_convert_with_fallback (tmp, len,
1322 NULL, NULL, &len, &error);
1327 g_warning ("Error converting from %s to %s: %s",
1328 charset, "UTF-8", error->message);
1329 g_error_free (error);
1334 else if (!g_utf8_validate (str, -1, NULL))
1336 g_warning ("Error converting from %s to %s: %s",
1337 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1343 result = normalize_to_lf (str, len);
1350 * gtk_selection_data_set_text:
1351 * @selection_data: a #GtkSelectionData
1352 * @str: a UTF-8 string
1353 * @len: the length of @str, or -1 if @str is nul-terminated.
1355 * Sets the contents of the selection from a UTF-8 encoded string.
1356 * The string is converted to the form determined by
1357 * @selection_data->target.
1359 * Return value: %TRUE if the selection was successfully set,
1363 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1372 if (selection_data->target == utf8_atom)
1374 gtk_selection_data_set (selection_data,
1376 8, (guchar *)str, len);
1379 else if (selection_data->target == GDK_TARGET_STRING)
1381 return selection_set_string (selection_data, str, len);
1383 else if (selection_data->target == ctext_atom ||
1384 selection_data->target == text_atom)
1386 if (selection_set_compound_text (selection_data, str, len))
1388 else if (selection_data->target == text_atom)
1389 return selection_set_string (selection_data, str, len);
1391 else if (selection_data->target == text_plain_atom ||
1392 selection_data->target == text_plain_utf8_atom ||
1393 selection_data->target == text_plain_locale_atom)
1395 return selection_set_text_plain (selection_data, str, len);
1402 * gtk_selection_data_get_text:
1403 * @selection_data: a #GtkSelectionData
1405 * Gets the contents of the selection data as a UTF-8 string.
1407 * Return value: if the selection data contained a recognized
1408 * text type and it could be converted to UTF-8, a newly allocated
1409 * string containing the converted text, otherwise %NULL.
1410 * If the result is non-%NULL it must be freed with g_free().
1413 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1415 guchar *result = NULL;
1419 if (selection_data->length >= 0 &&
1420 (selection_data->type == GDK_TARGET_STRING ||
1421 selection_data->type == ctext_atom ||
1422 selection_data->type == utf8_atom))
1426 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1427 selection_data->type,
1428 selection_data->format,
1429 selection_data->data,
1430 selection_data->length,
1435 for (i = 1; i < count; i++)
1439 else if (selection_data->length >= 0 &&
1440 (selection_data->type == text_plain_atom ||
1441 selection_data->type == text_plain_utf8_atom ||
1442 selection_data->type == text_plain_locale_atom))
1444 result = selection_get_text_plain (selection_data);
1451 * gtk_selection_data_set_pixbuf:
1452 * @selection_data: a #GtkSelectionData
1453 * @pixbuf: a #GdkPixbuf
1455 * Sets the contents of the selection from a #GdkPixbuf
1456 * The pixbuf is converted to the form determined by
1457 * @selection_data->target.
1459 * Return value: %TRUE if the selection was successfully set,
1465 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1468 GSList *formats, *f;
1475 formats = gdk_pixbuf_get_formats ();
1477 for (f = formats; f; f = f->next)
1479 GdkPixbufFormat *fmt = f->data;
1481 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1482 for (m = mimes; *m; m++)
1484 atom = gdk_atom_intern (*m, FALSE);
1485 if (selection_data->target == atom)
1488 type = gdk_pixbuf_format_get_name (fmt);
1489 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1491 ((strcmp (type, "png") == 0) ?
1492 "compression" : NULL), "2",
1495 gtk_selection_data_set (selection_data,
1496 atom, 8, (guchar *)str, len);
1500 g_slist_free (formats);
1509 g_slist_free (formats);
1515 * gtk_selection_data_get_pixbuf:
1516 * @selection_data: a #GtkSelectionData
1518 * Gets the contents of the selection data as a #GdkPixbuf.
1520 * Return value: if the selection data contained a recognized
1521 * image type and it could be converted to a #GdkPixbuf, a
1522 * newly allocated pixbuf is returned, otherwise %NULL.
1523 * If the result is non-%NULL it must be freed with g_object_unref().
1528 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1530 GdkPixbufLoader *loader;
1531 GdkPixbuf *result = NULL;
1533 if (selection_data->length > 0)
1535 loader = gdk_pixbuf_loader_new ();
1537 gdk_pixbuf_loader_write (loader,
1538 selection_data->data,
1539 selection_data->length,
1541 gdk_pixbuf_loader_close (loader, NULL);
1542 result = gdk_pixbuf_loader_get_pixbuf (loader);
1545 g_object_ref (result);
1547 g_object_unref (loader);
1554 * gtk_selection_data_set_uris:
1555 * @selection_data: a #GtkSelectionData
1556 * @uris: a %NULL-terminated array of strings hilding URIs
1558 * Sets the contents of the selection from a list of URIs.
1559 * The string is converted to the form determined by
1560 * @selection_data->target.
1562 * Return value: %TRUE if the selection was successfully set,
1568 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1573 if (selection_data->target == text_uri_list_atom)
1580 list = g_string_new (NULL);
1581 for (i = 0; uris[i]; i++)
1583 g_string_append (list, uris[i]);
1584 g_string_append (list, "\r\n");
1587 result = g_convert (list->str, list->len,
1589 NULL, &length, NULL);
1590 g_string_free (list, TRUE);
1594 gtk_selection_data_set (selection_data,
1596 8, (guchar *)result, length);
1608 * gtk_selection_data_get_uris:
1609 * @selection_data: a #GtkSelectionData
1611 * Gets the contents of the selection data as array of URIs.
1613 * Return value: if the selection data contains a list of
1614 * URIs, a newly allocated %NULL-terminated string array
1615 * containing the URIs, otherwise %NULL. If the result is
1616 * non-%NULL it must be freed with g_strfreev().
1621 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1623 gchar **result = NULL;
1627 if (selection_data->length >= 0 &&
1628 selection_data->type == text_uri_list_atom)
1631 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1633 selection_data->format,
1634 selection_data->data,
1635 selection_data->length,
1638 result = g_uri_list_extract_uris (list[0]);
1648 * gtk_selection_data_get_targets:
1649 * @selection_data: a #GtkSelectionData object
1650 * @targets: location to store an array of targets. The result
1651 * stored here must be freed with g_free().
1652 * @n_atoms: location to store number of items in @targets.
1654 * Gets the contents of @selection_data as an array of targets.
1655 * This can be used to interpret the results of getting
1656 * the standard TARGETS target that is always supplied for
1659 * Return value: %TRUE if @selection_data contains a valid
1660 * array of targets, otherwise %FALSE.
1663 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1667 if (selection_data->length >= 0 &&
1668 selection_data->format == 32 &&
1669 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1672 *targets = g_memdup (selection_data->data, selection_data->length);
1674 *n_atoms = selection_data->length / sizeof (GdkAtom);
1690 * gtk_targets_include_text:
1691 * @targets: an array of #GdkAtom<!-- -->s
1692 * @n_targets: the length of @targets
1694 * Determines if any of the targets in @targets can be used to
1697 * Return value: %TRUE if @targets include a suitable target for text,
1703 gtk_targets_include_text (GdkAtom *targets,
1707 gboolean result = FALSE;
1709 /* Keep in sync with gtk_target_list_add_text_targets()
1714 for (i = 0; i < n_targets; i++)
1716 if (targets[i] == utf8_atom ||
1717 targets[i] == text_atom ||
1718 targets[i] == GDK_TARGET_STRING ||
1719 targets[i] == ctext_atom ||
1720 targets[i] == text_plain_atom ||
1721 targets[i] == text_plain_utf8_atom ||
1722 targets[i] == text_plain_locale_atom)
1733 * gtk_targets_include_rich_text:
1734 * @targets: an array of #GdkAtom<!-- -->s
1735 * @n_targets: the length of @targets
1736 * @buffer: a #GtkTextBuffer
1738 * Determines if any of the targets in @targets can be used to
1739 * provide rich text.
1741 * Return value: %TRUE if @targets include a suitable target for rich text,
1747 gtk_targets_include_rich_text (GdkAtom *targets,
1749 GtkTextBuffer *buffer)
1751 GdkAtom *rich_targets;
1752 gint n_rich_targets;
1754 gboolean result = FALSE;
1756 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1760 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1763 for (i = 0; i < n_targets; i++)
1765 for (j = 0; j < n_rich_targets; j++)
1767 if (targets[i] == rich_targets[j])
1776 g_free (rich_targets);
1782 * gtk_selection_data_targets_include_text:
1783 * @selection_data: a #GtkSelectionData object
1785 * Given a #GtkSelectionData object holding a list of targets,
1786 * determines if any of the targets in @targets can be used to
1789 * Return value: %TRUE if @selection_data holds a list of targets,
1790 * and a suitable target for text is included, otherwise %FALSE.
1793 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1797 gboolean result = FALSE;
1801 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1803 result = gtk_targets_include_text (targets, n_targets);
1811 * gtk_selection_data_targets_include_rich_text:
1812 * @selection_data: a #GtkSelectionData object
1813 * @buffer: a #GtkTextBuffer
1815 * Given a #GtkSelectionData object holding a list of targets,
1816 * determines if any of the targets in @targets can be used to
1817 * provide rich text.
1819 * Return value: %TRUE if @selection_data holds a list of targets,
1820 * and a suitable target for rich text is included,
1826 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1827 GtkTextBuffer *buffer)
1831 gboolean result = FALSE;
1833 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1837 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1839 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1847 * gtk_targets_include_image:
1848 * @targets: an array of #GdkAtom<!-- -->s
1849 * @n_targets: the length of @targets
1850 * @writable: whether to accept only targets for which GTK+ knows
1851 * how to convert a pixbuf into the format
1853 * Determines if any of the targets in @targets can be used to
1854 * provide a #GdkPixbuf.
1856 * Return value: %TRUE if @targets include a suitable target for images,
1862 gtk_targets_include_image (GdkAtom *targets,
1866 GtkTargetList *list;
1869 gboolean result = FALSE;
1871 list = gtk_target_list_new (NULL, 0);
1872 gtk_target_list_add_image_targets (list, 0, writable);
1873 for (i = 0; i < n_targets && !result; i++)
1875 for (l = list->list; l; l = l->next)
1877 GtkTargetPair *pair = (GtkTargetPair *)l->data;
1878 if (pair->target == targets[i])
1885 gtk_target_list_unref (list);
1891 * gtk_selection_data_targets_include_image:
1892 * @selection_data: a #GtkSelectionData object
1893 * @writable: whether to accept only targets for which GTK+ knows
1894 * how to convert a pixbuf into the format
1896 * Given a #GtkSelectionData object holding a list of targets,
1897 * determines if any of the targets in @targets can be used to
1898 * provide a #GdkPixbuf.
1900 * Return value: %TRUE if @selection_data holds a list of targets,
1901 * and a suitable target for images is included, otherwise %FALSE.
1906 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
1911 gboolean result = FALSE;
1915 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1917 result = gtk_targets_include_image (targets, n_targets, writable);
1925 * gtk_targets_include_uri:
1926 * @targets: an array of #GdkAtom<!-- -->s
1927 * @n_targets: the length of @targets
1929 * Determines if any of the targets in @targets can be used to
1930 * provide an uri list.
1932 * Return value: %TRUE if @targets include a suitable target for uri lists,
1938 gtk_targets_include_uri (GdkAtom *targets,
1942 gboolean result = FALSE;
1944 /* Keep in sync with gtk_target_list_add_uri_targets()
1949 for (i = 0; i < n_targets; i++)
1951 if (targets[i] == text_uri_list_atom)
1962 * gtk_selection_data_targets_include_uri:
1963 * @selection_data: a #GtkSelectionData object
1965 * Given a #GtkSelectionData object holding a list of targets,
1966 * determines if any of the targets in @targets can be used to
1967 * provide a list or URIs.
1969 * Return value: %TRUE if @selection_data holds a list of targets,
1970 * and a suitable target for text is included, otherwise %FALSE.
1975 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
1979 gboolean result = FALSE;
1983 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1985 result = gtk_targets_include_uri (targets, n_targets);
1993 /*************************************************************
1994 * gtk_selection_init:
1995 * Initialize local variables
1999 *************************************************************/
2002 gtk_selection_init (void)
2004 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2005 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2006 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2007 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2013 * gtk_selection_clear:
2014 * @widget: a #GtkWidget
2017 * The default handler for the GtkWidget::selection_clear_event
2020 * Return value: %TRUE if the event was handled, otherwise false
2024 * Deprecated: 2.4: Instead of calling this function, chain up from
2025 * your selection_clear_event handler. Calling this function
2026 * from any other context is illegal.
2029 gtk_selection_clear (GtkWidget *widget,
2030 GdkEventSelection *event)
2032 /* Note that we filter clear events in gdkselection-x11.c, so
2033 * that we only will get here if the clear event actually
2034 * represents a change that we didn't do ourself.
2037 GtkSelectionInfo *selection_info = NULL;
2039 tmp_list = current_selections;
2042 selection_info = (GtkSelectionInfo *)tmp_list->data;
2044 if ((selection_info->selection == event->selection) &&
2045 (selection_info->widget == widget))
2048 tmp_list = tmp_list->next;
2053 current_selections = g_list_remove_link (current_selections, tmp_list);
2054 g_list_free (tmp_list);
2055 g_free (selection_info);
2062 /*************************************************************
2063 * _gtk_selection_request:
2064 * Handler for "selection_request_event"
2069 *************************************************************/
2072 _gtk_selection_request (GtkWidget *widget,
2073 GdkEventSelection *event)
2075 GdkDisplay *display = gtk_widget_get_display (widget);
2079 gulong selection_max_size;
2082 gtk_selection_init ();
2084 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2086 /* Check if we own selection */
2088 tmp_list = current_selections;
2091 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2093 if ((selection_info->selection == event->selection) &&
2094 (selection_info->widget == widget))
2097 tmp_list = tmp_list->next;
2100 if (tmp_list == NULL)
2103 info = g_new (GtkIncrInfo, 1);
2105 g_object_ref (widget);
2107 info->selection = event->selection;
2108 info->num_incrs = 0;
2110 /* Create GdkWindow structure for the requestor */
2112 info->requestor = gdk_window_lookup_for_display (display,
2114 if (!info->requestor)
2115 info->requestor = gdk_window_foreign_new_for_display (display,
2118 /* Determine conversions we need to perform */
2120 if (event->target == gtk_selection_atoms[MULTIPLE])
2129 gdk_error_trap_push ();
2130 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2131 0, selection_max_size, FALSE,
2132 &type, &format, &length, &mult_atoms))
2134 gdk_selection_send_notify_for_display (display,
2140 g_free (mult_atoms);
2142 gdk_error_trap_pop ();
2145 gdk_error_trap_pop ();
2147 /* This is annoying; the ICCCM doesn't specify the property type
2148 * used for the property contents, so the autoconversion for
2149 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2151 #ifdef GDK_WINDOWING_X11
2152 if (type != GDK_SELECTION_TYPE_ATOM &&
2153 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2155 info->num_conversions = length / (2*sizeof (glong));
2156 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2158 for (i=0; i<info->num_conversions; i++)
2160 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2161 ((glong *)mult_atoms)[2*i]);
2162 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2163 ((glong *)mult_atoms)[2*i + 1]);
2166 g_free (mult_atoms);
2171 info->num_conversions = length / (2*sizeof (GdkAtom));
2172 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2174 for (i=0; i<info->num_conversions; i++)
2176 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2177 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2180 g_free (mult_atoms);
2183 else /* only a single conversion */
2185 info->conversions = g_new (GtkIncrConversion, 1);
2186 info->num_conversions = 1;
2187 info->conversions[0].target = event->target;
2188 info->conversions[0].property = event->property;
2191 /* Loop through conversions and determine which of these are big
2192 enough to require doing them via INCR */
2193 for (i=0; i<info->num_conversions; i++)
2195 GtkSelectionData data;
2198 data.selection = event->selection;
2199 data.target = info->conversions[i].target;
2202 data.display = gtk_widget_get_display (widget);
2204 #ifdef DEBUG_SELECTION
2205 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2207 info->conversions[i].target,
2208 gdk_atom_name (info->conversions[i].target),
2209 event->requestor, info->conversions[i].property);
2212 gtk_selection_invoke_handler (widget, &data, event->time);
2214 if (data.length < 0)
2216 info->conversions[i].property = GDK_NONE;
2220 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2222 items = data.length / gtk_selection_bytes_per_item (data.format);
2224 if (data.length > selection_max_size)
2226 /* Sending via INCR */
2227 #ifdef DEBUG_SELECTION
2228 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2229 data.length, selection_max_size);
2232 info->conversions[i].offset = 0;
2233 info->conversions[i].data = data;
2236 gdk_property_change (info->requestor,
2237 info->conversions[i].property,
2238 gtk_selection_atoms[INCR],
2240 GDK_PROP_MODE_REPLACE,
2241 (guchar *)&items, 1);
2245 info->conversions[i].offset = -1;
2247 gdk_property_change (info->requestor,
2248 info->conversions[i].property,
2251 GDK_PROP_MODE_REPLACE,
2258 /* If we have some INCR's, we need to send the rest of the data in
2261 if (info->num_incrs > 0)
2263 /* FIXME: this could be dangerous if window doesn't still
2266 #ifdef DEBUG_SELECTION
2267 g_message ("Starting INCR...");
2270 gdk_window_set_events (info->requestor,
2271 gdk_window_get_events (info->requestor) |
2272 GDK_PROPERTY_CHANGE_MASK);
2273 current_incrs = g_list_append (current_incrs, info);
2274 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2277 /* If it was a MULTIPLE request, set the property to indicate which
2278 conversions succeeded */
2279 if (event->target == gtk_selection_atoms[MULTIPLE])
2281 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2282 for (i = 0; i < info->num_conversions; i++)
2284 mult_atoms[2*i] = info->conversions[i].target;
2285 mult_atoms[2*i+1] = info->conversions[i].property;
2288 gdk_property_change (info->requestor, event->property,
2289 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2290 GDK_PROP_MODE_REPLACE,
2291 (guchar *)mult_atoms, 2*info->num_conversions);
2292 g_free (mult_atoms);
2295 if (info->num_conversions == 1 &&
2296 info->conversions[0].property == GDK_NONE)
2298 /* Reject the entire conversion */
2299 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2308 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2316 if (info->num_incrs == 0)
2318 g_free (info->conversions);
2322 g_object_unref (widget);
2327 /*************************************************************
2328 * _gtk_selection_incr_event:
2329 * Called whenever an PropertyNotify event occurs for an
2330 * GdkWindow with user_data == NULL. These will be notifications
2331 * that a window we are sending the selection to via the
2332 * INCR protocol has deleted a property and is ready for
2336 * window: the requestor window
2337 * event: the property event structure
2340 *************************************************************/
2343 _gtk_selection_incr_event (GdkWindow *window,
2344 GdkEventProperty *event)
2347 GtkIncrInfo *info = NULL;
2350 gulong selection_max_size;
2354 if (event->state != GDK_PROPERTY_DELETE)
2357 #ifdef DEBUG_SELECTION
2358 g_message ("PropertyDelete, property %ld", event->atom);
2361 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2363 /* Now find the appropriate ongoing INCR */
2364 tmp_list = current_incrs;
2367 info = (GtkIncrInfo *)tmp_list->data;
2368 if (info->requestor == event->window)
2371 tmp_list = tmp_list->next;
2374 if (tmp_list == NULL)
2377 /* Find out which target this is for */
2378 for (i=0; i<info->num_conversions; i++)
2380 if (info->conversions[i].property == event->atom &&
2381 info->conversions[i].offset != -1)
2385 info->idle_time = 0;
2387 if (info->conversions[i].offset == -2) /* only the last 0-length
2395 num_bytes = info->conversions[i].data.length -
2396 info->conversions[i].offset;
2397 buffer = info->conversions[i].data.data +
2398 info->conversions[i].offset;
2400 if (num_bytes > selection_max_size)
2402 num_bytes = selection_max_size;
2403 info->conversions[i].offset += selection_max_size;
2406 info->conversions[i].offset = -2;
2408 #ifdef DEBUG_SELECTION
2409 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2410 num_bytes, info->conversions[i].offset,
2411 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2414 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2415 gdk_property_change (info->requestor, event->atom,
2416 info->conversions[i].data.type,
2417 info->conversions[i].data.format,
2418 GDK_PROP_MODE_REPLACE,
2420 num_bytes / bytes_per_item);
2422 if (info->conversions[i].offset == -2)
2424 g_free (info->conversions[i].data.data);
2425 info->conversions[i].data.data = NULL;
2431 info->conversions[i].offset = -1;
2436 /* Check if we're finished with all the targets */
2438 if (info->num_incrs == 0)
2440 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2441 g_list_free (tmp_list);
2442 /* Let the timeout free it */
2448 /*************************************************************
2449 * gtk_selection_incr_timeout:
2450 * Timeout callback for the sending portion of the INCR
2453 * info: Information about this incr
2455 *************************************************************/
2458 gtk_selection_incr_timeout (GtkIncrInfo *info)
2463 /* Determine if retrieval has finished by checking if it still in
2464 list of pending retrievals */
2466 tmp_list = current_incrs;
2469 if (info == (GtkIncrInfo *)tmp_list->data)
2471 tmp_list = tmp_list->next;
2474 /* If retrieval is finished */
2475 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2477 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2479 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2480 g_list_free (tmp_list);
2483 g_free (info->conversions);
2484 /* FIXME: we should check if requestor window is still in use,
2485 and if not, remove it? */
2489 retval = FALSE; /* remove timeout */
2495 retval = TRUE; /* timeout will happen again */
2501 /*************************************************************
2502 * _gtk_selection_notify:
2503 * Handler for "selection_notify_event" signals on windows
2504 * where a retrieval is currently in process. The selection
2505 * owner has responded to our conversion request.
2507 * widget: Widget getting signal
2508 * event: Selection event structure
2509 * info: Information about this retrieval
2511 * was event handled?
2512 *************************************************************/
2515 _gtk_selection_notify (GtkWidget *widget,
2516 GdkEventSelection *event)
2519 GtkRetrievalInfo *info = NULL;
2520 guchar *buffer = NULL;
2525 #ifdef DEBUG_SELECTION
2526 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2527 event->selection, event->target, event->property);
2530 tmp_list = current_retrievals;
2533 info = (GtkRetrievalInfo *)tmp_list->data;
2534 if (info->widget == widget && info->selection == event->selection)
2536 tmp_list = tmp_list->next;
2539 if (!tmp_list) /* no retrieval in progress */
2542 if (event->property != GDK_NONE)
2543 length = gdk_selection_property_get (widget->window, &buffer,
2546 length = 0; /* silence gcc */
2548 if (event->property == GDK_NONE || buffer == NULL)
2550 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2551 g_list_free (tmp_list);
2552 /* structure will be freed in timeout */
2553 gtk_selection_retrieval_report (info,
2554 GDK_NONE, 0, NULL, -1, event->time);
2559 if (type == gtk_selection_atoms[INCR])
2561 /* The remainder of the selection will come through PropertyNotify
2564 info->notify_time = event->time;
2565 info->idle_time = 0;
2566 info->offset = 0; /* Mark as OK to proceed */
2567 gdk_window_set_events (widget->window,
2568 gdk_window_get_events (widget->window)
2569 | GDK_PROPERTY_CHANGE_MASK);
2573 /* We don't delete the info structure - that will happen in timeout */
2574 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2575 g_list_free (tmp_list);
2577 info->offset = length;
2578 gtk_selection_retrieval_report (info,
2580 buffer, length, event->time);
2583 gdk_property_delete (widget->window, event->property);
2590 /*************************************************************
2591 * _gtk_selection_property_notify:
2592 * Handler for "property_notify_event" signals on windows
2593 * where a retrieval is currently in process. The selection
2594 * owner has added more data.
2596 * widget: Widget getting signal
2597 * event: Property event structure
2598 * info: Information about this retrieval
2600 * was event handled?
2601 *************************************************************/
2604 _gtk_selection_property_notify (GtkWidget *widget,
2605 GdkEventProperty *event)
2608 GtkRetrievalInfo *info = NULL;
2614 g_return_val_if_fail (widget != NULL, FALSE);
2615 g_return_val_if_fail (event != NULL, FALSE);
2617 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2618 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2619 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2623 #ifdef DEBUG_SELECTION
2624 g_message ("PropertyNewValue, property %ld",
2628 tmp_list = current_retrievals;
2631 info = (GtkRetrievalInfo *)tmp_list->data;
2632 if (info->widget == widget)
2634 tmp_list = tmp_list->next;
2637 if (!tmp_list) /* No retrieval in progress */
2640 if (info->offset < 0) /* We haven't got the SelectionNotify
2641 for this retrieval yet */
2644 info->idle_time = 0;
2646 length = gdk_selection_property_get (widget->window, &new_buffer,
2648 gdk_property_delete (widget->window, event->atom);
2650 /* We could do a lot better efficiency-wise by paying attention to
2651 what length was sent in the initial INCR transaction, instead of
2652 doing memory allocation at every step. But its only guaranteed to
2653 be a _lower bound_ (pretty useless!) */
2655 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2657 /* Info structure will be freed in timeout */
2658 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2659 g_list_free (tmp_list);
2660 gtk_selection_retrieval_report (info,
2662 (type == GDK_NONE) ? NULL : info->buffer,
2663 (type == GDK_NONE) ? -1 : info->offset,
2666 else /* append on newly arrived data */
2670 #ifdef DEBUG_SELECTION
2671 g_message ("Start - Adding %d bytes at offset 0",
2674 info->buffer = new_buffer;
2675 info->offset = length;
2680 #ifdef DEBUG_SELECTION
2681 g_message ("Appending %d bytes at offset %d",
2682 length,info->offset);
2684 /* We copy length+1 bytes to preserve guaranteed null termination */
2685 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2686 memcpy (info->buffer + info->offset, new_buffer, length+1);
2687 info->offset += length;
2688 g_free (new_buffer);
2695 /*************************************************************
2696 * gtk_selection_retrieval_timeout:
2697 * Timeout callback while receiving a selection.
2699 * info: Information about this retrieval
2701 *************************************************************/
2704 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2709 /* Determine if retrieval has finished by checking if it still in
2710 list of pending retrievals */
2712 tmp_list = current_retrievals;
2715 if (info == (GtkRetrievalInfo *)tmp_list->data)
2717 tmp_list = tmp_list->next;
2720 /* If retrieval is finished */
2721 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2723 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2725 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2726 g_list_free (tmp_list);
2727 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2730 g_free (info->buffer);
2733 retval = FALSE; /* remove timeout */
2739 retval = TRUE; /* timeout will happen again */
2745 /*************************************************************
2746 * gtk_selection_retrieval_report:
2747 * Emits a "selection_received" signal.
2749 * info: information about the retrieval that completed
2750 * buffer: buffer containing data (NULL => errror)
2751 * time: timestamp for data in buffer
2753 *************************************************************/
2756 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2757 GdkAtom type, gint format,
2758 guchar *buffer, gint length,
2761 GtkSelectionData data;
2763 data.selection = info->selection;
2764 data.target = info->target;
2766 data.format = format;
2768 data.length = length;
2770 data.display = gtk_widget_get_display (info->widget);
2772 g_signal_emit_by_name (info->widget,
2773 "selection_received",
2777 /*************************************************************
2778 * gtk_selection_invoke_handler:
2779 * Finds and invokes handler for specified
2780 * widget/selection/target combination, calls
2781 * gtk_selection_default_handler if none exists.
2784 * widget: selection owner
2785 * data: selection data [INOUT]
2786 * time: time from requeset
2789 * Number of bytes written to buffer, -1 if error
2790 *************************************************************/
2793 gtk_selection_invoke_handler (GtkWidget *widget,
2794 GtkSelectionData *data,
2797 GtkTargetList *target_list;
2801 g_return_if_fail (widget != NULL);
2803 target_list = gtk_selection_target_list_get (widget, data->selection);
2805 gtk_target_list_find (target_list, data->target, &info))
2807 g_signal_emit_by_name (widget,
2813 gtk_selection_default_handler (widget, data);
2816 /*************************************************************
2817 * gtk_selection_default_handler:
2818 * Handles some default targets that exist for any widget
2819 * If it can't fit results into buffer, returns -1. This
2820 * won't happen in any conceivable case, since it would
2821 * require 1000 selection targets!
2824 * widget: selection owner
2825 * data: selection data [INOUT]
2827 *************************************************************/
2830 gtk_selection_default_handler (GtkWidget *widget,
2831 GtkSelectionData *data)
2833 if (data->target == gtk_selection_atoms[TIMESTAMP])
2835 /* Time which was used to obtain selection */
2837 GtkSelectionInfo *selection_info;
2839 tmp_list = current_selections;
2842 selection_info = (GtkSelectionInfo *)tmp_list->data;
2843 if ((selection_info->widget == widget) &&
2844 (selection_info->selection == data->selection))
2846 gulong time = selection_info->time;
2848 gtk_selection_data_set (data,
2849 GDK_SELECTION_TYPE_INTEGER,
2856 tmp_list = tmp_list->next;
2861 else if (data->target == gtk_selection_atoms[TARGETS])
2863 /* List of all targets supported for this widget/selection pair */
2867 GtkTargetList *target_list;
2868 GtkTargetPair *pair;
2870 target_list = gtk_selection_target_list_get (widget,
2872 count = g_list_length (target_list->list) + 3;
2874 data->type = GDK_SELECTION_TYPE_ATOM;
2876 data->length = count * sizeof (GdkAtom);
2878 /* selection data is always terminated by a trailing \0
2880 p = g_malloc (data->length + 1);
2881 data->data = (guchar *)p;
2882 data->data[data->length] = '\0';
2884 *p++ = gtk_selection_atoms[TIMESTAMP];
2885 *p++ = gtk_selection_atoms[TARGETS];
2886 *p++ = gtk_selection_atoms[MULTIPLE];
2888 tmp_list = target_list->list;
2891 pair = (GtkTargetPair *)tmp_list->data;
2892 *p++ = pair->target;
2894 tmp_list = tmp_list->next;
2905 * gtk_selection_data_copy:
2906 * @data: a pointer to a #GtkSelectionData structure.
2908 * Makes a copy of a #GtkSelectionData structure and its data.
2910 * Return value: a pointer to a copy of @data.
2913 gtk_selection_data_copy (GtkSelectionData *data)
2915 GtkSelectionData *new_data;
2917 g_return_val_if_fail (data != NULL, NULL);
2919 new_data = g_new (GtkSelectionData, 1);
2924 new_data->data = g_malloc (data->length + 1);
2925 memcpy (new_data->data, data->data, data->length + 1);
2932 * gtk_selection_data_free:
2933 * @data: a pointer to a #GtkSelectionData structure.
2935 * Frees a #GtkSelectionData structure returned from
2936 * gtk_selection_data_copy().
2939 gtk_selection_data_free (GtkSelectionData *data)
2941 g_return_if_fail (data != NULL);
2943 g_free (data->data);
2949 gtk_selection_data_get_type (void)
2951 static GType our_type = 0;
2954 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
2955 (GBoxedCopyFunc) gtk_selection_data_copy,
2956 (GBoxedFreeFunc) gtk_selection_data_free);
2962 gtk_target_list_get_type (void)
2964 static GType our_type = 0;
2967 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
2968 (GBoxedCopyFunc) gtk_target_list_ref,
2969 (GBoxedFreeFunc) gtk_target_list_unref);
2975 gtk_selection_bytes_per_item (gint format)
2980 return sizeof (char);
2983 return sizeof (short);
2986 return sizeof (long);
2989 g_assert_not_reached();
2994 #define __GTK_SELECTION_C__
2995 #include "gtkaliasdef.c"