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 gint gtk_selection_incr_timeout (GtkIncrInfo *info);
156 static gint 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
535 * Looks up a given target in a #GtkTargetList.
537 * Return value: %TRUE if the target was found, otherwise %FALSE
540 gtk_target_list_find (GtkTargetList *list,
544 GList *tmp_list = list->list;
547 GtkTargetPair *pair = tmp_list->data;
549 if (pair->target == target)
554 tmp_list = tmp_list->next;
561 * gtk_target_table_new_from_list:
562 * @list: a #GtkTargetList
563 * @n_targets: return location for the number ot targets in the table
565 * This function creates an #GtkTargetEntry array that contains the
566 * same targets as the passed %list. The returned table is newly
567 * allocated and should be freed using gtk_target_table_free() when no
570 * Return value: the new table.
575 gtk_target_table_new_from_list (GtkTargetList *list,
578 GtkTargetEntry *targets;
582 g_return_val_if_fail (list != NULL, NULL);
583 g_return_val_if_fail (n_targets != NULL, NULL);
585 *n_targets = g_list_length (list->list);
586 targets = g_new0 (GtkTargetEntry, *n_targets);
588 for (i = 0, tmp_list = list->list;
590 i++, tmp_list = g_list_next (tmp_list))
592 GtkTargetPair *pair = tmp_list->data;
594 targets[i].target = gdk_atom_name (pair->target);
595 targets[i].flags = pair->flags;
596 targets[i].info = pair->info;
603 * gtk_target_table_free:
604 * @targets: a #GtkTargetEntry array
605 * @n_targets: the number of entries in the array
607 * This function frees a target table as returned by
608 * gtk_target_table_new_from_list()
613 gtk_target_table_free (GtkTargetEntry *targets,
618 g_return_if_fail (targets == NULL || n_targets > 0);
620 for (i = 0; i < n_targets; i++)
621 g_free (targets[i].target);
627 * gtk_selection_owner_set_for_display:
628 * @display: the #Gdkdisplay where the selection is set
629 * @widget: new selection owner (a #GdkWidget), or %NULL.
630 * @selection: an interned atom representing the selection to claim.
631 * @time_: timestamp with which to claim the selection
633 * Claim ownership of a given selection for a particular widget, or,
634 * if @widget is %NULL, release ownership of the selection.
636 * Return value: TRUE if the operation succeeded
641 gtk_selection_owner_set_for_display (GdkDisplay *display,
647 GtkWidget *old_owner;
648 GtkSelectionInfo *selection_info = NULL;
651 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
652 g_return_val_if_fail (selection != GDK_NONE, FALSE);
653 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
654 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
659 window = widget->window;
661 tmp_list = current_selections;
664 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
666 selection_info = tmp_list->data;
670 tmp_list = tmp_list->next;
673 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
681 old_owner = selection_info->widget;
682 current_selections = g_list_remove_link (current_selections,
684 g_list_free (tmp_list);
685 g_free (selection_info);
690 if (selection_info == NULL)
692 selection_info = g_new (GtkSelectionInfo, 1);
693 selection_info->selection = selection;
694 selection_info->widget = widget;
695 selection_info->time = time;
696 selection_info->display = display;
697 current_selections = g_list_prepend (current_selections,
702 old_owner = selection_info->widget;
703 selection_info->widget = widget;
704 selection_info->time = time;
705 selection_info->display = display;
708 /* If another widget in the application lost the selection,
709 * send it a GDK_SELECTION_CLEAR event.
711 if (old_owner && old_owner != widget)
713 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
715 event->selection.window = g_object_ref (old_owner->window);
716 event->selection.selection = selection;
717 event->selection.time = time;
719 gtk_widget_event (old_owner, event);
721 gdk_event_free (event);
730 * gtk_selection_owner_set:
731 * @widget: a #GtkWidget, or %NULL.
732 * @selection: an interned atom representing the selection to claim
733 * @time_: timestamp with which to claim the selection
735 * Claims ownership of a given selection for a particular widget,
736 * or, if @widget is %NULL, release ownership of the selection.
738 * Return value: %TRUE if the operation succeeded
741 gtk_selection_owner_set (GtkWidget *widget,
747 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
748 g_return_val_if_fail (selection != GDK_NONE, FALSE);
751 display = gtk_widget_get_display (widget);
755 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
757 display = gdk_display_get_default ();
760 return gtk_selection_owner_set_for_display (display, widget,
764 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
766 struct _GtkSelectionTargetList {
771 static GtkTargetList *
772 gtk_selection_target_list_get (GtkWidget *widget,
775 GtkSelectionTargetList *sellist;
779 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
784 sellist = tmp_list->data;
785 if (sellist->selection == selection)
786 return sellist->list;
787 tmp_list = tmp_list->next;
790 sellist = g_new (GtkSelectionTargetList, 1);
791 sellist->selection = selection;
792 sellist->list = gtk_target_list_new (NULL, 0);
794 lists = g_list_prepend (lists, sellist);
795 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
797 return sellist->list;
801 gtk_selection_target_list_remove (GtkWidget *widget)
803 GtkSelectionTargetList *sellist;
807 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
812 sellist = tmp_list->data;
814 gtk_target_list_unref (sellist->list);
817 tmp_list = tmp_list->next;
821 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
825 * gtk_selection_clear_targets:
826 * @widget: a #GtkWidget
827 * @selection: an atom representing a selection
829 * Remove all targets registered for the given selection for the
833 gtk_selection_clear_targets (GtkWidget *widget,
836 GtkSelectionTargetList *sellist;
840 g_return_if_fail (GTK_IS_WIDGET (widget));
841 g_return_if_fail (selection != GDK_NONE);
843 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
848 sellist = tmp_list->data;
849 if (sellist->selection == selection)
851 lists = g_list_delete_link (lists, tmp_list);
852 gtk_target_list_unref (sellist->list);
858 tmp_list = tmp_list->next;
861 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
865 * gtk_selection_add_target:
866 * @widget: a #GtkTarget
867 * @selection: the selection
868 * @target: target to add.
869 * @info: A unsigned integer which will be passed back to the application.
871 * Appends a specified target to the list of supported targets for a
872 * given widget and selection.
875 gtk_selection_add_target (GtkWidget *widget,
882 g_return_if_fail (GTK_IS_WIDGET (widget));
883 g_return_if_fail (selection != GDK_NONE);
885 list = gtk_selection_target_list_get (widget, selection);
886 gtk_target_list_add (list, target, 0, info);
887 #ifdef GDK_WINDOWING_WIN32
888 gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
893 * gtk_selection_add_targets:
894 * @widget: a #GtkWidget
895 * @selection: the selection
896 * @targets: a table of targets to add
897 * @ntargets: number of entries in @targets
899 * Prepends a table of targets to the list of supported targets
900 * for a given widget and selection.
903 gtk_selection_add_targets (GtkWidget *widget,
905 const GtkTargetEntry *targets,
910 g_return_if_fail (GTK_IS_WIDGET (widget));
911 g_return_if_fail (selection != GDK_NONE);
912 g_return_if_fail (targets != NULL);
914 list = gtk_selection_target_list_get (widget, selection);
915 gtk_target_list_add_table (list, targets, ntargets);
917 #ifdef GDK_WINDOWING_WIN32
920 GdkAtom *atoms = g_new (GdkAtom, ntargets);
922 for (i = 0; i < ntargets; ++i)
923 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
924 gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
932 * gtk_selection_remove_all:
933 * @widget: a #GtkWidget
935 * Removes all handlers and unsets ownership of all
936 * selections for a widget. Called when widget is being
937 * destroyed. This function will not generally be
938 * called by applications.
941 gtk_selection_remove_all (GtkWidget *widget)
945 GtkSelectionInfo *selection_info;
947 /* Remove pending requests/incrs for this widget */
949 tmp_list = current_retrievals;
952 next = tmp_list->next;
953 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
955 current_retrievals = g_list_remove_link (current_retrievals,
957 /* structure will be freed in timeout */
958 g_list_free (tmp_list);
963 /* Disclaim ownership of any selections */
965 tmp_list = current_selections;
968 next = tmp_list->next;
969 selection_info = (GtkSelectionInfo *)tmp_list->data;
971 if (selection_info->widget == widget)
973 gdk_selection_owner_set_for_display (selection_info->display,
975 selection_info->selection,
976 GDK_CURRENT_TIME, FALSE);
977 current_selections = g_list_remove_link (current_selections,
979 g_list_free (tmp_list);
980 g_free (selection_info);
986 /* Remove all selection lists */
987 gtk_selection_target_list_remove (widget);
992 * gtk_selection_convert:
993 * @widget: The widget which acts as requestor
994 * @selection: Which selection to get
995 * @target: Form of information desired (e.g., STRING)
996 * @time_: Time of request (usually of triggering event)
997 In emergency, you could use #GDK_CURRENT_TIME
999 * Requests the contents of a selection. When received,
1000 * a "selection_received" signal will be generated.
1002 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1003 * request. (e.g., there was already a request in process for
1007 gtk_selection_convert (GtkWidget *widget,
1012 GtkRetrievalInfo *info;
1014 GdkWindow *owner_window;
1015 GdkDisplay *display;
1017 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1018 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1021 gtk_selection_init ();
1023 if (!GTK_WIDGET_REALIZED (widget))
1024 gtk_widget_realize (widget);
1026 /* Check to see if there are already any retrievals in progress for
1027 this widget. If we changed GDK to use the selection for the
1028 window property in which to store the retrieved information, then
1029 we could support multiple retrievals for different selections.
1030 This might be useful for DND. */
1032 tmp_list = current_retrievals;
1035 info = (GtkRetrievalInfo *)tmp_list->data;
1036 if (info->widget == widget)
1038 tmp_list = tmp_list->next;
1041 info = g_new (GtkRetrievalInfo, 1);
1043 info->widget = widget;
1044 info->selection = selection;
1045 info->target = target;
1046 info->idle_time = 0;
1047 info->buffer = NULL;
1050 /* Check if this process has current owner. If so, call handler
1051 procedure directly to avoid deadlocks with INCR. */
1053 display = gtk_widget_get_display (widget);
1054 owner_window = gdk_selection_owner_get_for_display (display, selection);
1056 if (owner_window != NULL)
1058 GtkWidget *owner_widget;
1059 GtkSelectionData selection_data;
1061 selection_data.selection = selection;
1062 selection_data.target = target;
1063 selection_data.data = NULL;
1064 selection_data.length = -1;
1065 selection_data.display = display;
1067 gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget);
1069 if (owner_widget != NULL)
1071 gtk_selection_invoke_handler (owner_widget,
1075 gtk_selection_retrieval_report (info,
1076 selection_data.type,
1077 selection_data.format,
1078 selection_data.data,
1079 selection_data.length,
1082 g_free (selection_data.data);
1089 /* Otherwise, we need to go through X */
1091 current_retrievals = g_list_append (current_retrievals, info);
1092 gdk_selection_convert (widget->window, selection, target, time_);
1093 g_timeout_add (1000, (GSourceFunc) gtk_selection_retrieval_timeout, info);
1100 * gtk_selection_data_set:
1101 * @selection_data: a pointer to a #GtkSelectionData structure.
1102 * @type: the type of selection data
1103 * @format: format (number of bits in a unit)
1104 * @data: pointer to the data (will be copied)
1105 * @length: length of the data
1107 * Stores new data into a #GtkSelectionData object. Should
1108 * <emphasis>only</emphasis> be called from a selection handler callback.
1109 * Zero-terminates the stored data.
1112 gtk_selection_data_set (GtkSelectionData *selection_data,
1118 if (selection_data->data)
1119 g_free (selection_data->data);
1121 selection_data->type = type;
1122 selection_data->format = format;
1126 selection_data->data = g_new (guchar, length+1);
1127 memcpy (selection_data->data, data, length);
1128 selection_data->data[length] = 0;
1132 g_return_if_fail (length <= 0);
1135 selection_data->data = NULL;
1137 selection_data->data = g_strdup("");
1140 selection_data->length = length;
1144 selection_set_string (GtkSelectionData *selection_data,
1148 gchar *tmp = g_strndup (str, len);
1149 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1154 gtk_selection_data_set (selection_data,
1155 GDK_SELECTION_TYPE_STRING,
1156 8, latin1, strlen (latin1));
1166 selection_set_compound_text (GtkSelectionData *selection_data,
1175 gboolean result = FALSE;
1177 tmp = g_strndup (str, len);
1178 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1179 &encoding, &format, &text, &new_length))
1181 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1182 gdk_free_compound_text (text);
1192 /* Normalize \r and \n into \r\n
1195 normalize_to_crlf (const gchar *str,
1198 GString *result = g_string_sized_new (len);
1199 const gchar *p = str;
1204 g_string_append_c (result, '\r');
1208 g_string_append_c (result, *p);
1211 g_string_append_c (result, '\n');
1217 g_string_append_c (result, *p);
1221 return g_string_free (result, FALSE);
1224 /* Normalize \r and \r\n into \n
1227 normalize_to_lf (gchar *str,
1230 GString *result = g_string_sized_new (len);
1231 const gchar *p = str;
1239 g_string_append_c (result, '\n');
1245 g_string_append_c (result, *p);
1249 return g_string_free (result, FALSE);
1253 selection_set_text_plain (GtkSelectionData *selection_data,
1257 const gchar *charset = NULL;
1259 GError *error = NULL;
1261 result = normalize_to_crlf (str, len);
1262 if (selection_data->target == text_plain_atom)
1264 else if (selection_data->target == text_plain_locale_atom)
1265 g_get_charset (&charset);
1269 gchar *tmp = result;
1270 result = g_convert_with_fallback (tmp, -1,
1272 NULL, NULL, NULL, &error);
1278 g_warning ("Error converting from %s to %s: %s",
1279 "UTF-8", charset, error->message);
1280 g_error_free (error);
1285 gtk_selection_data_set (selection_data,
1286 selection_data->target,
1287 8, result, strlen (result));
1294 selection_get_text_plain (GtkSelectionData *selection_data)
1296 const gchar *charset = NULL;
1297 gchar *str, *result;
1299 GError *error = NULL;
1301 str = g_strdup (selection_data->data);
1302 len = selection_data->length;
1304 if (selection_data->type == text_plain_atom)
1305 charset = "ISO-8859-1";
1306 else if (selection_data->type == text_plain_locale_atom)
1307 g_get_charset (&charset);
1312 str = g_convert_with_fallback (tmp, len,
1314 NULL, NULL, &len, &error);
1319 g_warning ("Error converting from %s to %s: %s",
1320 charset, "UTF-8", error->message);
1321 g_error_free (error);
1326 else if (!g_utf8_validate (str, -1, NULL))
1328 g_warning ("Error converting from %s to %s: %s",
1329 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1335 result = normalize_to_lf (str, len);
1342 * gtk_selection_data_set_text:
1343 * @selection_data: a #GtkSelectionData
1344 * @str: a UTF-8 string
1345 * @len: the length of @str, or -1 if @str is nul-terminated.
1347 * Sets the contents of the selection from a UTF-8 encoded string.
1348 * The string is converted to the form determined by
1349 * @selection_data->target.
1351 * Return value: %TRUE if the selection was successfully set,
1355 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1364 if (selection_data->target == utf8_atom)
1366 gtk_selection_data_set (selection_data,
1368 8, (guchar *)str, len);
1371 else if (selection_data->target == GDK_TARGET_STRING)
1373 return selection_set_string (selection_data, str, len);
1375 else if (selection_data->target == ctext_atom ||
1376 selection_data->target == text_atom)
1378 if (selection_set_compound_text (selection_data, str, len))
1380 else if (selection_data->target == text_atom)
1381 return selection_set_string (selection_data, str, len);
1383 else if (selection_data->target == text_plain_atom ||
1384 selection_data->target == text_plain_utf8_atom ||
1385 selection_data->target == text_plain_locale_atom)
1387 return selection_set_text_plain (selection_data, str, len);
1394 * gtk_selection_data_get_text:
1395 * @selection_data: a #GtkSelectionData
1397 * Gets the contents of the selection data as a UTF-8 string.
1399 * Return value: if the selection data contained a recognized
1400 * text type and it could be converted to UTF-8, a newly allocated
1401 * string containing the converted text, otherwise %NULL.
1402 * If the result is non-%NULL it must be freed with g_free().
1405 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1407 guchar *result = NULL;
1411 if (selection_data->length >= 0 &&
1412 (selection_data->type == GDK_TARGET_STRING ||
1413 selection_data->type == ctext_atom ||
1414 selection_data->type == utf8_atom))
1418 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1419 selection_data->type,
1420 selection_data->format,
1421 selection_data->data,
1422 selection_data->length,
1427 for (i = 1; i < count; i++)
1431 else if (selection_data->length >= 0 &&
1432 (selection_data->type == text_plain_atom ||
1433 selection_data->type == text_plain_utf8_atom ||
1434 selection_data->type == text_plain_locale_atom))
1436 result = selection_get_text_plain (selection_data);
1443 * gtk_selection_data_set_pixbuf:
1444 * @selection_data: a #GtkSelectionData
1445 * @pixbuf: a #GdkPixbuf
1447 * Sets the contents of the selection from a #GdkPixbuf
1448 * The pixbuf is converted to the form determined by
1449 * @selection_data->target.
1451 * Return value: %TRUE if the selection was successfully set,
1457 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1460 GSList *formats, *f;
1467 formats = gdk_pixbuf_get_formats ();
1469 for (f = formats; f; f = f->next)
1471 GdkPixbufFormat *fmt = f->data;
1473 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1474 for (m = mimes; *m; m++)
1476 atom = gdk_atom_intern (*m, FALSE);
1477 if (selection_data->target == atom)
1480 type = gdk_pixbuf_format_get_name (fmt);
1481 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1483 ((strcmp (type, "png") == 0) ?
1484 "compression" : NULL), "2",
1487 gtk_selection_data_set (selection_data,
1488 atom, 8, (guchar *)str, len);
1492 g_slist_free (formats);
1501 g_slist_free (formats);
1507 * gtk_selection_data_get_pixbuf:
1508 * @selection_data: a #GtkSelectionData
1510 * Gets the contents of the selection data as a #GdkPixbuf.
1512 * Return value: if the selection data contained a recognized
1513 * image type and it could be converted to a #GdkPixbuf, a
1514 * newly allocated pixbuf is returned, otherwise %NULL.
1515 * If the result is non-%NULL it must be freed with g_object_unref().
1520 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1522 GdkPixbufLoader *loader;
1523 GdkPixbuf *result = NULL;
1525 if (selection_data->length > 0)
1527 loader = gdk_pixbuf_loader_new ();
1529 gdk_pixbuf_loader_write (loader,
1530 selection_data->data,
1531 selection_data->length,
1533 gdk_pixbuf_loader_close (loader, NULL);
1534 result = gdk_pixbuf_loader_get_pixbuf (loader);
1537 g_object_ref (result);
1539 g_object_unref (loader);
1546 * gtk_selection_data_set_uris:
1547 * @selection_data: a #GtkSelectionData
1548 * @uris: a %NULL-terminated array of strings hilding URIs
1550 * Sets the contents of the selection from a list of URIs.
1551 * The string is converted to the form determined by
1552 * @selection_data->target.
1554 * Return value: %TRUE if the selection was successfully set,
1560 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1565 if (selection_data->target == text_uri_list_atom)
1572 list = g_string_new (NULL);
1573 for (i = 0; uris[i]; i++)
1575 g_string_append (list, uris[i]);
1576 g_string_append (list, "\r\n");
1579 result = g_convert (list->str, list->len,
1581 NULL, &length, NULL);
1582 g_string_free (list, TRUE);
1586 gtk_selection_data_set (selection_data,
1588 8, (guchar *)result, length);
1600 * gtk_selection_data_get_uris:
1601 * @selection_data: a #GtkSelectionData
1603 * Gets the contents of the selection data as array of URIs.
1605 * Return value: if the selection data contains a list of
1606 * URIs, a newly allocated %NULL-terminated string array
1607 * containing the URIs, otherwise %NULL. If the result is
1608 * non-%NULL it must be freed with g_strfreev().
1613 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1615 gchar **result = NULL;
1619 if (selection_data->length >= 0 &&
1620 selection_data->type == text_uri_list_atom)
1623 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1625 selection_data->format,
1626 selection_data->data,
1627 selection_data->length,
1630 result = g_uri_list_extract_uris (list[0]);
1640 * gtk_selection_data_get_targets:
1641 * @selection_data: a #GtkSelectionData object
1642 * @targets: location to store an array of targets. The result
1643 * stored here must be freed with g_free().
1644 * @n_atoms: location to store number of items in @targets.
1646 * Gets the contents of @selection_data as an array of targets.
1647 * This can be used to interpret the results of getting
1648 * the standard TARGETS target that is always supplied for
1651 * Return value: %TRUE if @selection_data contains a valid
1652 * array of targets, otherwise %FALSE.
1655 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1659 if (selection_data->length >= 0 &&
1660 selection_data->format == 32 &&
1661 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1664 *targets = g_memdup (selection_data->data, selection_data->length);
1666 *n_atoms = selection_data->length / sizeof (GdkAtom);
1682 * gtk_targets_include_text:
1683 * @targets: an array of #GdkAtom<!-- -->s
1684 * @n_targets: the length of @targets
1686 * Determines if any of the targets in @targets can be used to
1689 * Return value: %TRUE if @targets include a suitable target for text,
1695 gtk_targets_include_text (GdkAtom *targets,
1699 gboolean result = FALSE;
1701 /* Keep in sync with gtk_target_list_add_text_targets()
1706 for (i = 0; i < n_targets; i++)
1708 if (targets[i] == utf8_atom ||
1709 targets[i] == text_atom ||
1710 targets[i] == GDK_TARGET_STRING ||
1711 targets[i] == ctext_atom ||
1712 targets[i] == text_plain_atom ||
1713 targets[i] == text_plain_utf8_atom ||
1714 targets[i] == text_plain_locale_atom)
1725 * gtk_targets_include_rich_text:
1726 * @targets: an array of #GdkAtom<!-- -->s
1727 * @n_targets: the length of @targets
1728 * @buffer: a #GtkTextBuffer
1730 * Determines if any of the targets in @targets can be used to
1731 * provide rich text.
1733 * Return value: %TRUE if @targets include a suitable target for rich text,
1739 gtk_targets_include_rich_text (GdkAtom *targets,
1741 GtkTextBuffer *buffer)
1743 GdkAtom *rich_targets;
1744 gint n_rich_targets;
1746 gboolean result = FALSE;
1748 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1752 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1755 for (i = 0; i < n_targets; i++)
1757 for (j = 0; j < n_rich_targets; j++)
1759 if (targets[i] == rich_targets[j])
1768 g_free (rich_targets);
1774 * gtk_selection_data_targets_include_text:
1775 * @selection_data: a #GtkSelectionData object
1777 * Given a #GtkSelectionData object holding a list of targets,
1778 * determines if any of the targets in @targets can be used to
1781 * Return value: %TRUE if @selection_data holds a list of targets,
1782 * and a suitable target for text is included, otherwise %FALSE.
1785 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1789 gboolean result = FALSE;
1793 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1795 result = gtk_targets_include_text (targets, n_targets);
1803 * gtk_selection_data_targets_include_rich_text:
1804 * @selection_data: a #GtkSelectionData object
1805 * @buffer: a #GtkTextBuffer
1807 * Given a #GtkSelectionData object holding a list of targets,
1808 * determines if any of the targets in @targets can be used to
1809 * provide rich text.
1811 * Return value: %TRUE if @selection_data holds a list of targets,
1812 * and a suitable target for rich text is included,
1818 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1819 GtkTextBuffer *buffer)
1823 gboolean result = FALSE;
1825 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1829 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1831 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1839 * gtk_targets_include_image:
1840 * @targets: an array of #GdkAtom<!-- -->s
1841 * @n_targets: the length of @targets
1842 * @writable: whether to accept only targets for which GTK+ knows
1843 * how to convert a pixbuf into the format
1845 * Determines if any of the targets in @targets can be used to
1846 * provide a #GdkPixbuf.
1848 * Return value: %TRUE if @targets include a suitable target for images,
1854 gtk_targets_include_image (GdkAtom *targets,
1858 GtkTargetList *list;
1861 gboolean result = FALSE;
1863 list = gtk_target_list_new (NULL, 0);
1864 gtk_target_list_add_image_targets (list, 0, writable);
1865 for (i = 0; i < n_targets && !result; i++)
1867 for (l = list->list; l; l = l->next)
1869 GtkTargetPair *pair = (GtkTargetPair *)l->data;
1870 if (pair->target == targets[i])
1877 gtk_target_list_unref (list);
1883 * gtk_selection_data_targets_include_image:
1884 * @selection_data: a #GtkSelectionData object
1885 * @writable: whether to accept only targets for which GTK+ knows
1886 * how to convert a pixbuf into the format
1888 * Given a #GtkSelectionData object holding a list of targets,
1889 * determines if any of the targets in @targets can be used to
1890 * provide a #GdkPixbuf.
1892 * Return value: %TRUE if @selection_data holds a list of targets,
1893 * and a suitable target for images is included, otherwise %FALSE.
1898 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
1903 gboolean result = FALSE;
1907 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1909 result = gtk_targets_include_image (targets, n_targets, writable);
1917 * gtk_targets_include_uri:
1918 * @targets: an array of #GdkAtom<!-- -->s
1919 * @n_targets: the length of @targets
1921 * Determines if any of the targets in @targets can be used to
1922 * provide an uri list.
1924 * Return value: %TRUE if @targets include a suitable target for uri lists,
1930 gtk_targets_include_uri (GdkAtom *targets,
1934 gboolean result = FALSE;
1936 /* Keep in sync with gtk_target_list_add_uri_targets()
1941 for (i = 0; i < n_targets; i++)
1943 if (targets[i] == text_uri_list_atom)
1954 * gtk_selection_data_targets_include_uri:
1955 * @selection_data: a #GtkSelectionData object
1957 * Given a #GtkSelectionData object holding a list of targets,
1958 * determines if any of the targets in @targets can be used to
1959 * provide a list or URIs.
1961 * Return value: %TRUE if @selection_data holds a list of targets,
1962 * and a suitable target for text is included, otherwise %FALSE.
1967 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
1971 gboolean result = FALSE;
1975 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1977 result = gtk_targets_include_uri (targets, n_targets);
1985 /*************************************************************
1986 * gtk_selection_init:
1987 * Initialize local variables
1991 *************************************************************/
1994 gtk_selection_init (void)
1996 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
1997 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
1998 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
1999 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2005 * gtk_selection_clear:
2006 * @widget: a #GtkWidget
2009 * The default handler for the GtkWidget::selection_clear_event
2012 * Return value: %TRUE if the event was handled, otherwise false
2016 * Deprecated: 2.4: Instead of calling this function, chain up from
2017 * your selection_clear_event handler. Calling this function
2018 * from any other context is illegal.
2021 gtk_selection_clear (GtkWidget *widget,
2022 GdkEventSelection *event)
2024 /* Note that we filter clear events in gdkselection-x11.c, so
2025 * that we only will get here if the clear event actually
2026 * represents a change that we didn't do ourself.
2029 GtkSelectionInfo *selection_info = NULL;
2031 tmp_list = current_selections;
2034 selection_info = (GtkSelectionInfo *)tmp_list->data;
2036 if ((selection_info->selection == event->selection) &&
2037 (selection_info->widget == widget))
2040 tmp_list = tmp_list->next;
2045 current_selections = g_list_remove_link (current_selections, tmp_list);
2046 g_list_free (tmp_list);
2047 g_free (selection_info);
2054 /*************************************************************
2055 * _gtk_selection_request:
2056 * Handler for "selection_request_event"
2061 *************************************************************/
2064 _gtk_selection_request (GtkWidget *widget,
2065 GdkEventSelection *event)
2067 GdkDisplay *display = gtk_widget_get_display (widget);
2071 gulong selection_max_size;
2074 gtk_selection_init ();
2076 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2078 /* Check if we own selection */
2080 tmp_list = current_selections;
2083 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2085 if ((selection_info->selection == event->selection) &&
2086 (selection_info->widget == widget))
2089 tmp_list = tmp_list->next;
2092 if (tmp_list == NULL)
2095 info = g_new (GtkIncrInfo, 1);
2097 g_object_ref (widget);
2099 info->selection = event->selection;
2100 info->num_incrs = 0;
2102 /* Create GdkWindow structure for the requestor */
2104 info->requestor = gdk_window_lookup_for_display (display,
2106 if (!info->requestor)
2107 info->requestor = gdk_window_foreign_new_for_display (display,
2110 /* Determine conversions we need to perform */
2112 if (event->target == gtk_selection_atoms[MULTIPLE])
2121 gdk_error_trap_push ();
2122 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2123 0, selection_max_size, FALSE,
2124 &type, &format, &length, &mult_atoms))
2126 gdk_selection_send_notify_for_display (display,
2132 g_free (mult_atoms);
2136 gdk_error_trap_pop ();
2138 /* This is annoying; the ICCCM doesn't specify the property type
2139 * used for the property contents, so the autoconversion for
2140 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2142 #ifdef GDK_WINDOWING_X11
2143 if (type != GDK_SELECTION_TYPE_ATOM &&
2144 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2146 info->num_conversions = length / (2*sizeof (glong));
2147 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2149 for (i=0; i<info->num_conversions; i++)
2151 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2152 ((glong *)mult_atoms)[2*i]);
2153 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2154 ((glong *)mult_atoms)[2*i + 1]);
2157 g_free (mult_atoms);
2162 info->num_conversions = length / (2*sizeof (GdkAtom));
2163 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2165 for (i=0; i<info->num_conversions; i++)
2167 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2168 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2172 else /* only a single conversion */
2174 info->conversions = g_new (GtkIncrConversion, 1);
2175 info->num_conversions = 1;
2176 info->conversions[0].target = event->target;
2177 info->conversions[0].property = event->property;
2180 /* Loop through conversions and determine which of these are big
2181 enough to require doing them via INCR */
2182 for (i=0; i<info->num_conversions; i++)
2184 GtkSelectionData data;
2187 data.selection = event->selection;
2188 data.target = info->conversions[i].target;
2191 data.display = gtk_widget_get_display (widget);
2193 #ifdef DEBUG_SELECTION
2194 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2196 info->conversions[i].target,
2197 gdk_atom_name (info->conversions[i].target),
2198 event->requestor, info->conversions[i].property);
2201 gtk_selection_invoke_handler (widget, &data, event->time);
2203 if (data.length < 0)
2205 info->conversions[i].property = GDK_NONE;
2209 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2211 items = data.length / gtk_selection_bytes_per_item (data.format);
2213 if (data.length > selection_max_size)
2215 /* Sending via INCR */
2216 #ifdef DEBUG_SELECTION
2217 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2218 data.length, selection_max_size);
2221 info->conversions[i].offset = 0;
2222 info->conversions[i].data = data;
2225 gdk_property_change (info->requestor,
2226 info->conversions[i].property,
2227 gtk_selection_atoms[INCR],
2229 GDK_PROP_MODE_REPLACE,
2230 (guchar *)&items, 1);
2234 info->conversions[i].offset = -1;
2236 gdk_property_change (info->requestor,
2237 info->conversions[i].property,
2240 GDK_PROP_MODE_REPLACE,
2247 /* If we have some INCR's, we need to send the rest of the data in
2250 if (info->num_incrs > 0)
2252 /* FIXME: this could be dangerous if window doesn't still
2255 #ifdef DEBUG_SELECTION
2256 g_message ("Starting INCR...");
2259 gdk_window_set_events (info->requestor,
2260 gdk_window_get_events (info->requestor) |
2261 GDK_PROPERTY_CHANGE_MASK);
2262 current_incrs = g_list_append (current_incrs, info);
2263 g_timeout_add (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2266 /* If it was a MULTIPLE request, set the property to indicate which
2267 conversions succeeded */
2268 if (event->target == gtk_selection_atoms[MULTIPLE])
2270 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2271 for (i = 0; i < info->num_conversions; i++)
2273 mult_atoms[2*i] = info->conversions[i].target;
2274 mult_atoms[2*i+1] = info->conversions[i].property;
2277 gdk_property_change (info->requestor, event->property,
2278 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2279 GDK_PROP_MODE_REPLACE,
2280 (guchar *)mult_atoms, 2*info->num_conversions);
2281 g_free (mult_atoms);
2284 if (info->num_conversions == 1 &&
2285 info->conversions[0].property == GDK_NONE)
2287 /* Reject the entire conversion */
2288 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2297 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2305 if (info->num_incrs == 0)
2307 g_free (info->conversions);
2311 g_object_unref (widget);
2316 /*************************************************************
2317 * _gtk_selection_incr_event:
2318 * Called whenever an PropertyNotify event occurs for an
2319 * GdkWindow with user_data == NULL. These will be notifications
2320 * that a window we are sending the selection to via the
2321 * INCR protocol has deleted a property and is ready for
2325 * window: the requestor window
2326 * event: the property event structure
2329 *************************************************************/
2332 _gtk_selection_incr_event (GdkWindow *window,
2333 GdkEventProperty *event)
2336 GtkIncrInfo *info = NULL;
2339 gulong selection_max_size;
2343 if (event->state != GDK_PROPERTY_DELETE)
2346 #ifdef DEBUG_SELECTION
2347 g_message ("PropertyDelete, property %ld", event->atom);
2350 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2352 /* Now find the appropriate ongoing INCR */
2353 tmp_list = current_incrs;
2356 info = (GtkIncrInfo *)tmp_list->data;
2357 if (info->requestor == event->window)
2360 tmp_list = tmp_list->next;
2363 if (tmp_list == NULL)
2366 /* Find out which target this is for */
2367 for (i=0; i<info->num_conversions; i++)
2369 if (info->conversions[i].property == event->atom &&
2370 info->conversions[i].offset != -1)
2374 info->idle_time = 0;
2376 if (info->conversions[i].offset == -2) /* only the last 0-length
2384 num_bytes = info->conversions[i].data.length -
2385 info->conversions[i].offset;
2386 buffer = info->conversions[i].data.data +
2387 info->conversions[i].offset;
2389 if (num_bytes > selection_max_size)
2391 num_bytes = selection_max_size;
2392 info->conversions[i].offset += selection_max_size;
2395 info->conversions[i].offset = -2;
2397 #ifdef DEBUG_SELECTION
2398 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2399 num_bytes, info->conversions[i].offset,
2400 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2403 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2404 gdk_property_change (info->requestor, event->atom,
2405 info->conversions[i].data.type,
2406 info->conversions[i].data.format,
2407 GDK_PROP_MODE_REPLACE,
2409 num_bytes / bytes_per_item);
2411 if (info->conversions[i].offset == -2)
2413 g_free (info->conversions[i].data.data);
2414 info->conversions[i].data.data = NULL;
2420 info->conversions[i].offset = -1;
2425 /* Check if we're finished with all the targets */
2427 if (info->num_incrs == 0)
2429 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2430 g_list_free (tmp_list);
2431 /* Let the timeout free it */
2437 /*************************************************************
2438 * gtk_selection_incr_timeout:
2439 * Timeout callback for the sending portion of the INCR
2442 * info: Information about this incr
2444 *************************************************************/
2447 gtk_selection_incr_timeout (GtkIncrInfo *info)
2452 GDK_THREADS_ENTER ();
2454 /* Determine if retrieval has finished by checking if it still in
2455 list of pending retrievals */
2457 tmp_list = current_incrs;
2460 if (info == (GtkIncrInfo *)tmp_list->data)
2462 tmp_list = tmp_list->next;
2465 /* If retrieval is finished */
2466 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2468 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2470 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2471 g_list_free (tmp_list);
2474 g_free (info->conversions);
2475 /* FIXME: we should check if requestor window is still in use,
2476 and if not, remove it? */
2480 retval = FALSE; /* remove timeout */
2486 retval = TRUE; /* timeout will happen again */
2489 GDK_THREADS_LEAVE ();
2494 /*************************************************************
2495 * _gtk_selection_notify:
2496 * Handler for "selection_notify_event" signals on windows
2497 * where a retrieval is currently in process. The selection
2498 * owner has responded to our conversion request.
2500 * widget: Widget getting signal
2501 * event: Selection event structure
2502 * info: Information about this retrieval
2504 * was event handled?
2505 *************************************************************/
2508 _gtk_selection_notify (GtkWidget *widget,
2509 GdkEventSelection *event)
2512 GtkRetrievalInfo *info = NULL;
2513 guchar *buffer = NULL;
2518 #ifdef DEBUG_SELECTION
2519 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2520 event->selection, event->target, event->property);
2523 tmp_list = current_retrievals;
2526 info = (GtkRetrievalInfo *)tmp_list->data;
2527 if (info->widget == widget && info->selection == event->selection)
2529 tmp_list = tmp_list->next;
2532 if (!tmp_list) /* no retrieval in progress */
2535 if (event->property != GDK_NONE)
2536 length = gdk_selection_property_get (widget->window, &buffer,
2539 length = 0; /* silence gcc */
2541 if (event->property == GDK_NONE || buffer == NULL)
2543 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2544 g_list_free (tmp_list);
2545 /* structure will be freed in timeout */
2546 gtk_selection_retrieval_report (info,
2547 GDK_NONE, 0, NULL, -1, event->time);
2552 if (type == gtk_selection_atoms[INCR])
2554 /* The remainder of the selection will come through PropertyNotify
2557 info->notify_time = event->time;
2558 info->idle_time = 0;
2559 info->offset = 0; /* Mark as OK to proceed */
2560 gdk_window_set_events (widget->window,
2561 gdk_window_get_events (widget->window)
2562 | GDK_PROPERTY_CHANGE_MASK);
2566 /* We don't delete the info structure - that will happen in timeout */
2567 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2568 g_list_free (tmp_list);
2570 info->offset = length;
2571 gtk_selection_retrieval_report (info,
2573 buffer, length, event->time);
2576 gdk_property_delete (widget->window, event->property);
2583 /*************************************************************
2584 * _gtk_selection_property_notify:
2585 * Handler for "property_notify_event" signals on windows
2586 * where a retrieval is currently in process. The selection
2587 * owner has added more data.
2589 * widget: Widget getting signal
2590 * event: Property event structure
2591 * info: Information about this retrieval
2593 * was event handled?
2594 *************************************************************/
2597 _gtk_selection_property_notify (GtkWidget *widget,
2598 GdkEventProperty *event)
2601 GtkRetrievalInfo *info = NULL;
2607 g_return_val_if_fail (widget != NULL, FALSE);
2608 g_return_val_if_fail (event != NULL, FALSE);
2610 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2611 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2612 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2616 #ifdef DEBUG_SELECTION
2617 g_message ("PropertyNewValue, property %ld",
2621 tmp_list = current_retrievals;
2624 info = (GtkRetrievalInfo *)tmp_list->data;
2625 if (info->widget == widget)
2627 tmp_list = tmp_list->next;
2630 if (!tmp_list) /* No retrieval in progress */
2633 if (info->offset < 0) /* We haven't got the SelectionNotify
2634 for this retrieval yet */
2637 info->idle_time = 0;
2639 length = gdk_selection_property_get (widget->window, &new_buffer,
2641 gdk_property_delete (widget->window, event->atom);
2643 /* We could do a lot better efficiency-wise by paying attention to
2644 what length was sent in the initial INCR transaction, instead of
2645 doing memory allocation at every step. But its only guaranteed to
2646 be a _lower bound_ (pretty useless!) */
2648 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2650 /* Info structure will be freed in timeout */
2651 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2652 g_list_free (tmp_list);
2653 gtk_selection_retrieval_report (info,
2655 (type == GDK_NONE) ? NULL : info->buffer,
2656 (type == GDK_NONE) ? -1 : info->offset,
2659 else /* append on newly arrived data */
2663 #ifdef DEBUG_SELECTION
2664 g_message ("Start - Adding %d bytes at offset 0",
2667 info->buffer = new_buffer;
2668 info->offset = length;
2673 #ifdef DEBUG_SELECTION
2674 g_message ("Appending %d bytes at offset %d",
2675 length,info->offset);
2677 /* We copy length+1 bytes to preserve guaranteed null termination */
2678 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2679 memcpy (info->buffer + info->offset, new_buffer, length+1);
2680 info->offset += length;
2681 g_free (new_buffer);
2688 /*************************************************************
2689 * gtk_selection_retrieval_timeout:
2690 * Timeout callback while receiving a selection.
2692 * info: Information about this retrieval
2694 *************************************************************/
2697 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2702 GDK_THREADS_ENTER ();
2704 /* Determine if retrieval has finished by checking if it still in
2705 list of pending retrievals */
2707 tmp_list = current_retrievals;
2710 if (info == (GtkRetrievalInfo *)tmp_list->data)
2712 tmp_list = tmp_list->next;
2715 /* If retrieval is finished */
2716 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2718 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2720 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2721 g_list_free (tmp_list);
2722 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2725 g_free (info->buffer);
2728 retval = FALSE; /* remove timeout */
2734 retval = TRUE; /* timeout will happen again */
2737 GDK_THREADS_LEAVE ();
2742 /*************************************************************
2743 * gtk_selection_retrieval_report:
2744 * Emits a "selection_received" signal.
2746 * info: information about the retrieval that completed
2747 * buffer: buffer containing data (NULL => errror)
2748 * time: timestamp for data in buffer
2750 *************************************************************/
2753 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2754 GdkAtom type, gint format,
2755 guchar *buffer, gint length,
2758 GtkSelectionData data;
2760 data.selection = info->selection;
2761 data.target = info->target;
2763 data.format = format;
2765 data.length = length;
2767 data.display = gtk_widget_get_display (info->widget);
2769 g_signal_emit_by_name (info->widget,
2770 "selection_received",
2774 /*************************************************************
2775 * gtk_selection_invoke_handler:
2776 * Finds and invokes handler for specified
2777 * widget/selection/target combination, calls
2778 * gtk_selection_default_handler if none exists.
2781 * widget: selection owner
2782 * data: selection data [INOUT]
2783 * time: time from requeset
2786 * Number of bytes written to buffer, -1 if error
2787 *************************************************************/
2790 gtk_selection_invoke_handler (GtkWidget *widget,
2791 GtkSelectionData *data,
2794 GtkTargetList *target_list;
2798 g_return_if_fail (widget != NULL);
2800 target_list = gtk_selection_target_list_get (widget, data->selection);
2802 gtk_target_list_find (target_list, data->target, &info))
2804 g_signal_emit_by_name (widget,
2810 gtk_selection_default_handler (widget, data);
2813 /*************************************************************
2814 * gtk_selection_default_handler:
2815 * Handles some default targets that exist for any widget
2816 * If it can't fit results into buffer, returns -1. This
2817 * won't happen in any conceivable case, since it would
2818 * require 1000 selection targets!
2821 * widget: selection owner
2822 * data: selection data [INOUT]
2824 *************************************************************/
2827 gtk_selection_default_handler (GtkWidget *widget,
2828 GtkSelectionData *data)
2830 if (data->target == gtk_selection_atoms[TIMESTAMP])
2832 /* Time which was used to obtain selection */
2834 GtkSelectionInfo *selection_info;
2836 tmp_list = current_selections;
2839 selection_info = (GtkSelectionInfo *)tmp_list->data;
2840 if ((selection_info->widget == widget) &&
2841 (selection_info->selection == data->selection))
2843 gulong time = selection_info->time;
2845 gtk_selection_data_set (data,
2846 GDK_SELECTION_TYPE_INTEGER,
2853 tmp_list = tmp_list->next;
2858 else if (data->target == gtk_selection_atoms[TARGETS])
2860 /* List of all targets supported for this widget/selection pair */
2864 GtkTargetList *target_list;
2865 GtkTargetPair *pair;
2867 target_list = gtk_selection_target_list_get (widget,
2869 count = g_list_length (target_list->list) + 3;
2871 data->type = GDK_SELECTION_TYPE_ATOM;
2873 data->length = count * sizeof (GdkAtom);
2875 /* selection data is always terminated by a trailing \0
2877 p = g_malloc (data->length + 1);
2878 data->data = (guchar *)p;
2879 data->data[data->length] = '\0';
2881 *p++ = gtk_selection_atoms[TIMESTAMP];
2882 *p++ = gtk_selection_atoms[TARGETS];
2883 *p++ = gtk_selection_atoms[MULTIPLE];
2885 tmp_list = target_list->list;
2888 pair = (GtkTargetPair *)tmp_list->data;
2889 *p++ = pair->target;
2891 tmp_list = tmp_list->next;
2902 * gtk_selection_data_copy:
2903 * @data: a pointer to a #GtkSelectionData structure.
2905 * Makes a copy of a #GtkSelectionData structure and its data.
2907 * Return value: a pointer to a copy of @data.
2910 gtk_selection_data_copy (GtkSelectionData *data)
2912 GtkSelectionData *new_data;
2914 g_return_val_if_fail (data != NULL, NULL);
2916 new_data = g_new (GtkSelectionData, 1);
2921 new_data->data = g_malloc (data->length + 1);
2922 memcpy (new_data->data, data->data, data->length + 1);
2929 * gtk_selection_data_free:
2930 * @data: a pointer to a #GtkSelectionData structure.
2932 * Frees a #GtkSelectionData structure returned from
2933 * gtk_selection_data_copy().
2936 gtk_selection_data_free (GtkSelectionData *data)
2938 g_return_if_fail (data != NULL);
2941 g_free (data->data);
2947 gtk_selection_data_get_type (void)
2949 static GType our_type = 0;
2952 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
2953 (GBoxedCopyFunc) gtk_selection_data_copy,
2954 (GBoxedFreeFunc) gtk_selection_data_free);
2960 gtk_target_list_get_type (void)
2962 static GType our_type = 0;
2965 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
2966 (GBoxedCopyFunc) gtk_target_list_ref,
2967 (GBoxedFreeFunc) gtk_target_list_unref);
2973 gtk_selection_bytes_per_item (gint format)
2978 return sizeof (char);
2981 return sizeof (short);
2984 return sizeof (long);
2987 g_assert_not_reached();
2992 #define __GTK_SELECTION_C__
2993 #include "gtkaliasdef.c"