1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 /* This file implements most of the work of the ICCCM selection protocol.
21 * The code was written after an intensive study of the equivalent part
22 * of John Ousterhout's Tk toolkit, and does many things in much the
25 * The one thing in the ICCCM that isn't fully supported here (or in Tk)
26 * is side effects targets. For these to be handled properly, MULTIPLE
27 * targets need to be done in the order specified. This cannot be
28 * guaranteed with the way we do things, since if we are doing INCR
29 * transfers, the order will depend on the timing of the requestor.
31 * By Owen Taylor <owt1@cornell.edu> 8/16/97
34 /* Terminology note: when not otherwise specified, the term "incr" below
35 * refers to the _sending_ part of the INCR protocol. The receiving
36 * portion is referred to just as "retrieval". (Terminology borrowed
37 * from Tk, because there is no good opposite to "retrieval" in English.
38 * "send" can't be made into a noun gracefully and we're already using
39 * "emission" for something else ....)
42 /* The MOTIF entry widget seems to ask for the TARGETS target, then
43 (regardless of the reply) ask for the TEXT target. It's slightly
44 possible though that it somehow thinks we are responding negatively
45 to the TARGETS request, though I don't really think so ... */
48 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
49 * file for a list of people on the GTK+ Team. See the ChangeLog
50 * files for a list of changes. These files are distributed with
51 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
60 #include "gtkselection.h"
61 #include "gtktextbufferrichtext.h"
63 #include "gdk-pixbuf/gdk-pixbuf.h"
65 #ifdef GDK_WINDOWING_X11
69 #ifdef GDK_WINDOWING_WIN32
70 #include "win32/gdkwin32.h"
75 #undef DEBUG_SELECTION
77 /* Maximum size of a sent chunk, in bytes. Also the default size of
79 #ifdef GDK_WINDOWING_X11
80 #define GTK_SELECTION_MAX_SIZE(display) \
82 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
83 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
84 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
86 /* No chunks on Win32 */
87 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
90 #define IDLE_ABORT_TIME 30
101 typedef struct _GtkSelectionInfo GtkSelectionInfo;
102 typedef struct _GtkIncrConversion GtkIncrConversion;
103 typedef struct _GtkIncrInfo GtkIncrInfo;
104 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
106 struct _GtkSelectionInfo
109 GtkWidget *widget; /* widget that owns selection */
110 guint32 time; /* time used to acquire selection */
111 GdkDisplay *display; /* needed in gtk_selection_remove_all */
114 struct _GtkIncrConversion
116 GdkAtom target; /* Requested target */
117 GdkAtom property; /* Property to store in */
118 GtkSelectionData data; /* The data being supplied */
119 gint offset; /* Current offset in sent selection.
121 * -2 => Only the final (empty) portion
127 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
128 so we can receive events */
129 GdkAtom selection; /* Selection we're sending */
131 GtkIncrConversion *conversions; /* Information about requested conversions -
132 * With MULTIPLE requests (benighted 1980's
133 * hardware idea), there can be more than
135 gint num_conversions;
136 gint num_incrs; /* number of remaining INCR style transactions */
141 struct _GtkRetrievalInfo
144 GdkAtom selection; /* Selection being retrieved. */
145 GdkAtom target; /* Form of selection that we requested */
146 guint32 idle_time; /* Number of seconds since we last heard
147 from selection owner */
148 guchar *buffer; /* Buffer in which to accumulate results */
149 gint offset; /* Current offset in buffer, -1 indicates
151 guint32 notify_time; /* Timestamp from SelectionNotify */
154 /* Local Functions */
155 static void gtk_selection_init (void);
156 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
157 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
158 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
164 static void gtk_selection_invoke_handler (GtkWidget *widget,
165 GtkSelectionData *data,
167 static void gtk_selection_default_handler (GtkWidget *widget,
168 GtkSelectionData *data);
169 static int gtk_selection_bytes_per_item (gint format);
172 static gint initialize = TRUE;
173 static GList *current_retrievals = NULL;
174 static GList *current_incrs = NULL;
175 static GList *current_selections = NULL;
177 static GdkAtom gtk_selection_atoms[LAST_ATOM];
178 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
190 * gtk_target_list_new:
191 * @targets: Pointer to an array of #GtkTargetEntry
192 * @ntargets: number of entries in @targets.
194 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
196 * Return value: the new #GtkTargetList.
199 gtk_target_list_new (const GtkTargetEntry *targets,
202 GtkTargetList *result = g_slice_new (GtkTargetList);
204 result->ref_count = 1;
207 gtk_target_list_add_table (result, targets, ntargets);
213 * gtk_target_list_ref:
214 * @list: a #GtkTargetList
216 * Increases the reference count of a #GtkTargetList by one.
218 * Return value: the passed in #GtkTargetList.
221 gtk_target_list_ref (GtkTargetList *list)
223 g_return_val_if_fail (list != NULL, NULL);
231 * gtk_target_list_unref:
232 * @list: a #GtkTargetList
234 * Decreases the reference count of a #GtkTargetList by one.
235 * If the resulting reference count is zero, frees the list.
238 gtk_target_list_unref (GtkTargetList *list)
240 g_return_if_fail (list != NULL);
241 g_return_if_fail (list->ref_count > 0);
244 if (list->ref_count == 0)
246 GList *tmp_list = list->list;
249 GtkTargetPair *pair = tmp_list->data;
250 g_slice_free (GtkTargetPair, pair);
252 tmp_list = tmp_list->next;
255 g_list_free (list->list);
256 g_slice_free (GtkTargetList, list);
261 * gtk_target_list_add:
262 * @list: a #GtkTargetList
263 * @target: the interned atom representing the target
264 * @flags: the flags for this target
265 * @info: an ID that will be passed back to the application
267 * Appends another target to a #GtkTargetList.
270 gtk_target_list_add (GtkTargetList *list,
277 g_return_if_fail (list != NULL);
279 pair = g_slice_new (GtkTargetPair);
280 pair->target = target;
284 list->list = g_list_append (list->list, pair);
287 static GdkAtom utf8_atom;
288 static GdkAtom text_atom;
289 static GdkAtom ctext_atom;
290 static GdkAtom text_plain_atom;
291 static GdkAtom text_plain_utf8_atom;
292 static GdkAtom text_plain_locale_atom;
293 static GdkAtom text_uri_list_atom;
299 const gchar *charset;
303 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
304 text_atom = gdk_atom_intern_static_string ("TEXT");
305 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
306 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
307 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
308 g_get_charset (&charset);
309 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
310 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
313 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
318 * gtk_target_list_add_text_targets:
319 * @list: a #GtkTargetList
320 * @info: an ID that will be passed back to the application
322 * Appends the text targets supported by #GtkSelection to
323 * the target list. All targets are added with the same @info.
328 gtk_target_list_add_text_targets (GtkTargetList *list,
331 g_return_if_fail (list != NULL);
335 /* Keep in sync with gtk_selection_data_targets_include_text()
337 gtk_target_list_add (list, utf8_atom, 0, info);
338 gtk_target_list_add (list, ctext_atom, 0, info);
339 gtk_target_list_add (list, text_atom, 0, info);
340 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
341 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
342 if (!g_get_charset (NULL))
343 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
344 gtk_target_list_add (list, text_plain_atom, 0, info);
348 * gtk_target_list_add_rich_text_targets:
349 * @list: a #GtkTargetList
350 * @info: an ID that will be passed back to the application
351 * @deserializable: if %TRUE, then deserializable rich text formats
352 * will be added, serializable formats otherwise.
353 * @buffer: a #GtkTextBuffer.
355 * Appends the rich text targets registered with
356 * gtk_text_buffer_register_serialize_format() or
357 * gtk_text_buffer_register_deserialize_format() to the target list. All
358 * targets are added with the same @info.
363 gtk_target_list_add_rich_text_targets (GtkTargetList *list,
365 gboolean deserializable,
366 GtkTextBuffer *buffer)
372 g_return_if_fail (list != NULL);
373 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
376 atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
378 atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
380 for (i = 0; i < n_atoms; i++)
381 gtk_target_list_add (list, atoms[i], 0, info);
387 * gtk_target_list_add_image_targets:
388 * @list: a #GtkTargetList
389 * @info: an ID that will be passed back to the application
390 * @writable: whether to add only targets for which GTK+ knows
391 * how to convert a pixbuf into the format
393 * Appends the image targets supported by #GtkSelection to
394 * the target list. All targets are added with the same @info.
399 gtk_target_list_add_image_targets (GtkTargetList *list,
407 g_return_if_fail (list != NULL);
409 formats = gdk_pixbuf_get_formats ();
411 /* Make sure png comes first */
412 for (f = formats; f; f = f->next)
414 GdkPixbufFormat *fmt = f->data;
417 name = gdk_pixbuf_format_get_name (fmt);
418 if (strcmp (name, "png") == 0)
420 formats = g_slist_delete_link (formats, f);
421 formats = g_slist_prepend (formats, fmt);
431 for (f = formats; f; f = f->next)
433 GdkPixbufFormat *fmt = f->data;
435 if (writable && !gdk_pixbuf_format_is_writable (fmt))
438 mimes = gdk_pixbuf_format_get_mime_types (fmt);
439 for (m = mimes; *m; m++)
441 atom = gdk_atom_intern (*m, FALSE);
442 gtk_target_list_add (list, atom, 0, info);
447 g_slist_free (formats);
451 * gtk_target_list_add_uri_targets:
452 * @list: a #GtkTargetList
453 * @info: an ID that will be passed back to the application
455 * Appends the URI targets supported by #GtkSelection to
456 * the target list. All targets are added with the same @info.
461 gtk_target_list_add_uri_targets (GtkTargetList *list,
464 g_return_if_fail (list != NULL);
468 gtk_target_list_add (list, text_uri_list_atom, 0, info);
472 * gtk_target_list_add_table:
473 * @list: a #GtkTargetList
474 * @targets: the table of #GtkTargetEntry
475 * @ntargets: number of targets in the table
477 * Prepends a table of #GtkTargetEntry to a target list.
480 gtk_target_list_add_table (GtkTargetList *list,
481 const GtkTargetEntry *targets,
486 for (i=ntargets-1; i >= 0; i--)
488 GtkTargetPair *pair = g_slice_new (GtkTargetPair);
489 pair->target = gdk_atom_intern (targets[i].target, FALSE);
490 pair->flags = targets[i].flags;
491 pair->info = targets[i].info;
493 list->list = g_list_prepend (list->list, pair);
498 * gtk_target_list_remove:
499 * @list: a #GtkTargetList
500 * @target: the interned atom representing the target
502 * Removes a target from a target list.
505 gtk_target_list_remove (GtkTargetList *list,
510 g_return_if_fail (list != NULL);
512 tmp_list = list->list;
515 GtkTargetPair *pair = tmp_list->data;
517 if (pair->target == target)
519 g_slice_free (GtkTargetPair, pair);
521 list->list = g_list_remove_link (list->list, tmp_list);
522 g_list_free_1 (tmp_list);
527 tmp_list = tmp_list->next;
532 * gtk_target_list_find:
533 * @list: a #GtkTargetList
534 * @target: an interned atom representing the target to search for
535 * @info: a pointer to the location to store application info for target,
538 * Looks up a given target in a #GtkTargetList.
540 * Return value: %TRUE if the target was found, otherwise %FALSE
543 gtk_target_list_find (GtkTargetList *list,
549 g_return_val_if_fail (list != NULL, FALSE);
551 tmp_list = list->list;
554 GtkTargetPair *pair = tmp_list->data;
556 if (pair->target == target)
564 tmp_list = tmp_list->next;
571 * gtk_target_table_new_from_list:
572 * @list: a #GtkTargetList
573 * @n_targets: return location for the number ot targets in the table
575 * This function creates an #GtkTargetEntry array that contains the
576 * same targets as the passed %list. The returned table is newly
577 * allocated and should be freed using gtk_target_table_free() when no
580 * Return value: the new table.
585 gtk_target_table_new_from_list (GtkTargetList *list,
588 GtkTargetEntry *targets;
592 g_return_val_if_fail (list != NULL, NULL);
593 g_return_val_if_fail (n_targets != NULL, NULL);
595 *n_targets = g_list_length (list->list);
596 targets = g_new0 (GtkTargetEntry, *n_targets);
598 for (i = 0, tmp_list = list->list;
600 i++, tmp_list = g_list_next (tmp_list))
602 GtkTargetPair *pair = tmp_list->data;
604 targets[i].target = gdk_atom_name (pair->target);
605 targets[i].flags = pair->flags;
606 targets[i].info = pair->info;
613 * gtk_target_table_free:
614 * @targets: a #GtkTargetEntry array
615 * @n_targets: the number of entries in the array
617 * This function frees a target table as returned by
618 * gtk_target_table_new_from_list()
623 gtk_target_table_free (GtkTargetEntry *targets,
628 g_return_if_fail (targets == NULL || n_targets > 0);
630 for (i = 0; i < n_targets; i++)
631 g_free (targets[i].target);
637 * gtk_selection_owner_set_for_display:
638 * @display: the #Gdkdisplay where the selection is set
639 * @widget: (allow-none): new selection owner (a #GdkWidget), or %NULL.
640 * @selection: an interned atom representing the selection to claim.
641 * @time_: timestamp with which to claim the selection
643 * Claim ownership of a given selection for a particular widget, or,
644 * if @widget is %NULL, release ownership of the selection.
646 * Return value: TRUE if the operation succeeded
651 gtk_selection_owner_set_for_display (GdkDisplay *display,
657 GtkWidget *old_owner;
658 GtkSelectionInfo *selection_info = NULL;
661 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
662 g_return_val_if_fail (selection != GDK_NONE, FALSE);
663 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
664 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
669 window = widget->window;
671 tmp_list = current_selections;
674 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
676 selection_info = tmp_list->data;
680 tmp_list = tmp_list->next;
683 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
691 old_owner = selection_info->widget;
692 current_selections = g_list_remove_link (current_selections,
694 g_list_free (tmp_list);
695 g_slice_free (GtkSelectionInfo, selection_info);
700 if (selection_info == NULL)
702 selection_info = g_slice_new (GtkSelectionInfo);
703 selection_info->selection = selection;
704 selection_info->widget = widget;
705 selection_info->time = time;
706 selection_info->display = display;
707 current_selections = g_list_prepend (current_selections,
712 old_owner = selection_info->widget;
713 selection_info->widget = widget;
714 selection_info->time = time;
715 selection_info->display = display;
718 /* If another widget in the application lost the selection,
719 * send it a GDK_SELECTION_CLEAR event.
721 if (old_owner && old_owner != widget)
723 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
725 event->selection.window = g_object_ref (old_owner->window);
726 event->selection.selection = selection;
727 event->selection.time = time;
729 gtk_widget_event (old_owner, event);
731 gdk_event_free (event);
740 * gtk_selection_owner_set:
741 * @widget: (allow-none): a #GtkWidget, or %NULL.
742 * @selection: an interned atom representing the selection to claim
743 * @time_: timestamp with which to claim the selection
745 * Claims ownership of a given selection for a particular widget,
746 * or, if @widget is %NULL, release ownership of the selection.
748 * Return value: %TRUE if the operation succeeded
751 gtk_selection_owner_set (GtkWidget *widget,
757 g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE);
758 g_return_val_if_fail (selection != GDK_NONE, FALSE);
761 display = gtk_widget_get_display (widget);
765 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
767 display = gdk_display_get_default ();
770 return gtk_selection_owner_set_for_display (display, widget,
774 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
776 struct _GtkSelectionTargetList {
781 static GtkTargetList *
782 gtk_selection_target_list_get (GtkWidget *widget,
785 GtkSelectionTargetList *sellist;
789 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
794 sellist = tmp_list->data;
795 if (sellist->selection == selection)
796 return sellist->list;
797 tmp_list = tmp_list->next;
800 sellist = g_slice_new (GtkSelectionTargetList);
801 sellist->selection = selection;
802 sellist->list = gtk_target_list_new (NULL, 0);
804 lists = g_list_prepend (lists, sellist);
805 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
807 return sellist->list;
811 gtk_selection_target_list_remove (GtkWidget *widget)
813 GtkSelectionTargetList *sellist;
817 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
822 sellist = tmp_list->data;
824 gtk_target_list_unref (sellist->list);
826 g_slice_free (GtkSelectionTargetList, sellist);
827 tmp_list = tmp_list->next;
831 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
835 * gtk_selection_clear_targets:
836 * @widget: a #GtkWidget
837 * @selection: an atom representing a selection
839 * Remove all targets registered for the given selection for the
843 gtk_selection_clear_targets (GtkWidget *widget,
846 GtkSelectionTargetList *sellist;
850 g_return_if_fail (GTK_IS_WIDGET (widget));
851 g_return_if_fail (selection != GDK_NONE);
853 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
858 sellist = tmp_list->data;
859 if (sellist->selection == selection)
861 lists = g_list_delete_link (lists, tmp_list);
862 gtk_target_list_unref (sellist->list);
863 g_slice_free (GtkSelectionTargetList, sellist);
868 tmp_list = tmp_list->next;
871 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
875 * gtk_selection_add_target:
876 * @widget: a #GtkTarget
877 * @selection: the selection
878 * @target: target to add.
879 * @info: A unsigned integer which will be passed back to the application.
881 * Appends a specified target to the list of supported targets for a
882 * given widget and selection.
885 gtk_selection_add_target (GtkWidget *widget,
892 g_return_if_fail (GTK_IS_WIDGET (widget));
893 g_return_if_fail (selection != GDK_NONE);
895 list = gtk_selection_target_list_get (widget, selection);
896 gtk_target_list_add (list, target, 0, info);
897 #ifdef GDK_WINDOWING_WIN32
898 gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
903 * gtk_selection_add_targets:
904 * @widget: a #GtkWidget
905 * @selection: the selection
906 * @targets: a table of targets to add
907 * @ntargets: number of entries in @targets
909 * Prepends a table of targets to the list of supported targets
910 * for a given widget and selection.
913 gtk_selection_add_targets (GtkWidget *widget,
915 const GtkTargetEntry *targets,
920 g_return_if_fail (GTK_IS_WIDGET (widget));
921 g_return_if_fail (selection != GDK_NONE);
922 g_return_if_fail (targets != NULL);
924 list = gtk_selection_target_list_get (widget, selection);
925 gtk_target_list_add_table (list, targets, ntargets);
927 #ifdef GDK_WINDOWING_WIN32
930 GdkAtom *atoms = g_new (GdkAtom, ntargets);
932 for (i = 0; i < ntargets; ++i)
933 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
934 gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
942 * gtk_selection_remove_all:
943 * @widget: a #GtkWidget
945 * Removes all handlers and unsets ownership of all
946 * selections for a widget. Called when widget is being
947 * destroyed. This function will not generally be
948 * called by applications.
951 gtk_selection_remove_all (GtkWidget *widget)
955 GtkSelectionInfo *selection_info;
957 g_return_if_fail (GTK_IS_WIDGET (widget));
959 /* Remove pending requests/incrs for this widget */
961 tmp_list = current_retrievals;
964 next = tmp_list->next;
965 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
967 current_retrievals = g_list_remove_link (current_retrievals,
969 /* structure will be freed in timeout */
970 g_list_free (tmp_list);
975 /* Disclaim ownership of any selections */
977 tmp_list = current_selections;
980 next = tmp_list->next;
981 selection_info = (GtkSelectionInfo *)tmp_list->data;
983 if (selection_info->widget == widget)
985 gdk_selection_owner_set_for_display (selection_info->display,
987 selection_info->selection,
988 GDK_CURRENT_TIME, FALSE);
989 current_selections = g_list_remove_link (current_selections,
991 g_list_free (tmp_list);
992 g_slice_free (GtkSelectionInfo, selection_info);
998 /* Remove all selection lists */
999 gtk_selection_target_list_remove (widget);
1004 * gtk_selection_convert:
1005 * @widget: The widget which acts as requestor
1006 * @selection: Which selection to get
1007 * @target: Form of information desired (e.g., STRING)
1008 * @time_: Time of request (usually of triggering event)
1009 In emergency, you could use #GDK_CURRENT_TIME
1011 * Requests the contents of a selection. When received,
1012 * a "selection-received" signal will be generated.
1014 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1015 * request. (e.g., there was already a request in process for
1019 gtk_selection_convert (GtkWidget *widget,
1024 GtkRetrievalInfo *info;
1026 GdkWindow *owner_window;
1027 GdkDisplay *display;
1029 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1030 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1033 gtk_selection_init ();
1035 if (!gtk_widget_get_realized (widget))
1036 gtk_widget_realize (widget);
1038 /* Check to see if there are already any retrievals in progress for
1039 this widget. If we changed GDK to use the selection for the
1040 window property in which to store the retrieved information, then
1041 we could support multiple retrievals for different selections.
1042 This might be useful for DND. */
1044 tmp_list = current_retrievals;
1047 info = (GtkRetrievalInfo *)tmp_list->data;
1048 if (info->widget == widget)
1050 tmp_list = tmp_list->next;
1053 info = g_slice_new (GtkRetrievalInfo);
1055 info->widget = widget;
1056 info->selection = selection;
1057 info->target = target;
1058 info->idle_time = 0;
1059 info->buffer = NULL;
1062 /* Check if this process has current owner. If so, call handler
1063 procedure directly to avoid deadlocks with INCR. */
1065 display = gtk_widget_get_display (widget);
1066 owner_window = gdk_selection_owner_get_for_display (display, selection);
1068 if (owner_window != NULL)
1070 GtkWidget *owner_widget;
1071 gpointer owner_widget_ptr;
1072 GtkSelectionData selection_data;
1074 selection_data.selection = selection;
1075 selection_data.target = target;
1076 selection_data.data = NULL;
1077 selection_data.length = -1;
1078 selection_data.display = display;
1080 gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1081 owner_widget = owner_widget_ptr;
1083 if (owner_widget != NULL)
1085 gtk_selection_invoke_handler (owner_widget,
1089 gtk_selection_retrieval_report (info,
1090 selection_data.type,
1091 selection_data.format,
1092 selection_data.data,
1093 selection_data.length,
1096 g_free (selection_data.data);
1097 selection_data.data = NULL;
1098 selection_data.length = -1;
1100 g_slice_free (GtkRetrievalInfo, info);
1105 /* Otherwise, we need to go through X */
1107 current_retrievals = g_list_append (current_retrievals, info);
1108 gdk_selection_convert (widget->window, selection, target, time_);
1109 gdk_threads_add_timeout (1000,
1110 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1116 * gtk_selection_data_get_selection:
1117 * @selection_data: a pointer to a #GtkSelectionData structure.
1119 * Retrieves the selection #GdkAtom of the selection data.
1121 * Returns: the selection #GdkAtom of the selection data.
1126 gtk_selection_data_get_selection (GtkSelectionData *selection_data)
1128 g_return_val_if_fail (selection_data != NULL, 0);
1130 return selection_data->selection;
1134 * gtk_selection_data_get_target:
1135 * @selection_data: a pointer to a #GtkSelectionData structure.
1137 * Retrieves the target of the selection.
1139 * Returns: the target of the selection.
1144 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1146 g_return_val_if_fail (selection_data != NULL, 0);
1148 return selection_data->target;
1152 * gtk_selection_data_get_data_type:
1153 * @selection_data: a pointer to a #GtkSelectionData structure.
1155 * Retrieves the data type of the selection.
1157 * Returns: the data type of the selection.
1162 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1164 g_return_val_if_fail (selection_data != NULL, 0);
1166 return selection_data->type;
1170 * gtk_selection_data_get_format:
1171 * @selection_data: a pointer to a #GtkSelectionData structure.
1173 * Retrieves the format of the selection.
1175 * Returns: the format of the selection.
1180 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1182 g_return_val_if_fail (selection_data != NULL, 0);
1184 return selection_data->format;
1188 * gtk_selection_data_get_data:
1189 * @selection_data: a pointer to a #GtkSelectionData structure.
1191 * Retrieves the raw data of the selection.
1193 * Returns: the raw data of the selection.
1198 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1200 g_return_val_if_fail (selection_data != NULL, NULL);
1202 return selection_data->data;
1206 * gtk_selection_data_get_length:
1207 * @selection_data: a pointer to a #GtkSelectionData structure.
1209 * Retrieves the length of the raw data of the selection.
1211 * Returns: the length of the data of the selection.
1216 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1218 g_return_val_if_fail (selection_data != NULL, -1);
1220 return selection_data->length;
1224 * gtk_selection_data_get_display:
1225 * @selection_data: a pointer to a #GtkSelectionData structure.
1227 * Retrieves the display of the selection.
1229 * Returns: the display of the selection.
1234 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1236 g_return_val_if_fail (selection_data != NULL, NULL);
1238 return selection_data->display;
1242 * gtk_selection_data_set:
1243 * @selection_data: a pointer to a #GtkSelectionData structure.
1244 * @type: the type of selection data
1245 * @format: format (number of bits in a unit)
1246 * @data: pointer to the data (will be copied)
1247 * @length: length of the data
1249 * Stores new data into a #GtkSelectionData object. Should
1250 * <emphasis>only</emphasis> be called from a selection handler callback.
1251 * Zero-terminates the stored data.
1254 gtk_selection_data_set (GtkSelectionData *selection_data,
1260 g_return_if_fail (selection_data != NULL);
1262 g_free (selection_data->data);
1264 selection_data->type = type;
1265 selection_data->format = format;
1269 selection_data->data = g_new (guchar, length+1);
1270 memcpy (selection_data->data, data, length);
1271 selection_data->data[length] = 0;
1275 g_return_if_fail (length <= 0);
1278 selection_data->data = NULL;
1280 selection_data->data = (guchar *) g_strdup ("");
1283 selection_data->length = length;
1287 selection_set_string (GtkSelectionData *selection_data,
1291 gchar *tmp = g_strndup (str, len);
1292 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1297 gtk_selection_data_set (selection_data,
1298 GDK_SELECTION_TYPE_STRING,
1299 8, (guchar *) latin1, strlen (latin1));
1309 selection_set_compound_text (GtkSelectionData *selection_data,
1318 gboolean result = FALSE;
1320 tmp = g_strndup (str, len);
1321 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1322 &encoding, &format, &text, &new_length))
1324 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1325 gdk_free_compound_text (text);
1335 /* Normalize \r and \n into \r\n
1338 normalize_to_crlf (const gchar *str,
1341 GString *result = g_string_sized_new (len);
1342 const gchar *p = str;
1343 const gchar *end = str + len;
1348 g_string_append_c (result, '\r');
1352 g_string_append_c (result, *p);
1354 if (p == end || *p != '\n')
1355 g_string_append_c (result, '\n');
1360 g_string_append_c (result, *p);
1364 return g_string_free (result, FALSE);
1367 /* Normalize \r and \r\n into \n
1370 normalize_to_lf (gchar *str,
1373 GString *result = g_string_sized_new (len);
1374 const gchar *p = str;
1382 g_string_append_c (result, '\n');
1388 g_string_append_c (result, *p);
1392 return g_string_free (result, FALSE);
1396 selection_set_text_plain (GtkSelectionData *selection_data,
1400 const gchar *charset = NULL;
1402 GError *error = NULL;
1404 result = normalize_to_crlf (str, len);
1405 if (selection_data->target == text_plain_atom)
1407 else if (selection_data->target == text_plain_locale_atom)
1408 g_get_charset (&charset);
1412 gchar *tmp = result;
1413 result = g_convert_with_fallback (tmp, -1,
1415 NULL, NULL, NULL, &error);
1421 g_warning ("Error converting from %s to %s: %s",
1422 "UTF-8", charset, error->message);
1423 g_error_free (error);
1428 gtk_selection_data_set (selection_data,
1429 selection_data->target,
1430 8, (guchar *) result, strlen (result));
1437 selection_get_text_plain (GtkSelectionData *selection_data)
1439 const gchar *charset = NULL;
1440 gchar *str, *result;
1442 GError *error = NULL;
1444 str = g_strdup ((const gchar *) selection_data->data);
1445 len = selection_data->length;
1447 if (selection_data->type == text_plain_atom)
1448 charset = "ISO-8859-1";
1449 else if (selection_data->type == text_plain_locale_atom)
1450 g_get_charset (&charset);
1455 str = g_convert_with_fallback (tmp, len,
1457 NULL, NULL, &len, &error);
1462 g_warning ("Error converting from %s to %s: %s",
1463 charset, "UTF-8", error->message);
1464 g_error_free (error);
1469 else if (!g_utf8_validate (str, -1, NULL))
1471 g_warning ("Error converting from %s to %s: %s",
1472 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1478 result = normalize_to_lf (str, len);
1481 return (guchar *) result;
1485 * gtk_selection_data_set_text:
1486 * @selection_data: a #GtkSelectionData
1487 * @str: a UTF-8 string
1488 * @len: the length of @str, or -1 if @str is nul-terminated.
1490 * Sets the contents of the selection from a UTF-8 encoded string.
1491 * The string is converted to the form determined by
1492 * @selection_data->target.
1494 * Return value: %TRUE if the selection was successfully set,
1498 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1502 g_return_val_if_fail (selection_data != NULL, FALSE);
1509 if (selection_data->target == utf8_atom)
1511 gtk_selection_data_set (selection_data,
1513 8, (guchar *)str, len);
1516 else if (selection_data->target == GDK_TARGET_STRING)
1518 return selection_set_string (selection_data, str, len);
1520 else if (selection_data->target == ctext_atom ||
1521 selection_data->target == text_atom)
1523 if (selection_set_compound_text (selection_data, str, len))
1525 else if (selection_data->target == text_atom)
1526 return selection_set_string (selection_data, str, len);
1528 else if (selection_data->target == text_plain_atom ||
1529 selection_data->target == text_plain_utf8_atom ||
1530 selection_data->target == text_plain_locale_atom)
1532 return selection_set_text_plain (selection_data, str, len);
1539 * gtk_selection_data_get_text:
1540 * @selection_data: a #GtkSelectionData
1542 * Gets the contents of the selection data as a UTF-8 string.
1544 * Return value: if the selection data contained a recognized
1545 * text type and it could be converted to UTF-8, a newly allocated
1546 * string containing the converted text, otherwise %NULL.
1547 * If the result is non-%NULL it must be freed with g_free().
1550 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1552 guchar *result = NULL;
1554 g_return_val_if_fail (selection_data != NULL, NULL);
1558 if (selection_data->length >= 0 &&
1559 (selection_data->type == GDK_TARGET_STRING ||
1560 selection_data->type == ctext_atom ||
1561 selection_data->type == utf8_atom))
1565 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1566 selection_data->type,
1567 selection_data->format,
1568 selection_data->data,
1569 selection_data->length,
1572 result = (guchar *) list[0];
1574 for (i = 1; i < count; i++)
1578 else if (selection_data->length >= 0 &&
1579 (selection_data->type == text_plain_atom ||
1580 selection_data->type == text_plain_utf8_atom ||
1581 selection_data->type == text_plain_locale_atom))
1583 result = selection_get_text_plain (selection_data);
1590 * gtk_selection_data_set_pixbuf:
1591 * @selection_data: a #GtkSelectionData
1592 * @pixbuf: a #GdkPixbuf
1594 * Sets the contents of the selection from a #GdkPixbuf
1595 * The pixbuf is converted to the form determined by
1596 * @selection_data->target.
1598 * Return value: %TRUE if the selection was successfully set,
1604 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1607 GSList *formats, *f;
1614 g_return_val_if_fail (selection_data != NULL, FALSE);
1615 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1617 formats = gdk_pixbuf_get_formats ();
1619 for (f = formats; f; f = f->next)
1621 GdkPixbufFormat *fmt = f->data;
1623 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1624 for (m = mimes; *m; m++)
1626 atom = gdk_atom_intern (*m, FALSE);
1627 if (selection_data->target == atom)
1630 type = gdk_pixbuf_format_get_name (fmt);
1631 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1633 ((strcmp (type, "png") == 0) ?
1634 "compression" : NULL), "2",
1637 gtk_selection_data_set (selection_data,
1638 atom, 8, (guchar *)str, len);
1642 g_slist_free (formats);
1651 g_slist_free (formats);
1657 * gtk_selection_data_get_pixbuf:
1658 * @selection_data: a #GtkSelectionData
1660 * Gets the contents of the selection data as a #GdkPixbuf.
1662 * Return value: if the selection data contained a recognized
1663 * image type and it could be converted to a #GdkPixbuf, a
1664 * newly allocated pixbuf is returned, otherwise %NULL.
1665 * If the result is non-%NULL it must be freed with g_object_unref().
1670 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1672 GdkPixbufLoader *loader;
1673 GdkPixbuf *result = NULL;
1675 g_return_val_if_fail (selection_data != NULL, NULL);
1677 if (selection_data->length > 0)
1679 loader = gdk_pixbuf_loader_new ();
1681 gdk_pixbuf_loader_write (loader,
1682 selection_data->data,
1683 selection_data->length,
1685 gdk_pixbuf_loader_close (loader, NULL);
1686 result = gdk_pixbuf_loader_get_pixbuf (loader);
1689 g_object_ref (result);
1691 g_object_unref (loader);
1698 * gtk_selection_data_set_uris:
1699 * @selection_data: a #GtkSelectionData
1700 * @uris: a %NULL-terminated array of strings holding URIs
1702 * Sets the contents of the selection from a list of URIs.
1703 * The string is converted to the form determined by
1704 * @selection_data->target.
1706 * Return value: %TRUE if the selection was successfully set,
1712 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1715 g_return_val_if_fail (selection_data != NULL, FALSE);
1716 g_return_val_if_fail (uris != NULL, FALSE);
1720 if (selection_data->target == text_uri_list_atom)
1727 list = g_string_new (NULL);
1728 for (i = 0; uris[i]; i++)
1730 g_string_append (list, uris[i]);
1731 g_string_append (list, "\r\n");
1734 result = g_convert (list->str, list->len,
1736 NULL, &length, NULL);
1737 g_string_free (list, TRUE);
1741 gtk_selection_data_set (selection_data,
1743 8, (guchar *)result, length);
1755 * gtk_selection_data_get_uris:
1756 * @selection_data: a #GtkSelectionData
1758 * Gets the contents of the selection data as array of URIs.
1760 * Return value: (array zero-terminated=1) (element-type utf8) (transfer full): if
1761 * the selection data contains a list of
1762 * URIs, a newly allocated %NULL-terminated string array
1763 * containing the URIs, otherwise %NULL. If the result is
1764 * non-%NULL it must be freed with g_strfreev().
1769 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1771 gchar **result = NULL;
1773 g_return_val_if_fail (selection_data != NULL, NULL);
1777 if (selection_data->length >= 0 &&
1778 selection_data->type == text_uri_list_atom)
1781 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1783 selection_data->format,
1784 selection_data->data,
1785 selection_data->length,
1788 result = g_uri_list_extract_uris (list[0]);
1798 * gtk_selection_data_get_targets:
1799 * @selection_data: a #GtkSelectionData object
1800 * @targets: location to store an array of targets. The result
1801 * stored here must be freed with g_free().
1802 * @n_atoms: location to store number of items in @targets.
1804 * Gets the contents of @selection_data as an array of targets.
1805 * This can be used to interpret the results of getting
1806 * the standard TARGETS target that is always supplied for
1809 * Return value: %TRUE if @selection_data contains a valid
1810 * array of targets, otherwise %FALSE.
1813 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1817 g_return_val_if_fail (selection_data != NULL, FALSE);
1819 if (selection_data->length >= 0 &&
1820 selection_data->format == 32 &&
1821 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1824 *targets = g_memdup (selection_data->data, selection_data->length);
1826 *n_atoms = selection_data->length / sizeof (GdkAtom);
1842 * gtk_targets_include_text:
1843 * @targets: an array of #GdkAtom<!-- -->s
1844 * @n_targets: the length of @targets
1846 * Determines if any of the targets in @targets can be used to
1849 * Return value: %TRUE if @targets include a suitable target for text,
1855 gtk_targets_include_text (GdkAtom *targets,
1859 gboolean result = FALSE;
1861 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1863 /* Keep in sync with gtk_target_list_add_text_targets()
1868 for (i = 0; i < n_targets; i++)
1870 if (targets[i] == utf8_atom ||
1871 targets[i] == text_atom ||
1872 targets[i] == GDK_TARGET_STRING ||
1873 targets[i] == ctext_atom ||
1874 targets[i] == text_plain_atom ||
1875 targets[i] == text_plain_utf8_atom ||
1876 targets[i] == text_plain_locale_atom)
1887 * gtk_targets_include_rich_text:
1888 * @targets: an array of #GdkAtom<!-- -->s
1889 * @n_targets: the length of @targets
1890 * @buffer: a #GtkTextBuffer
1892 * Determines if any of the targets in @targets can be used to
1893 * provide rich text.
1895 * Return value: %TRUE if @targets include a suitable target for rich text,
1901 gtk_targets_include_rich_text (GdkAtom *targets,
1903 GtkTextBuffer *buffer)
1905 GdkAtom *rich_targets;
1906 gint n_rich_targets;
1908 gboolean result = FALSE;
1910 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1911 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1915 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1918 for (i = 0; i < n_targets; i++)
1920 for (j = 0; j < n_rich_targets; j++)
1922 if (targets[i] == rich_targets[j])
1931 g_free (rich_targets);
1937 * gtk_selection_data_targets_include_text:
1938 * @selection_data: a #GtkSelectionData object
1940 * Given a #GtkSelectionData object holding a list of targets,
1941 * determines if any of the targets in @targets can be used to
1944 * Return value: %TRUE if @selection_data holds a list of targets,
1945 * and a suitable target for text is included, otherwise %FALSE.
1948 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1952 gboolean result = FALSE;
1954 g_return_val_if_fail (selection_data != NULL, FALSE);
1958 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1960 result = gtk_targets_include_text (targets, n_targets);
1968 * gtk_selection_data_targets_include_rich_text:
1969 * @selection_data: a #GtkSelectionData object
1970 * @buffer: a #GtkTextBuffer
1972 * Given a #GtkSelectionData object holding a list of targets,
1973 * determines if any of the targets in @targets can be used to
1974 * provide rich text.
1976 * Return value: %TRUE if @selection_data holds a list of targets,
1977 * and a suitable target for rich text is included,
1983 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1984 GtkTextBuffer *buffer)
1988 gboolean result = FALSE;
1990 g_return_val_if_fail (selection_data != NULL, FALSE);
1991 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1995 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1997 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2005 * gtk_targets_include_image:
2006 * @targets: an array of #GdkAtom<!-- -->s
2007 * @n_targets: the length of @targets
2008 * @writable: whether to accept only targets for which GTK+ knows
2009 * how to convert a pixbuf into the format
2011 * Determines if any of the targets in @targets can be used to
2012 * provide a #GdkPixbuf.
2014 * Return value: %TRUE if @targets include a suitable target for images,
2020 gtk_targets_include_image (GdkAtom *targets,
2024 GtkTargetList *list;
2027 gboolean result = FALSE;
2029 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2031 list = gtk_target_list_new (NULL, 0);
2032 gtk_target_list_add_image_targets (list, 0, writable);
2033 for (i = 0; i < n_targets && !result; i++)
2035 for (l = list->list; l; l = l->next)
2037 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2038 if (pair->target == targets[i])
2045 gtk_target_list_unref (list);
2051 * gtk_selection_data_targets_include_image:
2052 * @selection_data: a #GtkSelectionData object
2053 * @writable: whether to accept only targets for which GTK+ knows
2054 * how to convert a pixbuf into the format
2056 * Given a #GtkSelectionData object holding a list of targets,
2057 * determines if any of the targets in @targets can be used to
2058 * provide a #GdkPixbuf.
2060 * Return value: %TRUE if @selection_data holds a list of targets,
2061 * and a suitable target for images is included, otherwise %FALSE.
2066 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2071 gboolean result = FALSE;
2073 g_return_val_if_fail (selection_data != NULL, FALSE);
2077 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2079 result = gtk_targets_include_image (targets, n_targets, writable);
2087 * gtk_targets_include_uri:
2088 * @targets: an array of #GdkAtom<!-- -->s
2089 * @n_targets: the length of @targets
2091 * Determines if any of the targets in @targets can be used to
2092 * provide an uri list.
2094 * Return value: %TRUE if @targets include a suitable target for uri lists,
2100 gtk_targets_include_uri (GdkAtom *targets,
2104 gboolean result = FALSE;
2106 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2108 /* Keep in sync with gtk_target_list_add_uri_targets()
2113 for (i = 0; i < n_targets; i++)
2115 if (targets[i] == text_uri_list_atom)
2126 * gtk_selection_data_targets_include_uri:
2127 * @selection_data: a #GtkSelectionData object
2129 * Given a #GtkSelectionData object holding a list of targets,
2130 * determines if any of the targets in @targets can be used to
2131 * provide a list or URIs.
2133 * Return value: %TRUE if @selection_data holds a list of targets,
2134 * and a suitable target for URI lists is included, otherwise %FALSE.
2139 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2143 gboolean result = FALSE;
2145 g_return_val_if_fail (selection_data != NULL, FALSE);
2149 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2151 result = gtk_targets_include_uri (targets, n_targets);
2159 /*************************************************************
2160 * gtk_selection_init:
2161 * Initialize local variables
2165 *************************************************************/
2168 gtk_selection_init (void)
2170 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2171 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2172 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2173 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2174 gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS");
2180 * _gtk_selection_clear:
2181 * @widget: a #GtkWidget
2184 * The default handler for the #GtkWidget::selection-clear-event
2187 * Return value: %TRUE if the event was handled, otherwise false
2190 _gtk_selection_clear (GtkWidget *widget,
2191 GdkEventSelection *event)
2193 /* Note that we filter clear events in gdkselection-x11.c, so
2194 * that we only will get here if the clear event actually
2195 * represents a change that we didn't do ourself.
2198 GtkSelectionInfo *selection_info = NULL;
2200 tmp_list = current_selections;
2203 selection_info = (GtkSelectionInfo *)tmp_list->data;
2205 if ((selection_info->selection == event->selection) &&
2206 (selection_info->widget == widget))
2209 tmp_list = tmp_list->next;
2214 current_selections = g_list_remove_link (current_selections, tmp_list);
2215 g_list_free (tmp_list);
2216 g_slice_free (GtkSelectionInfo, selection_info);
2223 /*************************************************************
2224 * _gtk_selection_request:
2225 * Handler for "selection_request_event"
2230 *************************************************************/
2233 _gtk_selection_request (GtkWidget *widget,
2234 GdkEventSelection *event)
2236 GdkDisplay *display = gtk_widget_get_display (widget);
2240 gulong selection_max_size;
2243 gtk_selection_init ();
2245 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2247 /* Check if we own selection */
2249 tmp_list = current_selections;
2252 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2254 if ((selection_info->selection == event->selection) &&
2255 (selection_info->widget == widget))
2258 tmp_list = tmp_list->next;
2261 if (tmp_list == NULL)
2264 info = g_slice_new (GtkIncrInfo);
2266 g_object_ref (widget);
2268 info->selection = event->selection;
2269 info->num_incrs = 0;
2271 /* Create GdkWindow structure for the requestor */
2273 info->requestor = gdk_window_lookup_for_display (display,
2275 if (!info->requestor)
2276 info->requestor = gdk_window_foreign_new_for_display (display,
2279 /* Determine conversions we need to perform */
2281 if (event->target == gtk_selection_atoms[MULTIPLE])
2290 gdk_error_trap_push ();
2291 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2292 0, selection_max_size, FALSE,
2293 &type, &format, &length, &mult_atoms))
2295 gdk_selection_send_notify_for_display (display,
2301 g_free (mult_atoms);
2302 g_slice_free (GtkIncrInfo, info);
2303 gdk_error_trap_pop ();
2306 gdk_error_trap_pop ();
2308 /* This is annoying; the ICCCM doesn't specify the property type
2309 * used for the property contents, so the autoconversion for
2310 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2312 #ifdef GDK_WINDOWING_X11
2313 if (type != GDK_SELECTION_TYPE_ATOM &&
2314 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2316 info->num_conversions = length / (2*sizeof (glong));
2317 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2319 for (i=0; i<info->num_conversions; i++)
2321 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2322 ((glong *)mult_atoms)[2*i]);
2323 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2324 ((glong *)mult_atoms)[2*i + 1]);
2327 g_free (mult_atoms);
2332 info->num_conversions = length / (2*sizeof (GdkAtom));
2333 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2335 for (i=0; i<info->num_conversions; i++)
2337 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2338 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2341 g_free (mult_atoms);
2344 else /* only a single conversion */
2346 info->conversions = g_new (GtkIncrConversion, 1);
2347 info->num_conversions = 1;
2348 info->conversions[0].target = event->target;
2349 info->conversions[0].property = event->property;
2352 /* Loop through conversions and determine which of these are big
2353 enough to require doing them via INCR */
2354 for (i=0; i<info->num_conversions; i++)
2356 GtkSelectionData data;
2359 data.selection = event->selection;
2360 data.target = info->conversions[i].target;
2363 data.display = gtk_widget_get_display (widget);
2365 #ifdef DEBUG_SELECTION
2366 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2368 info->conversions[i].target,
2369 gdk_atom_name (info->conversions[i].target),
2370 event->requestor, info->conversions[i].property);
2373 gtk_selection_invoke_handler (widget, &data, event->time);
2374 if (data.length < 0)
2376 info->conversions[i].property = GDK_NONE;
2380 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2382 items = data.length / gtk_selection_bytes_per_item (data.format);
2384 if (data.length > selection_max_size)
2386 /* Sending via INCR */
2387 #ifdef DEBUG_SELECTION
2388 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2389 data.length, selection_max_size);
2392 info->conversions[i].offset = 0;
2393 info->conversions[i].data = data;
2396 gdk_property_change (info->requestor,
2397 info->conversions[i].property,
2398 gtk_selection_atoms[INCR],
2400 GDK_PROP_MODE_REPLACE,
2401 (guchar *)&items, 1);
2405 info->conversions[i].offset = -1;
2407 gdk_property_change (info->requestor,
2408 info->conversions[i].property,
2411 GDK_PROP_MODE_REPLACE,
2418 /* If we have some INCR's, we need to send the rest of the data in
2421 if (info->num_incrs > 0)
2423 /* FIXME: this could be dangerous if window doesn't still
2426 #ifdef DEBUG_SELECTION
2427 g_message ("Starting INCR...");
2430 gdk_window_set_events (info->requestor,
2431 gdk_window_get_events (info->requestor) |
2432 GDK_PROPERTY_CHANGE_MASK);
2433 current_incrs = g_list_append (current_incrs, info);
2434 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2437 /* If it was a MULTIPLE request, set the property to indicate which
2438 conversions succeeded */
2439 if (event->target == gtk_selection_atoms[MULTIPLE])
2441 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2442 for (i = 0; i < info->num_conversions; i++)
2444 mult_atoms[2*i] = info->conversions[i].target;
2445 mult_atoms[2*i+1] = info->conversions[i].property;
2448 gdk_property_change (info->requestor, event->property,
2449 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2450 GDK_PROP_MODE_REPLACE,
2451 (guchar *)mult_atoms, 2*info->num_conversions);
2452 g_free (mult_atoms);
2455 if (info->num_conversions == 1 &&
2456 info->conversions[0].property == GDK_NONE)
2458 /* Reject the entire conversion */
2459 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2468 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2476 if (info->num_incrs == 0)
2478 g_free (info->conversions);
2479 g_slice_free (GtkIncrInfo, info);
2482 g_object_unref (widget);
2487 /*************************************************************
2488 * _gtk_selection_incr_event:
2489 * Called whenever an PropertyNotify event occurs for an
2490 * GdkWindow with user_data == NULL. These will be notifications
2491 * that a window we are sending the selection to via the
2492 * INCR protocol has deleted a property and is ready for
2496 * window: the requestor window
2497 * event: the property event structure
2500 *************************************************************/
2503 _gtk_selection_incr_event (GdkWindow *window,
2504 GdkEventProperty *event)
2507 GtkIncrInfo *info = NULL;
2510 gulong selection_max_size;
2514 if (event->state != GDK_PROPERTY_DELETE)
2517 #ifdef DEBUG_SELECTION
2518 g_message ("PropertyDelete, property %ld", event->atom);
2521 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2523 /* Now find the appropriate ongoing INCR */
2524 tmp_list = current_incrs;
2527 info = (GtkIncrInfo *)tmp_list->data;
2528 if (info->requestor == event->window)
2531 tmp_list = tmp_list->next;
2534 if (tmp_list == NULL)
2537 /* Find out which target this is for */
2538 for (i=0; i<info->num_conversions; i++)
2540 if (info->conversions[i].property == event->atom &&
2541 info->conversions[i].offset != -1)
2545 info->idle_time = 0;
2547 if (info->conversions[i].offset == -2) /* only the last 0-length
2555 num_bytes = info->conversions[i].data.length -
2556 info->conversions[i].offset;
2557 buffer = info->conversions[i].data.data +
2558 info->conversions[i].offset;
2560 if (num_bytes > selection_max_size)
2562 num_bytes = selection_max_size;
2563 info->conversions[i].offset += selection_max_size;
2566 info->conversions[i].offset = -2;
2568 #ifdef DEBUG_SELECTION
2569 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2570 num_bytes, info->conversions[i].offset,
2571 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2574 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2575 gdk_property_change (info->requestor, event->atom,
2576 info->conversions[i].data.type,
2577 info->conversions[i].data.format,
2578 GDK_PROP_MODE_REPLACE,
2580 num_bytes / bytes_per_item);
2582 if (info->conversions[i].offset == -2)
2584 g_free (info->conversions[i].data.data);
2585 info->conversions[i].data.data = NULL;
2591 info->conversions[i].offset = -1;
2596 /* Check if we're finished with all the targets */
2598 if (info->num_incrs == 0)
2600 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2601 g_list_free (tmp_list);
2602 /* Let the timeout free it */
2608 /*************************************************************
2609 * gtk_selection_incr_timeout:
2610 * Timeout callback for the sending portion of the INCR
2613 * info: Information about this incr
2615 *************************************************************/
2618 gtk_selection_incr_timeout (GtkIncrInfo *info)
2623 /* Determine if retrieval has finished by checking if it still in
2624 list of pending retrievals */
2626 tmp_list = current_incrs;
2629 if (info == (GtkIncrInfo *)tmp_list->data)
2631 tmp_list = tmp_list->next;
2634 /* If retrieval is finished */
2635 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2637 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2639 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2640 g_list_free (tmp_list);
2643 g_free (info->conversions);
2644 /* FIXME: we should check if requestor window is still in use,
2645 and if not, remove it? */
2647 g_slice_free (GtkIncrInfo, info);
2649 retval = FALSE; /* remove timeout */
2655 retval = TRUE; /* timeout will happen again */
2661 /*************************************************************
2662 * _gtk_selection_notify:
2663 * Handler for "selection-notify-event" signals on windows
2664 * where a retrieval is currently in process. The selection
2665 * owner has responded to our conversion request.
2667 * widget: Widget getting signal
2668 * event: Selection event structure
2669 * info: Information about this retrieval
2671 * was event handled?
2672 *************************************************************/
2675 _gtk_selection_notify (GtkWidget *widget,
2676 GdkEventSelection *event)
2679 GtkRetrievalInfo *info = NULL;
2680 guchar *buffer = NULL;
2685 #ifdef DEBUG_SELECTION
2686 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2687 event->selection, event->target, event->property);
2690 tmp_list = current_retrievals;
2693 info = (GtkRetrievalInfo *)tmp_list->data;
2694 if (info->widget == widget && info->selection == event->selection)
2696 tmp_list = tmp_list->next;
2699 if (!tmp_list) /* no retrieval in progress */
2702 if (event->property != GDK_NONE)
2703 length = gdk_selection_property_get (widget->window, &buffer,
2706 length = 0; /* silence gcc */
2708 if (event->property == GDK_NONE || buffer == NULL)
2710 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2711 g_list_free (tmp_list);
2712 /* structure will be freed in timeout */
2713 gtk_selection_retrieval_report (info,
2714 GDK_NONE, 0, NULL, -1, event->time);
2719 if (type == gtk_selection_atoms[INCR])
2721 /* The remainder of the selection will come through PropertyNotify
2724 info->notify_time = event->time;
2725 info->idle_time = 0;
2726 info->offset = 0; /* Mark as OK to proceed */
2727 gdk_window_set_events (widget->window,
2728 gdk_window_get_events (widget->window)
2729 | GDK_PROPERTY_CHANGE_MASK);
2733 /* We don't delete the info structure - that will happen in timeout */
2734 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2735 g_list_free (tmp_list);
2737 info->offset = length;
2738 gtk_selection_retrieval_report (info,
2740 buffer, length, event->time);
2743 gdk_property_delete (widget->window, event->property);
2750 /*************************************************************
2751 * _gtk_selection_property_notify:
2752 * Handler for "property-notify-event" signals on windows
2753 * where a retrieval is currently in process. The selection
2754 * owner has added more data.
2756 * widget: Widget getting signal
2757 * event: Property event structure
2758 * info: Information about this retrieval
2760 * was event handled?
2761 *************************************************************/
2764 _gtk_selection_property_notify (GtkWidget *widget,
2765 GdkEventProperty *event)
2768 GtkRetrievalInfo *info = NULL;
2774 g_return_val_if_fail (widget != NULL, FALSE);
2775 g_return_val_if_fail (event != NULL, FALSE);
2777 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2778 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2779 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2783 #ifdef DEBUG_SELECTION
2784 g_message ("PropertyNewValue, property %ld",
2788 tmp_list = current_retrievals;
2791 info = (GtkRetrievalInfo *)tmp_list->data;
2792 if (info->widget == widget)
2794 tmp_list = tmp_list->next;
2797 if (!tmp_list) /* No retrieval in progress */
2800 if (info->offset < 0) /* We haven't got the SelectionNotify
2801 for this retrieval yet */
2804 info->idle_time = 0;
2806 length = gdk_selection_property_get (widget->window, &new_buffer,
2808 gdk_property_delete (widget->window, event->atom);
2810 /* We could do a lot better efficiency-wise by paying attention to
2811 what length was sent in the initial INCR transaction, instead of
2812 doing memory allocation at every step. But its only guaranteed to
2813 be a _lower bound_ (pretty useless!) */
2815 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2817 /* Info structure will be freed in timeout */
2818 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2819 g_list_free (tmp_list);
2820 gtk_selection_retrieval_report (info,
2822 (type == GDK_NONE) ? NULL : info->buffer,
2823 (type == GDK_NONE) ? -1 : info->offset,
2826 else /* append on newly arrived data */
2830 #ifdef DEBUG_SELECTION
2831 g_message ("Start - Adding %d bytes at offset 0",
2834 info->buffer = new_buffer;
2835 info->offset = length;
2840 #ifdef DEBUG_SELECTION
2841 g_message ("Appending %d bytes at offset %d",
2842 length,info->offset);
2844 /* We copy length+1 bytes to preserve guaranteed null termination */
2845 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2846 memcpy (info->buffer + info->offset, new_buffer, length+1);
2847 info->offset += length;
2848 g_free (new_buffer);
2855 /*************************************************************
2856 * gtk_selection_retrieval_timeout:
2857 * Timeout callback while receiving a selection.
2859 * info: Information about this retrieval
2861 *************************************************************/
2864 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2869 /* Determine if retrieval has finished by checking if it still in
2870 list of pending retrievals */
2872 tmp_list = current_retrievals;
2875 if (info == (GtkRetrievalInfo *)tmp_list->data)
2877 tmp_list = tmp_list->next;
2880 /* If retrieval is finished */
2881 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2883 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2885 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2886 g_list_free (tmp_list);
2887 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2890 g_free (info->buffer);
2891 g_slice_free (GtkRetrievalInfo, info);
2893 retval = FALSE; /* remove timeout */
2899 retval = TRUE; /* timeout will happen again */
2905 /*************************************************************
2906 * gtk_selection_retrieval_report:
2907 * Emits a "selection-received" signal.
2909 * info: information about the retrieval that completed
2910 * buffer: buffer containing data (NULL => errror)
2911 * time: timestamp for data in buffer
2913 *************************************************************/
2916 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2917 GdkAtom type, gint format,
2918 guchar *buffer, gint length,
2921 GtkSelectionData data;
2923 data.selection = info->selection;
2924 data.target = info->target;
2926 data.format = format;
2928 data.length = length;
2930 data.display = gtk_widget_get_display (info->widget);
2932 g_signal_emit_by_name (info->widget,
2933 "selection-received",
2937 /*************************************************************
2938 * gtk_selection_invoke_handler:
2939 * Finds and invokes handler for specified
2940 * widget/selection/target combination, calls
2941 * gtk_selection_default_handler if none exists.
2944 * widget: selection owner
2945 * data: selection data [INOUT]
2946 * time: time from requeset
2949 * Number of bytes written to buffer, -1 if error
2950 *************************************************************/
2953 gtk_selection_invoke_handler (GtkWidget *widget,
2954 GtkSelectionData *data,
2957 GtkTargetList *target_list;
2961 g_return_if_fail (widget != NULL);
2963 target_list = gtk_selection_target_list_get (widget, data->selection);
2964 if (data->target != gtk_selection_atoms[SAVE_TARGETS] &&
2966 gtk_target_list_find (target_list, data->target, &info))
2968 g_signal_emit_by_name (widget,
2974 gtk_selection_default_handler (widget, data);
2977 /*************************************************************
2978 * gtk_selection_default_handler:
2979 * Handles some default targets that exist for any widget
2980 * If it can't fit results into buffer, returns -1. This
2981 * won't happen in any conceivable case, since it would
2982 * require 1000 selection targets!
2985 * widget: selection owner
2986 * data: selection data [INOUT]
2988 *************************************************************/
2991 gtk_selection_default_handler (GtkWidget *widget,
2992 GtkSelectionData *data)
2994 if (data->target == gtk_selection_atoms[TIMESTAMP])
2996 /* Time which was used to obtain selection */
2998 GtkSelectionInfo *selection_info;
3000 tmp_list = current_selections;
3003 selection_info = (GtkSelectionInfo *)tmp_list->data;
3004 if ((selection_info->widget == widget) &&
3005 (selection_info->selection == data->selection))
3007 gulong time = selection_info->time;
3009 gtk_selection_data_set (data,
3010 GDK_SELECTION_TYPE_INTEGER,
3017 tmp_list = tmp_list->next;
3022 else if (data->target == gtk_selection_atoms[TARGETS])
3024 /* List of all targets supported for this widget/selection pair */
3028 GtkTargetList *target_list;
3029 GtkTargetPair *pair;
3031 target_list = gtk_selection_target_list_get (widget,
3033 count = g_list_length (target_list->list) + 3;
3035 data->type = GDK_SELECTION_TYPE_ATOM;
3037 data->length = count * sizeof (GdkAtom);
3039 /* selection data is always terminated by a trailing \0
3041 p = g_malloc (data->length + 1);
3042 data->data = (guchar *)p;
3043 data->data[data->length] = '\0';
3045 *p++ = gtk_selection_atoms[TIMESTAMP];
3046 *p++ = gtk_selection_atoms[TARGETS];
3047 *p++ = gtk_selection_atoms[MULTIPLE];
3049 tmp_list = target_list->list;
3052 pair = (GtkTargetPair *)tmp_list->data;
3053 *p++ = pair->target;
3055 tmp_list = tmp_list->next;
3058 else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
3060 gtk_selection_data_set (data,
3061 gdk_atom_intern_static_string ("NULL"),
3072 * gtk_selection_data_copy:
3073 * @data: a pointer to a #GtkSelectionData structure.
3075 * Makes a copy of a #GtkSelectionData structure and its data.
3077 * Return value: a pointer to a copy of @data.
3080 gtk_selection_data_copy (GtkSelectionData *data)
3082 GtkSelectionData *new_data;
3084 g_return_val_if_fail (data != NULL, NULL);
3086 new_data = g_slice_new (GtkSelectionData);
3091 new_data->data = g_malloc (data->length + 1);
3092 memcpy (new_data->data, data->data, data->length + 1);
3099 * gtk_selection_data_free:
3100 * @data: a pointer to a #GtkSelectionData structure.
3102 * Frees a #GtkSelectionData structure returned from
3103 * gtk_selection_data_copy().
3106 gtk_selection_data_free (GtkSelectionData *data)
3108 g_return_if_fail (data != NULL);
3110 g_free (data->data);
3112 g_slice_free (GtkSelectionData, data);
3116 gtk_selection_data_get_type (void)
3118 static GType our_type = 0;
3121 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3122 (GBoxedCopyFunc) gtk_selection_data_copy,
3123 (GBoxedFreeFunc) gtk_selection_data_free);
3129 gtk_target_list_get_type (void)
3131 static GType our_type = 0;
3134 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3135 (GBoxedCopyFunc) gtk_target_list_ref,
3136 (GBoxedFreeFunc) gtk_target_list_unref);
3142 gtk_selection_bytes_per_item (gint format)
3147 return sizeof (char);
3150 return sizeof (short);
3153 return sizeof (long);
3156 g_assert_not_reached();
3161 #define __GTK_SELECTION_C__
3162 #include "gtkaliasdef.c"