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.
1171 * @length: an integer to be filled in, or %NULL
1173 * Retrieves the raw data of the selection.
1175 * If @length is not %NULL it is filled with the length of data.
1177 * Returns: the raw data of the selection.
1182 gtk_selection_data_get_data (GtkSelectionData *selection_data,
1185 g_return_val_if_fail (selection_data != NULL, NULL);
1188 *length = selection_data->length;
1190 return selection_data->data;
1194 * gtk_selection_data_get_display:
1195 * @selection_data: a pointer to a #GtkSelectionData structure.
1197 * Retrieves the display of the selection.
1199 * Returns: the display of the selection.
1204 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1206 g_return_val_if_fail (selection_data != NULL, NULL);
1208 return selection_data->display;
1212 * gtk_selection_data_set:
1213 * @selection_data: a pointer to a #GtkSelectionData structure.
1214 * @type: the type of selection data
1215 * @format: format (number of bits in a unit)
1216 * @data: pointer to the data (will be copied)
1217 * @length: length of the data
1219 * Stores new data into a #GtkSelectionData object. Should
1220 * <emphasis>only</emphasis> be called from a selection handler callback.
1221 * Zero-terminates the stored data.
1224 gtk_selection_data_set (GtkSelectionData *selection_data,
1230 g_return_if_fail (selection_data != NULL);
1232 g_free (selection_data->data);
1234 selection_data->type = type;
1235 selection_data->format = format;
1239 selection_data->data = g_new (guchar, length+1);
1240 memcpy (selection_data->data, data, length);
1241 selection_data->data[length] = 0;
1245 g_return_if_fail (length <= 0);
1248 selection_data->data = NULL;
1250 selection_data->data = (guchar *) g_strdup ("");
1253 selection_data->length = length;
1257 selection_set_string (GtkSelectionData *selection_data,
1261 gchar *tmp = g_strndup (str, len);
1262 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1267 gtk_selection_data_set (selection_data,
1268 GDK_SELECTION_TYPE_STRING,
1269 8, (guchar *) latin1, strlen (latin1));
1279 selection_set_compound_text (GtkSelectionData *selection_data,
1288 gboolean result = FALSE;
1290 tmp = g_strndup (str, len);
1291 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1292 &encoding, &format, &text, &new_length))
1294 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1295 gdk_free_compound_text (text);
1305 /* Normalize \r and \n into \r\n
1308 normalize_to_crlf (const gchar *str,
1311 GString *result = g_string_sized_new (len);
1312 const gchar *p = str;
1313 const gchar *end = str + len;
1318 g_string_append_c (result, '\r');
1322 g_string_append_c (result, *p);
1324 if (p == end || *p != '\n')
1325 g_string_append_c (result, '\n');
1330 g_string_append_c (result, *p);
1334 return g_string_free (result, FALSE);
1337 /* Normalize \r and \r\n into \n
1340 normalize_to_lf (gchar *str,
1343 GString *result = g_string_sized_new (len);
1344 const gchar *p = str;
1352 g_string_append_c (result, '\n');
1358 g_string_append_c (result, *p);
1362 return g_string_free (result, FALSE);
1366 selection_set_text_plain (GtkSelectionData *selection_data,
1370 const gchar *charset = NULL;
1372 GError *error = NULL;
1374 result = normalize_to_crlf (str, len);
1375 if (selection_data->target == text_plain_atom)
1377 else if (selection_data->target == text_plain_locale_atom)
1378 g_get_charset (&charset);
1382 gchar *tmp = result;
1383 result = g_convert_with_fallback (tmp, -1,
1385 NULL, NULL, NULL, &error);
1391 g_warning ("Error converting from %s to %s: %s",
1392 "UTF-8", charset, error->message);
1393 g_error_free (error);
1398 gtk_selection_data_set (selection_data,
1399 selection_data->target,
1400 8, (guchar *) result, strlen (result));
1407 selection_get_text_plain (GtkSelectionData *selection_data)
1409 const gchar *charset = NULL;
1410 gchar *str, *result;
1412 GError *error = NULL;
1414 str = g_strdup ((const gchar *) selection_data->data);
1415 len = selection_data->length;
1417 if (selection_data->type == text_plain_atom)
1418 charset = "ISO-8859-1";
1419 else if (selection_data->type == text_plain_locale_atom)
1420 g_get_charset (&charset);
1425 str = g_convert_with_fallback (tmp, len,
1427 NULL, NULL, &len, &error);
1432 g_warning ("Error converting from %s to %s: %s",
1433 charset, "UTF-8", error->message);
1434 g_error_free (error);
1439 else if (!g_utf8_validate (str, -1, NULL))
1441 g_warning ("Error converting from %s to %s: %s",
1442 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1448 result = normalize_to_lf (str, len);
1451 return (guchar *) result;
1455 * gtk_selection_data_set_text:
1456 * @selection_data: a #GtkSelectionData
1457 * @str: a UTF-8 string
1458 * @len: the length of @str, or -1 if @str is nul-terminated.
1460 * Sets the contents of the selection from a UTF-8 encoded string.
1461 * The string is converted to the form determined by
1462 * @selection_data->target.
1464 * Return value: %TRUE if the selection was successfully set,
1468 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1472 g_return_val_if_fail (selection_data != NULL, FALSE);
1479 if (selection_data->target == utf8_atom)
1481 gtk_selection_data_set (selection_data,
1483 8, (guchar *)str, len);
1486 else if (selection_data->target == GDK_TARGET_STRING)
1488 return selection_set_string (selection_data, str, len);
1490 else if (selection_data->target == ctext_atom ||
1491 selection_data->target == text_atom)
1493 if (selection_set_compound_text (selection_data, str, len))
1495 else if (selection_data->target == text_atom)
1496 return selection_set_string (selection_data, str, len);
1498 else if (selection_data->target == text_plain_atom ||
1499 selection_data->target == text_plain_utf8_atom ||
1500 selection_data->target == text_plain_locale_atom)
1502 return selection_set_text_plain (selection_data, str, len);
1509 * gtk_selection_data_get_text:
1510 * @selection_data: a #GtkSelectionData
1512 * Gets the contents of the selection data as a UTF-8 string.
1514 * Return value: if the selection data contained a recognized
1515 * text type and it could be converted to UTF-8, a newly allocated
1516 * string containing the converted text, otherwise %NULL.
1517 * If the result is non-%NULL it must be freed with g_free().
1520 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1522 guchar *result = NULL;
1524 g_return_val_if_fail (selection_data != NULL, NULL);
1528 if (selection_data->length >= 0 &&
1529 (selection_data->type == GDK_TARGET_STRING ||
1530 selection_data->type == ctext_atom ||
1531 selection_data->type == utf8_atom))
1535 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1536 selection_data->type,
1537 selection_data->format,
1538 selection_data->data,
1539 selection_data->length,
1542 result = (guchar *) list[0];
1544 for (i = 1; i < count; i++)
1548 else if (selection_data->length >= 0 &&
1549 (selection_data->type == text_plain_atom ||
1550 selection_data->type == text_plain_utf8_atom ||
1551 selection_data->type == text_plain_locale_atom))
1553 result = selection_get_text_plain (selection_data);
1560 * gtk_selection_data_set_pixbuf:
1561 * @selection_data: a #GtkSelectionData
1562 * @pixbuf: a #GdkPixbuf
1564 * Sets the contents of the selection from a #GdkPixbuf
1565 * The pixbuf is converted to the form determined by
1566 * @selection_data->target.
1568 * Return value: %TRUE if the selection was successfully set,
1574 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1577 GSList *formats, *f;
1584 g_return_val_if_fail (selection_data != NULL, FALSE);
1585 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1587 formats = gdk_pixbuf_get_formats ();
1589 for (f = formats; f; f = f->next)
1591 GdkPixbufFormat *fmt = f->data;
1593 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1594 for (m = mimes; *m; m++)
1596 atom = gdk_atom_intern (*m, FALSE);
1597 if (selection_data->target == atom)
1600 type = gdk_pixbuf_format_get_name (fmt);
1601 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1603 ((strcmp (type, "png") == 0) ?
1604 "compression" : NULL), "2",
1607 gtk_selection_data_set (selection_data,
1608 atom, 8, (guchar *)str, len);
1612 g_slist_free (formats);
1621 g_slist_free (formats);
1627 * gtk_selection_data_get_pixbuf:
1628 * @selection_data: a #GtkSelectionData
1630 * Gets the contents of the selection data as a #GdkPixbuf.
1632 * Return value: if the selection data contained a recognized
1633 * image type and it could be converted to a #GdkPixbuf, a
1634 * newly allocated pixbuf is returned, otherwise %NULL.
1635 * If the result is non-%NULL it must be freed with g_object_unref().
1640 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1642 GdkPixbufLoader *loader;
1643 GdkPixbuf *result = NULL;
1645 g_return_val_if_fail (selection_data != NULL, NULL);
1647 if (selection_data->length > 0)
1649 loader = gdk_pixbuf_loader_new ();
1651 gdk_pixbuf_loader_write (loader,
1652 selection_data->data,
1653 selection_data->length,
1655 gdk_pixbuf_loader_close (loader, NULL);
1656 result = gdk_pixbuf_loader_get_pixbuf (loader);
1659 g_object_ref (result);
1661 g_object_unref (loader);
1668 * gtk_selection_data_set_uris:
1669 * @selection_data: a #GtkSelectionData
1670 * @uris: a %NULL-terminated array of strings hilding URIs
1672 * Sets the contents of the selection from a list of URIs.
1673 * The string is converted to the form determined by
1674 * @selection_data->target.
1676 * Return value: %TRUE if the selection was successfully set,
1682 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1685 g_return_val_if_fail (selection_data != NULL, FALSE);
1686 g_return_val_if_fail (uris != NULL, FALSE);
1690 if (selection_data->target == text_uri_list_atom)
1697 list = g_string_new (NULL);
1698 for (i = 0; uris[i]; i++)
1700 g_string_append (list, uris[i]);
1701 g_string_append (list, "\r\n");
1704 result = g_convert (list->str, list->len,
1706 NULL, &length, NULL);
1707 g_string_free (list, TRUE);
1711 gtk_selection_data_set (selection_data,
1713 8, (guchar *)result, length);
1725 * gtk_selection_data_get_uris:
1726 * @selection_data: a #GtkSelectionData
1728 * Gets the contents of the selection data as array of URIs.
1730 * Return value: if the selection data contains a list of
1731 * URIs, a newly allocated %NULL-terminated string array
1732 * containing the URIs, otherwise %NULL. If the result is
1733 * non-%NULL it must be freed with g_strfreev().
1738 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1740 gchar **result = NULL;
1742 g_return_val_if_fail (selection_data != NULL, NULL);
1746 if (selection_data->length >= 0 &&
1747 selection_data->type == text_uri_list_atom)
1750 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1752 selection_data->format,
1753 selection_data->data,
1754 selection_data->length,
1757 result = g_uri_list_extract_uris (list[0]);
1767 * gtk_selection_data_get_targets:
1768 * @selection_data: a #GtkSelectionData object
1769 * @targets: location to store an array of targets. The result
1770 * stored here must be freed with g_free().
1771 * @n_atoms: location to store number of items in @targets.
1773 * Gets the contents of @selection_data as an array of targets.
1774 * This can be used to interpret the results of getting
1775 * the standard TARGETS target that is always supplied for
1778 * Return value: %TRUE if @selection_data contains a valid
1779 * array of targets, otherwise %FALSE.
1782 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1786 g_return_val_if_fail (selection_data != NULL, FALSE);
1788 if (selection_data->length >= 0 &&
1789 selection_data->format == 32 &&
1790 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1793 *targets = g_memdup (selection_data->data, selection_data->length);
1795 *n_atoms = selection_data->length / sizeof (GdkAtom);
1811 * gtk_targets_include_text:
1812 * @targets: an array of #GdkAtom<!-- -->s
1813 * @n_targets: the length of @targets
1815 * Determines if any of the targets in @targets can be used to
1818 * Return value: %TRUE if @targets include a suitable target for text,
1824 gtk_targets_include_text (GdkAtom *targets,
1828 gboolean result = FALSE;
1830 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1832 /* Keep in sync with gtk_target_list_add_text_targets()
1837 for (i = 0; i < n_targets; i++)
1839 if (targets[i] == utf8_atom ||
1840 targets[i] == text_atom ||
1841 targets[i] == GDK_TARGET_STRING ||
1842 targets[i] == ctext_atom ||
1843 targets[i] == text_plain_atom ||
1844 targets[i] == text_plain_utf8_atom ||
1845 targets[i] == text_plain_locale_atom)
1856 * gtk_targets_include_rich_text:
1857 * @targets: an array of #GdkAtom<!-- -->s
1858 * @n_targets: the length of @targets
1859 * @buffer: a #GtkTextBuffer
1861 * Determines if any of the targets in @targets can be used to
1862 * provide rich text.
1864 * Return value: %TRUE if @targets include a suitable target for rich text,
1870 gtk_targets_include_rich_text (GdkAtom *targets,
1872 GtkTextBuffer *buffer)
1874 GdkAtom *rich_targets;
1875 gint n_rich_targets;
1877 gboolean result = FALSE;
1879 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1880 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1884 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1887 for (i = 0; i < n_targets; i++)
1889 for (j = 0; j < n_rich_targets; j++)
1891 if (targets[i] == rich_targets[j])
1900 g_free (rich_targets);
1906 * gtk_selection_data_targets_include_text:
1907 * @selection_data: a #GtkSelectionData object
1909 * Given a #GtkSelectionData object holding a list of targets,
1910 * determines if any of the targets in @targets can be used to
1913 * Return value: %TRUE if @selection_data holds a list of targets,
1914 * and a suitable target for text is included, otherwise %FALSE.
1917 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1921 gboolean result = FALSE;
1923 g_return_val_if_fail (selection_data != NULL, FALSE);
1927 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1929 result = gtk_targets_include_text (targets, n_targets);
1937 * gtk_selection_data_targets_include_rich_text:
1938 * @selection_data: a #GtkSelectionData object
1939 * @buffer: a #GtkTextBuffer
1941 * Given a #GtkSelectionData object holding a list of targets,
1942 * determines if any of the targets in @targets can be used to
1943 * provide rich text.
1945 * Return value: %TRUE if @selection_data holds a list of targets,
1946 * and a suitable target for rich text is included,
1952 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1953 GtkTextBuffer *buffer)
1957 gboolean result = FALSE;
1959 g_return_val_if_fail (selection_data != NULL, FALSE);
1960 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1964 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1966 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1974 * gtk_targets_include_image:
1975 * @targets: an array of #GdkAtom<!-- -->s
1976 * @n_targets: the length of @targets
1977 * @writable: whether to accept only targets for which GTK+ knows
1978 * how to convert a pixbuf into the format
1980 * Determines if any of the targets in @targets can be used to
1981 * provide a #GdkPixbuf.
1983 * Return value: %TRUE if @targets include a suitable target for images,
1989 gtk_targets_include_image (GdkAtom *targets,
1993 GtkTargetList *list;
1996 gboolean result = FALSE;
1998 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2000 list = gtk_target_list_new (NULL, 0);
2001 gtk_target_list_add_image_targets (list, 0, writable);
2002 for (i = 0; i < n_targets && !result; i++)
2004 for (l = list->list; l; l = l->next)
2006 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2007 if (pair->target == targets[i])
2014 gtk_target_list_unref (list);
2020 * gtk_selection_data_targets_include_image:
2021 * @selection_data: a #GtkSelectionData object
2022 * @writable: whether to accept only targets for which GTK+ knows
2023 * how to convert a pixbuf into the format
2025 * Given a #GtkSelectionData object holding a list of targets,
2026 * determines if any of the targets in @targets can be used to
2027 * provide a #GdkPixbuf.
2029 * Return value: %TRUE if @selection_data holds a list of targets,
2030 * and a suitable target for images is included, otherwise %FALSE.
2035 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2040 gboolean result = FALSE;
2042 g_return_val_if_fail (selection_data != NULL, FALSE);
2046 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2048 result = gtk_targets_include_image (targets, n_targets, writable);
2056 * gtk_targets_include_uri:
2057 * @targets: an array of #GdkAtom<!-- -->s
2058 * @n_targets: the length of @targets
2060 * Determines if any of the targets in @targets can be used to
2061 * provide an uri list.
2063 * Return value: %TRUE if @targets include a suitable target for uri lists,
2069 gtk_targets_include_uri (GdkAtom *targets,
2073 gboolean result = FALSE;
2075 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2077 /* Keep in sync with gtk_target_list_add_uri_targets()
2082 for (i = 0; i < n_targets; i++)
2084 if (targets[i] == text_uri_list_atom)
2095 * gtk_selection_data_targets_include_uri:
2096 * @selection_data: a #GtkSelectionData object
2098 * Given a #GtkSelectionData object holding a list of targets,
2099 * determines if any of the targets in @targets can be used to
2100 * provide a list or URIs.
2102 * Return value: %TRUE if @selection_data holds a list of targets,
2103 * and a suitable target for URI lists is included, otherwise %FALSE.
2108 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2112 gboolean result = FALSE;
2114 g_return_val_if_fail (selection_data != NULL, FALSE);
2118 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2120 result = gtk_targets_include_uri (targets, n_targets);
2128 /*************************************************************
2129 * gtk_selection_init:
2130 * Initialize local variables
2134 *************************************************************/
2137 gtk_selection_init (void)
2139 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2140 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2141 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2142 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2148 * gtk_selection_clear:
2149 * @widget: a #GtkWidget
2152 * The default handler for the GtkWidget::selection_clear_event
2155 * Return value: %TRUE if the event was handled, otherwise false
2159 * Deprecated: 2.4: Instead of calling this function, chain up from
2160 * your selection_clear_event handler. Calling this function
2161 * from any other context is illegal.
2164 gtk_selection_clear (GtkWidget *widget,
2165 GdkEventSelection *event)
2167 /* Note that we filter clear events in gdkselection-x11.c, so
2168 * that we only will get here if the clear event actually
2169 * represents a change that we didn't do ourself.
2172 GtkSelectionInfo *selection_info = NULL;
2174 tmp_list = current_selections;
2177 selection_info = (GtkSelectionInfo *)tmp_list->data;
2179 if ((selection_info->selection == event->selection) &&
2180 (selection_info->widget == widget))
2183 tmp_list = tmp_list->next;
2188 current_selections = g_list_remove_link (current_selections, tmp_list);
2189 g_list_free (tmp_list);
2190 g_slice_free (GtkSelectionInfo, selection_info);
2197 /*************************************************************
2198 * _gtk_selection_request:
2199 * Handler for "selection_request_event"
2204 *************************************************************/
2207 _gtk_selection_request (GtkWidget *widget,
2208 GdkEventSelection *event)
2210 GdkDisplay *display = gtk_widget_get_display (widget);
2214 gulong selection_max_size;
2217 gtk_selection_init ();
2219 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2221 /* Check if we own selection */
2223 tmp_list = current_selections;
2226 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2228 if ((selection_info->selection == event->selection) &&
2229 (selection_info->widget == widget))
2232 tmp_list = tmp_list->next;
2235 if (tmp_list == NULL)
2238 info = g_slice_new (GtkIncrInfo);
2240 g_object_ref (widget);
2242 info->selection = event->selection;
2243 info->num_incrs = 0;
2245 /* Create GdkWindow structure for the requestor */
2247 info->requestor = gdk_window_lookup_for_display (display,
2249 if (!info->requestor)
2250 info->requestor = gdk_window_foreign_new_for_display (display,
2253 /* Determine conversions we need to perform */
2255 if (event->target == gtk_selection_atoms[MULTIPLE])
2264 gdk_error_trap_push ();
2265 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2266 0, selection_max_size, FALSE,
2267 &type, &format, &length, &mult_atoms))
2269 gdk_selection_send_notify_for_display (display,
2275 g_free (mult_atoms);
2276 g_slice_free (GtkIncrInfo, info);
2277 gdk_error_trap_pop ();
2280 gdk_error_trap_pop ();
2282 /* This is annoying; the ICCCM doesn't specify the property type
2283 * used for the property contents, so the autoconversion for
2284 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2286 #ifdef GDK_WINDOWING_X11
2287 if (type != GDK_SELECTION_TYPE_ATOM &&
2288 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2290 info->num_conversions = length / (2*sizeof (glong));
2291 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2293 for (i=0; i<info->num_conversions; i++)
2295 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2296 ((glong *)mult_atoms)[2*i]);
2297 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2298 ((glong *)mult_atoms)[2*i + 1]);
2301 g_free (mult_atoms);
2306 info->num_conversions = length / (2*sizeof (GdkAtom));
2307 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2309 for (i=0; i<info->num_conversions; i++)
2311 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2312 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2315 g_free (mult_atoms);
2318 else /* only a single conversion */
2320 info->conversions = g_new (GtkIncrConversion, 1);
2321 info->num_conversions = 1;
2322 info->conversions[0].target = event->target;
2323 info->conversions[0].property = event->property;
2326 /* Loop through conversions and determine which of these are big
2327 enough to require doing them via INCR */
2328 for (i=0; i<info->num_conversions; i++)
2330 GtkSelectionData data;
2333 data.selection = event->selection;
2334 data.target = info->conversions[i].target;
2337 data.display = gtk_widget_get_display (widget);
2339 #ifdef DEBUG_SELECTION
2340 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2342 info->conversions[i].target,
2343 gdk_atom_name (info->conversions[i].target),
2344 event->requestor, info->conversions[i].property);
2347 gtk_selection_invoke_handler (widget, &data, event->time);
2349 if (data.length < 0)
2351 info->conversions[i].property = GDK_NONE;
2355 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2357 items = data.length / gtk_selection_bytes_per_item (data.format);
2359 if (data.length > selection_max_size)
2361 /* Sending via INCR */
2362 #ifdef DEBUG_SELECTION
2363 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2364 data.length, selection_max_size);
2367 info->conversions[i].offset = 0;
2368 info->conversions[i].data = data;
2371 gdk_property_change (info->requestor,
2372 info->conversions[i].property,
2373 gtk_selection_atoms[INCR],
2375 GDK_PROP_MODE_REPLACE,
2376 (guchar *)&items, 1);
2380 info->conversions[i].offset = -1;
2382 gdk_property_change (info->requestor,
2383 info->conversions[i].property,
2386 GDK_PROP_MODE_REPLACE,
2393 /* If we have some INCR's, we need to send the rest of the data in
2396 if (info->num_incrs > 0)
2398 /* FIXME: this could be dangerous if window doesn't still
2401 #ifdef DEBUG_SELECTION
2402 g_message ("Starting INCR...");
2405 gdk_window_set_events (info->requestor,
2406 gdk_window_get_events (info->requestor) |
2407 GDK_PROPERTY_CHANGE_MASK);
2408 current_incrs = g_list_append (current_incrs, info);
2409 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2412 /* If it was a MULTIPLE request, set the property to indicate which
2413 conversions succeeded */
2414 if (event->target == gtk_selection_atoms[MULTIPLE])
2416 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2417 for (i = 0; i < info->num_conversions; i++)
2419 mult_atoms[2*i] = info->conversions[i].target;
2420 mult_atoms[2*i+1] = info->conversions[i].property;
2423 gdk_property_change (info->requestor, event->property,
2424 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2425 GDK_PROP_MODE_REPLACE,
2426 (guchar *)mult_atoms, 2*info->num_conversions);
2427 g_free (mult_atoms);
2430 if (info->num_conversions == 1 &&
2431 info->conversions[0].property == GDK_NONE)
2433 /* Reject the entire conversion */
2434 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2443 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2451 if (info->num_incrs == 0)
2453 g_free (info->conversions);
2454 g_slice_free (GtkIncrInfo, info);
2457 g_object_unref (widget);
2462 /*************************************************************
2463 * _gtk_selection_incr_event:
2464 * Called whenever an PropertyNotify event occurs for an
2465 * GdkWindow with user_data == NULL. These will be notifications
2466 * that a window we are sending the selection to via the
2467 * INCR protocol has deleted a property and is ready for
2471 * window: the requestor window
2472 * event: the property event structure
2475 *************************************************************/
2478 _gtk_selection_incr_event (GdkWindow *window,
2479 GdkEventProperty *event)
2482 GtkIncrInfo *info = NULL;
2485 gulong selection_max_size;
2489 if (event->state != GDK_PROPERTY_DELETE)
2492 #ifdef DEBUG_SELECTION
2493 g_message ("PropertyDelete, property %ld", event->atom);
2496 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2498 /* Now find the appropriate ongoing INCR */
2499 tmp_list = current_incrs;
2502 info = (GtkIncrInfo *)tmp_list->data;
2503 if (info->requestor == event->window)
2506 tmp_list = tmp_list->next;
2509 if (tmp_list == NULL)
2512 /* Find out which target this is for */
2513 for (i=0; i<info->num_conversions; i++)
2515 if (info->conversions[i].property == event->atom &&
2516 info->conversions[i].offset != -1)
2520 info->idle_time = 0;
2522 if (info->conversions[i].offset == -2) /* only the last 0-length
2530 num_bytes = info->conversions[i].data.length -
2531 info->conversions[i].offset;
2532 buffer = info->conversions[i].data.data +
2533 info->conversions[i].offset;
2535 if (num_bytes > selection_max_size)
2537 num_bytes = selection_max_size;
2538 info->conversions[i].offset += selection_max_size;
2541 info->conversions[i].offset = -2;
2543 #ifdef DEBUG_SELECTION
2544 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2545 num_bytes, info->conversions[i].offset,
2546 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2549 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2550 gdk_property_change (info->requestor, event->atom,
2551 info->conversions[i].data.type,
2552 info->conversions[i].data.format,
2553 GDK_PROP_MODE_REPLACE,
2555 num_bytes / bytes_per_item);
2557 if (info->conversions[i].offset == -2)
2559 g_free (info->conversions[i].data.data);
2560 info->conversions[i].data.data = NULL;
2566 info->conversions[i].offset = -1;
2571 /* Check if we're finished with all the targets */
2573 if (info->num_incrs == 0)
2575 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2576 g_list_free (tmp_list);
2577 /* Let the timeout free it */
2583 /*************************************************************
2584 * gtk_selection_incr_timeout:
2585 * Timeout callback for the sending portion of the INCR
2588 * info: Information about this incr
2590 *************************************************************/
2593 gtk_selection_incr_timeout (GtkIncrInfo *info)
2598 /* Determine if retrieval has finished by checking if it still in
2599 list of pending retrievals */
2601 tmp_list = current_incrs;
2604 if (info == (GtkIncrInfo *)tmp_list->data)
2606 tmp_list = tmp_list->next;
2609 /* If retrieval is finished */
2610 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2612 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2614 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2615 g_list_free (tmp_list);
2618 g_free (info->conversions);
2619 /* FIXME: we should check if requestor window is still in use,
2620 and if not, remove it? */
2622 g_slice_free (GtkIncrInfo, info);
2624 retval = FALSE; /* remove timeout */
2630 retval = TRUE; /* timeout will happen again */
2636 /*************************************************************
2637 * _gtk_selection_notify:
2638 * Handler for "selection_notify_event" signals on windows
2639 * where a retrieval is currently in process. The selection
2640 * owner has responded to our conversion request.
2642 * widget: Widget getting signal
2643 * event: Selection event structure
2644 * info: Information about this retrieval
2646 * was event handled?
2647 *************************************************************/
2650 _gtk_selection_notify (GtkWidget *widget,
2651 GdkEventSelection *event)
2654 GtkRetrievalInfo *info = NULL;
2655 guchar *buffer = NULL;
2660 #ifdef DEBUG_SELECTION
2661 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2662 event->selection, event->target, event->property);
2665 tmp_list = current_retrievals;
2668 info = (GtkRetrievalInfo *)tmp_list->data;
2669 if (info->widget == widget && info->selection == event->selection)
2671 tmp_list = tmp_list->next;
2674 if (!tmp_list) /* no retrieval in progress */
2677 if (event->property != GDK_NONE)
2678 length = gdk_selection_property_get (widget->window, &buffer,
2681 length = 0; /* silence gcc */
2683 if (event->property == GDK_NONE || buffer == NULL)
2685 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2686 g_list_free (tmp_list);
2687 /* structure will be freed in timeout */
2688 gtk_selection_retrieval_report (info,
2689 GDK_NONE, 0, NULL, -1, event->time);
2694 if (type == gtk_selection_atoms[INCR])
2696 /* The remainder of the selection will come through PropertyNotify
2699 info->notify_time = event->time;
2700 info->idle_time = 0;
2701 info->offset = 0; /* Mark as OK to proceed */
2702 gdk_window_set_events (widget->window,
2703 gdk_window_get_events (widget->window)
2704 | GDK_PROPERTY_CHANGE_MASK);
2708 /* We don't delete the info structure - that will happen in timeout */
2709 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2710 g_list_free (tmp_list);
2712 info->offset = length;
2713 gtk_selection_retrieval_report (info,
2715 buffer, length, event->time);
2718 gdk_property_delete (widget->window, event->property);
2725 /*************************************************************
2726 * _gtk_selection_property_notify:
2727 * Handler for "property_notify_event" signals on windows
2728 * where a retrieval is currently in process. The selection
2729 * owner has added more data.
2731 * widget: Widget getting signal
2732 * event: Property event structure
2733 * info: Information about this retrieval
2735 * was event handled?
2736 *************************************************************/
2739 _gtk_selection_property_notify (GtkWidget *widget,
2740 GdkEventProperty *event)
2743 GtkRetrievalInfo *info = NULL;
2749 g_return_val_if_fail (widget != NULL, FALSE);
2750 g_return_val_if_fail (event != NULL, FALSE);
2752 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2753 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2754 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2758 #ifdef DEBUG_SELECTION
2759 g_message ("PropertyNewValue, property %ld",
2763 tmp_list = current_retrievals;
2766 info = (GtkRetrievalInfo *)tmp_list->data;
2767 if (info->widget == widget)
2769 tmp_list = tmp_list->next;
2772 if (!tmp_list) /* No retrieval in progress */
2775 if (info->offset < 0) /* We haven't got the SelectionNotify
2776 for this retrieval yet */
2779 info->idle_time = 0;
2781 length = gdk_selection_property_get (widget->window, &new_buffer,
2783 gdk_property_delete (widget->window, event->atom);
2785 /* We could do a lot better efficiency-wise by paying attention to
2786 what length was sent in the initial INCR transaction, instead of
2787 doing memory allocation at every step. But its only guaranteed to
2788 be a _lower bound_ (pretty useless!) */
2790 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2792 /* Info structure will be freed in timeout */
2793 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2794 g_list_free (tmp_list);
2795 gtk_selection_retrieval_report (info,
2797 (type == GDK_NONE) ? NULL : info->buffer,
2798 (type == GDK_NONE) ? -1 : info->offset,
2801 else /* append on newly arrived data */
2805 #ifdef DEBUG_SELECTION
2806 g_message ("Start - Adding %d bytes at offset 0",
2809 info->buffer = new_buffer;
2810 info->offset = length;
2815 #ifdef DEBUG_SELECTION
2816 g_message ("Appending %d bytes at offset %d",
2817 length,info->offset);
2819 /* We copy length+1 bytes to preserve guaranteed null termination */
2820 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2821 memcpy (info->buffer + info->offset, new_buffer, length+1);
2822 info->offset += length;
2823 g_free (new_buffer);
2830 /*************************************************************
2831 * gtk_selection_retrieval_timeout:
2832 * Timeout callback while receiving a selection.
2834 * info: Information about this retrieval
2836 *************************************************************/
2839 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2844 /* Determine if retrieval has finished by checking if it still in
2845 list of pending retrievals */
2847 tmp_list = current_retrievals;
2850 if (info == (GtkRetrievalInfo *)tmp_list->data)
2852 tmp_list = tmp_list->next;
2855 /* If retrieval is finished */
2856 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2858 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2860 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2861 g_list_free (tmp_list);
2862 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2865 g_free (info->buffer);
2866 g_slice_free (GtkRetrievalInfo, info);
2868 retval = FALSE; /* remove timeout */
2874 retval = TRUE; /* timeout will happen again */
2880 /*************************************************************
2881 * gtk_selection_retrieval_report:
2882 * Emits a "selection_received" signal.
2884 * info: information about the retrieval that completed
2885 * buffer: buffer containing data (NULL => errror)
2886 * time: timestamp for data in buffer
2888 *************************************************************/
2891 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2892 GdkAtom type, gint format,
2893 guchar *buffer, gint length,
2896 GtkSelectionData data;
2898 data.selection = info->selection;
2899 data.target = info->target;
2901 data.format = format;
2903 data.length = length;
2905 data.display = gtk_widget_get_display (info->widget);
2907 g_signal_emit_by_name (info->widget,
2908 "selection_received",
2912 /*************************************************************
2913 * gtk_selection_invoke_handler:
2914 * Finds and invokes handler for specified
2915 * widget/selection/target combination, calls
2916 * gtk_selection_default_handler if none exists.
2919 * widget: selection owner
2920 * data: selection data [INOUT]
2921 * time: time from requeset
2924 * Number of bytes written to buffer, -1 if error
2925 *************************************************************/
2928 gtk_selection_invoke_handler (GtkWidget *widget,
2929 GtkSelectionData *data,
2932 GtkTargetList *target_list;
2936 g_return_if_fail (widget != NULL);
2938 target_list = gtk_selection_target_list_get (widget, data->selection);
2940 gtk_target_list_find (target_list, data->target, &info))
2942 g_signal_emit_by_name (widget,
2948 gtk_selection_default_handler (widget, data);
2951 /*************************************************************
2952 * gtk_selection_default_handler:
2953 * Handles some default targets that exist for any widget
2954 * If it can't fit results into buffer, returns -1. This
2955 * won't happen in any conceivable case, since it would
2956 * require 1000 selection targets!
2959 * widget: selection owner
2960 * data: selection data [INOUT]
2962 *************************************************************/
2965 gtk_selection_default_handler (GtkWidget *widget,
2966 GtkSelectionData *data)
2968 if (data->target == gtk_selection_atoms[TIMESTAMP])
2970 /* Time which was used to obtain selection */
2972 GtkSelectionInfo *selection_info;
2974 tmp_list = current_selections;
2977 selection_info = (GtkSelectionInfo *)tmp_list->data;
2978 if ((selection_info->widget == widget) &&
2979 (selection_info->selection == data->selection))
2981 gulong time = selection_info->time;
2983 gtk_selection_data_set (data,
2984 GDK_SELECTION_TYPE_INTEGER,
2991 tmp_list = tmp_list->next;
2996 else if (data->target == gtk_selection_atoms[TARGETS])
2998 /* List of all targets supported for this widget/selection pair */
3002 GtkTargetList *target_list;
3003 GtkTargetPair *pair;
3005 target_list = gtk_selection_target_list_get (widget,
3007 count = g_list_length (target_list->list) + 3;
3009 data->type = GDK_SELECTION_TYPE_ATOM;
3011 data->length = count * sizeof (GdkAtom);
3013 /* selection data is always terminated by a trailing \0
3015 p = g_malloc (data->length + 1);
3016 data->data = (guchar *)p;
3017 data->data[data->length] = '\0';
3019 *p++ = gtk_selection_atoms[TIMESTAMP];
3020 *p++ = gtk_selection_atoms[TARGETS];
3021 *p++ = gtk_selection_atoms[MULTIPLE];
3023 tmp_list = target_list->list;
3026 pair = (GtkTargetPair *)tmp_list->data;
3027 *p++ = pair->target;
3029 tmp_list = tmp_list->next;
3040 * gtk_selection_data_copy:
3041 * @data: a pointer to a #GtkSelectionData structure.
3043 * Makes a copy of a #GtkSelectionData structure and its data.
3045 * Return value: a pointer to a copy of @data.
3048 gtk_selection_data_copy (GtkSelectionData *data)
3050 GtkSelectionData *new_data;
3052 g_return_val_if_fail (data != NULL, NULL);
3054 new_data = g_slice_new (GtkSelectionData);
3059 new_data->data = g_malloc (data->length + 1);
3060 memcpy (new_data->data, data->data, data->length + 1);
3067 * gtk_selection_data_free:
3068 * @data: a pointer to a #GtkSelectionData structure.
3070 * Frees a #GtkSelectionData structure returned from
3071 * gtk_selection_data_copy().
3074 gtk_selection_data_free (GtkSelectionData *data)
3076 g_return_if_fail (data != NULL);
3078 g_free (data->data);
3080 g_slice_free (GtkSelectionData, data);
3084 gtk_selection_data_get_type (void)
3086 static GType our_type = 0;
3089 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3090 (GBoxedCopyFunc) gtk_selection_data_copy,
3091 (GBoxedFreeFunc) gtk_selection_data_free);
3097 gtk_target_list_get_type (void)
3099 static GType our_type = 0;
3102 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3103 (GBoxedCopyFunc) gtk_target_list_ref,
3104 (GBoxedFreeFunc) gtk_target_list_unref);
3110 gtk_selection_bytes_per_item (gint format)
3115 return sizeof (char);
3118 return sizeof (short);
3121 return sizeof (long);
3124 g_assert_not_reached();
3129 #define __GTK_SELECTION_C__
3130 #include "gtkaliasdef.c"