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 /* As usual, java gets it wrong and sets the type to TARGETS, not ATOM
1819 if (selection_data->length >= 0 &&
1820 selection_data->format == 32 &&
1821 (selection_data->type == GDK_SELECTION_TYPE_ATOM ||
1822 selection_data->type == gtk_selection_atoms[TARGETS]))
1825 *targets = g_memdup (selection_data->data, selection_data->length);
1827 *n_atoms = selection_data->length / sizeof (GdkAtom);
1843 * gtk_targets_include_text:
1844 * @targets: an array of #GdkAtom<!-- -->s
1845 * @n_targets: the length of @targets
1847 * Determines if any of the targets in @targets can be used to
1850 * Return value: %TRUE if @targets include a suitable target for text,
1856 gtk_targets_include_text (GdkAtom *targets,
1860 gboolean result = FALSE;
1862 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1864 /* Keep in sync with gtk_target_list_add_text_targets()
1869 for (i = 0; i < n_targets; i++)
1871 if (targets[i] == utf8_atom ||
1872 targets[i] == text_atom ||
1873 targets[i] == GDK_TARGET_STRING ||
1874 targets[i] == ctext_atom ||
1875 targets[i] == text_plain_atom ||
1876 targets[i] == text_plain_utf8_atom ||
1877 targets[i] == text_plain_locale_atom)
1888 * gtk_targets_include_rich_text:
1889 * @targets: an array of #GdkAtom<!-- -->s
1890 * @n_targets: the length of @targets
1891 * @buffer: a #GtkTextBuffer
1893 * Determines if any of the targets in @targets can be used to
1894 * provide rich text.
1896 * Return value: %TRUE if @targets include a suitable target for rich text,
1902 gtk_targets_include_rich_text (GdkAtom *targets,
1904 GtkTextBuffer *buffer)
1906 GdkAtom *rich_targets;
1907 gint n_rich_targets;
1909 gboolean result = FALSE;
1911 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1912 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1916 rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1919 for (i = 0; i < n_targets; i++)
1921 for (j = 0; j < n_rich_targets; j++)
1923 if (targets[i] == rich_targets[j])
1932 g_free (rich_targets);
1938 * gtk_selection_data_targets_include_text:
1939 * @selection_data: a #GtkSelectionData object
1941 * Given a #GtkSelectionData object holding a list of targets,
1942 * determines if any of the targets in @targets can be used to
1945 * Return value: %TRUE if @selection_data holds a list of targets,
1946 * and a suitable target for text is included, otherwise %FALSE.
1949 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1953 gboolean result = FALSE;
1955 g_return_val_if_fail (selection_data != NULL, FALSE);
1959 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1961 result = gtk_targets_include_text (targets, n_targets);
1969 * gtk_selection_data_targets_include_rich_text:
1970 * @selection_data: a #GtkSelectionData object
1971 * @buffer: a #GtkTextBuffer
1973 * Given a #GtkSelectionData object holding a list of targets,
1974 * determines if any of the targets in @targets can be used to
1975 * provide rich text.
1977 * Return value: %TRUE if @selection_data holds a list of targets,
1978 * and a suitable target for rich text is included,
1984 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1985 GtkTextBuffer *buffer)
1989 gboolean result = FALSE;
1991 g_return_val_if_fail (selection_data != NULL, FALSE);
1992 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1996 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1998 result = gtk_targets_include_rich_text (targets, n_targets, buffer);
2006 * gtk_targets_include_image:
2007 * @targets: an array of #GdkAtom<!-- -->s
2008 * @n_targets: the length of @targets
2009 * @writable: whether to accept only targets for which GTK+ knows
2010 * how to convert a pixbuf into the format
2012 * Determines if any of the targets in @targets can be used to
2013 * provide a #GdkPixbuf.
2015 * Return value: %TRUE if @targets include a suitable target for images,
2021 gtk_targets_include_image (GdkAtom *targets,
2025 GtkTargetList *list;
2028 gboolean result = FALSE;
2030 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2032 list = gtk_target_list_new (NULL, 0);
2033 gtk_target_list_add_image_targets (list, 0, writable);
2034 for (i = 0; i < n_targets && !result; i++)
2036 for (l = list->list; l; l = l->next)
2038 GtkTargetPair *pair = (GtkTargetPair *)l->data;
2039 if (pair->target == targets[i])
2046 gtk_target_list_unref (list);
2052 * gtk_selection_data_targets_include_image:
2053 * @selection_data: a #GtkSelectionData object
2054 * @writable: whether to accept only targets for which GTK+ knows
2055 * how to convert a pixbuf into the format
2057 * Given a #GtkSelectionData object holding a list of targets,
2058 * determines if any of the targets in @targets can be used to
2059 * provide a #GdkPixbuf.
2061 * Return value: %TRUE if @selection_data holds a list of targets,
2062 * and a suitable target for images is included, otherwise %FALSE.
2067 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2072 gboolean result = FALSE;
2074 g_return_val_if_fail (selection_data != NULL, FALSE);
2078 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2080 result = gtk_targets_include_image (targets, n_targets, writable);
2088 * gtk_targets_include_uri:
2089 * @targets: an array of #GdkAtom<!-- -->s
2090 * @n_targets: the length of @targets
2092 * Determines if any of the targets in @targets can be used to
2093 * provide an uri list.
2095 * Return value: %TRUE if @targets include a suitable target for uri lists,
2101 gtk_targets_include_uri (GdkAtom *targets,
2105 gboolean result = FALSE;
2107 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2109 /* Keep in sync with gtk_target_list_add_uri_targets()
2114 for (i = 0; i < n_targets; i++)
2116 if (targets[i] == text_uri_list_atom)
2127 * gtk_selection_data_targets_include_uri:
2128 * @selection_data: a #GtkSelectionData object
2130 * Given a #GtkSelectionData object holding a list of targets,
2131 * determines if any of the targets in @targets can be used to
2132 * provide a list or URIs.
2134 * Return value: %TRUE if @selection_data holds a list of targets,
2135 * and a suitable target for URI lists is included, otherwise %FALSE.
2140 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2144 gboolean result = FALSE;
2146 g_return_val_if_fail (selection_data != NULL, FALSE);
2150 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2152 result = gtk_targets_include_uri (targets, n_targets);
2160 /*************************************************************
2161 * gtk_selection_init:
2162 * Initialize local variables
2166 *************************************************************/
2169 gtk_selection_init (void)
2171 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2172 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2173 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2174 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2180 * gtk_selection_clear:
2181 * @widget: a #GtkWidget
2184 * The default handler for the #GtkWidget::selection-clear-event
2187 * Return value: %TRUE if the event was handled, otherwise false
2191 * Deprecated: 2.4: Instead of calling this function, chain up from
2192 * your selection-clear-event handler. Calling this function
2193 * from any other context is illegal.
2196 gtk_selection_clear (GtkWidget *widget,
2197 GdkEventSelection *event)
2199 /* Note that we filter clear events in gdkselection-x11.c, so
2200 * that we only will get here if the clear event actually
2201 * represents a change that we didn't do ourself.
2204 GtkSelectionInfo *selection_info = NULL;
2206 tmp_list = current_selections;
2209 selection_info = (GtkSelectionInfo *)tmp_list->data;
2211 if ((selection_info->selection == event->selection) &&
2212 (selection_info->widget == widget))
2215 tmp_list = tmp_list->next;
2220 current_selections = g_list_remove_link (current_selections, tmp_list);
2221 g_list_free (tmp_list);
2222 g_slice_free (GtkSelectionInfo, selection_info);
2229 /*************************************************************
2230 * _gtk_selection_request:
2231 * Handler for "selection_request_event"
2236 *************************************************************/
2239 _gtk_selection_request (GtkWidget *widget,
2240 GdkEventSelection *event)
2242 GdkDisplay *display = gtk_widget_get_display (widget);
2246 gulong selection_max_size;
2249 gtk_selection_init ();
2251 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2253 /* Check if we own selection */
2255 tmp_list = current_selections;
2258 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2260 if ((selection_info->selection == event->selection) &&
2261 (selection_info->widget == widget))
2264 tmp_list = tmp_list->next;
2267 if (tmp_list == NULL)
2270 info = g_slice_new (GtkIncrInfo);
2272 g_object_ref (widget);
2274 info->selection = event->selection;
2275 info->num_incrs = 0;
2277 /* Create GdkWindow structure for the requestor */
2279 info->requestor = gdk_window_lookup_for_display (display,
2281 if (!info->requestor)
2282 info->requestor = gdk_window_foreign_new_for_display (display,
2285 /* Determine conversions we need to perform */
2287 if (event->target == gtk_selection_atoms[MULTIPLE])
2296 gdk_error_trap_push ();
2297 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2298 0, selection_max_size, FALSE,
2299 &type, &format, &length, &mult_atoms))
2301 gdk_selection_send_notify_for_display (display,
2307 g_free (mult_atoms);
2308 g_slice_free (GtkIncrInfo, info);
2309 gdk_error_trap_pop ();
2312 gdk_error_trap_pop ();
2314 /* This is annoying; the ICCCM doesn't specify the property type
2315 * used for the property contents, so the autoconversion for
2316 * ATOM / ATOM_PAIR in GDK doesn't work properly.
2318 #ifdef GDK_WINDOWING_X11
2319 if (type != GDK_SELECTION_TYPE_ATOM &&
2320 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2322 info->num_conversions = length / (2*sizeof (glong));
2323 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2325 for (i=0; i<info->num_conversions; i++)
2327 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2328 ((glong *)mult_atoms)[2*i]);
2329 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2330 ((glong *)mult_atoms)[2*i + 1]);
2333 g_free (mult_atoms);
2338 info->num_conversions = length / (2*sizeof (GdkAtom));
2339 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2341 for (i=0; i<info->num_conversions; i++)
2343 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2344 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2347 g_free (mult_atoms);
2350 else /* only a single conversion */
2352 info->conversions = g_new (GtkIncrConversion, 1);
2353 info->num_conversions = 1;
2354 info->conversions[0].target = event->target;
2355 info->conversions[0].property = event->property;
2358 /* Loop through conversions and determine which of these are big
2359 enough to require doing them via INCR */
2360 for (i=0; i<info->num_conversions; i++)
2362 GtkSelectionData data;
2365 data.selection = event->selection;
2366 data.target = info->conversions[i].target;
2369 data.display = gtk_widget_get_display (widget);
2371 #ifdef DEBUG_SELECTION
2372 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2374 info->conversions[i].target,
2375 gdk_atom_name (info->conversions[i].target),
2376 event->requestor, info->conversions[i].property);
2379 gtk_selection_invoke_handler (widget, &data, event->time);
2381 if (data.length < 0)
2383 info->conversions[i].property = GDK_NONE;
2387 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2389 items = data.length / gtk_selection_bytes_per_item (data.format);
2391 if (data.length > selection_max_size)
2393 /* Sending via INCR */
2394 #ifdef DEBUG_SELECTION
2395 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2396 data.length, selection_max_size);
2399 info->conversions[i].offset = 0;
2400 info->conversions[i].data = data;
2403 gdk_property_change (info->requestor,
2404 info->conversions[i].property,
2405 gtk_selection_atoms[INCR],
2407 GDK_PROP_MODE_REPLACE,
2408 (guchar *)&items, 1);
2412 info->conversions[i].offset = -1;
2414 gdk_property_change (info->requestor,
2415 info->conversions[i].property,
2418 GDK_PROP_MODE_REPLACE,
2425 /* If we have some INCR's, we need to send the rest of the data in
2428 if (info->num_incrs > 0)
2430 /* FIXME: this could be dangerous if window doesn't still
2433 #ifdef DEBUG_SELECTION
2434 g_message ("Starting INCR...");
2437 gdk_window_set_events (info->requestor,
2438 gdk_window_get_events (info->requestor) |
2439 GDK_PROPERTY_CHANGE_MASK);
2440 current_incrs = g_list_append (current_incrs, info);
2441 gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2444 /* If it was a MULTIPLE request, set the property to indicate which
2445 conversions succeeded */
2446 if (event->target == gtk_selection_atoms[MULTIPLE])
2448 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2449 for (i = 0; i < info->num_conversions; i++)
2451 mult_atoms[2*i] = info->conversions[i].target;
2452 mult_atoms[2*i+1] = info->conversions[i].property;
2455 gdk_property_change (info->requestor, event->property,
2456 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2457 GDK_PROP_MODE_REPLACE,
2458 (guchar *)mult_atoms, 2*info->num_conversions);
2459 g_free (mult_atoms);
2462 if (info->num_conversions == 1 &&
2463 info->conversions[0].property == GDK_NONE)
2465 /* Reject the entire conversion */
2466 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2475 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2483 if (info->num_incrs == 0)
2485 g_free (info->conversions);
2486 g_slice_free (GtkIncrInfo, info);
2489 g_object_unref (widget);
2494 /*************************************************************
2495 * _gtk_selection_incr_event:
2496 * Called whenever an PropertyNotify event occurs for an
2497 * GdkWindow with user_data == NULL. These will be notifications
2498 * that a window we are sending the selection to via the
2499 * INCR protocol has deleted a property and is ready for
2503 * window: the requestor window
2504 * event: the property event structure
2507 *************************************************************/
2510 _gtk_selection_incr_event (GdkWindow *window,
2511 GdkEventProperty *event)
2514 GtkIncrInfo *info = NULL;
2517 gulong selection_max_size;
2521 if (event->state != GDK_PROPERTY_DELETE)
2524 #ifdef DEBUG_SELECTION
2525 g_message ("PropertyDelete, property %ld", event->atom);
2528 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2530 /* Now find the appropriate ongoing INCR */
2531 tmp_list = current_incrs;
2534 info = (GtkIncrInfo *)tmp_list->data;
2535 if (info->requestor == event->window)
2538 tmp_list = tmp_list->next;
2541 if (tmp_list == NULL)
2544 /* Find out which target this is for */
2545 for (i=0; i<info->num_conversions; i++)
2547 if (info->conversions[i].property == event->atom &&
2548 info->conversions[i].offset != -1)
2552 info->idle_time = 0;
2554 if (info->conversions[i].offset == -2) /* only the last 0-length
2562 num_bytes = info->conversions[i].data.length -
2563 info->conversions[i].offset;
2564 buffer = info->conversions[i].data.data +
2565 info->conversions[i].offset;
2567 if (num_bytes > selection_max_size)
2569 num_bytes = selection_max_size;
2570 info->conversions[i].offset += selection_max_size;
2573 info->conversions[i].offset = -2;
2575 #ifdef DEBUG_SELECTION
2576 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2577 num_bytes, info->conversions[i].offset,
2578 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2581 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2582 gdk_property_change (info->requestor, event->atom,
2583 info->conversions[i].data.type,
2584 info->conversions[i].data.format,
2585 GDK_PROP_MODE_REPLACE,
2587 num_bytes / bytes_per_item);
2589 if (info->conversions[i].offset == -2)
2591 g_free (info->conversions[i].data.data);
2592 info->conversions[i].data.data = NULL;
2598 info->conversions[i].offset = -1;
2603 /* Check if we're finished with all the targets */
2605 if (info->num_incrs == 0)
2607 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2608 g_list_free (tmp_list);
2609 /* Let the timeout free it */
2615 /*************************************************************
2616 * gtk_selection_incr_timeout:
2617 * Timeout callback for the sending portion of the INCR
2620 * info: Information about this incr
2622 *************************************************************/
2625 gtk_selection_incr_timeout (GtkIncrInfo *info)
2630 /* Determine if retrieval has finished by checking if it still in
2631 list of pending retrievals */
2633 tmp_list = current_incrs;
2636 if (info == (GtkIncrInfo *)tmp_list->data)
2638 tmp_list = tmp_list->next;
2641 /* If retrieval is finished */
2642 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2644 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2646 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2647 g_list_free (tmp_list);
2650 g_free (info->conversions);
2651 /* FIXME: we should check if requestor window is still in use,
2652 and if not, remove it? */
2654 g_slice_free (GtkIncrInfo, info);
2656 retval = FALSE; /* remove timeout */
2662 retval = TRUE; /* timeout will happen again */
2668 /*************************************************************
2669 * _gtk_selection_notify:
2670 * Handler for "selection-notify-event" signals on windows
2671 * where a retrieval is currently in process. The selection
2672 * owner has responded to our conversion request.
2674 * widget: Widget getting signal
2675 * event: Selection event structure
2676 * info: Information about this retrieval
2678 * was event handled?
2679 *************************************************************/
2682 _gtk_selection_notify (GtkWidget *widget,
2683 GdkEventSelection *event)
2686 GtkRetrievalInfo *info = NULL;
2687 guchar *buffer = NULL;
2692 #ifdef DEBUG_SELECTION
2693 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2694 event->selection, event->target, event->property);
2697 tmp_list = current_retrievals;
2700 info = (GtkRetrievalInfo *)tmp_list->data;
2701 if (info->widget == widget && info->selection == event->selection)
2703 tmp_list = tmp_list->next;
2706 if (!tmp_list) /* no retrieval in progress */
2709 if (event->property != GDK_NONE)
2710 length = gdk_selection_property_get (widget->window, &buffer,
2713 length = 0; /* silence gcc */
2715 if (event->property == GDK_NONE || buffer == NULL)
2717 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2718 g_list_free (tmp_list);
2719 /* structure will be freed in timeout */
2720 gtk_selection_retrieval_report (info,
2721 GDK_NONE, 0, NULL, -1, event->time);
2726 if (type == gtk_selection_atoms[INCR])
2728 /* The remainder of the selection will come through PropertyNotify
2731 info->notify_time = event->time;
2732 info->idle_time = 0;
2733 info->offset = 0; /* Mark as OK to proceed */
2734 gdk_window_set_events (widget->window,
2735 gdk_window_get_events (widget->window)
2736 | GDK_PROPERTY_CHANGE_MASK);
2740 /* We don't delete the info structure - that will happen in timeout */
2741 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2742 g_list_free (tmp_list);
2744 info->offset = length;
2745 gtk_selection_retrieval_report (info,
2747 buffer, length, event->time);
2750 gdk_property_delete (widget->window, event->property);
2757 /*************************************************************
2758 * _gtk_selection_property_notify:
2759 * Handler for "property-notify-event" signals on windows
2760 * where a retrieval is currently in process. The selection
2761 * owner has added more data.
2763 * widget: Widget getting signal
2764 * event: Property event structure
2765 * info: Information about this retrieval
2767 * was event handled?
2768 *************************************************************/
2771 _gtk_selection_property_notify (GtkWidget *widget,
2772 GdkEventProperty *event)
2775 GtkRetrievalInfo *info = NULL;
2781 g_return_val_if_fail (widget != NULL, FALSE);
2782 g_return_val_if_fail (event != NULL, FALSE);
2784 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2785 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2786 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2790 #ifdef DEBUG_SELECTION
2791 g_message ("PropertyNewValue, property %ld",
2795 tmp_list = current_retrievals;
2798 info = (GtkRetrievalInfo *)tmp_list->data;
2799 if (info->widget == widget)
2801 tmp_list = tmp_list->next;
2804 if (!tmp_list) /* No retrieval in progress */
2807 if (info->offset < 0) /* We haven't got the SelectionNotify
2808 for this retrieval yet */
2811 info->idle_time = 0;
2813 length = gdk_selection_property_get (widget->window, &new_buffer,
2815 gdk_property_delete (widget->window, event->atom);
2817 /* We could do a lot better efficiency-wise by paying attention to
2818 what length was sent in the initial INCR transaction, instead of
2819 doing memory allocation at every step. But its only guaranteed to
2820 be a _lower bound_ (pretty useless!) */
2822 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2824 /* Info structure will be freed in timeout */
2825 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2826 g_list_free (tmp_list);
2827 gtk_selection_retrieval_report (info,
2829 (type == GDK_NONE) ? NULL : info->buffer,
2830 (type == GDK_NONE) ? -1 : info->offset,
2833 else /* append on newly arrived data */
2837 #ifdef DEBUG_SELECTION
2838 g_message ("Start - Adding %d bytes at offset 0",
2841 info->buffer = new_buffer;
2842 info->offset = length;
2847 #ifdef DEBUG_SELECTION
2848 g_message ("Appending %d bytes at offset %d",
2849 length,info->offset);
2851 /* We copy length+1 bytes to preserve guaranteed null termination */
2852 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2853 memcpy (info->buffer + info->offset, new_buffer, length+1);
2854 info->offset += length;
2855 g_free (new_buffer);
2862 /*************************************************************
2863 * gtk_selection_retrieval_timeout:
2864 * Timeout callback while receiving a selection.
2866 * info: Information about this retrieval
2868 *************************************************************/
2871 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2876 /* Determine if retrieval has finished by checking if it still in
2877 list of pending retrievals */
2879 tmp_list = current_retrievals;
2882 if (info == (GtkRetrievalInfo *)tmp_list->data)
2884 tmp_list = tmp_list->next;
2887 /* If retrieval is finished */
2888 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2890 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2892 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2893 g_list_free (tmp_list);
2894 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2897 g_free (info->buffer);
2898 g_slice_free (GtkRetrievalInfo, info);
2900 retval = FALSE; /* remove timeout */
2906 retval = TRUE; /* timeout will happen again */
2912 /*************************************************************
2913 * gtk_selection_retrieval_report:
2914 * Emits a "selection-received" signal.
2916 * info: information about the retrieval that completed
2917 * buffer: buffer containing data (NULL => errror)
2918 * time: timestamp for data in buffer
2920 *************************************************************/
2923 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2924 GdkAtom type, gint format,
2925 guchar *buffer, gint length,
2928 GtkSelectionData data;
2930 data.selection = info->selection;
2931 data.target = info->target;
2933 data.format = format;
2935 data.length = length;
2937 data.display = gtk_widget_get_display (info->widget);
2939 g_signal_emit_by_name (info->widget,
2940 "selection-received",
2944 /*************************************************************
2945 * gtk_selection_invoke_handler:
2946 * Finds and invokes handler for specified
2947 * widget/selection/target combination, calls
2948 * gtk_selection_default_handler if none exists.
2951 * widget: selection owner
2952 * data: selection data [INOUT]
2953 * time: time from requeset
2956 * Number of bytes written to buffer, -1 if error
2957 *************************************************************/
2960 gtk_selection_invoke_handler (GtkWidget *widget,
2961 GtkSelectionData *data,
2964 GtkTargetList *target_list;
2968 g_return_if_fail (widget != NULL);
2970 target_list = gtk_selection_target_list_get (widget, data->selection);
2972 gtk_target_list_find (target_list, data->target, &info))
2974 g_signal_emit_by_name (widget,
2980 gtk_selection_default_handler (widget, data);
2983 /*************************************************************
2984 * gtk_selection_default_handler:
2985 * Handles some default targets that exist for any widget
2986 * If it can't fit results into buffer, returns -1. This
2987 * won't happen in any conceivable case, since it would
2988 * require 1000 selection targets!
2991 * widget: selection owner
2992 * data: selection data [INOUT]
2994 *************************************************************/
2997 gtk_selection_default_handler (GtkWidget *widget,
2998 GtkSelectionData *data)
3000 if (data->target == gtk_selection_atoms[TIMESTAMP])
3002 /* Time which was used to obtain selection */
3004 GtkSelectionInfo *selection_info;
3006 tmp_list = current_selections;
3009 selection_info = (GtkSelectionInfo *)tmp_list->data;
3010 if ((selection_info->widget == widget) &&
3011 (selection_info->selection == data->selection))
3013 gulong time = selection_info->time;
3015 gtk_selection_data_set (data,
3016 GDK_SELECTION_TYPE_INTEGER,
3023 tmp_list = tmp_list->next;
3028 else if (data->target == gtk_selection_atoms[TARGETS])
3030 /* List of all targets supported for this widget/selection pair */
3034 GtkTargetList *target_list;
3035 GtkTargetPair *pair;
3037 target_list = gtk_selection_target_list_get (widget,
3039 count = g_list_length (target_list->list) + 3;
3041 data->type = GDK_SELECTION_TYPE_ATOM;
3043 data->length = count * sizeof (GdkAtom);
3045 /* selection data is always terminated by a trailing \0
3047 p = g_malloc (data->length + 1);
3048 data->data = (guchar *)p;
3049 data->data[data->length] = '\0';
3051 *p++ = gtk_selection_atoms[TIMESTAMP];
3052 *p++ = gtk_selection_atoms[TARGETS];
3053 *p++ = gtk_selection_atoms[MULTIPLE];
3055 tmp_list = target_list->list;
3058 pair = (GtkTargetPair *)tmp_list->data;
3059 *p++ = pair->target;
3061 tmp_list = tmp_list->next;
3072 * gtk_selection_data_copy:
3073 * @data: a pointer to a #GtkSelectionData structure.
3075 * Makes a copy of a #GtkSelectionData structure and its data.
3077 * Return value: a pointer to a copy of @data.
3080 gtk_selection_data_copy (GtkSelectionData *data)
3082 GtkSelectionData *new_data;
3084 g_return_val_if_fail (data != NULL, NULL);
3086 new_data = g_slice_new (GtkSelectionData);
3091 new_data->data = g_malloc (data->length + 1);
3092 memcpy (new_data->data, data->data, data->length + 1);
3099 * gtk_selection_data_free:
3100 * @data: a pointer to a #GtkSelectionData structure.
3102 * Frees a #GtkSelectionData structure returned from
3103 * gtk_selection_data_copy().
3106 gtk_selection_data_free (GtkSelectionData *data)
3108 g_return_if_fail (data != NULL);
3110 g_free (data->data);
3112 g_slice_free (GtkSelectionData, data);
3116 gtk_selection_data_get_type (void)
3118 static GType our_type = 0;
3121 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3122 (GBoxedCopyFunc) gtk_selection_data_copy,
3123 (GBoxedFreeFunc) gtk_selection_data_free);
3129 gtk_target_list_get_type (void)
3131 static GType our_type = 0;
3134 our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3135 (GBoxedCopyFunc) gtk_target_list_ref,
3136 (GBoxedFreeFunc) gtk_target_list_unref);
3142 gtk_selection_bytes_per_item (gint format)
3147 return sizeof (char);
3150 return sizeof (short);
3153 return sizeof (long);
3156 g_assert_not_reached();
3161 #define __GTK_SELECTION_C__
3162 #include "gtkaliasdef.c"