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/.
56 #include "gtkselection.h"
57 #include "gtkselectionprivate.h"
65 #include "gtktextbufferrichtext.h"
67 #include "gdk-pixbuf/gdk-pixbuf.h"
69 #ifdef GDK_WINDOWING_X11
73 #ifdef GDK_WINDOWING_WIN32
74 #include "win32/gdkwin32.h"
77 #undef DEBUG_SELECTION
79 /* Maximum size of a sent chunk, in bytes. Also the default size of
81 #ifdef GDK_WINDOWING_X11
82 #define GTK_SELECTION_MAX_SIZE(display) \
84 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
85 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
86 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
88 /* No chunks on Win32 */
89 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
92 #define IDLE_ABORT_TIME 30
103 typedef struct _GtkSelectionInfo GtkSelectionInfo;
104 typedef struct _GtkIncrConversion GtkIncrConversion;
105 typedef struct _GtkIncrInfo GtkIncrInfo;
106 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
108 struct _GtkSelectionInfo
111 GtkWidget *widget; /* widget that owns selection */
112 guint32 time; /* time used to acquire selection */
113 GdkDisplay *display; /* needed in gtk_selection_remove_all */
116 struct _GtkIncrConversion
118 GdkAtom target; /* Requested target */
119 GdkAtom property; /* Property to store in */
120 GtkSelectionData data; /* The data being supplied */
121 gint offset; /* Current offset in sent selection.
123 * -2 => Only the final (empty) portion
129 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
130 so we can receive events */
131 GdkAtom selection; /* Selection we're sending */
133 GtkIncrConversion *conversions; /* Information about requested conversions -
134 * With MULTIPLE requests (benighted 1980's
135 * hardware idea), there can be more than
137 gint num_conversions;
138 gint num_incrs; /* number of remaining INCR style transactions */
143 struct _GtkRetrievalInfo
146 GdkAtom selection; /* Selection being retrieved. */
147 GdkAtom target; /* Form of selection that we requested */
148 guint32 idle_time; /* Number of seconds since we last heard
149 from selection owner */
150 guchar *buffer; /* Buffer in which to accumulate results */
151 gint offset; /* Current offset in buffer, -1 indicates
153 guint32 notify_time; /* Timestamp from SelectionNotify */
156 /* Local Functions */
157 static void gtk_selection_init (void);
158 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
159 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
160 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
166 static void gtk_selection_invoke_handler (GtkWidget *widget,
167 GtkSelectionData *data,
169 static void gtk_selection_default_handler (GtkWidget *widget,
170 GtkSelectionData *data);
171 static int gtk_selection_bytes_per_item (gint format);
174 static gint initialize = TRUE;
175 static GList *current_retrievals = NULL;
176 static GList *current_incrs = NULL;
177 static GList *current_selections = NULL;
179 static GdkAtom gtk_selection_atoms[LAST_ATOM];
180 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
192 * gtk_target_list_new:
193 * @targets: Pointer to an array of #GtkTargetEntry
194 * @ntargets: number of entries in @targets.
196 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
198 * Return value: the new #GtkTargetList.
201 gtk_target_list_new (const GtkTargetEntry *targets,
204 GtkTargetList *result = g_slice_new (GtkTargetList);
206 result->ref_count = 1;
209 gtk_target_list_add_table (result, targets, ntargets);
215 * gtk_target_list_ref:
216 * @list: a #GtkTargetList
218 * Increases the reference count of a #GtkTargetList by one.
220 * Return value: the passed in #GtkTargetList.
223 gtk_target_list_ref (GtkTargetList *list)
225 g_return_val_if_fail (list != NULL, NULL);
233 * gtk_target_list_unref:
234 * @list: a #GtkTargetList
236 * Decreases the reference count of a #GtkTargetList by one.
237 * If the resulting reference count is zero, frees the list.
240 gtk_target_list_unref (GtkTargetList *list)
242 g_return_if_fail (list != NULL);
243 g_return_if_fail (list->ref_count > 0);
246 if (list->ref_count == 0)
248 GList *tmp_list = list->list;
251 GtkTargetPair *pair = tmp_list->data;
252 g_slice_free (GtkTargetPair, pair);
254 tmp_list = tmp_list->next;
257 g_list_free (list->list);
258 g_slice_free (GtkTargetList, list);
263 * gtk_target_list_add:
264 * @list: a #GtkTargetList
265 * @target: the interned atom representing the target
266 * @flags: the flags for this target
267 * @info: an ID that will be passed back to the application
269 * Appends another target to a #GtkTargetList.
272 gtk_target_list_add (GtkTargetList *list,
279 g_return_if_fail (list != NULL);
281 pair = g_slice_new (GtkTargetPair);
282 pair->target = target;
286 list->list = g_list_append (list->list, pair);
289 static GdkAtom utf8_atom;
290 static GdkAtom text_atom;
291 static GdkAtom ctext_atom;
292 static GdkAtom text_plain_atom;
293 static GdkAtom text_plain_utf8_atom;
294 static GdkAtom text_plain_locale_atom;
295 static GdkAtom text_uri_list_atom;
301 const gchar *charset;
305 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
306 text_atom = gdk_atom_intern_static_string ("TEXT");
307 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
308 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
309 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
310 g_get_charset (&charset);
311 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
312 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
315 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
320 * gtk_target_list_add_text_targets:
321 * @list: a #GtkTargetList
322 * @info: an ID that will be passed back to the application
324 * Appends the text targets supported by #GtkSelection to
325 * the target list. All targets are added with the same @info.
330 gtk_target_list_add_text_targets (GtkTargetList *list,
333 g_return_if_fail (list != NULL);
337 /* Keep in sync with gtk_selection_data_targets_include_text()
339 gtk_target_list_add (list, utf8_atom, 0, info);
340 gtk_target_list_add (list, ctext_atom, 0, info);
341 gtk_target_list_add (list, text_atom, 0, info);
342 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
343 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
344 if (!g_get_charset (NULL))
345 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
346 gtk_target_list_add (list, text_plain_atom, 0, info);
350 * gtk_target_list_add_rich_text_targets:
351 * @list: a #GtkTargetList
352 * @info: an ID that will be passed back to the application
353 * @deserializable: if %TRUE, then deserializable rich text formats
354 * will be added, serializable formats otherwise.
355 * @buffer: a #GtkTextBuffer.
357 * Appends the rich text targets registered with
358 * gtk_text_buffer_register_serialize_format() or
359 * gtk_text_buffer_register_deserialize_format() to the target list. All
360 * targets are added with the same @info.
365 gtk_target_list_add_rich_text_targets (GtkTargetList *list,
367 gboolean deserializable,
368 GtkTextBuffer *buffer)
374 g_return_if_fail (list != NULL);
375 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
378 atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
380 atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
382 for (i = 0; i < n_atoms; i++)
383 gtk_target_list_add (list, atoms[i], 0, info);
389 * gtk_target_list_add_image_targets:
390 * @list: a #GtkTargetList
391 * @info: an ID that will be passed back to the application
392 * @writable: whether to add only targets for which GTK+ knows
393 * how to convert a pixbuf into the format
395 * Appends the image targets supported by #GtkSelection to
396 * the target list. All targets are added with the same @info.
401 gtk_target_list_add_image_targets (GtkTargetList *list,
409 g_return_if_fail (list != NULL);
411 formats = gdk_pixbuf_get_formats ();
413 /* Make sure png comes first */
414 for (f = formats; f; f = f->next)
416 GdkPixbufFormat *fmt = f->data;
419 name = gdk_pixbuf_format_get_name (fmt);
420 if (strcmp (name, "png") == 0)
422 formats = g_slist_delete_link (formats, f);
423 formats = g_slist_prepend (formats, fmt);
433 for (f = formats; f; f = f->next)
435 GdkPixbufFormat *fmt = f->data;
437 if (writable && !gdk_pixbuf_format_is_writable (fmt))
440 mimes = gdk_pixbuf_format_get_mime_types (fmt);
441 for (m = mimes; *m; m++)
443 atom = gdk_atom_intern (*m, FALSE);
444 gtk_target_list_add (list, atom, 0, info);
449 g_slist_free (formats);
453 * gtk_target_list_add_uri_targets:
454 * @list: a #GtkTargetList
455 * @info: an ID that will be passed back to the application
457 * Appends the URI targets supported by #GtkSelection to
458 * the target list. All targets are added with the same @info.
463 gtk_target_list_add_uri_targets (GtkTargetList *list,
466 g_return_if_fail (list != NULL);
470 gtk_target_list_add (list, text_uri_list_atom, 0, info);
474 * gtk_target_list_add_table:
475 * @list: a #GtkTargetList
476 * @targets: the table of #GtkTargetEntry
477 * @ntargets: number of targets in the table
479 * Prepends a table of #GtkTargetEntry to a target list.
482 gtk_target_list_add_table (GtkTargetList *list,
483 const GtkTargetEntry *targets,
488 for (i=ntargets-1; i >= 0; i--)
490 GtkTargetPair *pair = g_slice_new (GtkTargetPair);
491 pair->target = gdk_atom_intern (targets[i].target, FALSE);
492 pair->flags = targets[i].flags;
493 pair->info = targets[i].info;
495 list->list = g_list_prepend (list->list, pair);
500 * gtk_target_list_remove:
501 * @list: a #GtkTargetList
502 * @target: the interned atom representing the target
504 * Removes a target from a target list.
507 gtk_target_list_remove (GtkTargetList *list,
512 g_return_if_fail (list != NULL);
514 tmp_list = list->list;
517 GtkTargetPair *pair = tmp_list->data;
519 if (pair->target == target)
521 g_slice_free (GtkTargetPair, pair);
523 list->list = g_list_remove_link (list->list, tmp_list);
524 g_list_free_1 (tmp_list);
529 tmp_list = tmp_list->next;
534 * gtk_target_list_find:
535 * @list: a #GtkTargetList
536 * @target: an interned atom representing the target to search for
537 * @info: a pointer to the location to store application info for target,
540 * Looks up a given target in a #GtkTargetList.
542 * Return value: %TRUE if the target was found, otherwise %FALSE
545 gtk_target_list_find (GtkTargetList *list,
551 g_return_val_if_fail (list != NULL, FALSE);
553 tmp_list = list->list;
556 GtkTargetPair *pair = tmp_list->data;
558 if (pair->target == target)
566 tmp_list = tmp_list->next;
573 * gtk_target_table_new_from_list:
574 * @list: a #GtkTargetList
575 * @n_targets: return location for the number ot targets in the table
577 * This function creates an #GtkTargetEntry array that contains the
578 * same targets as the passed %list. The returned table is newly
579 * allocated and should be freed using gtk_target_table_free() when no
582 * Return value: the new table.
587 gtk_target_table_new_from_list (GtkTargetList *list,
590 GtkTargetEntry *targets;
594 g_return_val_if_fail (list != NULL, NULL);
595 g_return_val_if_fail (n_targets != NULL, NULL);
597 *n_targets = g_list_length (list->list);
598 targets = g_new0 (GtkTargetEntry, *n_targets);
600 for (i = 0, tmp_list = list->list;
602 i++, tmp_list = g_list_next (tmp_list))
604 GtkTargetPair *pair = tmp_list->data;
606 targets[i].target = gdk_atom_name (pair->target);
607 targets[i].flags = pair->flags;
608 targets[i].info = pair->info;
615 * gtk_target_table_free:
616 * @targets: a #GtkTargetEntry array
617 * @n_targets: the number of entries in the array
619 * This function frees a target table as returned by
620 * gtk_target_table_new_from_list()
625 gtk_target_table_free (GtkTargetEntry *targets,
630 g_return_if_fail (targets == NULL || n_targets > 0);
632 for (i = 0; i < n_targets; i++)
633 g_free (targets[i].target);
639 * gtk_selection_owner_set_for_display:
640 * @display: the #Gdkdisplay where the selection is set
641 * @widget: (allow-none): new selection owner (a #GdkWidget), or %NULL.
642 * @selection: an interned atom representing the selection to claim.
643 * @time_: timestamp with which to claim the selection
645 * Claim ownership of a given selection for a particular widget, or,
646 * if @widget is %NULL, release ownership of the selection.
648 * Return value: TRUE if the operation succeeded
653 gtk_selection_owner_set_for_display (GdkDisplay *display,
659 GtkWidget *old_owner;
660 GtkSelectionInfo *selection_info = NULL;
663 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
664 g_return_val_if_fail (selection != GDK_NONE, FALSE);
665 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
666 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
671 window = gtk_widget_get_window (widget);
673 tmp_list = current_selections;
676 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
678 selection_info = tmp_list->data;
682 tmp_list = tmp_list->next;
685 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
693 old_owner = selection_info->widget;
694 current_selections = g_list_remove_link (current_selections,
696 g_list_free (tmp_list);
697 g_slice_free (GtkSelectionInfo, selection_info);
702 if (selection_info == NULL)
704 selection_info = g_slice_new (GtkSelectionInfo);
705 selection_info->selection = selection;
706 selection_info->widget = widget;
707 selection_info->time = time;
708 selection_info->display = display;
709 current_selections = g_list_prepend (current_selections,
714 old_owner = selection_info->widget;
715 selection_info->widget = widget;
716 selection_info->time = time;
717 selection_info->display = display;
720 /* If another widget in the application lost the selection,
721 * send it a GDK_SELECTION_CLEAR event.
723 if (old_owner && old_owner != widget)
725 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
727 event->selection.window = g_object_ref (gtk_widget_get_window (old_owner));
728 event->selection.selection = selection;
729 event->selection.time = time;
731 gtk_widget_event (old_owner, event);
733 gdk_event_free (event);
742 * gtk_selection_owner_set:
743 * @widget: (allow-none): a #GtkWidget, or %NULL.
744 * @selection: an interned atom representing the selection to claim
745 * @time_: timestamp with which to claim the selection
747 * Claims ownership of a given selection for a particular widget,
748 * or, if @widget is %NULL, release ownership of the selection.
750 * Return value: %TRUE if the operation succeeded
753 gtk_selection_owner_set (GtkWidget *widget,
759 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
760 g_return_val_if_fail (selection != GDK_NONE, FALSE);
763 display = gtk_widget_get_display (widget);
767 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
769 display = gdk_display_get_default ();
772 return gtk_selection_owner_set_for_display (display, widget,
776 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
778 struct _GtkSelectionTargetList {
783 static GtkTargetList *
784 gtk_selection_target_list_get (GtkWidget *widget,
787 GtkSelectionTargetList *sellist;
791 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
796 sellist = tmp_list->data;
797 if (sellist->selection == selection)
798 return sellist->list;
799 tmp_list = tmp_list->next;
802 sellist = g_slice_new (GtkSelectionTargetList);
803 sellist->selection = selection;
804 sellist->list = gtk_target_list_new (NULL, 0);
806 lists = g_list_prepend (lists, sellist);
807 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
809 return sellist->list;
813 gtk_selection_target_list_remove (GtkWidget *widget)
815 GtkSelectionTargetList *sellist;
819 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
824 sellist = tmp_list->data;
826 gtk_target_list_unref (sellist->list);
828 g_slice_free (GtkSelectionTargetList, sellist);
829 tmp_list = tmp_list->next;
833 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
837 * gtk_selection_clear_targets:
838 * @widget: a #GtkWidget
839 * @selection: an atom representing a selection
841 * Remove all targets registered for the given selection for the
845 gtk_selection_clear_targets (GtkWidget *widget,
848 GtkSelectionTargetList *sellist;
852 g_return_if_fail (GTK_IS_WIDGET (widget));
853 g_return_if_fail (selection != GDK_NONE);
855 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
860 sellist = tmp_list->data;
861 if (sellist->selection == selection)
863 lists = g_list_delete_link (lists, tmp_list);
864 gtk_target_list_unref (sellist->list);
865 g_slice_free (GtkSelectionTargetList, sellist);
870 tmp_list = tmp_list->next;
873 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
877 * gtk_selection_add_target:
878 * @widget: a #GtkTarget
879 * @selection: the selection
880 * @target: target to add.
881 * @info: A unsigned integer which will be passed back to the application.
883 * Appends a specified target to the list of supported targets for a
884 * given widget and selection.
887 gtk_selection_add_target (GtkWidget *widget,
894 g_return_if_fail (GTK_IS_WIDGET (widget));
895 g_return_if_fail (selection != GDK_NONE);
897 list = gtk_selection_target_list_get (widget, selection);
898 gtk_target_list_add (list, target, 0, info);
899 #ifdef GDK_WINDOWING_WIN32
900 gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target);
905 * gtk_selection_add_targets:
906 * @widget: a #GtkWidget
907 * @selection: the selection
908 * @targets: a table of targets to add
909 * @ntargets: number of entries in @targets
911 * Prepends a table of targets to the list of supported targets
912 * for a given widget and selection.
915 gtk_selection_add_targets (GtkWidget *widget,
917 const GtkTargetEntry *targets,
922 g_return_if_fail (GTK_IS_WIDGET (widget));
923 g_return_if_fail (selection != GDK_NONE);
924 g_return_if_fail (targets != NULL);
926 list = gtk_selection_target_list_get (widget, selection);
927 gtk_target_list_add_table (list, targets, ntargets);
929 #ifdef GDK_WINDOWING_WIN32
932 GdkAtom *atoms = g_new (GdkAtom, ntargets);
934 for (i = 0; i < ntargets; ++i)
935 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
936 gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, ntargets, atoms);
944 * gtk_selection_remove_all:
945 * @widget: a #GtkWidget
947 * Removes all handlers and unsets ownership of all
948 * selections for a widget. Called when widget is being
949 * destroyed. This function will not generally be
950 * called by applications.
953 gtk_selection_remove_all (GtkWidget *widget)
957 GtkSelectionInfo *selection_info;
959 g_return_if_fail (GTK_IS_WIDGET (widget));
961 /* Remove pending requests/incrs for this widget */
963 tmp_list = current_retrievals;
966 next = tmp_list->next;
967 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
969 current_retrievals = g_list_remove_link (current_retrievals,
971 /* structure will be freed in timeout */
972 g_list_free (tmp_list);
977 /* Disclaim ownership of any selections */
979 tmp_list = current_selections;
982 next = tmp_list->next;
983 selection_info = (GtkSelectionInfo *)tmp_list->data;
985 if (selection_info->widget == widget)
987 gdk_selection_owner_set_for_display (selection_info->display,
989 selection_info->selection,
990 GDK_CURRENT_TIME, FALSE);
991 current_selections = g_list_remove_link (current_selections,
993 g_list_free (tmp_list);
994 g_slice_free (GtkSelectionInfo, selection_info);
1000 /* Remove all selection lists */
1001 gtk_selection_target_list_remove (widget);
1006 * gtk_selection_convert:
1007 * @widget: The widget which acts as requestor
1008 * @selection: Which selection to get
1009 * @target: Form of information desired (e.g., STRING)
1010 * @time_: Time of request (usually of triggering event)
1011 In emergency, you could use #GDK_CURRENT_TIME
1013 * Requests the contents of a selection. When received,
1014 * a "selection-received" signal will be generated.
1016 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1017 * request. (e.g., there was already a request in process for
1021 gtk_selection_convert (GtkWidget *widget,
1026 GtkRetrievalInfo *info;
1028 GdkWindow *owner_window;
1029 GdkDisplay *display;
1031 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1032 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1035 gtk_selection_init ();
1037 if (!gtk_widget_get_realized (widget))
1038 gtk_widget_realize (widget);
1040 /* Check to see if there are already any retrievals in progress for
1041 this widget. If we changed GDK to use the selection for the
1042 window property in which to store the retrieved information, then
1043 we could support multiple retrievals for different selections.
1044 This might be useful for DND. */
1046 tmp_list = current_retrievals;
1049 info = (GtkRetrievalInfo *)tmp_list->data;
1050 if (info->widget == widget)
1052 tmp_list = tmp_list->next;
1055 info = g_slice_new (GtkRetrievalInfo);
1057 info->widget = widget;
1058 info->selection = selection;
1059 info->target = target;
1060 info->idle_time = 0;
1061 info->buffer = NULL;
1064 /* Check if this process has current owner. If so, call handler
1065 procedure directly to avoid deadlocks with INCR. */
1067 display = gtk_widget_get_display (widget);
1068 owner_window = gdk_selection_owner_get_for_display (display, selection);
1070 if (owner_window != NULL)
1072 GtkWidget *owner_widget;
1073 gpointer owner_widget_ptr;
1074 GtkSelectionData selection_data;
1076 selection_data.selection = selection;
1077 selection_data.target = target;
1078 selection_data.data = NULL;
1079 selection_data.length = -1;
1080 selection_data.display = display;
1082 gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1083 owner_widget = owner_widget_ptr;
1085 if (owner_widget != NULL)
1087 gtk_selection_invoke_handler (owner_widget,
1091 gtk_selection_retrieval_report (info,
1092 selection_data.type,
1093 selection_data.format,
1094 selection_data.data,
1095 selection_data.length,
1098 g_free (selection_data.data);
1099 selection_data.data = NULL;
1100 selection_data.length = -1;
1102 g_slice_free (GtkRetrievalInfo, info);
1107 /* Otherwise, we need to go through X */
1109 current_retrievals = g_list_append (current_retrievals, info);
1110 gdk_selection_convert (gtk_widget_get_window (widget), selection, target, time_);
1111 gdk_threads_add_timeout (1000,
1112 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1118 * gtk_selection_data_get_selection:
1119 * @selection_data: a pointer to a #GtkSelectionData structure.
1121 * Retrieves the selection #GdkAtom of the selection data.
1123 * Returns: the selection #GdkAtom of the selection data.
1128 gtk_selection_data_get_selection (const GtkSelectionData *selection_data)
1130 g_return_val_if_fail (selection_data != NULL, 0);
1132 return selection_data->selection;
1136 * gtk_selection_data_get_target:
1137 * @selection_data: a pointer to a #GtkSelectionData structure.
1139 * Retrieves the target of the selection.
1141 * Returns: the target of the selection.
1146 gtk_selection_data_get_target (const GtkSelectionData *selection_data)
1148 g_return_val_if_fail (selection_data != NULL, 0);
1150 return selection_data->target;
1154 * gtk_selection_data_get_data_type:
1155 * @selection_data: a pointer to a #GtkSelectionData structure.
1157 * Retrieves the data type of the selection.
1159 * Returns: the data type of the selection.
1164 gtk_selection_data_get_data_type (const GtkSelectionData *selection_data)
1166 g_return_val_if_fail (selection_data != NULL, 0);
1168 return selection_data->type;
1172 * gtk_selection_data_get_format:
1173 * @selection_data: a pointer to a #GtkSelectionData structure.
1175 * Retrieves the format of the selection.
1177 * Returns: the format of the selection.
1182 gtk_selection_data_get_format (const GtkSelectionData *selection_data)
1184 g_return_val_if_fail (selection_data != NULL, 0);
1186 return selection_data->format;
1190 * gtk_selection_data_get_data:
1191 * @selection_data: a pointer to a #GtkSelectionData structure.
1193 * Retrieves the raw data of the selection.
1195 * Returns: the raw data of the selection.
1200 gtk_selection_data_get_data (const GtkSelectionData *selection_data)
1202 g_return_val_if_fail (selection_data != NULL, NULL);
1204 return selection_data->data;
1208 * gtk_selection_data_get_length:
1209 * @selection_data: a pointer to a #GtkSelectionData structure.
1211 * Retrieves the length of the raw data of the selection.
1213 * Returns: the length of the data of the selection.
1218 gtk_selection_data_get_length (const GtkSelectionData *selection_data)
1220 g_return_val_if_fail (selection_data != NULL, -1);
1222 return selection_data->length;
1226 * gtk_selection_data_get_display:
1227 * @selection_data: a pointer to a #GtkSelectionData structure.
1229 * Retrieves the display of the selection.
1231 * Returns: (transfer none): the display of the selection.
1236 gtk_selection_data_get_display (const GtkSelectionData *selection_data)
1238 g_return_val_if_fail (selection_data != NULL, NULL);
1240 return selection_data->display;
1244 * gtk_selection_data_set:
1245 * @selection_data: a pointer to a #GtkSelectionData structure.
1246 * @type: the type of selection data
1247 * @format: format (number of bits in a unit)
1248 * @data: (array) (element-type guchar): pointer to the data (will be copied)
1249 * @length: length of the data
1251 * Stores new data into a #GtkSelectionData object. Should
1252 * <emphasis>only</emphasis> be called from a selection handler callback.
1253 * Zero-terminates the stored data.
1256 gtk_selection_data_set (GtkSelectionData *selection_data,
1262 g_return_if_fail (selection_data != NULL);
1264 g_free (selection_data->data);
1266 selection_data->type = type;
1267 selection_data->format = format;
1271 selection_data->data = g_new (guchar, length+1);
1272 memcpy (selection_data->data, data, length);
1273 selection_data->data[length] = 0;
1277 g_return_if_fail (length <= 0);
1280 selection_data->data = NULL;
1282 selection_data->data = (guchar *) g_strdup ("");
1285 selection_data->length = length;
1289 selection_set_string (GtkSelectionData *selection_data,
1293 gchar *tmp = g_strndup (str, len);
1294 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1299 gtk_selection_data_set (selection_data,
1300 GDK_SELECTION_TYPE_STRING,
1301 8, (guchar *) latin1, strlen (latin1));
1311 selection_set_compound_text (GtkSelectionData *selection_data,
1320 gboolean result = FALSE;
1322 tmp = g_strndup (str, len);
1323 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1324 &encoding, &format, &text, &new_length))
1326 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1327 gdk_free_compound_text (text);
1337 /* Normalize \r and \n into \r\n
1340 normalize_to_crlf (const gchar *str,
1343 GString *result = g_string_sized_new (len);
1344 const gchar *p = str;
1345 const gchar *end = str + len;
1350 g_string_append_c (result, '\r');
1354 g_string_append_c (result, *p);
1356 if (p == end || *p != '\n')
1357 g_string_append_c (result, '\n');
1362 g_string_append_c (result, *p);
1366 return g_string_free (result, FALSE);
1369 /* Normalize \r and \r\n into \n
1372 normalize_to_lf (gchar *str,
1375 GString *result = g_string_sized_new (len);
1376 const gchar *p = str;
1384 g_string_append_c (result, '\n');
1390 g_string_append_c (result, *p);
1394 return g_string_free (result, FALSE);
1398 selection_set_text_plain (GtkSelectionData *selection_data,
1402 const gchar *charset = NULL;
1404 GError *error = NULL;
1406 result = normalize_to_crlf (str, len);
1407 if (selection_data->target == text_plain_atom)
1409 else if (selection_data->target == text_plain_locale_atom)
1410 g_get_charset (&charset);
1414 gchar *tmp = result;
1415 result = g_convert_with_fallback (tmp, -1,
1417 NULL, NULL, NULL, &error);
1423 g_warning ("Error converting from %s to %s: %s",
1424 "UTF-8", charset, error->message);
1425 g_error_free (error);
1430 gtk_selection_data_set (selection_data,
1431 selection_data->target,
1432 8, (guchar *) result, strlen (result));
1439 selection_get_text_plain (const GtkSelectionData *selection_data)
1441 const gchar *charset = NULL;
1442 gchar *str, *result;
1444 GError *error = NULL;
1446 str = g_strdup ((const gchar *) selection_data->data);
1447 len = selection_data->length;
1449 if (selection_data->type == text_plain_atom)
1450 charset = "ISO-8859-1";
1451 else if (selection_data->type == text_plain_locale_atom)
1452 g_get_charset (&charset);
1457 str = g_convert_with_fallback (tmp, len,
1459 NULL, NULL, &len, &error);
1464 g_warning ("Error converting from %s to %s: %s",
1465 charset, "UTF-8", error->message);
1466 g_error_free (error);
1471 else if (!g_utf8_validate (str, -1, NULL))
1473 g_warning ("Error converting from %s to %s: %s",
1474 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1480 result = normalize_to_lf (str, len);
1483 return (guchar *) result;
1487 * gtk_selection_data_set_text:
1488 * @selection_data: a #GtkSelectionData
1489 * @str: a UTF-8 string
1490 * @len: the length of @str, or -1 if @str is nul-terminated.
1492 * Sets the contents of the selection from a UTF-8 encoded string.
1493 * The string is converted to the form determined by
1494 * @selection_data->target.
1496 * Return value: %TRUE if the selection was successfully set,
1500 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1504 g_return_val_if_fail (selection_data != NULL, FALSE);
1511 if (selection_data->target == utf8_atom)
1513 gtk_selection_data_set (selection_data,
1515 8, (guchar *)str, len);
1518 else if (selection_data->target == GDK_TARGET_STRING)
1520 return selection_set_string (selection_data, str, len);
1522 else if (selection_data->target == ctext_atom ||
1523 selection_data->target == text_atom)
1525 if (selection_set_compound_text (selection_data, str, len))
1527 else if (selection_data->target == text_atom)
1528 return selection_set_string (selection_data, str, len);
1530 else if (selection_data->target == text_plain_atom ||
1531 selection_data->target == text_plain_utf8_atom ||
1532 selection_data->target == text_plain_locale_atom)
1534 return selection_set_text_plain (selection_data, str, len);
1541 * gtk_selection_data_get_text:
1542 * @selection_data: a #GtkSelectionData
1544 * Gets the contents of the selection data as a UTF-8 string.
1546 * Return value: if the selection data contained a recognized
1547 * text type and it could be converted to UTF-8, a newly allocated
1548 * string containing the converted text, otherwise %NULL.
1549 * If the result is non-%NULL it must be freed with g_free().
1552 gtk_selection_data_get_text (const GtkSelectionData *selection_data)
1554 guchar *result = NULL;
1556 g_return_val_if_fail (selection_data != NULL, NULL);
1560 if (selection_data->length >= 0 &&
1561 (selection_data->type == GDK_TARGET_STRING ||
1562 selection_data->type == ctext_atom ||
1563 selection_data->type == utf8_atom))
1567 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1568 selection_data->type,
1569 selection_data->format,
1570 selection_data->data,
1571 selection_data->length,
1574 result = (guchar *) list[0];
1576 for (i = 1; i < count; i++)
1580 else if (selection_data->length >= 0 &&
1581 (selection_data->type == text_plain_atom ||
1582 selection_data->type == text_plain_utf8_atom ||
1583 selection_data->type == text_plain_locale_atom))
1585 result = selection_get_text_plain (selection_data);
1592 * gtk_selection_data_set_pixbuf:
1593 * @selection_data: a #GtkSelectionData
1594 * @pixbuf: a #GdkPixbuf
1596 * Sets the contents of the selection from a #GdkPixbuf
1597 * The pixbuf is converted to the form determined by
1598 * @selection_data->target.
1600 * Return value: %TRUE if the selection was successfully set,
1606 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1609 GSList *formats, *f;
1616 g_return_val_if_fail (selection_data != NULL, FALSE);
1617 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1619 formats = gdk_pixbuf_get_formats ();
1621 for (f = formats; f; f = f->next)
1623 GdkPixbufFormat *fmt = f->data;
1625 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1626 for (m = mimes; *m; m++)
1628 atom = gdk_atom_intern (*m, FALSE);
1629 if (selection_data->target == atom)
1632 type = gdk_pixbuf_format_get_name (fmt);
1633 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1635 ((strcmp (type, "png") == 0) ?
1636 "compression" : NULL), "2",
1639 gtk_selection_data_set (selection_data,
1640 atom, 8, (guchar *)str, len);
1644 g_slist_free (formats);
1653 g_slist_free (formats);
1659 * gtk_selection_data_get_pixbuf:
1660 * @selection_data: a #GtkSelectionData
1662 * Gets the contents of the selection data as a #GdkPixbuf.
1664 * Return value: (transfer full): if the selection data contained a recognized
1665 * image type and it could be converted to a #GdkPixbuf, a
1666 * newly allocated pixbuf is returned, otherwise %NULL.
1667 * If the result is non-%NULL it must be freed with g_object_unref().
1672 gtk_selection_data_get_pixbuf (const GtkSelectionData *selection_data)
1674 GdkPixbufLoader *loader;
1675 GdkPixbuf *result = NULL;
1677 g_return_val_if_fail (selection_data != NULL, NULL);
1679 if (selection_data->length > 0)
1681 loader = gdk_pixbuf_loader_new ();
1683 gdk_pixbuf_loader_write (loader,
1684 selection_data->data,
1685 selection_data->length,
1687 gdk_pixbuf_loader_close (loader, NULL);
1688 result = gdk_pixbuf_loader_get_pixbuf (loader);
1691 g_object_ref (result);
1693 g_object_unref (loader);
1700 * gtk_selection_data_set_uris:
1701 * @selection_data: a #GtkSelectionData
1702 * @uris: a %NULL-terminated array of strings holding URIs
1704 * Sets the contents of the selection from a list of URIs.
1705 * The string is converted to the form determined by
1706 * @selection_data->target.
1708 * Return value: %TRUE if the selection was successfully set,
1714 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1717 g_return_val_if_fail (selection_data != NULL, FALSE);
1718 g_return_val_if_fail (uris != NULL, FALSE);
1722 if (selection_data->target == text_uri_list_atom)
1729 list = g_string_new (NULL);
1730 for (i = 0; uris[i]; i++)
1732 g_string_append (list, uris[i]);
1733 g_string_append (list, "\r\n");
1736 result = g_convert (list->str, list->len,
1738 NULL, &length, NULL);
1739 g_string_free (list, TRUE);
1743 gtk_selection_data_set (selection_data,
1745 8, (guchar *)result, length);
1757 * gtk_selection_data_get_uris:
1758 * @selection_data: a #GtkSelectionData
1760 * Gets the contents of the selection data as array of URIs.
1762 * Return value: (array zero-terminated=1) (element-type utf8) (transfer full): if
1763 * the selection data contains a list of
1764 * URIs, a newly allocated %NULL-terminated string array
1765 * containing the URIs, otherwise %NULL. If the result is
1766 * non-%NULL it must be freed with g_strfreev().
1771 gtk_selection_data_get_uris (const GtkSelectionData *selection_data)
1773 gchar **result = NULL;
1775 g_return_val_if_fail (selection_data != NULL, NULL);
1779 if (selection_data->length >= 0 &&
1780 selection_data->type == text_uri_list_atom)
1783 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1785 selection_data->format,
1786 selection_data->data,
1787 selection_data->length,
1790 result = g_uri_list_extract_uris (list[0]);
1800 * gtk_selection_data_get_targets:
1801 * @selection_data: a #GtkSelectionData object
1802 * @targets: location to store an array of targets. The result
1803 * stored here must be freed with g_free().
1804 * @n_atoms: location to store number of items in @targets.
1806 * Gets the contents of @selection_data as an array of targets.
1807 * This can be used to interpret the results of getting
1808 * the standard TARGETS target that is always supplied for
1811 * Return value: %TRUE if @selection_data contains a valid
1812 * array of targets, otherwise %FALSE.
1815 gtk_selection_data_get_targets (const GtkSelectionData *selection_data,
1819 g_return_val_if_fail (selection_data != NULL, FALSE);
1821 if (selection_data->length >= 0 &&
1822 selection_data->format == 32 &&
1823 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1826 *targets = g_memdup (selection_data->data, selection_data->length);
1828 *n_atoms = selection_data->length / sizeof (GdkAtom);
1844 * gtk_targets_include_text:
1845 * @targets: an array of #GdkAtom<!-- -->s
1846 * @n_targets: the length of @targets
1848 * Determines if any of the targets in @targets can be used to
1851 * Return value: %TRUE if @targets include a suitable target for text,
1857 gtk_targets_include_text (GdkAtom *targets,
1861 gboolean result = FALSE;
1863 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1865 /* Keep in sync with gtk_target_list_add_text_targets()
1870 for (i = 0; i < n_targets; i++)
1872 if (targets[i] == utf8_atom ||
1873 targets[i] == text_atom ||
1874 targets[i] == GDK_TARGET_STRING ||
1875 targets[i] == ctext_atom ||
1876 targets[i] == text_plain_atom ||
1877 targets[i] == text_plain_utf8_atom ||
1878 targets[i] == text_plain_locale_atom)
1889 * gtk_targets_include_rich_text:
1890 * @targets: an array of #GdkAtom<!-- -->s
1891 * @n_targets: the length of @targets
1892 * @buffer: a #GtkTextBuffer
1894 * Determines if any of the targets in @targets can be used to
1895 * provide rich text.
1897 * Return value: %TRUE if @targets include a suitable target for rich text,
1903 gtk_targets_include_rich_text (GdkAtom *targets,
1905 GtkTextBuffer *buffer)
1907 GdkAtom *rich_targets;
1908 gint n_rich_targets;
1910 gboolean result = FALSE;
1912 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1913 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1917 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1920 for (i = 0; i < n_targets; i++)
1922 for (j = 0; j < n_rich_targets; j++)
1924 if (targets[i] == rich_targets[j])
1933 g_free (rich_targets);
1939 * gtk_selection_data_targets_include_text:
1940 * @selection_data: a #GtkSelectionData object
1942 * Given a #GtkSelectionData object holding a list of targets,
1943 * determines if any of the targets in @targets can be used to
1946 * Return value: %TRUE if @selection_data holds a list of targets,
1947 * and a suitable target for text is included, otherwise %FALSE.
1950 gtk_selection_data_targets_include_text (const GtkSelectionData *selection_data)
1954 gboolean result = FALSE;
1956 g_return_val_if_fail (selection_data != NULL, FALSE);
1960 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1962 result = gtk_targets_include_text (targets, n_targets);
1970 * gtk_selection_data_targets_include_rich_text:
1971 * @selection_data: a #GtkSelectionData object
1972 * @buffer: a #GtkTextBuffer
1974 * Given a #GtkSelectionData object holding a list of targets,
1975 * determines if any of the targets in @targets can be used to
1976 * provide rich text.
1978 * Return value: %TRUE if @selection_data holds a list of targets,
1979 * and a suitable target for rich text is included,
1985 gtk_selection_data_targets_include_rich_text (const GtkSelectionData *selection_data,
1986 GtkTextBuffer *buffer)
1990 gboolean result = FALSE;
1992 g_return_val_if_fail (selection_data != NULL, FALSE);
1993 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1997 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1999 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2007 * gtk_targets_include_image:
2008 * @targets: an array of #GdkAtom<!-- -->s
2009 * @n_targets: the length of @targets
2010 * @writable: whether to accept only targets for which GTK+ knows
2011 * how to convert a pixbuf into the format
2013 * Determines if any of the targets in @targets can be used to
2014 * provide a #GdkPixbuf.
2016 * Return value: %TRUE if @targets include a suitable target for images,
2022 gtk_targets_include_image (GdkAtom *targets,
2026 GtkTargetList *list;
2029 gboolean result = FALSE;
2031 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2033 list = gtk_target_list_new (NULL, 0);
2034 gtk_target_list_add_image_targets (list, 0, writable);
2035 for (i = 0; i < n_targets && !result; i++)
2037 for (l = list->list; l; l = l->next)
2039 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2040 if (pair->target == targets[i])
2047 gtk_target_list_unref (list);
2053 * gtk_selection_data_targets_include_image:
2054 * @selection_data: a #GtkSelectionData object
2055 * @writable: whether to accept only targets for which GTK+ knows
2056 * how to convert a pixbuf into the format
2058 * Given a #GtkSelectionData object holding a list of targets,
2059 * determines if any of the targets in @targets can be used to
2060 * provide a #GdkPixbuf.
2062 * Return value: %TRUE if @selection_data holds a list of targets,
2063 * and a suitable target for images is included, otherwise %FALSE.
2068 gtk_selection_data_targets_include_image (const GtkSelectionData *selection_data,
2073 gboolean result = FALSE;
2075 g_return_val_if_fail (selection_data != NULL, FALSE);
2079 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2081 result = gtk_targets_include_image (targets, n_targets, writable);
2089 * gtk_targets_include_uri:
2090 * @targets: an array of #GdkAtom<!-- -->s
2091 * @n_targets: the length of @targets
2093 * Determines if any of the targets in @targets can be used to
2094 * provide an uri list.
2096 * Return value: %TRUE if @targets include a suitable target for uri lists,
2102 gtk_targets_include_uri (GdkAtom *targets,
2106 gboolean result = FALSE;
2108 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2110 /* Keep in sync with gtk_target_list_add_uri_targets()
2115 for (i = 0; i < n_targets; i++)
2117 if (targets[i] == text_uri_list_atom)
2128 * gtk_selection_data_targets_include_uri:
2129 * @selection_data: a #GtkSelectionData object
2131 * Given a #GtkSelectionData object holding a list of targets,
2132 * determines if any of the targets in @targets can be used to
2133 * provide a list or URIs.
2135 * Return value: %TRUE if @selection_data holds a list of targets,
2136 * and a suitable target for URI lists is included, otherwise %FALSE.
2141 gtk_selection_data_targets_include_uri (const GtkSelectionData *selection_data)
2145 gboolean result = FALSE;
2147 g_return_val_if_fail (selection_data != NULL, FALSE);
2151 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2153 result = gtk_targets_include_uri (targets, n_targets);
2161 /*************************************************************
2162 * gtk_selection_init:
2163 * Initialize local variables
2167 *************************************************************/
2170 gtk_selection_init (void)
2172 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2173 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2174 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2175 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2176 gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS");
2182 * _gtk_selection_clear:
2183 * @widget: a #GtkWidget
2186 * The default handler for the #GtkWidget::selection-clear-event
2189 * Return value: %TRUE if the event was handled, otherwise false
2192 _gtk_selection_clear (GtkWidget *widget,
2193 GdkEventSelection *event)
2195 /* Note that we filter clear events in gdkselection-x11.c, so
2196 * that we only will get here if the clear event actually
2197 * represents a change that we didn't do ourself.
2200 GtkSelectionInfo *selection_info = NULL;
2202 tmp_list = current_selections;
2205 selection_info = (GtkSelectionInfo *)tmp_list->data;
2207 if ((selection_info->selection == event->selection) &&
2208 (selection_info->widget == widget))
2211 tmp_list = tmp_list->next;
2216 current_selections = g_list_remove_link (current_selections, tmp_list);
2217 g_list_free (tmp_list);
2218 g_slice_free (GtkSelectionInfo, selection_info);
2225 /*************************************************************
2226 * _gtk_selection_request:
2227 * Handler for "selection_request_event"
2232 *************************************************************/
2235 _gtk_selection_request (GtkWidget *widget,
2236 GdkEventSelection *event)
2238 GdkDisplay *display = gtk_widget_get_display (widget);
2242 gulong selection_max_size;
2245 gtk_selection_init ();
2247 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2249 /* Check if we own selection */
2251 tmp_list = current_selections;
2254 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2256 if ((selection_info->selection == event->selection) &&
2257 (selection_info->widget == widget))
2260 tmp_list = tmp_list->next;
2263 if (tmp_list == NULL)
2266 info = g_slice_new (GtkIncrInfo);
2268 g_object_ref (widget);
2270 info->selection = event->selection;
2271 info->num_incrs = 0;
2273 /* Create GdkWindow structure for the requestor */
2275 info->requestor = gdk_window_lookup_for_display (display,
2277 if (!info->requestor)
2278 info->requestor = gdk_window_foreign_new_for_display (display,
2281 /* Determine conversions we need to perform */
2283 if (event->target == gtk_selection_atoms[MULTIPLE])
2292 gdk_error_trap_push ();
2293 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2294 0, selection_max_size, FALSE,
2295 &type, &format, &length, &mult_atoms))
2297 gdk_selection_send_notify_for_display (display,
2303 g_free (mult_atoms);
2304 g_slice_free (GtkIncrInfo, info);
2305 gdk_error_trap_pop_ignored ();
2308 gdk_error_trap_pop_ignored ();
2310 /* This is annoying; the ICCCM doesn't specify the property type
2311 * used for the property contents, so the autoconversion for
2312 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2314 #ifdef GDK_WINDOWING_X11
2315 if (type != GDK_SELECTION_TYPE_ATOM &&
2316 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2318 info->num_conversions = length / (2*sizeof (glong));
2319 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2321 for (i=0; i<info->num_conversions; i++)
2323 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2324 ((glong *)mult_atoms)[2*i]);
2325 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2326 ((glong *)mult_atoms)[2*i + 1]);
2329 g_free (mult_atoms);
2334 info->num_conversions = length / (2*sizeof (GdkAtom));
2335 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2337 for (i=0; i<info->num_conversions; i++)
2339 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2340 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2343 g_free (mult_atoms);
2346 else /* only a single conversion */
2348 info->conversions = g_new (GtkIncrConversion, 1);
2349 info->num_conversions = 1;
2350 info->conversions[0].target = event->target;
2351 info->conversions[0].property = event->property;
2354 /* Loop through conversions and determine which of these are big
2355 enough to require doing them via INCR */
2356 for (i=0; i<info->num_conversions; i++)
2358 GtkSelectionData data;
2361 data.selection = event->selection;
2362 data.target = info->conversions[i].target;
2365 data.display = gtk_widget_get_display (widget);
2367 #ifdef DEBUG_SELECTION
2368 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2370 info->conversions[i].target,
2371 gdk_atom_name (info->conversions[i].target),
2372 event->requestor, info->conversions[i].property);
2375 gtk_selection_invoke_handler (widget, &data, event->time);
2376 if (data.length < 0)
2378 info->conversions[i].property = GDK_NONE;
2382 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2384 items = data.length / gtk_selection_bytes_per_item (data.format);
2386 if (data.length > selection_max_size)
2388 /* Sending via INCR */
2389 #ifdef DEBUG_SELECTION
2390 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2391 data.length, selection_max_size);
2394 info->conversions[i].offset = 0;
2395 info->conversions[i].data = data;
2398 gdk_property_change (info->requestor,
2399 info->conversions[i].property,
2400 gtk_selection_atoms[INCR],
2402 GDK_PROP_MODE_REPLACE,
2403 (guchar *)&items, 1);
2407 info->conversions[i].offset = -1;
2409 gdk_property_change (info->requestor,
2410 info->conversions[i].property,
2413 GDK_PROP_MODE_REPLACE,
2420 /* If we have some INCR's, we need to send the rest of the data in
2423 if (info->num_incrs > 0)
2425 /* FIXME: this could be dangerous if window doesn't still
2428 #ifdef DEBUG_SELECTION
2429 g_message ("Starting INCR...");
2432 gdk_window_set_events (info->requestor,
2433 gdk_window_get_events (info->requestor) |
2434 GDK_PROPERTY_CHANGE_MASK);
2435 current_incrs = g_list_append (current_incrs, info);
2436 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2439 /* If it was a MULTIPLE request, set the property to indicate which
2440 conversions succeeded */
2441 if (event->target == gtk_selection_atoms[MULTIPLE])
2443 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2444 for (i = 0; i < info->num_conversions; i++)
2446 mult_atoms[2*i] = info->conversions[i].target;
2447 mult_atoms[2*i+1] = info->conversions[i].property;
2450 gdk_property_change (info->requestor, event->property,
2451 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2452 GDK_PROP_MODE_REPLACE,
2453 (guchar *)mult_atoms, 2*info->num_conversions);
2454 g_free (mult_atoms);
2457 if (info->num_conversions == 1 &&
2458 info->conversions[0].property == GDK_NONE)
2460 /* Reject the entire conversion */
2461 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2470 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2478 if (info->num_incrs == 0)
2480 g_free (info->conversions);
2481 g_slice_free (GtkIncrInfo, info);
2484 g_object_unref (widget);
2489 /*************************************************************
2490 * _gtk_selection_incr_event:
2491 * Called whenever an PropertyNotify event occurs for an
2492 * GdkWindow with user_data == NULL. These will be notifications
2493 * that a window we are sending the selection to via the
2494 * INCR protocol has deleted a property and is ready for
2498 * window: the requestor window
2499 * event: the property event structure
2502 *************************************************************/
2505 _gtk_selection_incr_event (GdkWindow *window,
2506 GdkEventProperty *event)
2509 GtkIncrInfo *info = NULL;
2512 gulong selection_max_size;
2516 if (event->state != GDK_PROPERTY_DELETE)
2519 #ifdef DEBUG_SELECTION
2520 g_message ("PropertyDelete, property %ld", event->atom);
2523 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_window_get_display (window));
2525 /* Now find the appropriate ongoing INCR */
2526 tmp_list = current_incrs;
2529 info = (GtkIncrInfo *)tmp_list->data;
2530 if (info->requestor == event->window)
2533 tmp_list = tmp_list->next;
2536 if (tmp_list == NULL)
2539 /* Find out which target this is for */
2540 for (i=0; i<info->num_conversions; i++)
2542 if (info->conversions[i].property == event->atom &&
2543 info->conversions[i].offset != -1)
2547 info->idle_time = 0;
2549 if (info->conversions[i].offset == -2) /* only the last 0-length
2557 num_bytes = info->conversions[i].data.length -
2558 info->conversions[i].offset;
2559 buffer = info->conversions[i].data.data +
2560 info->conversions[i].offset;
2562 if (num_bytes > selection_max_size)
2564 num_bytes = selection_max_size;
2565 info->conversions[i].offset += selection_max_size;
2568 info->conversions[i].offset = -2;
2570 #ifdef DEBUG_SELECTION
2571 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2572 num_bytes, info->conversions[i].offset,
2573 GDK_WINDOW_XID(info->requestor), event->atom);
2576 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2577 gdk_property_change (info->requestor, event->atom,
2578 info->conversions[i].data.type,
2579 info->conversions[i].data.format,
2580 GDK_PROP_MODE_REPLACE,
2582 num_bytes / bytes_per_item);
2584 if (info->conversions[i].offset == -2)
2586 g_free (info->conversions[i].data.data);
2587 info->conversions[i].data.data = NULL;
2593 info->conversions[i].offset = -1;
2598 /* Check if we're finished with all the targets */
2600 if (info->num_incrs == 0)
2602 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2603 g_list_free (tmp_list);
2604 /* Let the timeout free it */
2610 /*************************************************************
2611 * gtk_selection_incr_timeout:
2612 * Timeout callback for the sending portion of the INCR
2615 * info: Information about this incr
2617 *************************************************************/
2620 gtk_selection_incr_timeout (GtkIncrInfo *info)
2625 /* Determine if retrieval has finished by checking if it still in
2626 list of pending retrievals */
2628 tmp_list = current_incrs;
2631 if (info == (GtkIncrInfo *)tmp_list->data)
2633 tmp_list = tmp_list->next;
2636 /* If retrieval is finished */
2637 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2639 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2641 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2642 g_list_free (tmp_list);
2645 g_free (info->conversions);
2646 /* FIXME: we should check if requestor window is still in use,
2647 and if not, remove it? */
2649 g_slice_free (GtkIncrInfo, info);
2651 retval = FALSE; /* remove timeout */
2657 retval = TRUE; /* timeout will happen again */
2663 /*************************************************************
2664 * _gtk_selection_notify:
2665 * Handler for "selection-notify-event" signals on windows
2666 * where a retrieval is currently in process. The selection
2667 * owner has responded to our conversion request.
2669 * widget: Widget getting signal
2670 * event: Selection event structure
2671 * info: Information about this retrieval
2673 * was event handled?
2674 *************************************************************/
2677 _gtk_selection_notify (GtkWidget *widget,
2678 GdkEventSelection *event)
2681 GtkRetrievalInfo *info = NULL;
2683 guchar *buffer = NULL;
2688 #ifdef DEBUG_SELECTION
2689 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2690 event->selection, event->target, event->property);
2693 window = gtk_widget_get_window (widget);
2695 tmp_list = current_retrievals;
2698 info = (GtkRetrievalInfo *)tmp_list->data;
2699 if (info->widget == widget && info->selection == event->selection)
2701 tmp_list = tmp_list->next;
2704 if (!tmp_list) /* no retrieval in progress */
2707 if (event->property != GDK_NONE)
2708 length = gdk_selection_property_get (window, &buffer,
2711 length = 0; /* silence gcc */
2713 if (event->property == GDK_NONE || buffer == NULL)
2715 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2716 g_list_free (tmp_list);
2717 /* structure will be freed in timeout */
2718 gtk_selection_retrieval_report (info,
2719 GDK_NONE, 0, NULL, -1, event->time);
2724 if (type == gtk_selection_atoms[INCR])
2726 /* The remainder of the selection will come through PropertyNotify
2729 info->notify_time = event->time;
2730 info->idle_time = 0;
2731 info->offset = 0; /* Mark as OK to proceed */
2732 gdk_window_set_events (window,
2733 gdk_window_get_events (window)
2734 | GDK_PROPERTY_CHANGE_MASK);
2738 /* We don't delete the info structure - that will happen in timeout */
2739 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2740 g_list_free (tmp_list);
2742 info->offset = length;
2743 gtk_selection_retrieval_report (info,
2745 buffer, length, event->time);
2748 gdk_property_delete (window, event->property);
2755 /*************************************************************
2756 * _gtk_selection_property_notify:
2757 * Handler for "property-notify-event" signals on windows
2758 * where a retrieval is currently in process. The selection
2759 * owner has added more data.
2761 * widget: Widget getting signal
2762 * event: Property event structure
2763 * info: Information about this retrieval
2765 * was event handled?
2766 *************************************************************/
2769 _gtk_selection_property_notify (GtkWidget *widget,
2770 GdkEventProperty *event)
2773 GtkRetrievalInfo *info = NULL;
2780 g_return_val_if_fail (widget != NULL, FALSE);
2781 g_return_val_if_fail (event != NULL, FALSE);
2783 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2784 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2785 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2789 #ifdef DEBUG_SELECTION
2790 g_message ("PropertyNewValue, property %ld",
2794 tmp_list = current_retrievals;
2797 info = (GtkRetrievalInfo *)tmp_list->data;
2798 if (info->widget == widget)
2800 tmp_list = tmp_list->next;
2803 if (!tmp_list) /* No retrieval in progress */
2806 if (info->offset < 0) /* We haven't got the SelectionNotify
2807 for this retrieval yet */
2810 info->idle_time = 0;
2812 window = gtk_widget_get_window (widget);
2813 length = gdk_selection_property_get (window, &new_buffer,
2815 gdk_property_delete (window, event->atom);
2817 /* We could do a lot better efficiency-wise by paying attention to
2818 what length was sent in the initial INCR transaction, instead of
2819 doing memory allocation at every step. But its only guaranteed to
2820 be a _lower bound_ (pretty useless!) */
2822 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2824 /* Info structure will be freed in timeout */
2825 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2826 g_list_free (tmp_list);
2827 gtk_selection_retrieval_report (info,
2829 (type == GDK_NONE) ? NULL : info->buffer,
2830 (type == GDK_NONE) ? -1 : info->offset,
2833 else /* append on newly arrived data */
2837 #ifdef DEBUG_SELECTION
2838 g_message ("Start - Adding %d bytes at offset 0",
2841 info->buffer = new_buffer;
2842 info->offset = length;
2847 #ifdef DEBUG_SELECTION
2848 g_message ("Appending %d bytes at offset %d",
2849 length,info->offset);
2851 /* We copy length+1 bytes to preserve guaranteed null termination */
2852 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2853 memcpy (info->buffer + info->offset, new_buffer, length+1);
2854 info->offset += length;
2855 g_free (new_buffer);
2862 /*************************************************************
2863 * gtk_selection_retrieval_timeout:
2864 * Timeout callback while receiving a selection.
2866 * info: Information about this retrieval
2868 *************************************************************/
2871 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2876 /* Determine if retrieval has finished by checking if it still in
2877 list of pending retrievals */
2879 tmp_list = current_retrievals;
2882 if (info == (GtkRetrievalInfo *)tmp_list->data)
2884 tmp_list = tmp_list->next;
2887 /* If retrieval is finished */
2888 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2890 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2892 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2893 g_list_free (tmp_list);
2894 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2897 g_free (info->buffer);
2898 g_slice_free (GtkRetrievalInfo, info);
2900 retval = FALSE; /* remove timeout */
2906 retval = TRUE; /* timeout will happen again */
2912 /*************************************************************
2913 * gtk_selection_retrieval_report:
2914 * Emits a "selection-received" signal.
2916 * info: information about the retrieval that completed
2917 * buffer: buffer containing data (NULL => errror)
2918 * time: timestamp for data in buffer
2920 *************************************************************/
2923 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2924 GdkAtom type, gint format,
2925 guchar *buffer, gint length,
2928 GtkSelectionData data;
2930 data.selection = info->selection;
2931 data.target = info->target;
2933 data.format = format;
2935 data.length = length;
2937 data.display = gtk_widget_get_display (info->widget);
2939 g_signal_emit_by_name (info->widget,
2940 "selection-received",
2944 /*************************************************************
2945 * gtk_selection_invoke_handler:
2946 * Finds and invokes handler for specified
2947 * widget/selection/target combination, calls
2948 * gtk_selection_default_handler if none exists.
2951 * widget: selection owner
2952 * data: selection data [INOUT]
2953 * time: time from requeset
2956 * Number of bytes written to buffer, -1 if error
2957 *************************************************************/
2960 gtk_selection_invoke_handler (GtkWidget *widget,
2961 GtkSelectionData *data,
2964 GtkTargetList *target_list;
2968 g_return_if_fail (widget != NULL);
2970 target_list = gtk_selection_target_list_get (widget, data->selection);
2971 if (data->target != gtk_selection_atoms[SAVE_TARGETS] &&
2973 gtk_target_list_find (target_list, data->target, &info))
2975 g_signal_emit_by_name (widget,
2981 gtk_selection_default_handler (widget, data);
2984 /*************************************************************
2985 * gtk_selection_default_handler:
2986 * Handles some default targets that exist for any widget
2987 * If it can't fit results into buffer, returns -1. This
2988 * won't happen in any conceivable case, since it would
2989 * require 1000 selection targets!
2992 * widget: selection owner
2993 * data: selection data [INOUT]
2995 *************************************************************/
2998 gtk_selection_default_handler (GtkWidget *widget,
2999 GtkSelectionData *data)
3001 if (data->target == gtk_selection_atoms[TIMESTAMP])
3003 /* Time which was used to obtain selection */
3005 GtkSelectionInfo *selection_info;
3007 tmp_list = current_selections;
3010 selection_info = (GtkSelectionInfo *)tmp_list->data;
3011 if ((selection_info->widget == widget) &&
3012 (selection_info->selection == data->selection))
3014 gulong time = selection_info->time;
3016 gtk_selection_data_set (data,
3017 GDK_SELECTION_TYPE_INTEGER,
3024 tmp_list = tmp_list->next;
3029 else if (data->target == gtk_selection_atoms[TARGETS])
3031 /* List of all targets supported for this widget/selection pair */
3035 GtkTargetList *target_list;
3036 GtkTargetPair *pair;
3038 target_list = gtk_selection_target_list_get (widget,
3040 count = g_list_length (target_list->list) + 3;
3042 data->type = GDK_SELECTION_TYPE_ATOM;
3044 data->length = count * sizeof (GdkAtom);
3046 /* selection data is always terminated by a trailing \0
3048 p = g_malloc (data->length + 1);
3049 data->data = (guchar *)p;
3050 data->data[data->length] = '\0';
3052 *p++ = gtk_selection_atoms[TIMESTAMP];
3053 *p++ = gtk_selection_atoms[TARGETS];
3054 *p++ = gtk_selection_atoms[MULTIPLE];
3056 tmp_list = target_list->list;
3059 pair = (GtkTargetPair *)tmp_list->data;
3060 *p++ = pair->target;
3062 tmp_list = tmp_list->next;
3065 else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
3067 gtk_selection_data_set (data,
3068 gdk_atom_intern_static_string ("NULL"),
3079 * gtk_selection_data_copy:
3080 * @data: a pointer to a #GtkSelectionData structure.
3082 * Makes a copy of a #GtkSelectionData structure and its data.
3084 * Return value: a pointer to a copy of @data.
3087 gtk_selection_data_copy (const GtkSelectionData *data)
3089 GtkSelectionData *new_data;
3091 g_return_val_if_fail (data != NULL, NULL);
3093 new_data = g_slice_new (GtkSelectionData);
3098 new_data->data = g_malloc (data->length + 1);
3099 memcpy (new_data->data, data->data, data->length + 1);
3106 * gtk_selection_data_free:
3107 * @data: a pointer to a #GtkSelectionData structure.
3109 * Frees a #GtkSelectionData structure returned from
3110 * gtk_selection_data_copy().
3113 gtk_selection_data_free (GtkSelectionData *data)
3115 g_return_if_fail (data != NULL);
3117 g_free (data->data);
3119 g_slice_free (GtkSelectionData, data);
3123 * gtk_target_entry_new:
3124 * @target: String identifier for target
3125 * @flags: Set of flags, see #GtkTargetFlags
3126 * @info: an ID that will be passed back to the application
3128 * Makes a new #GtkTargetEntry structure.
3130 * Return value: a pointer to a new GtkTargetEntry structure.
3131 * Free with gtk_target_entry_free()
3134 gtk_target_entry_new (const char *target,
3138 GtkTargetEntry entry = { (char *) target, flags, info };
3139 return gtk_target_entry_copy (&entry);
3143 * gtk_target_entry_copy:
3144 * @data: a pointer to a #GtkTargetEntry structure.
3146 * Makes a copy of a #GtkTargetEntry structure and its data.
3148 * Return value: a pointer to a copy of @data.
3149 * Free with gtk_target_entry_free()
3152 gtk_target_entry_copy (GtkTargetEntry *data)
3154 GtkTargetEntry *new_data;
3156 g_return_val_if_fail (data != NULL, NULL);
3158 new_data = g_slice_new (GtkTargetEntry);
3159 new_data->target = g_strdup (data->target);
3160 new_data->flags = data->flags;
3161 new_data->info = data->info;
3167 * gtk_target_entry_free:
3168 * @data: a pointer to a #GtkTargetEntry structure.
3170 * Frees a #GtkTargetEntry structure returned from
3171 * gtk_target_entry_new() or gtk_target_entry_copy().
3174 gtk_target_entry_free (GtkTargetEntry *data)
3176 g_return_if_fail (data != NULL);
3178 g_free (data->target);
3180 g_slice_free (GtkTargetEntry, data);
3184 G_DEFINE_BOXED_TYPE (GtkSelectionData, gtk_selection_data,
3185 gtk_selection_data_copy,
3186 gtk_selection_data_free)
3188 G_DEFINE_BOXED_TYPE (GtkTargetList, gtk_target_list,
3189 gtk_target_list_ref,
3190 gtk_target_list_unref)
3192 G_DEFINE_BOXED_TYPE (GtkTargetEntry, gtk_target_entry,
3193 gtk_target_entry_copy,
3194 gtk_target_entry_free)
3197 gtk_selection_bytes_per_item (gint format)
3202 return sizeof (char);
3205 return sizeof (short);
3208 return sizeof (long);
3211 g_assert_not_reached();