1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 /* This file implements most of the work of the ICCCM selection protocol.
21 * The code was written after an intensive study of the equivalent part
22 * of John Ousterhout's Tk toolkit, and does many things in much the
25 * The one thing in the ICCCM that isn't fully supported here (or in Tk)
26 * is side effects targets. For these to be handled properly, MULTIPLE
27 * targets need to be done in the order specified. This cannot be
28 * guaranteed with the way we do things, since if we are doing INCR
29 * transfers, the order will depend on the timing of the requestor.
31 * By Owen Taylor <owt1@cornell.edu> 8/16/97
34 /* Terminology note: when not otherwise specified, the term "incr" below
35 * refers to the _sending_ part of the INCR protocol. The receiving
36 * portion is referred to just as "retrieval". (Terminology borrowed
37 * from Tk, because there is no good opposite to "retrieval" in English.
38 * "send" can't be made into a noun gracefully and we're already using
39 * "emission" for something else ....)
42 /* The MOTIF entry widget seems to ask for the TARGETS target, then
43 (regardless of the reply) ask for the TEXT target. It's slightly
44 possible though that it somehow thinks we are responding negatively
45 to the TARGETS request, though I don't really think so ... */
48 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
49 * file for a list of people on the GTK+ Team. See the ChangeLog
50 * files for a list of changes. These files are distributed with
51 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
60 #include "gtkselection.h"
61 #include "gtktextbufferrichtext.h"
63 #include "gdk-pixbuf/gdk-pixbuf.h"
65 #ifdef GDK_WINDOWING_X11
69 #ifdef GDK_WINDOWING_WIN32
70 #include "win32/gdkwin32.h"
75 #undef DEBUG_SELECTION
77 /* Maximum size of a sent chunk, in bytes. Also the default size of
79 #ifdef GDK_WINDOWING_X11
80 #define GTK_SELECTION_MAX_SIZE(display) \
82 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
83 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
84 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
86 /* No chunks on Win32 */
87 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
90 #define IDLE_ABORT_TIME 30
100 typedef struct _GtkSelectionInfo GtkSelectionInfo;
101 typedef struct _GtkIncrConversion GtkIncrConversion;
102 typedef struct _GtkIncrInfo GtkIncrInfo;
103 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
105 struct _GtkSelectionInfo
108 GtkWidget *widget; /* widget that owns selection */
109 guint32 time; /* time used to acquire selection */
110 GdkDisplay *display; /* needed in gtk_selection_remove_all */
113 struct _GtkIncrConversion
115 GdkAtom target; /* Requested target */
116 GdkAtom property; /* Property to store in */
117 GtkSelectionData data; /* The data being supplied */
118 gint offset; /* Current offset in sent selection.
120 * -2 => Only the final (empty) portion
126 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
127 so we can receive events */
128 GdkAtom selection; /* Selection we're sending */
130 GtkIncrConversion *conversions; /* Information about requested conversions -
131 * With MULTIPLE requests (benighted 1980's
132 * hardware idea), there can be more than
134 gint num_conversions;
135 gint num_incrs; /* number of remaining INCR style transactions */
140 struct _GtkRetrievalInfo
143 GdkAtom selection; /* Selection being retrieved. */
144 GdkAtom target; /* Form of selection that we requested */
145 guint32 idle_time; /* Number of seconds since we last heard
146 from selection owner */
147 guchar *buffer; /* Buffer in which to accumulate results */
148 gint offset; /* Current offset in buffer, -1 indicates
150 guint32 notify_time; /* Timestamp from SelectionNotify */
153 /* Local Functions */
154 static void gtk_selection_init (void);
155 static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info);
156 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
157 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
163 static void gtk_selection_invoke_handler (GtkWidget *widget,
164 GtkSelectionData *data,
166 static void gtk_selection_default_handler (GtkWidget *widget,
167 GtkSelectionData *data);
168 static int gtk_selection_bytes_per_item (gint format);
171 static gint initialize = TRUE;
172 static GList *current_retrievals = NULL;
173 static GList *current_incrs = NULL;
174 static GList *current_selections = NULL;
176 static GdkAtom gtk_selection_atoms[LAST_ATOM];
177 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
189 * gtk_target_list_new:
190 * @targets: Pointer to an array of #GtkTargetEntry
191 * @ntargets: number of entries in @targets.
193 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
195 * Return value: the new #GtkTargetList.
198 gtk_target_list_new (const GtkTargetEntry *targets,
201 GtkTargetList *result = g_slice_new (GtkTargetList);
203 result->ref_count = 1;
206 gtk_target_list_add_table (result, targets, ntargets);
212 * gtk_target_list_ref:
213 * @list: a #GtkTargetList
215 * Increases the reference count of a #GtkTargetList by one.
217 * Return value: the passed in #GtkTargetList.
220 gtk_target_list_ref (GtkTargetList *list)
222 g_return_val_if_fail (list != NULL, NULL);
230 * gtk_target_list_unref:
231 * @list: a #GtkTargetList
233 * Decreases the reference count of a #GtkTargetList by one.
234 * If the resulting reference count is zero, frees the list.
237 gtk_target_list_unref (GtkTargetList *list)
239 g_return_if_fail (list != NULL);
240 g_return_if_fail (list->ref_count > 0);
243 if (list->ref_count == 0)
245 GList *tmp_list = list->list;
248 GtkTargetPair *pair = tmp_list->data;
249 g_slice_free (GtkTargetPair, pair);
251 tmp_list = tmp_list->next;
254 g_list_free (list->list);
255 g_slice_free (GtkTargetList, list);
260 * gtk_target_list_add:
261 * @list: a #GtkTargetList
262 * @target: the interned atom representing the target
263 * @flags: the flags for this target
264 * @info: an ID that will be passed back to the application
266 * Appends another target to a #GtkTargetList.
269 gtk_target_list_add (GtkTargetList *list,
276 g_return_if_fail (list != NULL);
278 pair = g_slice_new (GtkTargetPair);
279 pair->target = target;
283 list->list = g_list_append (list->list, pair);
286 static GdkAtom utf8_atom;
287 static GdkAtom text_atom;
288 static GdkAtom ctext_atom;
289 static GdkAtom text_plain_atom;
290 static GdkAtom text_plain_utf8_atom;
291 static GdkAtom text_plain_locale_atom;
292 static GdkAtom text_uri_list_atom;
298 const gchar *charset;
302 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
303 text_atom = gdk_atom_intern_static_string ("TEXT");
304 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
305 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
306 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
307 g_get_charset (&charset);
308 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
309 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
312 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
317 * gtk_target_list_add_text_targets:
318 * @list: a #GtkTargetList
319 * @info: an ID that will be passed back to the application
321 * Appends the text targets supported by #GtkSelection to
322 * the target list. All targets are added with the same @info.
327 gtk_target_list_add_text_targets (GtkTargetList *list,
330 g_return_if_fail (list != NULL);
334 /* Keep in sync with gtk_selection_data_targets_include_text()
336 gtk_target_list_add (list, utf8_atom, 0, info);
337 gtk_target_list_add (list, ctext_atom, 0, info);
338 gtk_target_list_add (list, text_atom, 0, info);
339 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
340 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
341 if (!g_get_charset (NULL))
342 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
343 gtk_target_list_add (list, text_plain_atom, 0, info);
347 * gtk_target_list_add_rich_text_targets:
348 * @list: a #GtkTargetList
349 * @info: an ID that will be passed back to the application
350 * @deserializable: if %TRUE, then deserializable rich text formats
351 * will be added, serializable formats otherwise.
352 * @buffer: a #GtkTextBuffer.
354 * Appends the rich text targets registered with
355 * gtk_text_buffer_register_serialize_format() or
356 * gtk_text_buffer_register_deserialize_format() to the target list. All
357 * targets are added with the same @info.
362 gtk_target_list_add_rich_text_targets (GtkTargetList *list,
364 gboolean deserializable,
365 GtkTextBuffer *buffer)
371 g_return_if_fail (list != NULL);
372 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
375 atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
377 atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
379 for (i = 0; i < n_atoms; i++)
380 gtk_target_list_add (list, atoms[i], 0, info);
386 * gtk_target_list_add_image_targets:
387 * @list: a #GtkTargetList
388 * @info: an ID that will be passed back to the application
389 * @writable: whether to add only targets for which GTK+ knows
390 * how to convert a pixbuf into the format
392 * Appends the image targets supported by #GtkSelection to
393 * the target list. All targets are added with the same @info.
398 gtk_target_list_add_image_targets (GtkTargetList *list,
406 g_return_if_fail (list != NULL);
408 formats = gdk_pixbuf_get_formats ();
410 /* Make sure png comes first */
411 for (f = formats; f; f = f->next)
413 GdkPixbufFormat *fmt = f->data;
416 name = gdk_pixbuf_format_get_name (fmt);
417 if (strcmp (name, "png") == 0)
419 formats = g_slist_delete_link (formats, f);
420 formats = g_slist_prepend (formats, fmt);
430 for (f = formats; f; f = f->next)
432 GdkPixbufFormat *fmt = f->data;
434 if (writable && !gdk_pixbuf_format_is_writable (fmt))
437 mimes = gdk_pixbuf_format_get_mime_types (fmt);
438 for (m = mimes; *m; m++)
440 atom = gdk_atom_intern (*m, FALSE);
441 gtk_target_list_add (list, atom, 0, info);
446 g_slist_free (formats);
450 * gtk_target_list_add_uri_targets:
451 * @list: a #GtkTargetList
452 * @info: an ID that will be passed back to the application
454 * Appends the URI targets supported by #GtkSelection to
455 * the target list. All targets are added with the same @info.
460 gtk_target_list_add_uri_targets (GtkTargetList *list,
463 g_return_if_fail (list != NULL);
467 gtk_target_list_add (list, text_uri_list_atom, 0, info);
471 * gtk_target_list_add_table:
472 * @list: a #GtkTargetList
473 * @targets: the table of #GtkTargetEntry
474 * @ntargets: number of targets in the table
476 * Prepends a table of #GtkTargetEntry to a target list.
479 gtk_target_list_add_table (GtkTargetList *list,
480 const GtkTargetEntry *targets,
485 for (i=ntargets-1; i >= 0; i--)
487 GtkTargetPair *pair = g_slice_new (GtkTargetPair);
488 pair->target = gdk_atom_intern (targets[i].target, FALSE);
489 pair->flags = targets[i].flags;
490 pair->info = targets[i].info;
492 list->list = g_list_prepend (list->list, pair);
497 * gtk_target_list_remove:
498 * @list: a #GtkTargetList
499 * @target: the interned atom representing the target
501 * Removes a target from a target list.
504 gtk_target_list_remove (GtkTargetList *list,
509 g_return_if_fail (list != NULL);
511 tmp_list = list->list;
514 GtkTargetPair *pair = tmp_list->data;
516 if (pair->target == target)
518 g_slice_free (GtkTargetPair, pair);
520 list->list = g_list_remove_link (list->list, tmp_list);
521 g_list_free_1 (tmp_list);
526 tmp_list = tmp_list->next;
531 * gtk_target_list_find:
532 * @list: a #GtkTargetList
533 * @target: an interned atom representing the target to search for
534 * @info: a pointer to the location to store application info for target,
537 * Looks up a given target in a #GtkTargetList.
539 * Return value: %TRUE if the target was found, otherwise %FALSE
542 gtk_target_list_find (GtkTargetList *list,
548 g_return_val_if_fail (list != NULL, FALSE);
550 tmp_list = list->list;
553 GtkTargetPair *pair = tmp_list->data;
555 if (pair->target == target)
563 tmp_list = tmp_list->next;
570 * gtk_target_table_new_from_list:
571 * @list: a #GtkTargetList
572 * @n_targets: return location for the number ot targets in the table
574 * This function creates an #GtkTargetEntry array that contains the
575 * same targets as the passed %list. The returned table is newly
576 * allocated and should be freed using gtk_target_table_free() when no
579 * Return value: the new table.
584 gtk_target_table_new_from_list (GtkTargetList *list,
587 GtkTargetEntry *targets;
591 g_return_val_if_fail (list != NULL, NULL);
592 g_return_val_if_fail (n_targets != NULL, NULL);
594 *n_targets = g_list_length (list->list);
595 targets = g_new0 (GtkTargetEntry, *n_targets);
597 for (i = 0, tmp_list = list->list;
599 i++, tmp_list = g_list_next (tmp_list))
601 GtkTargetPair *pair = tmp_list->data;
603 targets[i].target = gdk_atom_name (pair->target);
604 targets[i].flags = pair->flags;
605 targets[i].info = pair->info;
612 * gtk_target_table_free:
613 * @targets: a #GtkTargetEntry array
614 * @n_targets: the number of entries in the array
616 * This function frees a target table as returned by
617 * gtk_target_table_new_from_list()
622 gtk_target_table_free (GtkTargetEntry *targets,
627 g_return_if_fail (targets == NULL || n_targets > 0);
629 for (i = 0; i < n_targets; i++)
630 g_free (targets[i].target);
636 * gtk_selection_owner_set_for_display:
637 * @display: the #Gdkdisplay where the selection is set
638 * @widget: new selection owner (a #GdkWidget), or %NULL.
639 * @selection: an interned atom representing the selection to claim.
640 * @time_: timestamp with which to claim the selection
642 * Claim ownership of a given selection for a particular widget, or,
643 * if @widget is %NULL, release ownership of the selection.
645 * Return value: TRUE if the operation succeeded
650 gtk_selection_owner_set_for_display (GdkDisplay *display,
656 GtkWidget *old_owner;
657 GtkSelectionInfo *selection_info = NULL;
660 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
661 g_return_val_if_fail (selection != GDK_NONE, FALSE);
662 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
663 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
668 window = widget->window;
670 tmp_list = current_selections;
673 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
675 selection_info = tmp_list->data;
679 tmp_list = tmp_list->next;
682 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
690 old_owner = selection_info->widget;
691 current_selections = g_list_remove_link (current_selections,
693 g_list_free (tmp_list);
694 g_slice_free (GtkSelectionInfo, selection_info);
699 if (selection_info == NULL)
701 selection_info = g_slice_new (GtkSelectionInfo);
702 selection_info->selection = selection;
703 selection_info->widget = widget;
704 selection_info->time = time;
705 selection_info->display = display;
706 current_selections = g_list_prepend (current_selections,
711 old_owner = selection_info->widget;
712 selection_info->widget = widget;
713 selection_info->time = time;
714 selection_info->display = display;
717 /* If another widget in the application lost the selection,
718 * send it a GDK_SELECTION_CLEAR event.
720 if (old_owner && old_owner != widget)
722 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
724 event->selection.window = g_object_ref (old_owner->window);
725 event->selection.selection = selection;
726 event->selection.time = time;
728 gtk_widget_event (old_owner, event);
730 gdk_event_free (event);
739 * gtk_selection_owner_set:
740 * @widget: a #GtkWidget, or %NULL.
741 * @selection: an interned atom representing the selection to claim
742 * @time_: timestamp with which to claim the selection
744 * Claims ownership of a given selection for a particular widget,
745 * or, if @widget is %NULL, release ownership of the selection.
747 * Return value: %TRUE if the operation succeeded
750 gtk_selection_owner_set (GtkWidget *widget,
756 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
757 g_return_val_if_fail (selection != GDK_NONE, FALSE);
760 display = gtk_widget_get_display (widget);
764 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
766 display = gdk_display_get_default ();
769 return gtk_selection_owner_set_for_display (display, widget,
773 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
775 struct _GtkSelectionTargetList {
780 static GtkTargetList *
781 gtk_selection_target_list_get (GtkWidget *widget,
784 GtkSelectionTargetList *sellist;
788 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
793 sellist = tmp_list->data;
794 if (sellist->selection == selection)
795 return sellist->list;
796 tmp_list = tmp_list->next;
799 sellist = g_slice_new (GtkSelectionTargetList);
800 sellist->selection = selection;
801 sellist->list = gtk_target_list_new (NULL, 0);
803 lists = g_list_prepend (lists, sellist);
804 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
806 return sellist->list;
810 gtk_selection_target_list_remove (GtkWidget *widget)
812 GtkSelectionTargetList *sellist;
816 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
821 sellist = tmp_list->data;
823 gtk_target_list_unref (sellist->list);
825 g_slice_free (GtkSelectionTargetList, sellist);
826 tmp_list = tmp_list->next;
830 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
834 * gtk_selection_clear_targets:
835 * @widget: a #GtkWidget
836 * @selection: an atom representing a selection
838 * Remove all targets registered for the given selection for the
842 gtk_selection_clear_targets (GtkWidget *widget,
845 GtkSelectionTargetList *sellist;
849 g_return_if_fail (GTK_IS_WIDGET (widget));
850 g_return_if_fail (selection != GDK_NONE);
852 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
857 sellist = tmp_list->data;
858 if (sellist->selection == selection)
860 lists = g_list_delete_link (lists, tmp_list);
861 gtk_target_list_unref (sellist->list);
862 g_slice_free (GtkSelectionTargetList, sellist);
867 tmp_list = tmp_list->next;
870 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
874 * gtk_selection_add_target:
875 * @widget: a #GtkTarget
876 * @selection: the selection
877 * @target: target to add.
878 * @info: A unsigned integer which will be passed back to the application.
880 * Appends a specified target to the list of supported targets for a
881 * given widget and selection.
884 gtk_selection_add_target (GtkWidget *widget,
891 g_return_if_fail (GTK_IS_WIDGET (widget));
892 g_return_if_fail (selection != GDK_NONE);
894 list = gtk_selection_target_list_get (widget, selection);
895 gtk_target_list_add (list, target, 0, info);
896 #ifdef GDK_WINDOWING_WIN32
897 gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
902 * gtk_selection_add_targets:
903 * @widget: a #GtkWidget
904 * @selection: the selection
905 * @targets: a table of targets to add
906 * @ntargets: number of entries in @targets
908 * Prepends a table of targets to the list of supported targets
909 * for a given widget and selection.
912 gtk_selection_add_targets (GtkWidget *widget,
914 const GtkTargetEntry *targets,
919 g_return_if_fail (GTK_IS_WIDGET (widget));
920 g_return_if_fail (selection != GDK_NONE);
921 g_return_if_fail (targets != NULL);
923 list = gtk_selection_target_list_get (widget, selection);
924 gtk_target_list_add_table (list, targets, ntargets);
926 #ifdef GDK_WINDOWING_WIN32
929 GdkAtom *atoms = g_new (GdkAtom, ntargets);
931 for (i = 0; i < ntargets; ++i)
932 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
933 gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
941 * gtk_selection_remove_all:
942 * @widget: a #GtkWidget
944 * Removes all handlers and unsets ownership of all
945 * selections for a widget. Called when widget is being
946 * destroyed. This function will not generally be
947 * called by applications.
950 gtk_selection_remove_all (GtkWidget *widget)
954 GtkSelectionInfo *selection_info;
956 g_return_if_fail (GTK_IS_WIDGET (widget));
958 /* Remove pending requests/incrs for this widget */
960 tmp_list = current_retrievals;
963 next = tmp_list->next;
964 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
966 current_retrievals = g_list_remove_link (current_retrievals,
968 /* structure will be freed in timeout */
969 g_list_free (tmp_list);
974 /* Disclaim ownership of any selections */
976 tmp_list = current_selections;
979 next = tmp_list->next;
980 selection_info = (GtkSelectionInfo *)tmp_list->data;
982 if (selection_info->widget == widget)
984 gdk_selection_owner_set_for_display (selection_info->display,
986 selection_info->selection,
987 GDK_CURRENT_TIME, FALSE);
988 current_selections = g_list_remove_link (current_selections,
990 g_list_free (tmp_list);
991 g_slice_free (GtkSelectionInfo, selection_info);
997 /* Remove all selection lists */
998 gtk_selection_target_list_remove (widget);
1003 * gtk_selection_convert:
1004 * @widget: The widget which acts as requestor
1005 * @selection: Which selection to get
1006 * @target: Form of information desired (e.g., STRING)
1007 * @time_: Time of request (usually of triggering event)
1008 In emergency, you could use #GDK_CURRENT_TIME
1010 * Requests the contents of a selection. When received,
1011 * a "selection_received" signal will be generated.
1013 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1014 * request. (e.g., there was already a request in process for
1018 gtk_selection_convert (GtkWidget *widget,
1023 GtkRetrievalInfo *info;
1025 GdkWindow *owner_window;
1026 GdkDisplay *display;
1028 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1029 g_return_val_if_fail (selection != GDK_NONE, FALSE);
1032 gtk_selection_init ();
1034 if (!GTK_WIDGET_REALIZED (widget))
1035 gtk_widget_realize (widget);
1037 /* Check to see if there are already any retrievals in progress for
1038 this widget. If we changed GDK to use the selection for the
1039 window property in which to store the retrieved information, then
1040 we could support multiple retrievals for different selections.
1041 This might be useful for DND. */
1043 tmp_list = current_retrievals;
1046 info = (GtkRetrievalInfo *)tmp_list->data;
1047 if (info->widget == widget)
1049 tmp_list = tmp_list->next;
1052 info = g_slice_new (GtkRetrievalInfo);
1054 info->widget = widget;
1055 info->selection = selection;
1056 info->target = target;
1057 info->idle_time = 0;
1058 info->buffer = NULL;
1061 /* Check if this process has current owner. If so, call handler
1062 procedure directly to avoid deadlocks with INCR. */
1064 display = gtk_widget_get_display (widget);
1065 owner_window = gdk_selection_owner_get_for_display (display, selection);
1067 if (owner_window != NULL)
1069 GtkWidget *owner_widget;
1070 GtkSelectionData selection_data;
1072 selection_data.selection = selection;
1073 selection_data.target = target;
1074 selection_data.data = NULL;
1075 selection_data.length = -1;
1076 selection_data.display = display;
1078 gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget);
1080 if (owner_widget != NULL)
1082 gtk_selection_invoke_handler (owner_widget,
1086 gtk_selection_retrieval_report (info,
1087 selection_data.type,
1088 selection_data.format,
1089 selection_data.data,
1090 selection_data.length,
1093 g_free (selection_data.data);
1094 selection_data.data = NULL;
1095 selection_data.length = -1;
1097 g_slice_free (GtkRetrievalInfo, info);
1102 /* Otherwise, we need to go through X */
1104 current_retrievals = g_list_append (current_retrievals, info);
1105 gdk_selection_convert (widget->window, selection, target, time_);
1106 gdk_threads_add_timeout (1000,
1107 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1113 * gtk_selection_data_get_target:
1114 * @selection_data: a pointer to a #GtkSelectionData structure.
1116 * Retrieves the target of the selection.
1121 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1123 g_return_val_if_fail (selection_data != NULL, 0);
1125 return selection_data->target;
1129 * gtk_selection_data_get_data_type:
1130 * @selection_data: a pointer to a #GtkSelectionData structure.
1132 * Retrieves the data type of the selection.
1137 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1139 g_return_val_if_fail (selection_data != NULL, 0);
1141 return selection_data->type;
1145 * gtk_selection_data_get_format:
1146 * @selection_data: a pointer to a #GtkSelectionData structure.
1148 * Retrieves the format of the selection.
1153 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1155 g_return_val_if_fail (selection_data != NULL, 0);
1157 return selection_data->format;
1161 * gtk_selection_data_get_data:
1162 * @selection_data: a pointer to a #GtkSelectionData structure.
1163 * @length: an integer to be filled in, or %NULL
1165 * Retrieves the raw data of the selection.
1167 * If @length is not %NULL it is filled with the length of data.
1172 gtk_selection_data_get_data (GtkSelectionData *selection_data,
1175 g_return_val_if_fail (selection_data != NULL, NULL);
1178 *length = selection_data->length;
1180 return selection_data->data;
1184 * gtk_selection_data_get_display:
1185 * @selection_data: a pointer to a #GtkSelectionData structure.
1187 * Retrieves the display of the selection.
1192 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1194 g_return_val_if_fail (selection_data != NULL, NULL);
1196 return selection_data->display;
1200 * gtk_selection_data_set:
1201 * @selection_data: a pointer to a #GtkSelectionData structure.
1202 * @type: the type of selection data
1203 * @format: format (number of bits in a unit)
1204 * @data: pointer to the data (will be copied)
1205 * @length: length of the data
1207 * Stores new data into a #GtkSelectionData object. Should
1208 * <emphasis>only</emphasis> be called from a selection handler callback.
1209 * Zero-terminates the stored data.
1212 gtk_selection_data_set (GtkSelectionData *selection_data,
1218 g_return_if_fail (selection_data != NULL);
1220 g_free (selection_data->data);
1222 selection_data->type = type;
1223 selection_data->format = format;
1227 selection_data->data = g_new (guchar, length+1);
1228 memcpy (selection_data->data, data, length);
1229 selection_data->data[length] = 0;
1233 g_return_if_fail (length <= 0);
1236 selection_data->data = NULL;
1238 selection_data->data = (guchar *) g_strdup ("");
1241 selection_data->length = length;
1245 selection_set_string (GtkSelectionData *selection_data,
1249 gchar *tmp = g_strndup (str, len);
1250 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1255 gtk_selection_data_set (selection_data,
1256 GDK_SELECTION_TYPE_STRING,
1257 8, (guchar *) latin1, strlen (latin1));
1267 selection_set_compound_text (GtkSelectionData *selection_data,
1276 gboolean result = FALSE;
1278 tmp = g_strndup (str, len);
1279 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1280 &encoding, &format, &text, &new_length))
1282 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1283 gdk_free_compound_text (text);
1293 /* Normalize \r and \n into \r\n
1296 normalize_to_crlf (const gchar *str,
1299 GString *result = g_string_sized_new (len);
1300 const gchar *p = str;
1301 const gchar *end = str + len;
1306 g_string_append_c (result, '\r');
1310 g_string_append_c (result, *p);
1312 if (p == end || *p != '\n')
1313 g_string_append_c (result, '\n');
1318 g_string_append_c (result, *p);
1322 return g_string_free (result, FALSE);
1325 /* Normalize \r and \r\n into \n
1328 normalize_to_lf (gchar *str,
1331 GString *result = g_string_sized_new (len);
1332 const gchar *p = str;
1340 g_string_append_c (result, '\n');
1346 g_string_append_c (result, *p);
1350 return g_string_free (result, FALSE);
1354 selection_set_text_plain (GtkSelectionData *selection_data,
1358 const gchar *charset = NULL;
1360 GError *error = NULL;
1362 result = normalize_to_crlf (str, len);
1363 if (selection_data->target == text_plain_atom)
1365 else if (selection_data->target == text_plain_locale_atom)
1366 g_get_charset (&charset);
1370 gchar *tmp = result;
1371 result = g_convert_with_fallback (tmp, -1,
1373 NULL, NULL, NULL, &error);
1379 g_warning ("Error converting from %s to %s: %s",
1380 "UTF-8", charset, error->message);
1381 g_error_free (error);
1386 gtk_selection_data_set (selection_data,
1387 selection_data->target,
1388 8, (guchar *) result, strlen (result));
1395 selection_get_text_plain (GtkSelectionData *selection_data)
1397 const gchar *charset = NULL;
1398 gchar *str, *result;
1400 GError *error = NULL;
1402 str = g_strdup ((const gchar *) selection_data->data);
1403 len = selection_data->length;
1405 if (selection_data->type == text_plain_atom)
1406 charset = "ISO-8859-1";
1407 else if (selection_data->type == text_plain_locale_atom)
1408 g_get_charset (&charset);
1413 str = g_convert_with_fallback (tmp, len,
1415 NULL, NULL, &len, &error);
1420 g_warning ("Error converting from %s to %s: %s",
1421 charset, "UTF-8", error->message);
1422 g_error_free (error);
1427 else if (!g_utf8_validate (str, -1, NULL))
1429 g_warning ("Error converting from %s to %s: %s",
1430 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1436 result = normalize_to_lf (str, len);
1439 return (guchar *) result;
1443 * gtk_selection_data_set_text:
1444 * @selection_data: a #GtkSelectionData
1445 * @str: a UTF-8 string
1446 * @len: the length of @str, or -1 if @str is nul-terminated.
1448 * Sets the contents of the selection from a UTF-8 encoded string.
1449 * The string is converted to the form determined by
1450 * @selection_data->target.
1452 * Return value: %TRUE if the selection was successfully set,
1456 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1460 g_return_val_if_fail (selection_data != NULL, FALSE);
1467 if (selection_data->target == utf8_atom)
1469 gtk_selection_data_set (selection_data,
1471 8, (guchar *)str, len);
1474 else if (selection_data->target == GDK_TARGET_STRING)
1476 return selection_set_string (selection_data, str, len);
1478 else if (selection_data->target == ctext_atom ||
1479 selection_data->target == text_atom)
1481 if (selection_set_compound_text (selection_data, str, len))
1483 else if (selection_data->target == text_atom)
1484 return selection_set_string (selection_data, str, len);
1486 else if (selection_data->target == text_plain_atom ||
1487 selection_data->target == text_plain_utf8_atom ||
1488 selection_data->target == text_plain_locale_atom)
1490 return selection_set_text_plain (selection_data, str, len);
1497 * gtk_selection_data_get_text:
1498 * @selection_data: a #GtkSelectionData
1500 * Gets the contents of the selection data as a UTF-8 string.
1502 * Return value: if the selection data contained a recognized
1503 * text type and it could be converted to UTF-8, a newly allocated
1504 * string containing the converted text, otherwise %NULL.
1505 * If the result is non-%NULL it must be freed with g_free().
1508 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1510 guchar *result = NULL;
1512 g_return_val_if_fail (selection_data != NULL, NULL);
1516 if (selection_data->length >= 0 &&
1517 (selection_data->type == GDK_TARGET_STRING ||
1518 selection_data->type == ctext_atom ||
1519 selection_data->type == utf8_atom))
1523 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1524 selection_data->type,
1525 selection_data->format,
1526 selection_data->data,
1527 selection_data->length,
1530 result = (guchar *) list[0];
1532 for (i = 1; i < count; i++)
1536 else if (selection_data->length >= 0 &&
1537 (selection_data->type == text_plain_atom ||
1538 selection_data->type == text_plain_utf8_atom ||
1539 selection_data->type == text_plain_locale_atom))
1541 result = selection_get_text_plain (selection_data);
1548 * gtk_selection_data_set_pixbuf:
1549 * @selection_data: a #GtkSelectionData
1550 * @pixbuf: a #GdkPixbuf
1552 * Sets the contents of the selection from a #GdkPixbuf
1553 * The pixbuf is converted to the form determined by
1554 * @selection_data->target.
1556 * Return value: %TRUE if the selection was successfully set,
1562 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1565 GSList *formats, *f;
1572 g_return_val_if_fail (selection_data != NULL, FALSE);
1573 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1575 formats = gdk_pixbuf_get_formats ();
1577 for (f = formats; f; f = f->next)
1579 GdkPixbufFormat *fmt = f->data;
1581 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1582 for (m = mimes; *m; m++)
1584 atom = gdk_atom_intern (*m, FALSE);
1585 if (selection_data->target == atom)
1588 type = gdk_pixbuf_format_get_name (fmt);
1589 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1591 ((strcmp (type, "png") == 0) ?
1592 "compression" : NULL), "2",
1595 gtk_selection_data_set (selection_data,
1596 atom, 8, (guchar *)str, len);
1600 g_slist_free (formats);
1609 g_slist_free (formats);
1615 * gtk_selection_data_get_pixbuf:
1616 * @selection_data: a #GtkSelectionData
1618 * Gets the contents of the selection data as a #GdkPixbuf.
1620 * Return value: if the selection data contained a recognized
1621 * image type and it could be converted to a #GdkPixbuf, a
1622 * newly allocated pixbuf is returned, otherwise %NULL.
1623 * If the result is non-%NULL it must be freed with g_object_unref().
1628 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1630 GdkPixbufLoader *loader;
1631 GdkPixbuf *result = NULL;
1633 g_return_val_if_fail (selection_data != NULL, NULL);
1635 if (selection_data->length > 0)
1637 loader = gdk_pixbuf_loader_new ();
1639 gdk_pixbuf_loader_write (loader,
1640 selection_data->data,
1641 selection_data->length,
1643 gdk_pixbuf_loader_close (loader, NULL);
1644 result = gdk_pixbuf_loader_get_pixbuf (loader);
1647 g_object_ref (result);
1649 g_object_unref (loader);
1656 * gtk_selection_data_set_uris:
1657 * @selection_data: a #GtkSelectionData
1658 * @uris: a %NULL-terminated array of strings hilding URIs
1660 * Sets the contents of the selection from a list of URIs.
1661 * The string is converted to the form determined by
1662 * @selection_data->target.
1664 * Return value: %TRUE if the selection was successfully set,
1670 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1673 g_return_val_if_fail (selection_data != NULL, FALSE);
1674 g_return_val_if_fail (uris != NULL, FALSE);
1678 if (selection_data->target == text_uri_list_atom)
1685 list = g_string_new (NULL);
1686 for (i = 0; uris[i]; i++)
1688 g_string_append (list, uris[i]);
1689 g_string_append (list, "\r\n");
1692 result = g_convert (list->str, list->len,
1694 NULL, &length, NULL);
1695 g_string_free (list, TRUE);
1699 gtk_selection_data_set (selection_data,
1701 8, (guchar *)result, length);
1713 * gtk_selection_data_get_uris:
1714 * @selection_data: a #GtkSelectionData
1716 * Gets the contents of the selection data as array of URIs.
1718 * Return value: if the selection data contains a list of
1719 * URIs, a newly allocated %NULL-terminated string array
1720 * containing the URIs, otherwise %NULL. If the result is
1721 * non-%NULL it must be freed with g_strfreev().
1726 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1728 gchar **result = NULL;
1730 g_return_val_if_fail (selection_data != NULL, NULL);
1734 if (selection_data->length >= 0 &&
1735 selection_data->type == text_uri_list_atom)
1738 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1740 selection_data->format,
1741 selection_data->data,
1742 selection_data->length,
1745 result = g_uri_list_extract_uris (list[0]);
1755 * gtk_selection_data_get_targets:
1756 * @selection_data: a #GtkSelectionData object
1757 * @targets: location to store an array of targets. The result
1758 * stored here must be freed with g_free().
1759 * @n_atoms: location to store number of items in @targets.
1761 * Gets the contents of @selection_data as an array of targets.
1762 * This can be used to interpret the results of getting
1763 * the standard TARGETS target that is always supplied for
1766 * Return value: %TRUE if @selection_data contains a valid
1767 * array of targets, otherwise %FALSE.
1770 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1774 g_return_val_if_fail (selection_data != NULL, FALSE);
1776 if (selection_data->length >= 0 &&
1777 selection_data->format == 32 &&
1778 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1781 *targets = g_memdup (selection_data->data, selection_data->length);
1783 *n_atoms = selection_data->length / sizeof (GdkAtom);
1799 * gtk_targets_include_text:
1800 * @targets: an array of #GdkAtom<!-- -->s
1801 * @n_targets: the length of @targets
1803 * Determines if any of the targets in @targets can be used to
1806 * Return value: %TRUE if @targets include a suitable target for text,
1812 gtk_targets_include_text (GdkAtom *targets,
1816 gboolean result = FALSE;
1818 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1820 /* Keep in sync with gtk_target_list_add_text_targets()
1825 for (i = 0; i < n_targets; i++)
1827 if (targets[i] == utf8_atom ||
1828 targets[i] == text_atom ||
1829 targets[i] == GDK_TARGET_STRING ||
1830 targets[i] == ctext_atom ||
1831 targets[i] == text_plain_atom ||
1832 targets[i] == text_plain_utf8_atom ||
1833 targets[i] == text_plain_locale_atom)
1844 * gtk_targets_include_rich_text:
1845 * @targets: an array of #GdkAtom<!-- -->s
1846 * @n_targets: the length of @targets
1847 * @buffer: a #GtkTextBuffer
1849 * Determines if any of the targets in @targets can be used to
1850 * provide rich text.
1852 * Return value: %TRUE if @targets include a suitable target for rich text,
1858 gtk_targets_include_rich_text (GdkAtom *targets,
1860 GtkTextBuffer *buffer)
1862 GdkAtom *rich_targets;
1863 gint n_rich_targets;
1865 gboolean result = FALSE;
1867 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1868 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1872 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1875 for (i = 0; i < n_targets; i++)
1877 for (j = 0; j < n_rich_targets; j++)
1879 if (targets[i] == rich_targets[j])
1888 g_free (rich_targets);
1894 * gtk_selection_data_targets_include_text:
1895 * @selection_data: a #GtkSelectionData object
1897 * Given a #GtkSelectionData object holding a list of targets,
1898 * determines if any of the targets in @targets can be used to
1901 * Return value: %TRUE if @selection_data holds a list of targets,
1902 * and a suitable target for text is included, otherwise %FALSE.
1905 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1909 gboolean result = FALSE;
1911 g_return_val_if_fail (selection_data != NULL, FALSE);
1915 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1917 result = gtk_targets_include_text (targets, n_targets);
1925 * gtk_selection_data_targets_include_rich_text:
1926 * @selection_data: a #GtkSelectionData object
1927 * @buffer: a #GtkTextBuffer
1929 * Given a #GtkSelectionData object holding a list of targets,
1930 * determines if any of the targets in @targets can be used to
1931 * provide rich text.
1933 * Return value: %TRUE if @selection_data holds a list of targets,
1934 * and a suitable target for rich text is included,
1940 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1941 GtkTextBuffer *buffer)
1945 gboolean result = FALSE;
1947 g_return_val_if_fail (selection_data != NULL, FALSE);
1948 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1952 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1954 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1962 * gtk_targets_include_image:
1963 * @targets: an array of #GdkAtom<!-- -->s
1964 * @n_targets: the length of @targets
1965 * @writable: whether to accept only targets for which GTK+ knows
1966 * how to convert a pixbuf into the format
1968 * Determines if any of the targets in @targets can be used to
1969 * provide a #GdkPixbuf.
1971 * Return value: %TRUE if @targets include a suitable target for images,
1977 gtk_targets_include_image (GdkAtom *targets,
1981 GtkTargetList *list;
1984 gboolean result = FALSE;
1986 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1988 list = gtk_target_list_new (NULL, 0);
1989 gtk_target_list_add_image_targets (list, 0, writable);
1990 for (i = 0; i < n_targets && !result; i++)
1992 for (l = list->list; l; l = l->next)
1994 GtkTargetPair *pair = (GtkTargetPair *)l->data;
1995 if (pair->target == targets[i])
2002 gtk_target_list_unref (list);
2008 * gtk_selection_data_targets_include_image:
2009 * @selection_data: a #GtkSelectionData object
2010 * @writable: whether to accept only targets for which GTK+ knows
2011 * how to convert a pixbuf into the format
2013 * Given a #GtkSelectionData object holding a list of targets,
2014 * determines if any of the targets in @targets can be used to
2015 * provide a #GdkPixbuf.
2017 * Return value: %TRUE if @selection_data holds a list of targets,
2018 * and a suitable target for images is included, otherwise %FALSE.
2023 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2028 gboolean result = FALSE;
2030 g_return_val_if_fail (selection_data != NULL, FALSE);
2034 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2036 result = gtk_targets_include_image (targets, n_targets, writable);
2044 * gtk_targets_include_uri:
2045 * @targets: an array of #GdkAtom<!-- -->s
2046 * @n_targets: the length of @targets
2048 * Determines if any of the targets in @targets can be used to
2049 * provide an uri list.
2051 * Return value: %TRUE if @targets include a suitable target for uri lists,
2057 gtk_targets_include_uri (GdkAtom *targets,
2061 gboolean result = FALSE;
2063 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2065 /* Keep in sync with gtk_target_list_add_uri_targets()
2070 for (i = 0; i < n_targets; i++)
2072 if (targets[i] == text_uri_list_atom)
2083 * gtk_selection_data_targets_include_uri:
2084 * @selection_data: a #GtkSelectionData object
2086 * Given a #GtkSelectionData object holding a list of targets,
2087 * determines if any of the targets in @targets can be used to
2088 * provide a list or URIs.
2090 * Return value: %TRUE if @selection_data holds a list of targets,
2091 * and a suitable target for URI lists is included, otherwise %FALSE.
2096 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2100 gboolean result = FALSE;
2102 g_return_val_if_fail (selection_data != NULL, FALSE);
2106 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2108 result = gtk_targets_include_uri (targets, n_targets);
2116 /*************************************************************
2117 * gtk_selection_init:
2118 * Initialize local variables
2122 *************************************************************/
2125 gtk_selection_init (void)
2127 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2128 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2129 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2130 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2136 * gtk_selection_clear:
2137 * @widget: a #GtkWidget
2140 * The default handler for the GtkWidget::selection_clear_event
2143 * Return value: %TRUE if the event was handled, otherwise false
2147 * Deprecated: 2.4: Instead of calling this function, chain up from
2148 * your selection_clear_event handler. Calling this function
2149 * from any other context is illegal.
2152 gtk_selection_clear (GtkWidget *widget,
2153 GdkEventSelection *event)
2155 /* Note that we filter clear events in gdkselection-x11.c, so
2156 * that we only will get here if the clear event actually
2157 * represents a change that we didn't do ourself.
2160 GtkSelectionInfo *selection_info = NULL;
2162 tmp_list = current_selections;
2165 selection_info = (GtkSelectionInfo *)tmp_list->data;
2167 if ((selection_info->selection == event->selection) &&
2168 (selection_info->widget == widget))
2171 tmp_list = tmp_list->next;
2176 current_selections = g_list_remove_link (current_selections, tmp_list);
2177 g_list_free (tmp_list);
2178 g_slice_free (GtkSelectionInfo, selection_info);
2185 /*************************************************************
2186 * _gtk_selection_request:
2187 * Handler for "selection_request_event"
2192 *************************************************************/
2195 _gtk_selection_request (GtkWidget *widget,
2196 GdkEventSelection *event)
2198 GdkDisplay *display = gtk_widget_get_display (widget);
2202 gulong selection_max_size;
2205 gtk_selection_init ();
2207 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2209 /* Check if we own selection */
2211 tmp_list = current_selections;
2214 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2216 if ((selection_info->selection == event->selection) &&
2217 (selection_info->widget == widget))
2220 tmp_list = tmp_list->next;
2223 if (tmp_list == NULL)
2226 info = g_slice_new (GtkIncrInfo);
2228 g_object_ref (widget);
2230 info->selection = event->selection;
2231 info->num_incrs = 0;
2233 /* Create GdkWindow structure for the requestor */
2235 info->requestor = gdk_window_lookup_for_display (display,
2237 if (!info->requestor)
2238 info->requestor = gdk_window_foreign_new_for_display (display,
2241 /* Determine conversions we need to perform */
2243 if (event->target == gtk_selection_atoms[MULTIPLE])
2252 gdk_error_trap_push ();
2253 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2254 0, selection_max_size, FALSE,
2255 &type, &format, &length, &mult_atoms))
2257 gdk_selection_send_notify_for_display (display,
2263 g_free (mult_atoms);
2264 g_slice_free (GtkIncrInfo, info);
2265 gdk_error_trap_pop ();
2268 gdk_error_trap_pop ();
2270 /* This is annoying; the ICCCM doesn't specify the property type
2271 * used for the property contents, so the autoconversion for
2272 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2274 #ifdef GDK_WINDOWING_X11
2275 if (type != GDK_SELECTION_TYPE_ATOM &&
2276 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2278 info->num_conversions = length / (2*sizeof (glong));
2279 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2281 for (i=0; i<info->num_conversions; i++)
2283 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2284 ((glong *)mult_atoms)[2*i]);
2285 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2286 ((glong *)mult_atoms)[2*i + 1]);
2289 g_free (mult_atoms);
2294 info->num_conversions = length / (2*sizeof (GdkAtom));
2295 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2297 for (i=0; i<info->num_conversions; i++)
2299 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2300 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2303 g_free (mult_atoms);
2306 else /* only a single conversion */
2308 info->conversions = g_new (GtkIncrConversion, 1);
2309 info->num_conversions = 1;
2310 info->conversions[0].target = event->target;
2311 info->conversions[0].property = event->property;
2314 /* Loop through conversions and determine which of these are big
2315 enough to require doing them via INCR */
2316 for (i=0; i<info->num_conversions; i++)
2318 GtkSelectionData data;
2321 data.selection = event->selection;
2322 data.target = info->conversions[i].target;
2325 data.display = gtk_widget_get_display (widget);
2327 #ifdef DEBUG_SELECTION
2328 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2330 info->conversions[i].target,
2331 gdk_atom_name (info->conversions[i].target),
2332 event->requestor, info->conversions[i].property);
2335 gtk_selection_invoke_handler (widget, &data, event->time);
2337 if (data.length < 0)
2339 info->conversions[i].property = GDK_NONE;
2343 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2345 items = data.length / gtk_selection_bytes_per_item (data.format);
2347 if (data.length > selection_max_size)
2349 /* Sending via INCR */
2350 #ifdef DEBUG_SELECTION
2351 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2352 data.length, selection_max_size);
2355 info->conversions[i].offset = 0;
2356 info->conversions[i].data = data;
2359 gdk_property_change (info->requestor,
2360 info->conversions[i].property,
2361 gtk_selection_atoms[INCR],
2363 GDK_PROP_MODE_REPLACE,
2364 (guchar *)&items, 1);
2368 info->conversions[i].offset = -1;
2370 gdk_property_change (info->requestor,
2371 info->conversions[i].property,
2374 GDK_PROP_MODE_REPLACE,
2381 /* If we have some INCR's, we need to send the rest of the data in
2384 if (info->num_incrs > 0)
2386 /* FIXME: this could be dangerous if window doesn't still
2389 #ifdef DEBUG_SELECTION
2390 g_message ("Starting INCR...");
2393 gdk_window_set_events (info->requestor,
2394 gdk_window_get_events (info->requestor) |
2395 GDK_PROPERTY_CHANGE_MASK);
2396 current_incrs = g_list_append (current_incrs, info);
2397 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2400 /* If it was a MULTIPLE request, set the property to indicate which
2401 conversions succeeded */
2402 if (event->target == gtk_selection_atoms[MULTIPLE])
2404 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2405 for (i = 0; i < info->num_conversions; i++)
2407 mult_atoms[2*i] = info->conversions[i].target;
2408 mult_atoms[2*i+1] = info->conversions[i].property;
2411 gdk_property_change (info->requestor, event->property,
2412 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2413 GDK_PROP_MODE_REPLACE,
2414 (guchar *)mult_atoms, 2*info->num_conversions);
2415 g_free (mult_atoms);
2418 if (info->num_conversions == 1 &&
2419 info->conversions[0].property == GDK_NONE)
2421 /* Reject the entire conversion */
2422 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2431 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2439 if (info->num_incrs == 0)
2441 g_free (info->conversions);
2442 g_slice_free (GtkIncrInfo, info);
2445 g_object_unref (widget);
2450 /*************************************************************
2451 * _gtk_selection_incr_event:
2452 * Called whenever an PropertyNotify event occurs for an
2453 * GdkWindow with user_data == NULL. These will be notifications
2454 * that a window we are sending the selection to via the
2455 * INCR protocol has deleted a property and is ready for
2459 * window: the requestor window
2460 * event: the property event structure
2463 *************************************************************/
2466 _gtk_selection_incr_event (GdkWindow *window,
2467 GdkEventProperty *event)
2470 GtkIncrInfo *info = NULL;
2473 gulong selection_max_size;
2477 if (event->state != GDK_PROPERTY_DELETE)
2480 #ifdef DEBUG_SELECTION
2481 g_message ("PropertyDelete, property %ld", event->atom);
2484 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2486 /* Now find the appropriate ongoing INCR */
2487 tmp_list = current_incrs;
2490 info = (GtkIncrInfo *)tmp_list->data;
2491 if (info->requestor == event->window)
2494 tmp_list = tmp_list->next;
2497 if (tmp_list == NULL)
2500 /* Find out which target this is for */
2501 for (i=0; i<info->num_conversions; i++)
2503 if (info->conversions[i].property == event->atom &&
2504 info->conversions[i].offset != -1)
2508 info->idle_time = 0;
2510 if (info->conversions[i].offset == -2) /* only the last 0-length
2518 num_bytes = info->conversions[i].data.length -
2519 info->conversions[i].offset;
2520 buffer = info->conversions[i].data.data +
2521 info->conversions[i].offset;
2523 if (num_bytes > selection_max_size)
2525 num_bytes = selection_max_size;
2526 info->conversions[i].offset += selection_max_size;
2529 info->conversions[i].offset = -2;
2531 #ifdef DEBUG_SELECTION
2532 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2533 num_bytes, info->conversions[i].offset,
2534 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2537 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2538 gdk_property_change (info->requestor, event->atom,
2539 info->conversions[i].data.type,
2540 info->conversions[i].data.format,
2541 GDK_PROP_MODE_REPLACE,
2543 num_bytes / bytes_per_item);
2545 if (info->conversions[i].offset == -2)
2547 g_free (info->conversions[i].data.data);
2548 info->conversions[i].data.data = NULL;
2554 info->conversions[i].offset = -1;
2559 /* Check if we're finished with all the targets */
2561 if (info->num_incrs == 0)
2563 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2564 g_list_free (tmp_list);
2565 /* Let the timeout free it */
2571 /*************************************************************
2572 * gtk_selection_incr_timeout:
2573 * Timeout callback for the sending portion of the INCR
2576 * info: Information about this incr
2578 *************************************************************/
2581 gtk_selection_incr_timeout (GtkIncrInfo *info)
2586 /* Determine if retrieval has finished by checking if it still in
2587 list of pending retrievals */
2589 tmp_list = current_incrs;
2592 if (info == (GtkIncrInfo *)tmp_list->data)
2594 tmp_list = tmp_list->next;
2597 /* If retrieval is finished */
2598 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2600 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2602 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2603 g_list_free (tmp_list);
2606 g_free (info->conversions);
2607 /* FIXME: we should check if requestor window is still in use,
2608 and if not, remove it? */
2610 g_slice_free (GtkIncrInfo, info);
2612 retval = FALSE; /* remove timeout */
2618 retval = TRUE; /* timeout will happen again */
2624 /*************************************************************
2625 * _gtk_selection_notify:
2626 * Handler for "selection_notify_event" signals on windows
2627 * where a retrieval is currently in process. The selection
2628 * owner has responded to our conversion request.
2630 * widget: Widget getting signal
2631 * event: Selection event structure
2632 * info: Information about this retrieval
2634 * was event handled?
2635 *************************************************************/
2638 _gtk_selection_notify (GtkWidget *widget,
2639 GdkEventSelection *event)
2642 GtkRetrievalInfo *info = NULL;
2643 guchar *buffer = NULL;
2648 #ifdef DEBUG_SELECTION
2649 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2650 event->selection, event->target, event->property);
2653 tmp_list = current_retrievals;
2656 info = (GtkRetrievalInfo *)tmp_list->data;
2657 if (info->widget == widget && info->selection == event->selection)
2659 tmp_list = tmp_list->next;
2662 if (!tmp_list) /* no retrieval in progress */
2665 if (event->property != GDK_NONE)
2666 length = gdk_selection_property_get (widget->window, &buffer,
2669 length = 0; /* silence gcc */
2671 if (event->property == GDK_NONE || buffer == NULL)
2673 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2674 g_list_free (tmp_list);
2675 /* structure will be freed in timeout */
2676 gtk_selection_retrieval_report (info,
2677 GDK_NONE, 0, NULL, -1, event->time);
2682 if (type == gtk_selection_atoms[INCR])
2684 /* The remainder of the selection will come through PropertyNotify
2687 info->notify_time = event->time;
2688 info->idle_time = 0;
2689 info->offset = 0; /* Mark as OK to proceed */
2690 gdk_window_set_events (widget->window,
2691 gdk_window_get_events (widget->window)
2692 | GDK_PROPERTY_CHANGE_MASK);
2696 /* We don't delete the info structure - that will happen in timeout */
2697 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2698 g_list_free (tmp_list);
2700 info->offset = length;
2701 gtk_selection_retrieval_report (info,
2703 buffer, length, event->time);
2706 gdk_property_delete (widget->window, event->property);
2713 /*************************************************************
2714 * _gtk_selection_property_notify:
2715 * Handler for "property_notify_event" signals on windows
2716 * where a retrieval is currently in process. The selection
2717 * owner has added more data.
2719 * widget: Widget getting signal
2720 * event: Property event structure
2721 * info: Information about this retrieval
2723 * was event handled?
2724 *************************************************************/
2727 _gtk_selection_property_notify (GtkWidget *widget,
2728 GdkEventProperty *event)
2731 GtkRetrievalInfo *info = NULL;
2737 g_return_val_if_fail (widget != NULL, FALSE);
2738 g_return_val_if_fail (event != NULL, FALSE);
2740 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2741 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2742 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2746 #ifdef DEBUG_SELECTION
2747 g_message ("PropertyNewValue, property %ld",
2751 tmp_list = current_retrievals;
2754 info = (GtkRetrievalInfo *)tmp_list->data;
2755 if (info->widget == widget)
2757 tmp_list = tmp_list->next;
2760 if (!tmp_list) /* No retrieval in progress */
2763 if (info->offset < 0) /* We haven't got the SelectionNotify
2764 for this retrieval yet */
2767 info->idle_time = 0;
2769 length = gdk_selection_property_get (widget->window, &new_buffer,
2771 gdk_property_delete (widget->window, event->atom);
2773 /* We could do a lot better efficiency-wise by paying attention to
2774 what length was sent in the initial INCR transaction, instead of
2775 doing memory allocation at every step. But its only guaranteed to
2776 be a _lower bound_ (pretty useless!) */
2778 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2780 /* Info structure will be freed in timeout */
2781 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2782 g_list_free (tmp_list);
2783 gtk_selection_retrieval_report (info,
2785 (type == GDK_NONE) ? NULL : info->buffer,
2786 (type == GDK_NONE) ? -1 : info->offset,
2789 else /* append on newly arrived data */
2793 #ifdef DEBUG_SELECTION
2794 g_message ("Start - Adding %d bytes at offset 0",
2797 info->buffer = new_buffer;
2798 info->offset = length;
2803 #ifdef DEBUG_SELECTION
2804 g_message ("Appending %d bytes at offset %d",
2805 length,info->offset);
2807 /* We copy length+1 bytes to preserve guaranteed null termination */
2808 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2809 memcpy (info->buffer + info->offset, new_buffer, length+1);
2810 info->offset += length;
2811 g_free (new_buffer);
2818 /*************************************************************
2819 * gtk_selection_retrieval_timeout:
2820 * Timeout callback while receiving a selection.
2822 * info: Information about this retrieval
2824 *************************************************************/
2827 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2832 /* Determine if retrieval has finished by checking if it still in
2833 list of pending retrievals */
2835 tmp_list = current_retrievals;
2838 if (info == (GtkRetrievalInfo *)tmp_list->data)
2840 tmp_list = tmp_list->next;
2843 /* If retrieval is finished */
2844 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2846 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2848 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2849 g_list_free (tmp_list);
2850 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2853 g_free (info->buffer);
2854 g_slice_free (GtkRetrievalInfo, info);
2856 retval = FALSE; /* remove timeout */
2862 retval = TRUE; /* timeout will happen again */
2868 /*************************************************************
2869 * gtk_selection_retrieval_report:
2870 * Emits a "selection_received" signal.
2872 * info: information about the retrieval that completed
2873 * buffer: buffer containing data (NULL => errror)
2874 * time: timestamp for data in buffer
2876 *************************************************************/
2879 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2880 GdkAtom type, gint format,
2881 guchar *buffer, gint length,
2884 GtkSelectionData data;
2886 data.selection = info->selection;
2887 data.target = info->target;
2889 data.format = format;
2891 data.length = length;
2893 data.display = gtk_widget_get_display (info->widget);
2895 g_signal_emit_by_name (info->widget,
2896 "selection_received",
2900 /*************************************************************
2901 * gtk_selection_invoke_handler:
2902 * Finds and invokes handler for specified
2903 * widget/selection/target combination, calls
2904 * gtk_selection_default_handler if none exists.
2907 * widget: selection owner
2908 * data: selection data [INOUT]
2909 * time: time from requeset
2912 * Number of bytes written to buffer, -1 if error
2913 *************************************************************/
2916 gtk_selection_invoke_handler (GtkWidget *widget,
2917 GtkSelectionData *data,
2920 GtkTargetList *target_list;
2924 g_return_if_fail (widget != NULL);
2926 target_list = gtk_selection_target_list_get (widget, data->selection);
2928 gtk_target_list_find (target_list, data->target, &info))
2930 g_signal_emit_by_name (widget,
2936 gtk_selection_default_handler (widget, data);
2939 /*************************************************************
2940 * gtk_selection_default_handler:
2941 * Handles some default targets that exist for any widget
2942 * If it can't fit results into buffer, returns -1. This
2943 * won't happen in any conceivable case, since it would
2944 * require 1000 selection targets!
2947 * widget: selection owner
2948 * data: selection data [INOUT]
2950 *************************************************************/
2953 gtk_selection_default_handler (GtkWidget *widget,
2954 GtkSelectionData *data)
2956 if (data->target == gtk_selection_atoms[TIMESTAMP])
2958 /* Time which was used to obtain selection */
2960 GtkSelectionInfo *selection_info;
2962 tmp_list = current_selections;
2965 selection_info = (GtkSelectionInfo *)tmp_list->data;
2966 if ((selection_info->widget == widget) &&
2967 (selection_info->selection == data->selection))
2969 gulong time = selection_info->time;
2971 gtk_selection_data_set (data,
2972 GDK_SELECTION_TYPE_INTEGER,
2979 tmp_list = tmp_list->next;
2984 else if (data->target == gtk_selection_atoms[TARGETS])
2986 /* List of all targets supported for this widget/selection pair */
2990 GtkTargetList *target_list;
2991 GtkTargetPair *pair;
2993 target_list = gtk_selection_target_list_get (widget,
2995 count = g_list_length (target_list->list) + 3;
2997 data->type = GDK_SELECTION_TYPE_ATOM;
2999 data->length = count * sizeof (GdkAtom);
3001 /* selection data is always terminated by a trailing \0
3003 p = g_malloc (data->length + 1);
3004 data->data = (guchar *)p;
3005 data->data[data->length] = '\0';
3007 *p++ = gtk_selection_atoms[TIMESTAMP];
3008 *p++ = gtk_selection_atoms[TARGETS];
3009 *p++ = gtk_selection_atoms[MULTIPLE];
3011 tmp_list = target_list->list;
3014 pair = (GtkTargetPair *)tmp_list->data;
3015 *p++ = pair->target;
3017 tmp_list = tmp_list->next;
3028 * gtk_selection_data_copy:
3029 * @data: a pointer to a #GtkSelectionData structure.
3031 * Makes a copy of a #GtkSelectionData structure and its data.
3033 * Return value: a pointer to a copy of @data.
3036 gtk_selection_data_copy (GtkSelectionData *data)
3038 GtkSelectionData *new_data;
3040 g_return_val_if_fail (data != NULL, NULL);
3042 new_data = g_slice_new (GtkSelectionData);
3047 new_data->data = g_malloc (data->length + 1);
3048 memcpy (new_data->data, data->data, data->length + 1);
3055 * gtk_selection_data_free:
3056 * @data: a pointer to a #GtkSelectionData structure.
3058 * Frees a #GtkSelectionData structure returned from
3059 * gtk_selection_data_copy().
3062 gtk_selection_data_free (GtkSelectionData *data)
3064 g_return_if_fail (data != NULL);
3066 g_free (data->data);
3068 g_slice_free (GtkSelectionData, data);
3072 gtk_selection_data_get_type (void)
3074 static GType our_type = 0;
3077 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3078 (GBoxedCopyFunc) gtk_selection_data_copy,
3079 (GBoxedFreeFunc) gtk_selection_data_free);
3085 gtk_target_list_get_type (void)
3087 static GType our_type = 0;
3090 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3091 (GBoxedCopyFunc) gtk_target_list_ref,
3092 (GBoxedFreeFunc) gtk_target_list_unref);
3098 gtk_selection_bytes_per_item (gint format)
3103 return sizeof (char);
3106 return sizeof (short);
3109 return sizeof (long);
3112 g_assert_not_reached();
3117 #define __GTK_SELECTION_C__
3118 #include "gtkaliasdef.c"