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 gpointer owner_widget_ptr;
1071 GtkSelectionData selection_data;
1073 selection_data.selection = selection;
1074 selection_data.target = target;
1075 selection_data.data = NULL;
1076 selection_data.length = -1;
1077 selection_data.display = display;
1079 gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1080 owner_widget = owner_widget_ptr;
1082 if (owner_widget != NULL)
1084 gtk_selection_invoke_handler (owner_widget,
1088 gtk_selection_retrieval_report (info,
1089 selection_data.type,
1090 selection_data.format,
1091 selection_data.data,
1092 selection_data.length,
1095 g_free (selection_data.data);
1096 selection_data.data = NULL;
1097 selection_data.length = -1;
1099 g_slice_free (GtkRetrievalInfo, info);
1104 /* Otherwise, we need to go through X */
1106 current_retrievals = g_list_append (current_retrievals, info);
1107 gdk_selection_convert (widget->window, selection, target, time_);
1108 gdk_threads_add_timeout (1000,
1109 (GSourceFunc) gtk_selection_retrieval_timeout, info);
1115 * gtk_selection_data_get_target:
1116 * @selection_data: a pointer to a #GtkSelectionData structure.
1118 * Retrieves the target of the selection.
1120 * Returns: the target of the selection.
1125 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1127 g_return_val_if_fail (selection_data != NULL, 0);
1129 return selection_data->target;
1133 * gtk_selection_data_get_data_type:
1134 * @selection_data: a pointer to a #GtkSelectionData structure.
1136 * Retrieves the data type of the selection.
1138 * Returns: the data type of the selection.
1143 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1145 g_return_val_if_fail (selection_data != NULL, 0);
1147 return selection_data->type;
1151 * gtk_selection_data_get_format:
1152 * @selection_data: a pointer to a #GtkSelectionData structure.
1154 * Retrieves the format of the selection.
1156 * Returns: the format of the selection.
1161 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1163 g_return_val_if_fail (selection_data != NULL, 0);
1165 return selection_data->format;
1169 * gtk_selection_data_get_data:
1170 * @selection_data: a pointer to a #GtkSelectionData structure.
1172 * Retrieves the raw data of the selection.
1174 * Returns: the raw data of the selection.
1179 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1181 g_return_val_if_fail (selection_data != NULL, NULL);
1183 return selection_data->data;
1187 * gtk_selection_data_get_length:
1188 * @selection_data: a pointer to a #GtkSelectionData structure.
1190 * Retrieves the length of the raw data of the selection.
1192 * Returns: the length of the data of the selection.
1197 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1199 g_return_val_if_fail (selection_data != NULL, -1);
1201 return selection_data->length;
1205 * gtk_selection_data_get_display:
1206 * @selection_data: a pointer to a #GtkSelectionData structure.
1208 * Retrieves the display of the selection.
1210 * Returns: the display of the selection.
1215 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1217 g_return_val_if_fail (selection_data != NULL, NULL);
1219 return selection_data->display;
1223 * gtk_selection_data_set:
1224 * @selection_data: a pointer to a #GtkSelectionData structure.
1225 * @type: the type of selection data
1226 * @format: format (number of bits in a unit)
1227 * @data: pointer to the data (will be copied)
1228 * @length: length of the data
1230 * Stores new data into a #GtkSelectionData object. Should
1231 * <emphasis>only</emphasis> be called from a selection handler callback.
1232 * Zero-terminates the stored data.
1235 gtk_selection_data_set (GtkSelectionData *selection_data,
1241 g_return_if_fail (selection_data != NULL);
1243 g_free (selection_data->data);
1245 selection_data->type = type;
1246 selection_data->format = format;
1250 selection_data->data = g_new (guchar, length+1);
1251 memcpy (selection_data->data, data, length);
1252 selection_data->data[length] = 0;
1256 g_return_if_fail (length <= 0);
1259 selection_data->data = NULL;
1261 selection_data->data = (guchar *) g_strdup ("");
1264 selection_data->length = length;
1268 selection_set_string (GtkSelectionData *selection_data,
1272 gchar *tmp = g_strndup (str, len);
1273 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1278 gtk_selection_data_set (selection_data,
1279 GDK_SELECTION_TYPE_STRING,
1280 8, (guchar *) latin1, strlen (latin1));
1290 selection_set_compound_text (GtkSelectionData *selection_data,
1299 gboolean result = FALSE;
1301 tmp = g_strndup (str, len);
1302 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1303 &encoding, &format, &text, &new_length))
1305 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1306 gdk_free_compound_text (text);
1316 /* Normalize \r and \n into \r\n
1319 normalize_to_crlf (const gchar *str,
1322 GString *result = g_string_sized_new (len);
1323 const gchar *p = str;
1324 const gchar *end = str + len;
1329 g_string_append_c (result, '\r');
1333 g_string_append_c (result, *p);
1335 if (p == end || *p != '\n')
1336 g_string_append_c (result, '\n');
1341 g_string_append_c (result, *p);
1345 return g_string_free (result, FALSE);
1348 /* Normalize \r and \r\n into \n
1351 normalize_to_lf (gchar *str,
1354 GString *result = g_string_sized_new (len);
1355 const gchar *p = str;
1363 g_string_append_c (result, '\n');
1369 g_string_append_c (result, *p);
1373 return g_string_free (result, FALSE);
1377 selection_set_text_plain (GtkSelectionData *selection_data,
1381 const gchar *charset = NULL;
1383 GError *error = NULL;
1385 result = normalize_to_crlf (str, len);
1386 if (selection_data->target == text_plain_atom)
1388 else if (selection_data->target == text_plain_locale_atom)
1389 g_get_charset (&charset);
1393 gchar *tmp = result;
1394 result = g_convert_with_fallback (tmp, -1,
1396 NULL, NULL, NULL, &error);
1402 g_warning ("Error converting from %s to %s: %s",
1403 "UTF-8", charset, error->message);
1404 g_error_free (error);
1409 gtk_selection_data_set (selection_data,
1410 selection_data->target,
1411 8, (guchar *) result, strlen (result));
1418 selection_get_text_plain (GtkSelectionData *selection_data)
1420 const gchar *charset = NULL;
1421 gchar *str, *result;
1423 GError *error = NULL;
1425 str = g_strdup ((const gchar *) selection_data->data);
1426 len = selection_data->length;
1428 if (selection_data->type == text_plain_atom)
1429 charset = "ISO-8859-1";
1430 else if (selection_data->type == text_plain_locale_atom)
1431 g_get_charset (&charset);
1436 str = g_convert_with_fallback (tmp, len,
1438 NULL, NULL, &len, &error);
1443 g_warning ("Error converting from %s to %s: %s",
1444 charset, "UTF-8", error->message);
1445 g_error_free (error);
1450 else if (!g_utf8_validate (str, -1, NULL))
1452 g_warning ("Error converting from %s to %s: %s",
1453 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1459 result = normalize_to_lf (str, len);
1462 return (guchar *) result;
1466 * gtk_selection_data_set_text:
1467 * @selection_data: a #GtkSelectionData
1468 * @str: a UTF-8 string
1469 * @len: the length of @str, or -1 if @str is nul-terminated.
1471 * Sets the contents of the selection from a UTF-8 encoded string.
1472 * The string is converted to the form determined by
1473 * @selection_data->target.
1475 * Return value: %TRUE if the selection was successfully set,
1479 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1483 g_return_val_if_fail (selection_data != NULL, FALSE);
1490 if (selection_data->target == utf8_atom)
1492 gtk_selection_data_set (selection_data,
1494 8, (guchar *)str, len);
1497 else if (selection_data->target == GDK_TARGET_STRING)
1499 return selection_set_string (selection_data, str, len);
1501 else if (selection_data->target == ctext_atom ||
1502 selection_data->target == text_atom)
1504 if (selection_set_compound_text (selection_data, str, len))
1506 else if (selection_data->target == text_atom)
1507 return selection_set_string (selection_data, str, len);
1509 else if (selection_data->target == text_plain_atom ||
1510 selection_data->target == text_plain_utf8_atom ||
1511 selection_data->target == text_plain_locale_atom)
1513 return selection_set_text_plain (selection_data, str, len);
1520 * gtk_selection_data_get_text:
1521 * @selection_data: a #GtkSelectionData
1523 * Gets the contents of the selection data as a UTF-8 string.
1525 * Return value: if the selection data contained a recognized
1526 * text type and it could be converted to UTF-8, a newly allocated
1527 * string containing the converted text, otherwise %NULL.
1528 * If the result is non-%NULL it must be freed with g_free().
1531 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1533 guchar *result = NULL;
1535 g_return_val_if_fail (selection_data != NULL, NULL);
1539 if (selection_data->length >= 0 &&
1540 (selection_data->type == GDK_TARGET_STRING ||
1541 selection_data->type == ctext_atom ||
1542 selection_data->type == utf8_atom))
1546 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1547 selection_data->type,
1548 selection_data->format,
1549 selection_data->data,
1550 selection_data->length,
1553 result = (guchar *) list[0];
1555 for (i = 1; i < count; i++)
1559 else if (selection_data->length >= 0 &&
1560 (selection_data->type == text_plain_atom ||
1561 selection_data->type == text_plain_utf8_atom ||
1562 selection_data->type == text_plain_locale_atom))
1564 result = selection_get_text_plain (selection_data);
1571 * gtk_selection_data_set_pixbuf:
1572 * @selection_data: a #GtkSelectionData
1573 * @pixbuf: a #GdkPixbuf
1575 * Sets the contents of the selection from a #GdkPixbuf
1576 * The pixbuf is converted to the form determined by
1577 * @selection_data->target.
1579 * Return value: %TRUE if the selection was successfully set,
1585 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1588 GSList *formats, *f;
1595 g_return_val_if_fail (selection_data != NULL, FALSE);
1596 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1598 formats = gdk_pixbuf_get_formats ();
1600 for (f = formats; f; f = f->next)
1602 GdkPixbufFormat *fmt = f->data;
1604 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1605 for (m = mimes; *m; m++)
1607 atom = gdk_atom_intern (*m, FALSE);
1608 if (selection_data->target == atom)
1611 type = gdk_pixbuf_format_get_name (fmt);
1612 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1614 ((strcmp (type, "png") == 0) ?
1615 "compression" : NULL), "2",
1618 gtk_selection_data_set (selection_data,
1619 atom, 8, (guchar *)str, len);
1623 g_slist_free (formats);
1632 g_slist_free (formats);
1638 * gtk_selection_data_get_pixbuf:
1639 * @selection_data: a #GtkSelectionData
1641 * Gets the contents of the selection data as a #GdkPixbuf.
1643 * Return value: if the selection data contained a recognized
1644 * image type and it could be converted to a #GdkPixbuf, a
1645 * newly allocated pixbuf is returned, otherwise %NULL.
1646 * If the result is non-%NULL it must be freed with g_object_unref().
1651 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1653 GdkPixbufLoader *loader;
1654 GdkPixbuf *result = NULL;
1656 g_return_val_if_fail (selection_data != NULL, NULL);
1658 if (selection_data->length > 0)
1660 loader = gdk_pixbuf_loader_new ();
1662 gdk_pixbuf_loader_write (loader,
1663 selection_data->data,
1664 selection_data->length,
1666 gdk_pixbuf_loader_close (loader, NULL);
1667 result = gdk_pixbuf_loader_get_pixbuf (loader);
1670 g_object_ref (result);
1672 g_object_unref (loader);
1679 * gtk_selection_data_set_uris:
1680 * @selection_data: a #GtkSelectionData
1681 * @uris: a %NULL-terminated array of strings hilding URIs
1683 * Sets the contents of the selection from a list of URIs.
1684 * The string is converted to the form determined by
1685 * @selection_data->target.
1687 * Return value: %TRUE if the selection was successfully set,
1693 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1696 g_return_val_if_fail (selection_data != NULL, FALSE);
1697 g_return_val_if_fail (uris != NULL, FALSE);
1701 if (selection_data->target == text_uri_list_atom)
1708 list = g_string_new (NULL);
1709 for (i = 0; uris[i]; i++)
1711 g_string_append (list, uris[i]);
1712 g_string_append (list, "\r\n");
1715 result = g_convert (list->str, list->len,
1717 NULL, &length, NULL);
1718 g_string_free (list, TRUE);
1722 gtk_selection_data_set (selection_data,
1724 8, (guchar *)result, length);
1736 * gtk_selection_data_get_uris:
1737 * @selection_data: a #GtkSelectionData
1739 * Gets the contents of the selection data as array of URIs.
1741 * Return value: if the selection data contains a list of
1742 * URIs, a newly allocated %NULL-terminated string array
1743 * containing the URIs, otherwise %NULL. If the result is
1744 * non-%NULL it must be freed with g_strfreev().
1749 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1751 gchar **result = NULL;
1753 g_return_val_if_fail (selection_data != NULL, NULL);
1757 if (selection_data->length >= 0 &&
1758 selection_data->type == text_uri_list_atom)
1761 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1763 selection_data->format,
1764 selection_data->data,
1765 selection_data->length,
1768 result = g_uri_list_extract_uris (list[0]);
1778 * gtk_selection_data_get_targets:
1779 * @selection_data: a #GtkSelectionData object
1780 * @targets: location to store an array of targets. The result
1781 * stored here must be freed with g_free().
1782 * @n_atoms: location to store number of items in @targets.
1784 * Gets the contents of @selection_data as an array of targets.
1785 * This can be used to interpret the results of getting
1786 * the standard TARGETS target that is always supplied for
1789 * Return value: %TRUE if @selection_data contains a valid
1790 * array of targets, otherwise %FALSE.
1793 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1797 g_return_val_if_fail (selection_data != NULL, FALSE);
1799 if (selection_data->length >= 0 &&
1800 selection_data->format == 32 &&
1801 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1804 *targets = g_memdup (selection_data->data, selection_data->length);
1806 *n_atoms = selection_data->length / sizeof (GdkAtom);
1822 * gtk_targets_include_text:
1823 * @targets: an array of #GdkAtom<!-- -->s
1824 * @n_targets: the length of @targets
1826 * Determines if any of the targets in @targets can be used to
1829 * Return value: %TRUE if @targets include a suitable target for text,
1835 gtk_targets_include_text (GdkAtom *targets,
1839 gboolean result = FALSE;
1841 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1843 /* Keep in sync with gtk_target_list_add_text_targets()
1848 for (i = 0; i < n_targets; i++)
1850 if (targets[i] == utf8_atom ||
1851 targets[i] == text_atom ||
1852 targets[i] == GDK_TARGET_STRING ||
1853 targets[i] == ctext_atom ||
1854 targets[i] == text_plain_atom ||
1855 targets[i] == text_plain_utf8_atom ||
1856 targets[i] == text_plain_locale_atom)
1867 * gtk_targets_include_rich_text:
1868 * @targets: an array of #GdkAtom<!-- -->s
1869 * @n_targets: the length of @targets
1870 * @buffer: a #GtkTextBuffer
1872 * Determines if any of the targets in @targets can be used to
1873 * provide rich text.
1875 * Return value: %TRUE if @targets include a suitable target for rich text,
1881 gtk_targets_include_rich_text (GdkAtom *targets,
1883 GtkTextBuffer *buffer)
1885 GdkAtom *rich_targets;
1886 gint n_rich_targets;
1888 gboolean result = FALSE;
1890 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1891 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1895 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1898 for (i = 0; i < n_targets; i++)
1900 for (j = 0; j < n_rich_targets; j++)
1902 if (targets[i] == rich_targets[j])
1911 g_free (rich_targets);
1917 * gtk_selection_data_targets_include_text:
1918 * @selection_data: a #GtkSelectionData object
1920 * Given a #GtkSelectionData object holding a list of targets,
1921 * determines if any of the targets in @targets can be used to
1924 * Return value: %TRUE if @selection_data holds a list of targets,
1925 * and a suitable target for text is included, otherwise %FALSE.
1928 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1932 gboolean result = FALSE;
1934 g_return_val_if_fail (selection_data != NULL, FALSE);
1938 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1940 result = gtk_targets_include_text (targets, n_targets);
1948 * gtk_selection_data_targets_include_rich_text:
1949 * @selection_data: a #GtkSelectionData object
1950 * @buffer: a #GtkTextBuffer
1952 * Given a #GtkSelectionData object holding a list of targets,
1953 * determines if any of the targets in @targets can be used to
1954 * provide rich text.
1956 * Return value: %TRUE if @selection_data holds a list of targets,
1957 * and a suitable target for rich text is included,
1963 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1964 GtkTextBuffer *buffer)
1968 gboolean result = FALSE;
1970 g_return_val_if_fail (selection_data != NULL, FALSE);
1971 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1975 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1977 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1985 * gtk_targets_include_image:
1986 * @targets: an array of #GdkAtom<!-- -->s
1987 * @n_targets: the length of @targets
1988 * @writable: whether to accept only targets for which GTK+ knows
1989 * how to convert a pixbuf into the format
1991 * Determines if any of the targets in @targets can be used to
1992 * provide a #GdkPixbuf.
1994 * Return value: %TRUE if @targets include a suitable target for images,
2000 gtk_targets_include_image (GdkAtom *targets,
2004 GtkTargetList *list;
2007 gboolean result = FALSE;
2009 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2011 list = gtk_target_list_new (NULL, 0);
2012 gtk_target_list_add_image_targets (list, 0, writable);
2013 for (i = 0; i < n_targets && !result; i++)
2015 for (l = list->list; l; l = l->next)
2017 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2018 if (pair->target == targets[i])
2025 gtk_target_list_unref (list);
2031 * gtk_selection_data_targets_include_image:
2032 * @selection_data: a #GtkSelectionData object
2033 * @writable: whether to accept only targets for which GTK+ knows
2034 * how to convert a pixbuf into the format
2036 * Given a #GtkSelectionData object holding a list of targets,
2037 * determines if any of the targets in @targets can be used to
2038 * provide a #GdkPixbuf.
2040 * Return value: %TRUE if @selection_data holds a list of targets,
2041 * and a suitable target for images is included, otherwise %FALSE.
2046 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2051 gboolean result = FALSE;
2053 g_return_val_if_fail (selection_data != NULL, FALSE);
2057 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2059 result = gtk_targets_include_image (targets, n_targets, writable);
2067 * gtk_targets_include_uri:
2068 * @targets: an array of #GdkAtom<!-- -->s
2069 * @n_targets: the length of @targets
2071 * Determines if any of the targets in @targets can be used to
2072 * provide an uri list.
2074 * Return value: %TRUE if @targets include a suitable target for uri lists,
2080 gtk_targets_include_uri (GdkAtom *targets,
2084 gboolean result = FALSE;
2086 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2088 /* Keep in sync with gtk_target_list_add_uri_targets()
2093 for (i = 0; i < n_targets; i++)
2095 if (targets[i] == text_uri_list_atom)
2106 * gtk_selection_data_targets_include_uri:
2107 * @selection_data: a #GtkSelectionData object
2109 * Given a #GtkSelectionData object holding a list of targets,
2110 * determines if any of the targets in @targets can be used to
2111 * provide a list or URIs.
2113 * Return value: %TRUE if @selection_data holds a list of targets,
2114 * and a suitable target for URI lists is included, otherwise %FALSE.
2119 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2123 gboolean result = FALSE;
2125 g_return_val_if_fail (selection_data != NULL, FALSE);
2129 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2131 result = gtk_targets_include_uri (targets, n_targets);
2139 /*************************************************************
2140 * gtk_selection_init:
2141 * Initialize local variables
2145 *************************************************************/
2148 gtk_selection_init (void)
2150 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2151 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2152 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2153 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2159 * gtk_selection_clear:
2160 * @widget: a #GtkWidget
2163 * The default handler for the GtkWidget::selection_clear_event
2166 * Return value: %TRUE if the event was handled, otherwise false
2170 * Deprecated: 2.4: Instead of calling this function, chain up from
2171 * your selection_clear_event handler. Calling this function
2172 * from any other context is illegal.
2175 gtk_selection_clear (GtkWidget *widget,
2176 GdkEventSelection *event)
2178 /* Note that we filter clear events in gdkselection-x11.c, so
2179 * that we only will get here if the clear event actually
2180 * represents a change that we didn't do ourself.
2183 GtkSelectionInfo *selection_info = NULL;
2185 tmp_list = current_selections;
2188 selection_info = (GtkSelectionInfo *)tmp_list->data;
2190 if ((selection_info->selection == event->selection) &&
2191 (selection_info->widget == widget))
2194 tmp_list = tmp_list->next;
2199 current_selections = g_list_remove_link (current_selections, tmp_list);
2200 g_list_free (tmp_list);
2201 g_slice_free (GtkSelectionInfo, selection_info);
2208 /*************************************************************
2209 * _gtk_selection_request:
2210 * Handler for "selection_request_event"
2215 *************************************************************/
2218 _gtk_selection_request (GtkWidget *widget,
2219 GdkEventSelection *event)
2221 GdkDisplay *display = gtk_widget_get_display (widget);
2225 gulong selection_max_size;
2228 gtk_selection_init ();
2230 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2232 /* Check if we own selection */
2234 tmp_list = current_selections;
2237 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2239 if ((selection_info->selection == event->selection) &&
2240 (selection_info->widget == widget))
2243 tmp_list = tmp_list->next;
2246 if (tmp_list == NULL)
2249 info = g_slice_new (GtkIncrInfo);
2251 g_object_ref (widget);
2253 info->selection = event->selection;
2254 info->num_incrs = 0;
2256 /* Create GdkWindow structure for the requestor */
2258 info->requestor = gdk_window_lookup_for_display (display,
2260 if (!info->requestor)
2261 info->requestor = gdk_window_foreign_new_for_display (display,
2264 /* Determine conversions we need to perform */
2266 if (event->target == gtk_selection_atoms[MULTIPLE])
2275 gdk_error_trap_push ();
2276 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2277 0, selection_max_size, FALSE,
2278 &type, &format, &length, &mult_atoms))
2280 gdk_selection_send_notify_for_display (display,
2286 g_free (mult_atoms);
2287 g_slice_free (GtkIncrInfo, info);
2288 gdk_error_trap_pop ();
2291 gdk_error_trap_pop ();
2293 /* This is annoying; the ICCCM doesn't specify the property type
2294 * used for the property contents, so the autoconversion for
2295 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2297 #ifdef GDK_WINDOWING_X11
2298 if (type != GDK_SELECTION_TYPE_ATOM &&
2299 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2301 info->num_conversions = length / (2*sizeof (glong));
2302 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2304 for (i=0; i<info->num_conversions; i++)
2306 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2307 ((glong *)mult_atoms)[2*i]);
2308 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2309 ((glong *)mult_atoms)[2*i + 1]);
2312 g_free (mult_atoms);
2317 info->num_conversions = length / (2*sizeof (GdkAtom));
2318 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2320 for (i=0; i<info->num_conversions; i++)
2322 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2323 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2326 g_free (mult_atoms);
2329 else /* only a single conversion */
2331 info->conversions = g_new (GtkIncrConversion, 1);
2332 info->num_conversions = 1;
2333 info->conversions[0].target = event->target;
2334 info->conversions[0].property = event->property;
2337 /* Loop through conversions and determine which of these are big
2338 enough to require doing them via INCR */
2339 for (i=0; i<info->num_conversions; i++)
2341 GtkSelectionData data;
2344 data.selection = event->selection;
2345 data.target = info->conversions[i].target;
2348 data.display = gtk_widget_get_display (widget);
2350 #ifdef DEBUG_SELECTION
2351 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2353 info->conversions[i].target,
2354 gdk_atom_name (info->conversions[i].target),
2355 event->requestor, info->conversions[i].property);
2358 gtk_selection_invoke_handler (widget, &data, event->time);
2360 if (data.length < 0)
2362 info->conversions[i].property = GDK_NONE;
2366 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2368 items = data.length / gtk_selection_bytes_per_item (data.format);
2370 if (data.length > selection_max_size)
2372 /* Sending via INCR */
2373 #ifdef DEBUG_SELECTION
2374 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2375 data.length, selection_max_size);
2378 info->conversions[i].offset = 0;
2379 info->conversions[i].data = data;
2382 gdk_property_change (info->requestor,
2383 info->conversions[i].property,
2384 gtk_selection_atoms[INCR],
2386 GDK_PROP_MODE_REPLACE,
2387 (guchar *)&items, 1);
2391 info->conversions[i].offset = -1;
2393 gdk_property_change (info->requestor,
2394 info->conversions[i].property,
2397 GDK_PROP_MODE_REPLACE,
2404 /* If we have some INCR's, we need to send the rest of the data in
2407 if (info->num_incrs > 0)
2409 /* FIXME: this could be dangerous if window doesn't still
2412 #ifdef DEBUG_SELECTION
2413 g_message ("Starting INCR...");
2416 gdk_window_set_events (info->requestor,
2417 gdk_window_get_events (info->requestor) |
2418 GDK_PROPERTY_CHANGE_MASK);
2419 current_incrs = g_list_append (current_incrs, info);
2420 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2423 /* If it was a MULTIPLE request, set the property to indicate which
2424 conversions succeeded */
2425 if (event->target == gtk_selection_atoms[MULTIPLE])
2427 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2428 for (i = 0; i < info->num_conversions; i++)
2430 mult_atoms[2*i] = info->conversions[i].target;
2431 mult_atoms[2*i+1] = info->conversions[i].property;
2434 gdk_property_change (info->requestor, event->property,
2435 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2436 GDK_PROP_MODE_REPLACE,
2437 (guchar *)mult_atoms, 2*info->num_conversions);
2438 g_free (mult_atoms);
2441 if (info->num_conversions == 1 &&
2442 info->conversions[0].property == GDK_NONE)
2444 /* Reject the entire conversion */
2445 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2454 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2462 if (info->num_incrs == 0)
2464 g_free (info->conversions);
2465 g_slice_free (GtkIncrInfo, info);
2468 g_object_unref (widget);
2473 /*************************************************************
2474 * _gtk_selection_incr_event:
2475 * Called whenever an PropertyNotify event occurs for an
2476 * GdkWindow with user_data == NULL. These will be notifications
2477 * that a window we are sending the selection to via the
2478 * INCR protocol has deleted a property and is ready for
2482 * window: the requestor window
2483 * event: the property event structure
2486 *************************************************************/
2489 _gtk_selection_incr_event (GdkWindow *window,
2490 GdkEventProperty *event)
2493 GtkIncrInfo *info = NULL;
2496 gulong selection_max_size;
2500 if (event->state != GDK_PROPERTY_DELETE)
2503 #ifdef DEBUG_SELECTION
2504 g_message ("PropertyDelete, property %ld", event->atom);
2507 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2509 /* Now find the appropriate ongoing INCR */
2510 tmp_list = current_incrs;
2513 info = (GtkIncrInfo *)tmp_list->data;
2514 if (info->requestor == event->window)
2517 tmp_list = tmp_list->next;
2520 if (tmp_list == NULL)
2523 /* Find out which target this is for */
2524 for (i=0; i<info->num_conversions; i++)
2526 if (info->conversions[i].property == event->atom &&
2527 info->conversions[i].offset != -1)
2531 info->idle_time = 0;
2533 if (info->conversions[i].offset == -2) /* only the last 0-length
2541 num_bytes = info->conversions[i].data.length -
2542 info->conversions[i].offset;
2543 buffer = info->conversions[i].data.data +
2544 info->conversions[i].offset;
2546 if (num_bytes > selection_max_size)
2548 num_bytes = selection_max_size;
2549 info->conversions[i].offset += selection_max_size;
2552 info->conversions[i].offset = -2;
2554 #ifdef DEBUG_SELECTION
2555 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2556 num_bytes, info->conversions[i].offset,
2557 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2560 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2561 gdk_property_change (info->requestor, event->atom,
2562 info->conversions[i].data.type,
2563 info->conversions[i].data.format,
2564 GDK_PROP_MODE_REPLACE,
2566 num_bytes / bytes_per_item);
2568 if (info->conversions[i].offset == -2)
2570 g_free (info->conversions[i].data.data);
2571 info->conversions[i].data.data = NULL;
2577 info->conversions[i].offset = -1;
2582 /* Check if we're finished with all the targets */
2584 if (info->num_incrs == 0)
2586 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2587 g_list_free (tmp_list);
2588 /* Let the timeout free it */
2594 /*************************************************************
2595 * gtk_selection_incr_timeout:
2596 * Timeout callback for the sending portion of the INCR
2599 * info: Information about this incr
2601 *************************************************************/
2604 gtk_selection_incr_timeout (GtkIncrInfo *info)
2609 /* Determine if retrieval has finished by checking if it still in
2610 list of pending retrievals */
2612 tmp_list = current_incrs;
2615 if (info == (GtkIncrInfo *)tmp_list->data)
2617 tmp_list = tmp_list->next;
2620 /* If retrieval is finished */
2621 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2623 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2625 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2626 g_list_free (tmp_list);
2629 g_free (info->conversions);
2630 /* FIXME: we should check if requestor window is still in use,
2631 and if not, remove it? */
2633 g_slice_free (GtkIncrInfo, info);
2635 retval = FALSE; /* remove timeout */
2641 retval = TRUE; /* timeout will happen again */
2647 /*************************************************************
2648 * _gtk_selection_notify:
2649 * Handler for "selection-notify-event" signals on windows
2650 * where a retrieval is currently in process. The selection
2651 * owner has responded to our conversion request.
2653 * widget: Widget getting signal
2654 * event: Selection event structure
2655 * info: Information about this retrieval
2657 * was event handled?
2658 *************************************************************/
2661 _gtk_selection_notify (GtkWidget *widget,
2662 GdkEventSelection *event)
2665 GtkRetrievalInfo *info = NULL;
2666 guchar *buffer = NULL;
2671 #ifdef DEBUG_SELECTION
2672 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2673 event->selection, event->target, event->property);
2676 tmp_list = current_retrievals;
2679 info = (GtkRetrievalInfo *)tmp_list->data;
2680 if (info->widget == widget && info->selection == event->selection)
2682 tmp_list = tmp_list->next;
2685 if (!tmp_list) /* no retrieval in progress */
2688 if (event->property != GDK_NONE)
2689 length = gdk_selection_property_get (widget->window, &buffer,
2692 length = 0; /* silence gcc */
2694 if (event->property == GDK_NONE || buffer == NULL)
2696 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2697 g_list_free (tmp_list);
2698 /* structure will be freed in timeout */
2699 gtk_selection_retrieval_report (info,
2700 GDK_NONE, 0, NULL, -1, event->time);
2705 if (type == gtk_selection_atoms[INCR])
2707 /* The remainder of the selection will come through PropertyNotify
2710 info->notify_time = event->time;
2711 info->idle_time = 0;
2712 info->offset = 0; /* Mark as OK to proceed */
2713 gdk_window_set_events (widget->window,
2714 gdk_window_get_events (widget->window)
2715 | GDK_PROPERTY_CHANGE_MASK);
2719 /* We don't delete the info structure - that will happen in timeout */
2720 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2721 g_list_free (tmp_list);
2723 info->offset = length;
2724 gtk_selection_retrieval_report (info,
2726 buffer, length, event->time);
2729 gdk_property_delete (widget->window, event->property);
2736 /*************************************************************
2737 * _gtk_selection_property_notify:
2738 * Handler for "property-notify-event" signals on windows
2739 * where a retrieval is currently in process. The selection
2740 * owner has added more data.
2742 * widget: Widget getting signal
2743 * event: Property event structure
2744 * info: Information about this retrieval
2746 * was event handled?
2747 *************************************************************/
2750 _gtk_selection_property_notify (GtkWidget *widget,
2751 GdkEventProperty *event)
2754 GtkRetrievalInfo *info = NULL;
2760 g_return_val_if_fail (widget != NULL, FALSE);
2761 g_return_val_if_fail (event != NULL, FALSE);
2763 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2764 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2765 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2769 #ifdef DEBUG_SELECTION
2770 g_message ("PropertyNewValue, property %ld",
2774 tmp_list = current_retrievals;
2777 info = (GtkRetrievalInfo *)tmp_list->data;
2778 if (info->widget == widget)
2780 tmp_list = tmp_list->next;
2783 if (!tmp_list) /* No retrieval in progress */
2786 if (info->offset < 0) /* We haven't got the SelectionNotify
2787 for this retrieval yet */
2790 info->idle_time = 0;
2792 length = gdk_selection_property_get (widget->window, &new_buffer,
2794 gdk_property_delete (widget->window, event->atom);
2796 /* We could do a lot better efficiency-wise by paying attention to
2797 what length was sent in the initial INCR transaction, instead of
2798 doing memory allocation at every step. But its only guaranteed to
2799 be a _lower bound_ (pretty useless!) */
2801 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2803 /* Info structure will be freed in timeout */
2804 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2805 g_list_free (tmp_list);
2806 gtk_selection_retrieval_report (info,
2808 (type == GDK_NONE) ? NULL : info->buffer,
2809 (type == GDK_NONE) ? -1 : info->offset,
2812 else /* append on newly arrived data */
2816 #ifdef DEBUG_SELECTION
2817 g_message ("Start - Adding %d bytes at offset 0",
2820 info->buffer = new_buffer;
2821 info->offset = length;
2826 #ifdef DEBUG_SELECTION
2827 g_message ("Appending %d bytes at offset %d",
2828 length,info->offset);
2830 /* We copy length+1 bytes to preserve guaranteed null termination */
2831 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2832 memcpy (info->buffer + info->offset, new_buffer, length+1);
2833 info->offset += length;
2834 g_free (new_buffer);
2841 /*************************************************************
2842 * gtk_selection_retrieval_timeout:
2843 * Timeout callback while receiving a selection.
2845 * info: Information about this retrieval
2847 *************************************************************/
2850 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2855 /* Determine if retrieval has finished by checking if it still in
2856 list of pending retrievals */
2858 tmp_list = current_retrievals;
2861 if (info == (GtkRetrievalInfo *)tmp_list->data)
2863 tmp_list = tmp_list->next;
2866 /* If retrieval is finished */
2867 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2869 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2871 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2872 g_list_free (tmp_list);
2873 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2876 g_free (info->buffer);
2877 g_slice_free (GtkRetrievalInfo, info);
2879 retval = FALSE; /* remove timeout */
2885 retval = TRUE; /* timeout will happen again */
2891 /*************************************************************
2892 * gtk_selection_retrieval_report:
2893 * Emits a "selection-received" signal.
2895 * info: information about the retrieval that completed
2896 * buffer: buffer containing data (NULL => errror)
2897 * time: timestamp for data in buffer
2899 *************************************************************/
2902 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2903 GdkAtom type, gint format,
2904 guchar *buffer, gint length,
2907 GtkSelectionData data;
2909 data.selection = info->selection;
2910 data.target = info->target;
2912 data.format = format;
2914 data.length = length;
2916 data.display = gtk_widget_get_display (info->widget);
2918 g_signal_emit_by_name (info->widget,
2919 "selection-received",
2923 /*************************************************************
2924 * gtk_selection_invoke_handler:
2925 * Finds and invokes handler for specified
2926 * widget/selection/target combination, calls
2927 * gtk_selection_default_handler if none exists.
2930 * widget: selection owner
2931 * data: selection data [INOUT]
2932 * time: time from requeset
2935 * Number of bytes written to buffer, -1 if error
2936 *************************************************************/
2939 gtk_selection_invoke_handler (GtkWidget *widget,
2940 GtkSelectionData *data,
2943 GtkTargetList *target_list;
2947 g_return_if_fail (widget != NULL);
2949 target_list = gtk_selection_target_list_get (widget, data->selection);
2951 gtk_target_list_find (target_list, data->target, &info))
2953 g_signal_emit_by_name (widget,
2959 gtk_selection_default_handler (widget, data);
2962 /*************************************************************
2963 * gtk_selection_default_handler:
2964 * Handles some default targets that exist for any widget
2965 * If it can't fit results into buffer, returns -1. This
2966 * won't happen in any conceivable case, since it would
2967 * require 1000 selection targets!
2970 * widget: selection owner
2971 * data: selection data [INOUT]
2973 *************************************************************/
2976 gtk_selection_default_handler (GtkWidget *widget,
2977 GtkSelectionData *data)
2979 if (data->target == gtk_selection_atoms[TIMESTAMP])
2981 /* Time which was used to obtain selection */
2983 GtkSelectionInfo *selection_info;
2985 tmp_list = current_selections;
2988 selection_info = (GtkSelectionInfo *)tmp_list->data;
2989 if ((selection_info->widget == widget) &&
2990 (selection_info->selection == data->selection))
2992 gulong time = selection_info->time;
2994 gtk_selection_data_set (data,
2995 GDK_SELECTION_TYPE_INTEGER,
3002 tmp_list = tmp_list->next;
3007 else if (data->target == gtk_selection_atoms[TARGETS])
3009 /* List of all targets supported for this widget/selection pair */
3013 GtkTargetList *target_list;
3014 GtkTargetPair *pair;
3016 target_list = gtk_selection_target_list_get (widget,
3018 count = g_list_length (target_list->list) + 3;
3020 data->type = GDK_SELECTION_TYPE_ATOM;
3022 data->length = count * sizeof (GdkAtom);
3024 /* selection data is always terminated by a trailing \0
3026 p = g_malloc (data->length + 1);
3027 data->data = (guchar *)p;
3028 data->data[data->length] = '\0';
3030 *p++ = gtk_selection_atoms[TIMESTAMP];
3031 *p++ = gtk_selection_atoms[TARGETS];
3032 *p++ = gtk_selection_atoms[MULTIPLE];
3034 tmp_list = target_list->list;
3037 pair = (GtkTargetPair *)tmp_list->data;
3038 *p++ = pair->target;
3040 tmp_list = tmp_list->next;
3051 * gtk_selection_data_copy:
3052 * @data: a pointer to a #GtkSelectionData structure.
3054 * Makes a copy of a #GtkSelectionData structure and its data.
3056 * Return value: a pointer to a copy of @data.
3059 gtk_selection_data_copy (GtkSelectionData *data)
3061 GtkSelectionData *new_data;
3063 g_return_val_if_fail (data != NULL, NULL);
3065 new_data = g_slice_new (GtkSelectionData);
3070 new_data->data = g_malloc (data->length + 1);
3071 memcpy (new_data->data, data->data, data->length + 1);
3078 * gtk_selection_data_free:
3079 * @data: a pointer to a #GtkSelectionData structure.
3081 * Frees a #GtkSelectionData structure returned from
3082 * gtk_selection_data_copy().
3085 gtk_selection_data_free (GtkSelectionData *data)
3087 g_return_if_fail (data != NULL);
3089 g_free (data->data);
3091 g_slice_free (GtkSelectionData, data);
3095 gtk_selection_data_get_type (void)
3097 static GType our_type = 0;
3100 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3101 (GBoxedCopyFunc) gtk_selection_data_copy,
3102 (GBoxedFreeFunc) gtk_selection_data_free);
3108 gtk_target_list_get_type (void)
3110 static GType our_type = 0;
3113 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3114 (GBoxedCopyFunc) gtk_target_list_ref,
3115 (GBoxedFreeFunc) gtk_target_list_unref);
3121 gtk_selection_bytes_per_item (gint format)
3126 return sizeof (char);
3129 return sizeof (short);
3132 return sizeof (long);
3135 g_assert_not_reached();
3140 #define __GTK_SELECTION_C__
3141 #include "gtkaliasdef.c"