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/.
61 #include "gtkselection.h"
62 #include "gtktextbufferrichtext.h"
64 #include "gdk-pixbuf/gdk-pixbuf.h"
66 #ifdef GDK_WINDOWING_X11
70 #ifdef GDK_WINDOWING_WIN32
71 #include "win32/gdkwin32.h"
74 #undef DEBUG_SELECTION
76 /* Maximum size of a sent chunk, in bytes. Also the default size of
78 #ifdef GDK_WINDOWING_X11
79 #define GTK_SELECTION_MAX_SIZE(display) \
81 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
82 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
83 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
85 /* No chunks on Win32 */
86 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
89 #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: (allow-none): 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_get_realized (widget), FALSE);
663 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
668 window = gtk_widget_get_window (widget);
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 (gtk_widget_get_window (old_owner));
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: (allow-none): 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_get_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 (gtk_widget_get_window (widget), 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 (gtk_widget_get_window (widget), 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_get_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 (gtk_widget_get_window (widget), 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: (transfer none): 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: (array) (element-type guchar): 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: (transfer full): 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 holding 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: (array zero-terminated=1) (element-type utf8) (transfer full): if
1760 * the selection data contains a list of
1761 * URIs, a newly allocated %NULL-terminated string array
1762 * containing the URIs, otherwise %NULL. If the result is
1763 * non-%NULL it must be freed with g_strfreev().
1768 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1770 gchar **result = NULL;
1772 g_return_val_if_fail (selection_data != NULL, NULL);
1776 if (selection_data->length >= 0 &&
1777 selection_data->type == text_uri_list_atom)
1780 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1782 selection_data->format,
1783 selection_data->data,
1784 selection_data->length,
1787 result = g_uri_list_extract_uris (list[0]);
1797 * gtk_selection_data_get_targets:
1798 * @selection_data: a #GtkSelectionData object
1799 * @targets: location to store an array of targets. The result
1800 * stored here must be freed with g_free().
1801 * @n_atoms: location to store number of items in @targets.
1803 * Gets the contents of @selection_data as an array of targets.
1804 * This can be used to interpret the results of getting
1805 * the standard TARGETS target that is always supplied for
1808 * Return value: %TRUE if @selection_data contains a valid
1809 * array of targets, otherwise %FALSE.
1812 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1816 g_return_val_if_fail (selection_data != NULL, FALSE);
1818 if (selection_data->length >= 0 &&
1819 selection_data->format == 32 &&
1820 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1823 *targets = g_memdup (selection_data->data, selection_data->length);
1825 *n_atoms = selection_data->length / sizeof (GdkAtom);
1841 * gtk_targets_include_text:
1842 * @targets: an array of #GdkAtom<!-- -->s
1843 * @n_targets: the length of @targets
1845 * Determines if any of the targets in @targets can be used to
1848 * Return value: %TRUE if @targets include a suitable target for text,
1854 gtk_targets_include_text (GdkAtom *targets,
1858 gboolean result = FALSE;
1860 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1862 /* Keep in sync with gtk_target_list_add_text_targets()
1867 for (i = 0; i < n_targets; i++)
1869 if (targets[i] == utf8_atom ||
1870 targets[i] == text_atom ||
1871 targets[i] == GDK_TARGET_STRING ||
1872 targets[i] == ctext_atom ||
1873 targets[i] == text_plain_atom ||
1874 targets[i] == text_plain_utf8_atom ||
1875 targets[i] == text_plain_locale_atom)
1886 * gtk_targets_include_rich_text:
1887 * @targets: an array of #GdkAtom<!-- -->s
1888 * @n_targets: the length of @targets
1889 * @buffer: a #GtkTextBuffer
1891 * Determines if any of the targets in @targets can be used to
1892 * provide rich text.
1894 * Return value: %TRUE if @targets include a suitable target for rich text,
1900 gtk_targets_include_rich_text (GdkAtom *targets,
1902 GtkTextBuffer *buffer)
1904 GdkAtom *rich_targets;
1905 gint n_rich_targets;
1907 gboolean result = FALSE;
1909 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1910 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1914 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1917 for (i = 0; i < n_targets; i++)
1919 for (j = 0; j < n_rich_targets; j++)
1921 if (targets[i] == rich_targets[j])
1930 g_free (rich_targets);
1936 * gtk_selection_data_targets_include_text:
1937 * @selection_data: a #GtkSelectionData object
1939 * Given a #GtkSelectionData object holding a list of targets,
1940 * determines if any of the targets in @targets can be used to
1943 * Return value: %TRUE if @selection_data holds a list of targets,
1944 * and a suitable target for text is included, otherwise %FALSE.
1947 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1951 gboolean result = FALSE;
1953 g_return_val_if_fail (selection_data != NULL, FALSE);
1957 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1959 result = gtk_targets_include_text (targets, n_targets);
1967 * gtk_selection_data_targets_include_rich_text:
1968 * @selection_data: a #GtkSelectionData object
1969 * @buffer: a #GtkTextBuffer
1971 * Given a #GtkSelectionData object holding a list of targets,
1972 * determines if any of the targets in @targets can be used to
1973 * provide rich text.
1975 * Return value: %TRUE if @selection_data holds a list of targets,
1976 * and a suitable target for rich text is included,
1982 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1983 GtkTextBuffer *buffer)
1987 gboolean result = FALSE;
1989 g_return_val_if_fail (selection_data != NULL, FALSE);
1990 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1994 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1996 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2004 * gtk_targets_include_image:
2005 * @targets: an array of #GdkAtom<!-- -->s
2006 * @n_targets: the length of @targets
2007 * @writable: whether to accept only targets for which GTK+ knows
2008 * how to convert a pixbuf into the format
2010 * Determines if any of the targets in @targets can be used to
2011 * provide a #GdkPixbuf.
2013 * Return value: %TRUE if @targets include a suitable target for images,
2019 gtk_targets_include_image (GdkAtom *targets,
2023 GtkTargetList *list;
2026 gboolean result = FALSE;
2028 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2030 list = gtk_target_list_new (NULL, 0);
2031 gtk_target_list_add_image_targets (list, 0, writable);
2032 for (i = 0; i < n_targets && !result; i++)
2034 for (l = list->list; l; l = l->next)
2036 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2037 if (pair->target == targets[i])
2044 gtk_target_list_unref (list);
2050 * gtk_selection_data_targets_include_image:
2051 * @selection_data: a #GtkSelectionData object
2052 * @writable: whether to accept only targets for which GTK+ knows
2053 * how to convert a pixbuf into the format
2055 * Given a #GtkSelectionData object holding a list of targets,
2056 * determines if any of the targets in @targets can be used to
2057 * provide a #GdkPixbuf.
2059 * Return value: %TRUE if @selection_data holds a list of targets,
2060 * and a suitable target for images is included, otherwise %FALSE.
2065 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2070 gboolean result = FALSE;
2072 g_return_val_if_fail (selection_data != NULL, FALSE);
2076 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2078 result = gtk_targets_include_image (targets, n_targets, writable);
2086 * gtk_targets_include_uri:
2087 * @targets: an array of #GdkAtom<!-- -->s
2088 * @n_targets: the length of @targets
2090 * Determines if any of the targets in @targets can be used to
2091 * provide an uri list.
2093 * Return value: %TRUE if @targets include a suitable target for uri lists,
2099 gtk_targets_include_uri (GdkAtom *targets,
2103 gboolean result = FALSE;
2105 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2107 /* Keep in sync with gtk_target_list_add_uri_targets()
2112 for (i = 0; i < n_targets; i++)
2114 if (targets[i] == text_uri_list_atom)
2125 * gtk_selection_data_targets_include_uri:
2126 * @selection_data: a #GtkSelectionData object
2128 * Given a #GtkSelectionData object holding a list of targets,
2129 * determines if any of the targets in @targets can be used to
2130 * provide a list or URIs.
2132 * Return value: %TRUE if @selection_data holds a list of targets,
2133 * and a suitable target for URI lists is included, otherwise %FALSE.
2138 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2142 gboolean result = FALSE;
2144 g_return_val_if_fail (selection_data != NULL, FALSE);
2148 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2150 result = gtk_targets_include_uri (targets, n_targets);
2158 /*************************************************************
2159 * gtk_selection_init:
2160 * Initialize local variables
2164 *************************************************************/
2167 gtk_selection_init (void)
2169 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2170 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2171 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2172 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2173 gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS");
2179 * _gtk_selection_clear:
2180 * @widget: a #GtkWidget
2183 * The default handler for the #GtkWidget::selection-clear-event
2186 * Return value: %TRUE if the event was handled, otherwise false
2189 _gtk_selection_clear (GtkWidget *widget,
2190 GdkEventSelection *event)
2192 /* Note that we filter clear events in gdkselection-x11.c, so
2193 * that we only will get here if the clear event actually
2194 * represents a change that we didn't do ourself.
2197 GtkSelectionInfo *selection_info = NULL;
2199 tmp_list = current_selections;
2202 selection_info = (GtkSelectionInfo *)tmp_list->data;
2204 if ((selection_info->selection == event->selection) &&
2205 (selection_info->widget == widget))
2208 tmp_list = tmp_list->next;
2213 current_selections = g_list_remove_link (current_selections, tmp_list);
2214 g_list_free (tmp_list);
2215 g_slice_free (GtkSelectionInfo, selection_info);
2222 /*************************************************************
2223 * _gtk_selection_request:
2224 * Handler for "selection_request_event"
2229 *************************************************************/
2232 _gtk_selection_request (GtkWidget *widget,
2233 GdkEventSelection *event)
2235 GdkDisplay *display = gtk_widget_get_display (widget);
2239 gulong selection_max_size;
2242 gtk_selection_init ();
2244 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2246 /* Check if we own selection */
2248 tmp_list = current_selections;
2251 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2253 if ((selection_info->selection == event->selection) &&
2254 (selection_info->widget == widget))
2257 tmp_list = tmp_list->next;
2260 if (tmp_list == NULL)
2263 info = g_slice_new (GtkIncrInfo);
2265 g_object_ref (widget);
2267 info->selection = event->selection;
2268 info->num_incrs = 0;
2270 /* Create GdkWindow structure for the requestor */
2272 info->requestor = gdk_window_lookup_for_display (display,
2274 if (!info->requestor)
2275 info->requestor = gdk_window_foreign_new_for_display (display,
2278 /* Determine conversions we need to perform */
2280 if (event->target == gtk_selection_atoms[MULTIPLE])
2289 gdk_error_trap_push ();
2290 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2291 0, selection_max_size, FALSE,
2292 &type, &format, &length, &mult_atoms))
2294 gdk_selection_send_notify_for_display (display,
2300 g_free (mult_atoms);
2301 g_slice_free (GtkIncrInfo, info);
2302 gdk_error_trap_pop_ignored ();
2305 gdk_error_trap_pop_ignored ();
2307 /* This is annoying; the ICCCM doesn't specify the property type
2308 * used for the property contents, so the autoconversion for
2309 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2311 #ifdef GDK_WINDOWING_X11
2312 if (type != GDK_SELECTION_TYPE_ATOM &&
2313 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2315 info->num_conversions = length / (2*sizeof (glong));
2316 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2318 for (i=0; i<info->num_conversions; i++)
2320 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2321 ((glong *)mult_atoms)[2*i]);
2322 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2323 ((glong *)mult_atoms)[2*i + 1]);
2326 g_free (mult_atoms);
2331 info->num_conversions = length / (2*sizeof (GdkAtom));
2332 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2334 for (i=0; i<info->num_conversions; i++)
2336 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2337 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2340 g_free (mult_atoms);
2343 else /* only a single conversion */
2345 info->conversions = g_new (GtkIncrConversion, 1);
2346 info->num_conversions = 1;
2347 info->conversions[0].target = event->target;
2348 info->conversions[0].property = event->property;
2351 /* Loop through conversions and determine which of these are big
2352 enough to require doing them via INCR */
2353 for (i=0; i<info->num_conversions; i++)
2355 GtkSelectionData data;
2358 data.selection = event->selection;
2359 data.target = info->conversions[i].target;
2362 data.display = gtk_widget_get_display (widget);
2364 #ifdef DEBUG_SELECTION
2365 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2367 info->conversions[i].target,
2368 gdk_atom_name (info->conversions[i].target),
2369 event->requestor, info->conversions[i].property);
2372 gtk_selection_invoke_handler (widget, &data, event->time);
2373 if (data.length < 0)
2375 info->conversions[i].property = GDK_NONE;
2379 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2381 items = data.length / gtk_selection_bytes_per_item (data.format);
2383 if (data.length > selection_max_size)
2385 /* Sending via INCR */
2386 #ifdef DEBUG_SELECTION
2387 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2388 data.length, selection_max_size);
2391 info->conversions[i].offset = 0;
2392 info->conversions[i].data = data;
2395 gdk_property_change (info->requestor,
2396 info->conversions[i].property,
2397 gtk_selection_atoms[INCR],
2399 GDK_PROP_MODE_REPLACE,
2400 (guchar *)&items, 1);
2404 info->conversions[i].offset = -1;
2406 gdk_property_change (info->requestor,
2407 info->conversions[i].property,
2410 GDK_PROP_MODE_REPLACE,
2417 /* If we have some INCR's, we need to send the rest of the data in
2420 if (info->num_incrs > 0)
2422 /* FIXME: this could be dangerous if window doesn't still
2425 #ifdef DEBUG_SELECTION
2426 g_message ("Starting INCR...");
2429 gdk_window_set_events (info->requestor,
2430 gdk_window_get_events (info->requestor) |
2431 GDK_PROPERTY_CHANGE_MASK);
2432 current_incrs = g_list_append (current_incrs, info);
2433 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2436 /* If it was a MULTIPLE request, set the property to indicate which
2437 conversions succeeded */
2438 if (event->target == gtk_selection_atoms[MULTIPLE])
2440 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2441 for (i = 0; i < info->num_conversions; i++)
2443 mult_atoms[2*i] = info->conversions[i].target;
2444 mult_atoms[2*i+1] = info->conversions[i].property;
2447 gdk_property_change (info->requestor, event->property,
2448 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2449 GDK_PROP_MODE_REPLACE,
2450 (guchar *)mult_atoms, 2*info->num_conversions);
2451 g_free (mult_atoms);
2454 if (info->num_conversions == 1 &&
2455 info->conversions[0].property == GDK_NONE)
2457 /* Reject the entire conversion */
2458 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2467 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2475 if (info->num_incrs == 0)
2477 g_free (info->conversions);
2478 g_slice_free (GtkIncrInfo, info);
2481 g_object_unref (widget);
2486 /*************************************************************
2487 * _gtk_selection_incr_event:
2488 * Called whenever an PropertyNotify event occurs for an
2489 * GdkWindow with user_data == NULL. These will be notifications
2490 * that a window we are sending the selection to via the
2491 * INCR protocol has deleted a property and is ready for
2495 * window: the requestor window
2496 * event: the property event structure
2499 *************************************************************/
2502 _gtk_selection_incr_event (GdkWindow *window,
2503 GdkEventProperty *event)
2506 GtkIncrInfo *info = NULL;
2509 gulong selection_max_size;
2513 if (event->state != GDK_PROPERTY_DELETE)
2516 #ifdef DEBUG_SELECTION
2517 g_message ("PropertyDelete, property %ld", event->atom);
2520 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_window_get_display (window));
2522 /* Now find the appropriate ongoing INCR */
2523 tmp_list = current_incrs;
2526 info = (GtkIncrInfo *)tmp_list->data;
2527 if (info->requestor == event->window)
2530 tmp_list = tmp_list->next;
2533 if (tmp_list == NULL)
2536 /* Find out which target this is for */
2537 for (i=0; i<info->num_conversions; i++)
2539 if (info->conversions[i].property == event->atom &&
2540 info->conversions[i].offset != -1)
2544 info->idle_time = 0;
2546 if (info->conversions[i].offset == -2) /* only the last 0-length
2554 num_bytes = info->conversions[i].data.length -
2555 info->conversions[i].offset;
2556 buffer = info->conversions[i].data.data +
2557 info->conversions[i].offset;
2559 if (num_bytes > selection_max_size)
2561 num_bytes = selection_max_size;
2562 info->conversions[i].offset += selection_max_size;
2565 info->conversions[i].offset = -2;
2567 #ifdef DEBUG_SELECTION
2568 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2569 num_bytes, info->conversions[i].offset,
2570 GDK_WINDOW_XID(info->requestor), event->atom);
2573 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2574 gdk_property_change (info->requestor, event->atom,
2575 info->conversions[i].data.type,
2576 info->conversions[i].data.format,
2577 GDK_PROP_MODE_REPLACE,
2579 num_bytes / bytes_per_item);
2581 if (info->conversions[i].offset == -2)
2583 g_free (info->conversions[i].data.data);
2584 info->conversions[i].data.data = NULL;
2590 info->conversions[i].offset = -1;
2595 /* Check if we're finished with all the targets */
2597 if (info->num_incrs == 0)
2599 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2600 g_list_free (tmp_list);
2601 /* Let the timeout free it */
2607 /*************************************************************
2608 * gtk_selection_incr_timeout:
2609 * Timeout callback for the sending portion of the INCR
2612 * info: Information about this incr
2614 *************************************************************/
2617 gtk_selection_incr_timeout (GtkIncrInfo *info)
2622 /* Determine if retrieval has finished by checking if it still in
2623 list of pending retrievals */
2625 tmp_list = current_incrs;
2628 if (info == (GtkIncrInfo *)tmp_list->data)
2630 tmp_list = tmp_list->next;
2633 /* If retrieval is finished */
2634 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2636 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2638 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2639 g_list_free (tmp_list);
2642 g_free (info->conversions);
2643 /* FIXME: we should check if requestor window is still in use,
2644 and if not, remove it? */
2646 g_slice_free (GtkIncrInfo, info);
2648 retval = FALSE; /* remove timeout */
2654 retval = TRUE; /* timeout will happen again */
2660 /*************************************************************
2661 * _gtk_selection_notify:
2662 * Handler for "selection-notify-event" signals on windows
2663 * where a retrieval is currently in process. The selection
2664 * owner has responded to our conversion request.
2666 * widget: Widget getting signal
2667 * event: Selection event structure
2668 * info: Information about this retrieval
2670 * was event handled?
2671 *************************************************************/
2674 _gtk_selection_notify (GtkWidget *widget,
2675 GdkEventSelection *event)
2678 GtkRetrievalInfo *info = NULL;
2680 guchar *buffer = NULL;
2685 #ifdef DEBUG_SELECTION
2686 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2687 event->selection, event->target, event->property);
2690 window = gtk_widget_get_window (widget);
2692 tmp_list = current_retrievals;
2695 info = (GtkRetrievalInfo *)tmp_list->data;
2696 if (info->widget == widget && info->selection == event->selection)
2698 tmp_list = tmp_list->next;
2701 if (!tmp_list) /* no retrieval in progress */
2704 if (event->property != GDK_NONE)
2705 length = gdk_selection_property_get (window, &buffer,
2708 length = 0; /* silence gcc */
2710 if (event->property == GDK_NONE || buffer == NULL)
2712 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2713 g_list_free (tmp_list);
2714 /* structure will be freed in timeout */
2715 gtk_selection_retrieval_report (info,
2716 GDK_NONE, 0, NULL, -1, event->time);
2721 if (type == gtk_selection_atoms[INCR])
2723 /* The remainder of the selection will come through PropertyNotify
2726 info->notify_time = event->time;
2727 info->idle_time = 0;
2728 info->offset = 0; /* Mark as OK to proceed */
2729 gdk_window_set_events (window,
2730 gdk_window_get_events (window)
2731 | GDK_PROPERTY_CHANGE_MASK);
2735 /* We don't delete the info structure - that will happen in timeout */
2736 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2737 g_list_free (tmp_list);
2739 info->offset = length;
2740 gtk_selection_retrieval_report (info,
2742 buffer, length, event->time);
2745 gdk_property_delete (window, event->property);
2752 /*************************************************************
2753 * _gtk_selection_property_notify:
2754 * Handler for "property-notify-event" signals on windows
2755 * where a retrieval is currently in process. The selection
2756 * owner has added more data.
2758 * widget: Widget getting signal
2759 * event: Property event structure
2760 * info: Information about this retrieval
2762 * was event handled?
2763 *************************************************************/
2766 _gtk_selection_property_notify (GtkWidget *widget,
2767 GdkEventProperty *event)
2770 GtkRetrievalInfo *info = NULL;
2777 g_return_val_if_fail (widget != NULL, FALSE);
2778 g_return_val_if_fail (event != NULL, FALSE);
2780 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2781 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2782 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2786 #ifdef DEBUG_SELECTION
2787 g_message ("PropertyNewValue, property %ld",
2791 tmp_list = current_retrievals;
2794 info = (GtkRetrievalInfo *)tmp_list->data;
2795 if (info->widget == widget)
2797 tmp_list = tmp_list->next;
2800 if (!tmp_list) /* No retrieval in progress */
2803 if (info->offset < 0) /* We haven't got the SelectionNotify
2804 for this retrieval yet */
2807 info->idle_time = 0;
2809 window = gtk_widget_get_window (widget);
2810 length = gdk_selection_property_get (window, &new_buffer,
2812 gdk_property_delete (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);
2968 if (data->target != gtk_selection_atoms[SAVE_TARGETS] &&
2970 gtk_target_list_find (target_list, data->target, &info))
2972 g_signal_emit_by_name (widget,
2978 gtk_selection_default_handler (widget, data);
2981 /*************************************************************
2982 * gtk_selection_default_handler:
2983 * Handles some default targets that exist for any widget
2984 * If it can't fit results into buffer, returns -1. This
2985 * won't happen in any conceivable case, since it would
2986 * require 1000 selection targets!
2989 * widget: selection owner
2990 * data: selection data [INOUT]
2992 *************************************************************/
2995 gtk_selection_default_handler (GtkWidget *widget,
2996 GtkSelectionData *data)
2998 if (data->target == gtk_selection_atoms[TIMESTAMP])
3000 /* Time which was used to obtain selection */
3002 GtkSelectionInfo *selection_info;
3004 tmp_list = current_selections;
3007 selection_info = (GtkSelectionInfo *)tmp_list->data;
3008 if ((selection_info->widget == widget) &&
3009 (selection_info->selection == data->selection))
3011 gulong time = selection_info->time;
3013 gtk_selection_data_set (data,
3014 GDK_SELECTION_TYPE_INTEGER,
3021 tmp_list = tmp_list->next;
3026 else if (data->target == gtk_selection_atoms[TARGETS])
3028 /* List of all targets supported for this widget/selection pair */
3032 GtkTargetList *target_list;
3033 GtkTargetPair *pair;
3035 target_list = gtk_selection_target_list_get (widget,
3037 count = g_list_length (target_list->list) + 3;
3039 data->type = GDK_SELECTION_TYPE_ATOM;
3041 data->length = count * sizeof (GdkAtom);
3043 /* selection data is always terminated by a trailing \0
3045 p = g_malloc (data->length + 1);
3046 data->data = (guchar *)p;
3047 data->data[data->length] = '\0';
3049 *p++ = gtk_selection_atoms[TIMESTAMP];
3050 *p++ = gtk_selection_atoms[TARGETS];
3051 *p++ = gtk_selection_atoms[MULTIPLE];
3053 tmp_list = target_list->list;
3056 pair = (GtkTargetPair *)tmp_list->data;
3057 *p++ = pair->target;
3059 tmp_list = tmp_list->next;
3062 else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
3064 gtk_selection_data_set (data,
3065 gdk_atom_intern_static_string ("NULL"),
3076 * gtk_selection_data_copy:
3077 * @data: a pointer to a #GtkSelectionData structure.
3079 * Makes a copy of a #GtkSelectionData structure and its data.
3081 * Return value: a pointer to a copy of @data.
3084 gtk_selection_data_copy (GtkSelectionData *data)
3086 GtkSelectionData *new_data;
3088 g_return_val_if_fail (data != NULL, NULL);
3090 new_data = g_slice_new (GtkSelectionData);
3095 new_data->data = g_malloc (data->length + 1);
3096 memcpy (new_data->data, data->data, data->length + 1);
3103 * gtk_selection_data_free:
3104 * @data: a pointer to a #GtkSelectionData structure.
3106 * Frees a #GtkSelectionData structure returned from
3107 * gtk_selection_data_copy().
3110 gtk_selection_data_free (GtkSelectionData *data)
3112 g_return_if_fail (data != NULL);
3114 g_free (data->data);
3116 g_slice_free (GtkSelectionData, data);
3120 * gtk_target_entry_new:
3121 * @target: String identifier for target
3122 * @flags: Set of flags, see #GtkTargetFlags
3123 * @info: an ID that will be passed back to the application
3125 * Makes a new #GtkTargetEntry structure.
3127 * Return value: a pointer to a new GtkTargetEntry structure.
3128 * Free with gtk_target_entry_free()
3131 gtk_target_entry_new (const char *target,
3135 GtkTargetEntry entry = { (char *) target, flags, info };
3136 return gtk_target_entry_copy (&entry);
3140 * gtk_target_entry_copy:
3141 * @data: a pointer to a #GtkTargetEntry structure.
3143 * Makes a copy of a #GtkTargetEntry structure and its data.
3145 * Return value: a pointer to a copy of @data.
3146 * Free with gtk_target_entry_free()
3149 gtk_target_entry_copy (GtkTargetEntry *data)
3151 GtkTargetEntry *new_data;
3153 g_return_val_if_fail (data != NULL, NULL);
3155 new_data = g_slice_new (GtkTargetEntry);
3156 new_data->target = g_strdup (data->target);
3157 new_data->flags = data->flags;
3158 new_data->info = data->info;
3164 * gtk_target_entry_free:
3165 * @data: a pointer to a #GtkTargetEntry structure.
3167 * Frees a #GtkTargetEntry structure returned from
3168 * gtk_target_entry_new() or gtk_target_entry_copy().
3171 gtk_target_entry_free (GtkTargetEntry *data)
3173 g_return_if_fail (data != NULL);
3175 g_free (data->target);
3177 g_slice_free (GtkTargetEntry, data);
3181 G_DEFINE_BOXED_TYPE (GtkSelectionData, gtk_selection_data,
3182 gtk_selection_data_copy,
3183 gtk_selection_data_free)
3185 G_DEFINE_BOXED_TYPE (GtkTargetList, gtk_target_list,
3186 gtk_target_list_ref,
3187 gtk_target_list_unref)
3189 G_DEFINE_BOXED_TYPE (GtkTargetEntry, gtk_target_entry,
3190 gtk_target_entry_copy,
3191 gtk_target_entry_free)
3194 gtk_selection_bytes_per_item (gint format)
3199 return sizeof (char);
3202 return sizeof (short);
3205 return sizeof (long);
3208 g_assert_not_reached();