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_selection:
1116 * @selection_data: a pointer to a #GtkSelectionData structure.
1118 * Retrieves the selection #GdkAtom of the selection data.
1120 * Returns: the selection #GdkAtom of the selection data.
1125 gtk_selection_data_get_selection (GtkSelectionData *selection_data)
1127 g_return_val_if_fail (selection_data != NULL, 0);
1129 return selection_data->selection;
1133 * gtk_selection_data_get_target:
1134 * @selection_data: a pointer to a #GtkSelectionData structure.
1136 * Retrieves the target of the selection.
1138 * Returns: the target of the selection.
1143 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1145 g_return_val_if_fail (selection_data != NULL, 0);
1147 return selection_data->target;
1151 * gtk_selection_data_get_data_type:
1152 * @selection_data: a pointer to a #GtkSelectionData structure.
1154 * Retrieves the data type of the selection.
1156 * Returns: the data type of the selection.
1161 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1163 g_return_val_if_fail (selection_data != NULL, 0);
1165 return selection_data->type;
1169 * gtk_selection_data_get_format:
1170 * @selection_data: a pointer to a #GtkSelectionData structure.
1172 * Retrieves the format of the selection.
1174 * Returns: the format of the selection.
1179 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1181 g_return_val_if_fail (selection_data != NULL, 0);
1183 return selection_data->format;
1187 * gtk_selection_data_get_data:
1188 * @selection_data: a pointer to a #GtkSelectionData structure.
1190 * Retrieves the raw data of the selection.
1192 * Returns: the raw data of the selection.
1197 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1199 g_return_val_if_fail (selection_data != NULL, NULL);
1201 return selection_data->data;
1205 * gtk_selection_data_get_length:
1206 * @selection_data: a pointer to a #GtkSelectionData structure.
1208 * Retrieves the length of the raw data of the selection.
1210 * Returns: the length of the data of the selection.
1215 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1217 g_return_val_if_fail (selection_data != NULL, -1);
1219 return selection_data->length;
1223 * gtk_selection_data_get_display:
1224 * @selection_data: a pointer to a #GtkSelectionData structure.
1226 * Retrieves the display of the selection.
1228 * Returns: the display of the selection.
1233 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1235 g_return_val_if_fail (selection_data != NULL, NULL);
1237 return selection_data->display;
1241 * gtk_selection_data_set:
1242 * @selection_data: a pointer to a #GtkSelectionData structure.
1243 * @type: the type of selection data
1244 * @format: format (number of bits in a unit)
1245 * @data: pointer to the data (will be copied)
1246 * @length: length of the data
1248 * Stores new data into a #GtkSelectionData object. Should
1249 * <emphasis>only</emphasis> be called from a selection handler callback.
1250 * Zero-terminates the stored data.
1253 gtk_selection_data_set (GtkSelectionData *selection_data,
1259 g_return_if_fail (selection_data != NULL);
1261 g_free (selection_data->data);
1263 selection_data->type = type;
1264 selection_data->format = format;
1268 selection_data->data = g_new (guchar, length+1);
1269 memcpy (selection_data->data, data, length);
1270 selection_data->data[length] = 0;
1274 g_return_if_fail (length <= 0);
1277 selection_data->data = NULL;
1279 selection_data->data = (guchar *) g_strdup ("");
1282 selection_data->length = length;
1286 selection_set_string (GtkSelectionData *selection_data,
1290 gchar *tmp = g_strndup (str, len);
1291 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1296 gtk_selection_data_set (selection_data,
1297 GDK_SELECTION_TYPE_STRING,
1298 8, (guchar *) latin1, strlen (latin1));
1308 selection_set_compound_text (GtkSelectionData *selection_data,
1317 gboolean result = FALSE;
1319 tmp = g_strndup (str, len);
1320 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1321 &encoding, &format, &text, &new_length))
1323 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1324 gdk_free_compound_text (text);
1334 /* Normalize \r and \n into \r\n
1337 normalize_to_crlf (const gchar *str,
1340 GString *result = g_string_sized_new (len);
1341 const gchar *p = str;
1342 const gchar *end = str + len;
1347 g_string_append_c (result, '\r');
1351 g_string_append_c (result, *p);
1353 if (p == end || *p != '\n')
1354 g_string_append_c (result, '\n');
1359 g_string_append_c (result, *p);
1363 return g_string_free (result, FALSE);
1366 /* Normalize \r and \r\n into \n
1369 normalize_to_lf (gchar *str,
1372 GString *result = g_string_sized_new (len);
1373 const gchar *p = str;
1381 g_string_append_c (result, '\n');
1387 g_string_append_c (result, *p);
1391 return g_string_free (result, FALSE);
1395 selection_set_text_plain (GtkSelectionData *selection_data,
1399 const gchar *charset = NULL;
1401 GError *error = NULL;
1403 result = normalize_to_crlf (str, len);
1404 if (selection_data->target == text_plain_atom)
1406 else if (selection_data->target == text_plain_locale_atom)
1407 g_get_charset (&charset);
1411 gchar *tmp = result;
1412 result = g_convert_with_fallback (tmp, -1,
1414 NULL, NULL, NULL, &error);
1420 g_warning ("Error converting from %s to %s: %s",
1421 "UTF-8", charset, error->message);
1422 g_error_free (error);
1427 gtk_selection_data_set (selection_data,
1428 selection_data->target,
1429 8, (guchar *) result, strlen (result));
1436 selection_get_text_plain (GtkSelectionData *selection_data)
1438 const gchar *charset = NULL;
1439 gchar *str, *result;
1441 GError *error = NULL;
1443 str = g_strdup ((const gchar *) selection_data->data);
1444 len = selection_data->length;
1446 if (selection_data->type == text_plain_atom)
1447 charset = "ISO-8859-1";
1448 else if (selection_data->type == text_plain_locale_atom)
1449 g_get_charset (&charset);
1454 str = g_convert_with_fallback (tmp, len,
1456 NULL, NULL, &len, &error);
1461 g_warning ("Error converting from %s to %s: %s",
1462 charset, "UTF-8", error->message);
1463 g_error_free (error);
1468 else if (!g_utf8_validate (str, -1, NULL))
1470 g_warning ("Error converting from %s to %s: %s",
1471 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1477 result = normalize_to_lf (str, len);
1480 return (guchar *) result;
1484 * gtk_selection_data_set_text:
1485 * @selection_data: a #GtkSelectionData
1486 * @str: a UTF-8 string
1487 * @len: the length of @str, or -1 if @str is nul-terminated.
1489 * Sets the contents of the selection from a UTF-8 encoded string.
1490 * The string is converted to the form determined by
1491 * @selection_data->target.
1493 * Return value: %TRUE if the selection was successfully set,
1497 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1501 g_return_val_if_fail (selection_data != NULL, FALSE);
1508 if (selection_data->target == utf8_atom)
1510 gtk_selection_data_set (selection_data,
1512 8, (guchar *)str, len);
1515 else if (selection_data->target == GDK_TARGET_STRING)
1517 return selection_set_string (selection_data, str, len);
1519 else if (selection_data->target == ctext_atom ||
1520 selection_data->target == text_atom)
1522 if (selection_set_compound_text (selection_data, str, len))
1524 else if (selection_data->target == text_atom)
1525 return selection_set_string (selection_data, str, len);
1527 else if (selection_data->target == text_plain_atom ||
1528 selection_data->target == text_plain_utf8_atom ||
1529 selection_data->target == text_plain_locale_atom)
1531 return selection_set_text_plain (selection_data, str, len);
1538 * gtk_selection_data_get_text:
1539 * @selection_data: a #GtkSelectionData
1541 * Gets the contents of the selection data as a UTF-8 string.
1543 * Return value: if the selection data contained a recognized
1544 * text type and it could be converted to UTF-8, a newly allocated
1545 * string containing the converted text, otherwise %NULL.
1546 * If the result is non-%NULL it must be freed with g_free().
1549 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1551 guchar *result = NULL;
1553 g_return_val_if_fail (selection_data != NULL, NULL);
1557 if (selection_data->length >= 0 &&
1558 (selection_data->type == GDK_TARGET_STRING ||
1559 selection_data->type == ctext_atom ||
1560 selection_data->type == utf8_atom))
1564 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1565 selection_data->type,
1566 selection_data->format,
1567 selection_data->data,
1568 selection_data->length,
1571 result = (guchar *) list[0];
1573 for (i = 1; i < count; i++)
1577 else if (selection_data->length >= 0 &&
1578 (selection_data->type == text_plain_atom ||
1579 selection_data->type == text_plain_utf8_atom ||
1580 selection_data->type == text_plain_locale_atom))
1582 result = selection_get_text_plain (selection_data);
1589 * gtk_selection_data_set_pixbuf:
1590 * @selection_data: a #GtkSelectionData
1591 * @pixbuf: a #GdkPixbuf
1593 * Sets the contents of the selection from a #GdkPixbuf
1594 * The pixbuf is converted to the form determined by
1595 * @selection_data->target.
1597 * Return value: %TRUE if the selection was successfully set,
1603 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1606 GSList *formats, *f;
1613 g_return_val_if_fail (selection_data != NULL, FALSE);
1614 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1616 formats = gdk_pixbuf_get_formats ();
1618 for (f = formats; f; f = f->next)
1620 GdkPixbufFormat *fmt = f->data;
1622 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1623 for (m = mimes; *m; m++)
1625 atom = gdk_atom_intern (*m, FALSE);
1626 if (selection_data->target == atom)
1629 type = gdk_pixbuf_format_get_name (fmt);
1630 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1632 ((strcmp (type, "png") == 0) ?
1633 "compression" : NULL), "2",
1636 gtk_selection_data_set (selection_data,
1637 atom, 8, (guchar *)str, len);
1641 g_slist_free (formats);
1650 g_slist_free (formats);
1656 * gtk_selection_data_get_pixbuf:
1657 * @selection_data: a #GtkSelectionData
1659 * Gets the contents of the selection data as a #GdkPixbuf.
1661 * Return value: if the selection data contained a recognized
1662 * image type and it could be converted to a #GdkPixbuf, a
1663 * newly allocated pixbuf is returned, otherwise %NULL.
1664 * If the result is non-%NULL it must be freed with g_object_unref().
1669 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1671 GdkPixbufLoader *loader;
1672 GdkPixbuf *result = NULL;
1674 g_return_val_if_fail (selection_data != NULL, NULL);
1676 if (selection_data->length > 0)
1678 loader = gdk_pixbuf_loader_new ();
1680 gdk_pixbuf_loader_write (loader,
1681 selection_data->data,
1682 selection_data->length,
1684 gdk_pixbuf_loader_close (loader, NULL);
1685 result = gdk_pixbuf_loader_get_pixbuf (loader);
1688 g_object_ref (result);
1690 g_object_unref (loader);
1697 * gtk_selection_data_set_uris:
1698 * @selection_data: a #GtkSelectionData
1699 * @uris: a %NULL-terminated array of strings hilding URIs
1701 * Sets the contents of the selection from a list of URIs.
1702 * The string is converted to the form determined by
1703 * @selection_data->target.
1705 * Return value: %TRUE if the selection was successfully set,
1711 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1714 g_return_val_if_fail (selection_data != NULL, FALSE);
1715 g_return_val_if_fail (uris != NULL, FALSE);
1719 if (selection_data->target == text_uri_list_atom)
1726 list = g_string_new (NULL);
1727 for (i = 0; uris[i]; i++)
1729 g_string_append (list, uris[i]);
1730 g_string_append (list, "\r\n");
1733 result = g_convert (list->str, list->len,
1735 NULL, &length, NULL);
1736 g_string_free (list, TRUE);
1740 gtk_selection_data_set (selection_data,
1742 8, (guchar *)result, length);
1754 * gtk_selection_data_get_uris:
1755 * @selection_data: a #GtkSelectionData
1757 * Gets the contents of the selection data as array of URIs.
1759 * Return value: if the selection data contains a list of
1760 * URIs, a newly allocated %NULL-terminated string array
1761 * containing the URIs, otherwise %NULL. If the result is
1762 * non-%NULL it must be freed with g_strfreev().
1767 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1769 gchar **result = NULL;
1771 g_return_val_if_fail (selection_data != NULL, NULL);
1775 if (selection_data->length >= 0 &&
1776 selection_data->type == text_uri_list_atom)
1779 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1781 selection_data->format,
1782 selection_data->data,
1783 selection_data->length,
1786 result = g_uri_list_extract_uris (list[0]);
1796 * gtk_selection_data_get_targets:
1797 * @selection_data: a #GtkSelectionData object
1798 * @targets: location to store an array of targets. The result
1799 * stored here must be freed with g_free().
1800 * @n_atoms: location to store number of items in @targets.
1802 * Gets the contents of @selection_data as an array of targets.
1803 * This can be used to interpret the results of getting
1804 * the standard TARGETS target that is always supplied for
1807 * Return value: %TRUE if @selection_data contains a valid
1808 * array of targets, otherwise %FALSE.
1811 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1815 g_return_val_if_fail (selection_data != NULL, FALSE);
1817 if (selection_data->length >= 0 &&
1818 selection_data->format == 32 &&
1819 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1822 *targets = g_memdup (selection_data->data, selection_data->length);
1824 *n_atoms = selection_data->length / sizeof (GdkAtom);
1840 * gtk_targets_include_text:
1841 * @targets: an array of #GdkAtom<!-- -->s
1842 * @n_targets: the length of @targets
1844 * Determines if any of the targets in @targets can be used to
1847 * Return value: %TRUE if @targets include a suitable target for text,
1853 gtk_targets_include_text (GdkAtom *targets,
1857 gboolean result = FALSE;
1859 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1861 /* Keep in sync with gtk_target_list_add_text_targets()
1866 for (i = 0; i < n_targets; i++)
1868 if (targets[i] == utf8_atom ||
1869 targets[i] == text_atom ||
1870 targets[i] == GDK_TARGET_STRING ||
1871 targets[i] == ctext_atom ||
1872 targets[i] == text_plain_atom ||
1873 targets[i] == text_plain_utf8_atom ||
1874 targets[i] == text_plain_locale_atom)
1885 * gtk_targets_include_rich_text:
1886 * @targets: an array of #GdkAtom<!-- -->s
1887 * @n_targets: the length of @targets
1888 * @buffer: a #GtkTextBuffer
1890 * Determines if any of the targets in @targets can be used to
1891 * provide rich text.
1893 * Return value: %TRUE if @targets include a suitable target for rich text,
1899 gtk_targets_include_rich_text (GdkAtom *targets,
1901 GtkTextBuffer *buffer)
1903 GdkAtom *rich_targets;
1904 gint n_rich_targets;
1906 gboolean result = FALSE;
1908 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1909 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1913 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1916 for (i = 0; i < n_targets; i++)
1918 for (j = 0; j < n_rich_targets; j++)
1920 if (targets[i] == rich_targets[j])
1929 g_free (rich_targets);
1935 * gtk_selection_data_targets_include_text:
1936 * @selection_data: a #GtkSelectionData object
1938 * Given a #GtkSelectionData object holding a list of targets,
1939 * determines if any of the targets in @targets can be used to
1942 * Return value: %TRUE if @selection_data holds a list of targets,
1943 * and a suitable target for text is included, otherwise %FALSE.
1946 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1950 gboolean result = FALSE;
1952 g_return_val_if_fail (selection_data != NULL, FALSE);
1956 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1958 result = gtk_targets_include_text (targets, n_targets);
1966 * gtk_selection_data_targets_include_rich_text:
1967 * @selection_data: a #GtkSelectionData object
1968 * @buffer: a #GtkTextBuffer
1970 * Given a #GtkSelectionData object holding a list of targets,
1971 * determines if any of the targets in @targets can be used to
1972 * provide rich text.
1974 * Return value: %TRUE if @selection_data holds a list of targets,
1975 * and a suitable target for rich text is included,
1981 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1982 GtkTextBuffer *buffer)
1986 gboolean result = FALSE;
1988 g_return_val_if_fail (selection_data != NULL, FALSE);
1989 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1993 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1995 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2003 * gtk_targets_include_image:
2004 * @targets: an array of #GdkAtom<!-- -->s
2005 * @n_targets: the length of @targets
2006 * @writable: whether to accept only targets for which GTK+ knows
2007 * how to convert a pixbuf into the format
2009 * Determines if any of the targets in @targets can be used to
2010 * provide a #GdkPixbuf.
2012 * Return value: %TRUE if @targets include a suitable target for images,
2018 gtk_targets_include_image (GdkAtom *targets,
2022 GtkTargetList *list;
2025 gboolean result = FALSE;
2027 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2029 list = gtk_target_list_new (NULL, 0);
2030 gtk_target_list_add_image_targets (list, 0, writable);
2031 for (i = 0; i < n_targets && !result; i++)
2033 for (l = list->list; l; l = l->next)
2035 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2036 if (pair->target == targets[i])
2043 gtk_target_list_unref (list);
2049 * gtk_selection_data_targets_include_image:
2050 * @selection_data: a #GtkSelectionData object
2051 * @writable: whether to accept only targets for which GTK+ knows
2052 * how to convert a pixbuf into the format
2054 * Given a #GtkSelectionData object holding a list of targets,
2055 * determines if any of the targets in @targets can be used to
2056 * provide a #GdkPixbuf.
2058 * Return value: %TRUE if @selection_data holds a list of targets,
2059 * and a suitable target for images is included, otherwise %FALSE.
2064 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2069 gboolean result = FALSE;
2071 g_return_val_if_fail (selection_data != NULL, FALSE);
2075 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2077 result = gtk_targets_include_image (targets, n_targets, writable);
2085 * gtk_targets_include_uri:
2086 * @targets: an array of #GdkAtom<!-- -->s
2087 * @n_targets: the length of @targets
2089 * Determines if any of the targets in @targets can be used to
2090 * provide an uri list.
2092 * Return value: %TRUE if @targets include a suitable target for uri lists,
2098 gtk_targets_include_uri (GdkAtom *targets,
2102 gboolean result = FALSE;
2104 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2106 /* Keep in sync with gtk_target_list_add_uri_targets()
2111 for (i = 0; i < n_targets; i++)
2113 if (targets[i] == text_uri_list_atom)
2124 * gtk_selection_data_targets_include_uri:
2125 * @selection_data: a #GtkSelectionData object
2127 * Given a #GtkSelectionData object holding a list of targets,
2128 * determines if any of the targets in @targets can be used to
2129 * provide a list or URIs.
2131 * Return value: %TRUE if @selection_data holds a list of targets,
2132 * and a suitable target for URI lists is included, otherwise %FALSE.
2137 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2141 gboolean result = FALSE;
2143 g_return_val_if_fail (selection_data != NULL, FALSE);
2147 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2149 result = gtk_targets_include_uri (targets, n_targets);
2157 /*************************************************************
2158 * gtk_selection_init:
2159 * Initialize local variables
2163 *************************************************************/
2166 gtk_selection_init (void)
2168 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2169 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2170 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2171 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2177 * gtk_selection_clear:
2178 * @widget: a #GtkWidget
2181 * The default handler for the #GtkWidget::selection-clear-event
2184 * Return value: %TRUE if the event was handled, otherwise false
2188 * Deprecated: 2.4: Instead of calling this function, chain up from
2189 * your selection-clear-event handler. Calling this function
2190 * from any other context is illegal.
2193 gtk_selection_clear (GtkWidget *widget,
2194 GdkEventSelection *event)
2196 /* Note that we filter clear events in gdkselection-x11.c, so
2197 * that we only will get here if the clear event actually
2198 * represents a change that we didn't do ourself.
2201 GtkSelectionInfo *selection_info = NULL;
2203 tmp_list = current_selections;
2206 selection_info = (GtkSelectionInfo *)tmp_list->data;
2208 if ((selection_info->selection == event->selection) &&
2209 (selection_info->widget == widget))
2212 tmp_list = tmp_list->next;
2217 current_selections = g_list_remove_link (current_selections, tmp_list);
2218 g_list_free (tmp_list);
2219 g_slice_free (GtkSelectionInfo, selection_info);
2226 /*************************************************************
2227 * _gtk_selection_request:
2228 * Handler for "selection_request_event"
2233 *************************************************************/
2236 _gtk_selection_request (GtkWidget *widget,
2237 GdkEventSelection *event)
2239 GdkDisplay *display = gtk_widget_get_display (widget);
2243 gulong selection_max_size;
2246 gtk_selection_init ();
2248 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2250 /* Check if we own selection */
2252 tmp_list = current_selections;
2255 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2257 if ((selection_info->selection == event->selection) &&
2258 (selection_info->widget == widget))
2261 tmp_list = tmp_list->next;
2264 if (tmp_list == NULL)
2267 info = g_slice_new (GtkIncrInfo);
2269 g_object_ref (widget);
2271 info->selection = event->selection;
2272 info->num_incrs = 0;
2274 /* Create GdkWindow structure for the requestor */
2276 info->requestor = gdk_window_lookup_for_display (display,
2278 if (!info->requestor)
2279 info->requestor = gdk_window_foreign_new_for_display (display,
2282 /* Determine conversions we need to perform */
2284 if (event->target == gtk_selection_atoms[MULTIPLE])
2293 gdk_error_trap_push ();
2294 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2295 0, selection_max_size, FALSE,
2296 &type, &format, &length, &mult_atoms))
2298 gdk_selection_send_notify_for_display (display,
2304 g_free (mult_atoms);
2305 g_slice_free (GtkIncrInfo, info);
2306 gdk_error_trap_pop ();
2309 gdk_error_trap_pop ();
2311 /* This is annoying; the ICCCM doesn't specify the property type
2312 * used for the property contents, so the autoconversion for
2313 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2315 #ifdef GDK_WINDOWING_X11
2316 if (type != GDK_SELECTION_TYPE_ATOM &&
2317 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2319 info->num_conversions = length / (2*sizeof (glong));
2320 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2322 for (i=0; i<info->num_conversions; i++)
2324 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2325 ((glong *)mult_atoms)[2*i]);
2326 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2327 ((glong *)mult_atoms)[2*i + 1]);
2330 g_free (mult_atoms);
2335 info->num_conversions = length / (2*sizeof (GdkAtom));
2336 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2338 for (i=0; i<info->num_conversions; i++)
2340 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2341 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2344 g_free (mult_atoms);
2347 else /* only a single conversion */
2349 info->conversions = g_new (GtkIncrConversion, 1);
2350 info->num_conversions = 1;
2351 info->conversions[0].target = event->target;
2352 info->conversions[0].property = event->property;
2355 /* Loop through conversions and determine which of these are big
2356 enough to require doing them via INCR */
2357 for (i=0; i<info->num_conversions; i++)
2359 GtkSelectionData data;
2362 data.selection = event->selection;
2363 data.target = info->conversions[i].target;
2366 data.display = gtk_widget_get_display (widget);
2368 #ifdef DEBUG_SELECTION
2369 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2371 info->conversions[i].target,
2372 gdk_atom_name (info->conversions[i].target),
2373 event->requestor, info->conversions[i].property);
2376 gtk_selection_invoke_handler (widget, &data, event->time);
2378 if (data.length < 0)
2380 info->conversions[i].property = GDK_NONE;
2384 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2386 items = data.length / gtk_selection_bytes_per_item (data.format);
2388 if (data.length > selection_max_size)
2390 /* Sending via INCR */
2391 #ifdef DEBUG_SELECTION
2392 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2393 data.length, selection_max_size);
2396 info->conversions[i].offset = 0;
2397 info->conversions[i].data = data;
2400 gdk_property_change (info->requestor,
2401 info->conversions[i].property,
2402 gtk_selection_atoms[INCR],
2404 GDK_PROP_MODE_REPLACE,
2405 (guchar *)&items, 1);
2409 info->conversions[i].offset = -1;
2411 gdk_property_change (info->requestor,
2412 info->conversions[i].property,
2415 GDK_PROP_MODE_REPLACE,
2422 /* If we have some INCR's, we need to send the rest of the data in
2425 if (info->num_incrs > 0)
2427 /* FIXME: this could be dangerous if window doesn't still
2430 #ifdef DEBUG_SELECTION
2431 g_message ("Starting INCR...");
2434 gdk_window_set_events (info->requestor,
2435 gdk_window_get_events (info->requestor) |
2436 GDK_PROPERTY_CHANGE_MASK);
2437 current_incrs = g_list_append (current_incrs, info);
2438 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2441 /* If it was a MULTIPLE request, set the property to indicate which
2442 conversions succeeded */
2443 if (event->target == gtk_selection_atoms[MULTIPLE])
2445 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2446 for (i = 0; i < info->num_conversions; i++)
2448 mult_atoms[2*i] = info->conversions[i].target;
2449 mult_atoms[2*i+1] = info->conversions[i].property;
2452 gdk_property_change (info->requestor, event->property,
2453 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2454 GDK_PROP_MODE_REPLACE,
2455 (guchar *)mult_atoms, 2*info->num_conversions);
2456 g_free (mult_atoms);
2459 if (info->num_conversions == 1 &&
2460 info->conversions[0].property == GDK_NONE)
2462 /* Reject the entire conversion */
2463 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2472 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2480 if (info->num_incrs == 0)
2482 g_free (info->conversions);
2483 g_slice_free (GtkIncrInfo, info);
2486 g_object_unref (widget);
2491 /*************************************************************
2492 * _gtk_selection_incr_event:
2493 * Called whenever an PropertyNotify event occurs for an
2494 * GdkWindow with user_data == NULL. These will be notifications
2495 * that a window we are sending the selection to via the
2496 * INCR protocol has deleted a property and is ready for
2500 * window: the requestor window
2501 * event: the property event structure
2504 *************************************************************/
2507 _gtk_selection_incr_event (GdkWindow *window,
2508 GdkEventProperty *event)
2511 GtkIncrInfo *info = NULL;
2514 gulong selection_max_size;
2518 if (event->state != GDK_PROPERTY_DELETE)
2521 #ifdef DEBUG_SELECTION
2522 g_message ("PropertyDelete, property %ld", event->atom);
2525 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2527 /* Now find the appropriate ongoing INCR */
2528 tmp_list = current_incrs;
2531 info = (GtkIncrInfo *)tmp_list->data;
2532 if (info->requestor == event->window)
2535 tmp_list = tmp_list->next;
2538 if (tmp_list == NULL)
2541 /* Find out which target this is for */
2542 for (i=0; i<info->num_conversions; i++)
2544 if (info->conversions[i].property == event->atom &&
2545 info->conversions[i].offset != -1)
2549 info->idle_time = 0;
2551 if (info->conversions[i].offset == -2) /* only the last 0-length
2559 num_bytes = info->conversions[i].data.length -
2560 info->conversions[i].offset;
2561 buffer = info->conversions[i].data.data +
2562 info->conversions[i].offset;
2564 if (num_bytes > selection_max_size)
2566 num_bytes = selection_max_size;
2567 info->conversions[i].offset += selection_max_size;
2570 info->conversions[i].offset = -2;
2572 #ifdef DEBUG_SELECTION
2573 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2574 num_bytes, info->conversions[i].offset,
2575 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2578 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2579 gdk_property_change (info->requestor, event->atom,
2580 info->conversions[i].data.type,
2581 info->conversions[i].data.format,
2582 GDK_PROP_MODE_REPLACE,
2584 num_bytes / bytes_per_item);
2586 if (info->conversions[i].offset == -2)
2588 g_free (info->conversions[i].data.data);
2589 info->conversions[i].data.data = NULL;
2595 info->conversions[i].offset = -1;
2600 /* Check if we're finished with all the targets */
2602 if (info->num_incrs == 0)
2604 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2605 g_list_free (tmp_list);
2606 /* Let the timeout free it */
2612 /*************************************************************
2613 * gtk_selection_incr_timeout:
2614 * Timeout callback for the sending portion of the INCR
2617 * info: Information about this incr
2619 *************************************************************/
2622 gtk_selection_incr_timeout (GtkIncrInfo *info)
2627 /* Determine if retrieval has finished by checking if it still in
2628 list of pending retrievals */
2630 tmp_list = current_incrs;
2633 if (info == (GtkIncrInfo *)tmp_list->data)
2635 tmp_list = tmp_list->next;
2638 /* If retrieval is finished */
2639 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2641 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2643 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2644 g_list_free (tmp_list);
2647 g_free (info->conversions);
2648 /* FIXME: we should check if requestor window is still in use,
2649 and if not, remove it? */
2651 g_slice_free (GtkIncrInfo, info);
2653 retval = FALSE; /* remove timeout */
2659 retval = TRUE; /* timeout will happen again */
2665 /*************************************************************
2666 * _gtk_selection_notify:
2667 * Handler for "selection-notify-event" signals on windows
2668 * where a retrieval is currently in process. The selection
2669 * owner has responded to our conversion request.
2671 * widget: Widget getting signal
2672 * event: Selection event structure
2673 * info: Information about this retrieval
2675 * was event handled?
2676 *************************************************************/
2679 _gtk_selection_notify (GtkWidget *widget,
2680 GdkEventSelection *event)
2683 GtkRetrievalInfo *info = NULL;
2684 guchar *buffer = NULL;
2689 #ifdef DEBUG_SELECTION
2690 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2691 event->selection, event->target, event->property);
2694 tmp_list = current_retrievals;
2697 info = (GtkRetrievalInfo *)tmp_list->data;
2698 if (info->widget == widget && info->selection == event->selection)
2700 tmp_list = tmp_list->next;
2703 if (!tmp_list) /* no retrieval in progress */
2706 if (event->property != GDK_NONE)
2707 length = gdk_selection_property_get (widget->window, &buffer,
2710 length = 0; /* silence gcc */
2712 if (event->property == GDK_NONE || buffer == NULL)
2714 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2715 g_list_free (tmp_list);
2716 /* structure will be freed in timeout */
2717 gtk_selection_retrieval_report (info,
2718 GDK_NONE, 0, NULL, -1, event->time);
2723 if (type == gtk_selection_atoms[INCR])
2725 /* The remainder of the selection will come through PropertyNotify
2728 info->notify_time = event->time;
2729 info->idle_time = 0;
2730 info->offset = 0; /* Mark as OK to proceed */
2731 gdk_window_set_events (widget->window,
2732 gdk_window_get_events (widget->window)
2733 | GDK_PROPERTY_CHANGE_MASK);
2737 /* We don't delete the info structure - that will happen in timeout */
2738 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2739 g_list_free (tmp_list);
2741 info->offset = length;
2742 gtk_selection_retrieval_report (info,
2744 buffer, length, event->time);
2747 gdk_property_delete (widget->window, event->property);
2754 /*************************************************************
2755 * _gtk_selection_property_notify:
2756 * Handler for "property-notify-event" signals on windows
2757 * where a retrieval is currently in process. The selection
2758 * owner has added more data.
2760 * widget: Widget getting signal
2761 * event: Property event structure
2762 * info: Information about this retrieval
2764 * was event handled?
2765 *************************************************************/
2768 _gtk_selection_property_notify (GtkWidget *widget,
2769 GdkEventProperty *event)
2772 GtkRetrievalInfo *info = NULL;
2778 g_return_val_if_fail (widget != NULL, FALSE);
2779 g_return_val_if_fail (event != NULL, FALSE);
2781 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2782 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2783 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2787 #ifdef DEBUG_SELECTION
2788 g_message ("PropertyNewValue, property %ld",
2792 tmp_list = current_retrievals;
2795 info = (GtkRetrievalInfo *)tmp_list->data;
2796 if (info->widget == widget)
2798 tmp_list = tmp_list->next;
2801 if (!tmp_list) /* No retrieval in progress */
2804 if (info->offset < 0) /* We haven't got the SelectionNotify
2805 for this retrieval yet */
2808 info->idle_time = 0;
2810 length = gdk_selection_property_get (widget->window, &new_buffer,
2812 gdk_property_delete (widget->window, event->atom);
2814 /* We could do a lot better efficiency-wise by paying attention to
2815 what length was sent in the initial INCR transaction, instead of
2816 doing memory allocation at every step. But its only guaranteed to
2817 be a _lower bound_ (pretty useless!) */
2819 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2821 /* Info structure will be freed in timeout */
2822 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2823 g_list_free (tmp_list);
2824 gtk_selection_retrieval_report (info,
2826 (type == GDK_NONE) ? NULL : info->buffer,
2827 (type == GDK_NONE) ? -1 : info->offset,
2830 else /* append on newly arrived data */
2834 #ifdef DEBUG_SELECTION
2835 g_message ("Start - Adding %d bytes at offset 0",
2838 info->buffer = new_buffer;
2839 info->offset = length;
2844 #ifdef DEBUG_SELECTION
2845 g_message ("Appending %d bytes at offset %d",
2846 length,info->offset);
2848 /* We copy length+1 bytes to preserve guaranteed null termination */
2849 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2850 memcpy (info->buffer + info->offset, new_buffer, length+1);
2851 info->offset += length;
2852 g_free (new_buffer);
2859 /*************************************************************
2860 * gtk_selection_retrieval_timeout:
2861 * Timeout callback while receiving a selection.
2863 * info: Information about this retrieval
2865 *************************************************************/
2868 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2873 /* Determine if retrieval has finished by checking if it still in
2874 list of pending retrievals */
2876 tmp_list = current_retrievals;
2879 if (info == (GtkRetrievalInfo *)tmp_list->data)
2881 tmp_list = tmp_list->next;
2884 /* If retrieval is finished */
2885 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2887 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2889 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2890 g_list_free (tmp_list);
2891 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2894 g_free (info->buffer);
2895 g_slice_free (GtkRetrievalInfo, info);
2897 retval = FALSE; /* remove timeout */
2903 retval = TRUE; /* timeout will happen again */
2909 /*************************************************************
2910 * gtk_selection_retrieval_report:
2911 * Emits a "selection-received" signal.
2913 * info: information about the retrieval that completed
2914 * buffer: buffer containing data (NULL => errror)
2915 * time: timestamp for data in buffer
2917 *************************************************************/
2920 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2921 GdkAtom type, gint format,
2922 guchar *buffer, gint length,
2925 GtkSelectionData data;
2927 data.selection = info->selection;
2928 data.target = info->target;
2930 data.format = format;
2932 data.length = length;
2934 data.display = gtk_widget_get_display (info->widget);
2936 g_signal_emit_by_name (info->widget,
2937 "selection-received",
2941 /*************************************************************
2942 * gtk_selection_invoke_handler:
2943 * Finds and invokes handler for specified
2944 * widget/selection/target combination, calls
2945 * gtk_selection_default_handler if none exists.
2948 * widget: selection owner
2949 * data: selection data [INOUT]
2950 * time: time from requeset
2953 * Number of bytes written to buffer, -1 if error
2954 *************************************************************/
2957 gtk_selection_invoke_handler (GtkWidget *widget,
2958 GtkSelectionData *data,
2961 GtkTargetList *target_list;
2965 g_return_if_fail (widget != NULL);
2967 target_list = gtk_selection_target_list_get (widget, data->selection);
2969 gtk_target_list_find (target_list, data->target, &info))
2971 g_signal_emit_by_name (widget,
2977 gtk_selection_default_handler (widget, data);
2980 /*************************************************************
2981 * gtk_selection_default_handler:
2982 * Handles some default targets that exist for any widget
2983 * If it can't fit results into buffer, returns -1. This
2984 * won't happen in any conceivable case, since it would
2985 * require 1000 selection targets!
2988 * widget: selection owner
2989 * data: selection data [INOUT]
2991 *************************************************************/
2994 gtk_selection_default_handler (GtkWidget *widget,
2995 GtkSelectionData *data)
2997 if (data->target == gtk_selection_atoms[TIMESTAMP])
2999 /* Time which was used to obtain selection */
3001 GtkSelectionInfo *selection_info;
3003 tmp_list = current_selections;
3006 selection_info = (GtkSelectionInfo *)tmp_list->data;
3007 if ((selection_info->widget == widget) &&
3008 (selection_info->selection == data->selection))
3010 gulong time = selection_info->time;
3012 gtk_selection_data_set (data,
3013 GDK_SELECTION_TYPE_INTEGER,
3020 tmp_list = tmp_list->next;
3025 else if (data->target == gtk_selection_atoms[TARGETS])
3027 /* List of all targets supported for this widget/selection pair */
3031 GtkTargetList *target_list;
3032 GtkTargetPair *pair;
3034 target_list = gtk_selection_target_list_get (widget,
3036 count = g_list_length (target_list->list) + 3;
3038 data->type = GDK_SELECTION_TYPE_ATOM;
3040 data->length = count * sizeof (GdkAtom);
3042 /* selection data is always terminated by a trailing \0
3044 p = g_malloc (data->length + 1);
3045 data->data = (guchar *)p;
3046 data->data[data->length] = '\0';
3048 *p++ = gtk_selection_atoms[TIMESTAMP];
3049 *p++ = gtk_selection_atoms[TARGETS];
3050 *p++ = gtk_selection_atoms[MULTIPLE];
3052 tmp_list = target_list->list;
3055 pair = (GtkTargetPair *)tmp_list->data;
3056 *p++ = pair->target;
3058 tmp_list = tmp_list->next;
3069 * gtk_selection_data_copy:
3070 * @data: a pointer to a #GtkSelectionData structure.
3072 * Makes a copy of a #GtkSelectionData structure and its data.
3074 * Return value: a pointer to a copy of @data.
3077 gtk_selection_data_copy (GtkSelectionData *data)
3079 GtkSelectionData *new_data;
3081 g_return_val_if_fail (data != NULL, NULL);
3083 new_data = g_slice_new (GtkSelectionData);
3088 new_data->data = g_malloc (data->length + 1);
3089 memcpy (new_data->data, data->data, data->length + 1);
3096 * gtk_selection_data_free:
3097 * @data: a pointer to a #GtkSelectionData structure.
3099 * Frees a #GtkSelectionData structure returned from
3100 * gtk_selection_data_copy().
3103 gtk_selection_data_free (GtkSelectionData *data)
3105 g_return_if_fail (data != NULL);
3107 g_free (data->data);
3109 g_slice_free (GtkSelectionData, data);
3113 gtk_selection_data_get_type (void)
3115 static GType our_type = 0;
3118 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3119 (GBoxedCopyFunc) gtk_selection_data_copy,
3120 (GBoxedFreeFunc) gtk_selection_data_free);
3126 gtk_target_list_get_type (void)
3128 static GType our_type = 0;
3131 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3132 (GBoxedCopyFunc) gtk_target_list_ref,
3133 (GBoxedFreeFunc) gtk_target_list_unref);
3139 gtk_selection_bytes_per_item (gint format)
3144 return sizeof (char);
3147 return sizeof (short);
3150 return sizeof (long);
3153 g_assert_not_reached();
3158 #define __GTK_SELECTION_C__
3159 #include "gtkaliasdef.c"