X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkselection.c;h=67a774f7683107abffe95c8d9a9ddef0e1b6f7f7;hb=61344219d4ba6d81854cc5bea8cf90f600358501;hp=5a88069aab071f4ffcf730a9af982a0bc75748cc;hpb=721c3bc10182cacf1a98baddde3c94e59797ddb7;p=~andy%2Fgtk diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c index 5a88069aa..67a774f76 100644 --- a/gtk/gtkselection.c +++ b/gtk/gtkselection.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* This file implements most of the work of the ICCCM selection protocol. @@ -51,13 +49,43 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include +/** + * SECTION:gtkselection + * @Title: Selections + * @Short_description: Functions for handling inter-process communication + * via selections + * @See_also: #GtkWidget - Much of the operation of selections happens via + * signals for #GtkWidget. In particular, if you are using the functions + * in this section, you may need to pay attention to + * #GtkWidget::selection-get, #GtkWidget::selection-received and + * #GtkWidget::selection-clear-event signals + * + * The selection mechanism provides the basis for different types + * of communication between processes. In particular, drag and drop and + * #GtkClipboard work via selections. You will very seldom or + * never need to use most of the functions in this section directly; + * #GtkClipboard provides a nicer interface to the same functionality. + * + * Some of the datatypes defined this section are used in + * the #GtkClipboard and drag-and-drop API's as well. The + * #GtkTargetEntry structure and #GtkTargetList objects represent + * lists of data types that are supported when sending or + * receiving data. The #GtkSelectionData object is used to + * store a chunk of data along with the data type and other + * associated information. + */ + +#include "config.h" + +#include "gtkselection.h" +#include "gtkselectionprivate.h" + #include #include #include "gdk.h" #include "gtkmain.h" -#include "gtkselection.h" +#include "gtkdebug.h" #include "gtktextbufferrichtext.h" #include "gtkintl.h" #include "gdk-pixbuf/gdk-pixbuf.h" @@ -70,8 +98,6 @@ #include "win32/gdkwin32.h" #endif -#include "gtkalias.h" - #undef DEBUG_SELECTION /* Maximum size of a sent chunk, in bytes. Also the default size of @@ -94,6 +120,7 @@ enum { MULTIPLE, TARGETS, TIMESTAMP, + SAVE_TARGETS, LAST_ATOM }; @@ -187,18 +214,18 @@ static const char gtk_selection_handler_key[] = "gtk-selection-handlers"; /** * gtk_target_list_new: - * @targets: Pointer to an array of #GtkTargetEntry - * @ntargets: number of entries in @targets. + * @targets: (array length=ntargets): Pointer to an array of #GtkTargetEntry + * @ntargets: number of entries in @targets. * * Creates a new #GtkTargetList from an array of #GtkTargetEntry. * - * Return value: the new #GtkTargetList. + * Return value: (transfer full): the new #GtkTargetList. **/ GtkTargetList * gtk_target_list_new (const GtkTargetEntry *targets, guint ntargets) { - GtkTargetList *result = g_new (GtkTargetList, 1); + GtkTargetList *result = g_slice_new (GtkTargetList); result->list = NULL; result->ref_count = 1; @@ -246,13 +273,13 @@ gtk_target_list_unref (GtkTargetList *list) while (tmp_list) { GtkTargetPair *pair = tmp_list->data; - g_free (pair); + g_slice_free (GtkTargetPair, pair); tmp_list = tmp_list->next; } g_list_free (list->list); - g_free (list); + g_slice_free (GtkTargetList, list); } } @@ -275,7 +302,7 @@ gtk_target_list_add (GtkTargetList *list, g_return_if_fail (list != NULL); - pair = g_new (GtkTargetPair, 1); + pair = g_slice_new (GtkTargetPair); pair->target = target; pair->flags = flags; pair->info = info; @@ -338,7 +365,8 @@ gtk_target_list_add_text_targets (GtkTargetList *list, gtk_target_list_add (list, text_atom, 0, info); gtk_target_list_add (list, GDK_TARGET_STRING, 0, info); gtk_target_list_add (list, text_plain_utf8_atom, 0, info); - gtk_target_list_add (list, text_plain_locale_atom, 0, info); + if (!g_get_charset (NULL)) + gtk_target_list_add (list, text_plain_locale_atom, 0, info); gtk_target_list_add (list, text_plain_atom, 0, info); } @@ -469,7 +497,7 @@ gtk_target_list_add_uri_targets (GtkTargetList *list, /** * gtk_target_list_add_table: * @list: a #GtkTargetList - * @targets: the table of #GtkTargetEntry + * @targets: (array length=ntargets): the table of #GtkTargetEntry * @ntargets: number of targets in the table * * Prepends a table of #GtkTargetEntry to a target list. @@ -483,7 +511,7 @@ gtk_target_list_add_table (GtkTargetList *list, for (i=ntargets-1; i >= 0; i--) { - GtkTargetPair *pair = g_new (GtkTargetPair, 1); + GtkTargetPair *pair = g_slice_new (GtkTargetPair); pair->target = gdk_atom_intern (targets[i].target, FALSE); pair->flags = targets[i].flags; pair->info = targets[i].info; @@ -514,7 +542,7 @@ gtk_target_list_remove (GtkTargetList *list, if (pair->target == target) { - g_free (pair); + g_slice_free (GtkTargetPair, pair); list->list = g_list_remove_link (list->list, tmp_list); g_list_free_1 (tmp_list); @@ -530,10 +558,11 @@ gtk_target_list_remove (GtkTargetList *list, * gtk_target_list_find: * @list: a #GtkTargetList * @target: an interned atom representing the target to search for - * @info: a pointer to the location to store application info for target - * + * @info: a pointer to the location to store application info for target, + * or %NULL + * * Looks up a given target in a #GtkTargetList. - * + * * Return value: %TRUE if the target was found, otherwise %FALSE **/ gboolean @@ -541,16 +570,23 @@ gtk_target_list_find (GtkTargetList *list, GdkAtom target, guint *info) { - GList *tmp_list = list->list; + GList *tmp_list; + + g_return_val_if_fail (list != NULL, FALSE); + + tmp_list = list->list; while (tmp_list) { GtkTargetPair *pair = tmp_list->data; if (pair->target == target) { - *info = pair->info; + if (info) + *info = pair->info; + return TRUE; } + tmp_list = tmp_list->next; } @@ -560,14 +596,14 @@ gtk_target_list_find (GtkTargetList *list, /** * gtk_target_table_new_from_list: * @list: a #GtkTargetList - * @n_targets: return location for the number ot targets in the table + * @n_targets: (out): return location for the number ot targets in the table * * This function creates an #GtkTargetEntry array that contains the * same targets as the passed %list. The returned table is newly * allocated and should be freed using gtk_target_table_free() when no * longer needed. * - * Return value: the new table. + * Return value: (array length=n_targets) (transfer full): the new table. * * Since: 2.10 **/ @@ -601,7 +637,7 @@ gtk_target_table_new_from_list (GtkTargetList *list, /** * gtk_target_table_free: - * @targets: a #GtkTargetEntry array + * @targets: (array length=n_targets): a #GtkTargetEntry array * @n_targets: the number of entries in the array * * This function frees a target table as returned by @@ -625,8 +661,8 @@ gtk_target_table_free (GtkTargetEntry *targets, /** * gtk_selection_owner_set_for_display: - * @display: the #Gdkdisplay where the selection is set - * @widget: new selection owner (a #GdkWidget), or %NULL. + * @display: the #GdkDisplay where the selection is set + * @widget: (allow-none): new selection owner (a #GtkWidget), or %NULL. * @selection: an interned atom representing the selection to claim. * @time_: timestamp with which to claim the selection * @@ -650,13 +686,13 @@ gtk_selection_owner_set_for_display (GdkDisplay *display, g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); g_return_val_if_fail (selection != GDK_NONE, FALSE); - g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE); + g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE); g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE); if (widget == NULL) window = NULL; else - window = widget->window; + window = gtk_widget_get_window (widget); tmp_list = current_selections; while (tmp_list) @@ -682,14 +718,14 @@ gtk_selection_owner_set_for_display (GdkDisplay *display, current_selections = g_list_remove_link (current_selections, tmp_list); g_list_free (tmp_list); - g_free (selection_info); + g_slice_free (GtkSelectionInfo, selection_info); } } else { if (selection_info == NULL) { - selection_info = g_new (GtkSelectionInfo, 1); + selection_info = g_slice_new (GtkSelectionInfo); selection_info->selection = selection; selection_info->widget = widget; selection_info->time = time; @@ -711,8 +747,8 @@ gtk_selection_owner_set_for_display (GdkDisplay *display, if (old_owner && old_owner != widget) { GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR); - - event->selection.window = g_object_ref (old_owner->window); + + event->selection.window = g_object_ref (gtk_widget_get_window (old_owner)); event->selection.selection = selection; event->selection.time = time; @@ -728,7 +764,7 @@ gtk_selection_owner_set_for_display (GdkDisplay *display, /** * gtk_selection_owner_set: - * @widget: a #GtkWidget, or %NULL. + * @widget: (allow-none): a #GtkWidget, or %NULL. * @selection: an interned atom representing the selection to claim * @time_: timestamp with which to claim the selection * @@ -744,7 +780,7 @@ gtk_selection_owner_set (GtkWidget *widget, { GdkDisplay *display; - g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE); + g_return_val_if_fail (widget == NULL || gtk_widget_get_realized (widget), FALSE); g_return_val_if_fail (selection != GDK_NONE, FALSE); if (widget) @@ -787,7 +823,7 @@ gtk_selection_target_list_get (GtkWidget *widget, tmp_list = tmp_list->next; } - sellist = g_new (GtkSelectionTargetList, 1); + sellist = g_slice_new (GtkSelectionTargetList); sellist->selection = selection; sellist->list = gtk_target_list_new (NULL, 0); @@ -813,7 +849,7 @@ gtk_selection_target_list_remove (GtkWidget *widget) gtk_target_list_unref (sellist->list); - g_free (sellist); + g_slice_free (GtkSelectionTargetList, sellist); tmp_list = tmp_list->next; } @@ -850,7 +886,7 @@ gtk_selection_clear_targets (GtkWidget *widget, { lists = g_list_delete_link (lists, tmp_list); gtk_target_list_unref (sellist->list); - g_free (sellist); + g_slice_free (GtkSelectionTargetList, sellist); break; } @@ -885,7 +921,7 @@ gtk_selection_add_target (GtkWidget *widget, list = gtk_selection_target_list_get (widget, selection); gtk_target_list_add (list, target, 0, info); #ifdef GDK_WINDOWING_WIN32 - gdk_win32_selection_add_targets (widget->window, selection, 1, &target); + gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target); #endif } @@ -893,7 +929,7 @@ gtk_selection_add_target (GtkWidget *widget, * gtk_selection_add_targets: * @widget: a #GtkWidget * @selection: the selection - * @targets: a table of targets to add + * @targets: (array length=ntargets): a table of targets to add * @ntargets: number of entries in @targets * * Prepends a table of targets to the list of supported targets @@ -921,7 +957,7 @@ gtk_selection_add_targets (GtkWidget *widget, for (i = 0; i < ntargets; ++i) atoms[i] = gdk_atom_intern (targets[i].target, FALSE); - gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms); + gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, ntargets, atoms); g_free (atoms); } #endif @@ -943,7 +979,9 @@ gtk_selection_remove_all (GtkWidget *widget) GList *tmp_list; GList *next; GtkSelectionInfo *selection_info; - + + g_return_if_fail (GTK_IS_WIDGET (widget)); + /* Remove pending requests/incrs for this widget */ tmp_list = current_retrievals; @@ -977,7 +1015,7 @@ gtk_selection_remove_all (GtkWidget *widget) current_selections = g_list_remove_link (current_selections, tmp_list); g_list_free (tmp_list); - g_free (selection_info); + g_slice_free (GtkSelectionInfo, selection_info); } tmp_list = next; @@ -997,7 +1035,7 @@ gtk_selection_remove_all (GtkWidget *widget) In emergency, you could use #GDK_CURRENT_TIME * * Requests the contents of a selection. When received, - * a "selection_received" signal will be generated. + * a "selection-received" signal will be generated. * * Return value: %TRUE if requested succeeded. %FALSE if we could not process * request. (e.g., there was already a request in process for @@ -1020,7 +1058,7 @@ gtk_selection_convert (GtkWidget *widget, if (initialize) gtk_selection_init (); - if (!GTK_WIDGET_REALIZED (widget)) + if (!gtk_widget_get_realized (widget)) gtk_widget_realize (widget); /* Check to see if there are already any retrievals in progress for @@ -1038,7 +1076,7 @@ gtk_selection_convert (GtkWidget *widget, tmp_list = tmp_list->next; } - info = g_new (GtkRetrievalInfo, 1); + info = g_slice_new (GtkRetrievalInfo); info->widget = widget; info->selection = selection; @@ -1056,15 +1094,16 @@ gtk_selection_convert (GtkWidget *widget, if (owner_window != NULL) { GtkWidget *owner_widget; - GtkSelectionData selection_data; + gpointer owner_widget_ptr; + GtkSelectionData selection_data = {0}; selection_data.selection = selection; selection_data.target = target; - selection_data.data = NULL; selection_data.length = -1; selection_data.display = display; - gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget); + gdk_window_get_user_data (owner_window, &owner_widget_ptr); + owner_widget = owner_widget_ptr; if (owner_widget != NULL) { @@ -1080,8 +1119,10 @@ gtk_selection_convert (GtkWidget *widget, time_); g_free (selection_data.data); + selection_data.data = NULL; + selection_data.length = -1; - g_free (info); + g_slice_free (GtkRetrievalInfo, info); return TRUE; } } @@ -1089,20 +1130,168 @@ gtk_selection_convert (GtkWidget *widget, /* Otherwise, we need to go through X */ current_retrievals = g_list_append (current_retrievals, info); - gdk_selection_convert (widget->window, selection, target, time_); + gdk_selection_convert (gtk_widget_get_window (widget), selection, target, time_); gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_retrieval_timeout, info); return TRUE; } +/** + * gtk_selection_data_get_selection: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the selection #GdkAtom of the selection data. + * + * Returns: (transfer none): the selection #GdkAtom of the selection data. + * + * Since: 2.16 + **/ +GdkAtom +gtk_selection_data_get_selection (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, 0); + + return selection_data->selection; +} + +/** + * gtk_selection_data_get_target: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the target of the selection. + * + * Returns: (transfer none): the target of the selection. + * + * Since: 2.14 + **/ +GdkAtom +gtk_selection_data_get_target (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, 0); + + return selection_data->target; +} + +/** + * gtk_selection_data_get_data_type: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the data type of the selection. + * + * Returns: (transfer none): the data type of the selection. + * + * Since: 2.14 + **/ +GdkAtom +gtk_selection_data_get_data_type (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, 0); + + return selection_data->type; +} + +/** + * gtk_selection_data_get_format: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the format of the selection. + * + * Returns: the format of the selection. + * + * Since: 2.14 + **/ +gint +gtk_selection_data_get_format (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, 0); + + return selection_data->format; +} + +/** + * gtk_selection_data_get_data: (skip) + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the raw data of the selection. + * + * Returns: the raw data of the selection. + * + * Since: 2.14 + **/ +const guchar* +gtk_selection_data_get_data (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, NULL); + + return selection_data->data; +} + +/** + * gtk_selection_data_get_length: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the length of the raw data of the selection. + * + * Returns: the length of the data of the selection. + * + * Since: 2.14 + */ +gint +gtk_selection_data_get_length (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, -1); + + return selection_data->length; +} + +/** + * gtk_selection_data_get_data_with_length: + * @selection_data: a pointer to a #GtkSelectionData structure + * @length: (out): return location for length of the data segment + * + * Retrieves the raw data of the selection along with its length. + * + * Returns: (array length=length): the raw data of the selection + * + * Rename to: gtk_selection_data_get_data + * Since: 3.0 + */ +const guchar* +gtk_selection_data_get_data_with_length (const GtkSelectionData *selection_data, + gint *length) +{ + g_return_val_if_fail (selection_data != NULL, NULL); + + *length = selection_data->length; + + return selection_data->data; +} + +/** + * gtk_selection_data_get_display: + * @selection_data: a pointer to a #GtkSelectionData structure. + * + * Retrieves the display of the selection. + * + * Returns: (transfer none): the display of the selection. + * + * Since: 2.14 + **/ +GdkDisplay * +gtk_selection_data_get_display (const GtkSelectionData *selection_data) +{ + g_return_val_if_fail (selection_data != NULL, NULL); + + return selection_data->display; +} /** * gtk_selection_data_set: * @selection_data: a pointer to a #GtkSelectionData structure. * @type: the type of selection data * @format: format (number of bits in a unit) - * @data: pointer to the data (will be copied) + * @data: (array length=length): pointer to the data (will be copied) * @length: length of the data * * Stores new data into a #GtkSelectionData object. Should @@ -1116,8 +1305,9 @@ gtk_selection_data_set (GtkSelectionData *selection_data, const guchar *data, gint length) { - if (selection_data->data) - g_free (selection_data->data); + g_return_if_fail (selection_data != NULL); + + g_free (selection_data->data); selection_data->type = type; selection_data->format = format; @@ -1135,7 +1325,7 @@ gtk_selection_data_set (GtkSelectionData *selection_data, if (length < 0) selection_data->data = NULL; else - selection_data->data = g_strdup(""); + selection_data->data = (guchar *) g_strdup (""); } selection_data->length = length; @@ -1154,7 +1344,7 @@ selection_set_string (GtkSelectionData *selection_data, { gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, latin1, strlen (latin1)); + 8, (guchar *) latin1, strlen (latin1)); g_free (latin1); return TRUE; @@ -1174,18 +1364,22 @@ selection_set_compound_text (GtkSelectionData *selection_data, gint format; gint new_length; gboolean result = FALSE; - - tmp = g_strndup (str, len); - if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp, - &encoding, &format, &text, &new_length)) + +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY (selection_data->display)) { - gtk_selection_data_set (selection_data, encoding, format, text, new_length); - gdk_free_compound_text (text); - - result = TRUE; - } + tmp = g_strndup (str, len); + if (gdk_x11_display_utf8_to_compound_text (selection_data->display, tmp, + &encoding, &format, &text, &new_length)) + { + gtk_selection_data_set (selection_data, encoding, format, text, new_length); + gdk_x11_free_compound_text (text); - g_free (tmp); + result = TRUE; + } + g_free (tmp); + } +#endif return result; } @@ -1198,8 +1392,9 @@ normalize_to_crlf (const gchar *str, { GString *result = g_string_sized_new (len); const gchar *p = str; + const gchar *end = str + len; - while (1) + while (p < end) { if (*p == '\n') g_string_append_c (result, '\r'); @@ -1208,13 +1403,12 @@ normalize_to_crlf (const gchar *str, { g_string_append_c (result, *p); p++; - if (*p != '\n') + if (p == end || *p != '\n') g_string_append_c (result, '\n'); + if (p == end) + break; } - if (*p == '\0') - break; - g_string_append_c (result, *p); p++; } @@ -1285,21 +1479,21 @@ selection_set_text_plain (GtkSelectionData *selection_data, gtk_selection_data_set (selection_data, selection_data->target, - 8, result, strlen (result)); + 8, (guchar *) result, strlen (result)); g_free (result); return TRUE; } -static gchar * -selection_get_text_plain (GtkSelectionData *selection_data) +static guchar * +selection_get_text_plain (const GtkSelectionData *selection_data) { const gchar *charset = NULL; gchar *str, *result; gsize len; GError *error = NULL; - str = g_strdup (selection_data->data); + str = g_strdup ((const gchar *) selection_data->data); len = selection_data->length; if (selection_data->type == text_plain_atom) @@ -1311,7 +1505,7 @@ selection_get_text_plain (GtkSelectionData *selection_data) { gchar *tmp = str; str = g_convert_with_fallback (tmp, len, - charset, "UTF-8", + "UTF-8", charset, NULL, NULL, &len, &error); g_free (tmp); @@ -1336,7 +1530,7 @@ selection_get_text_plain (GtkSelectionData *selection_data) result = normalize_to_lf (str, len); g_free (str); - return result; + return (guchar *) result; } /** @@ -1357,6 +1551,8 @@ gtk_selection_data_set_text (GtkSelectionData *selection_data, const gchar *str, gint len) { + g_return_val_if_fail (selection_data != NULL, FALSE); + if (len < 0) len = strlen (str); @@ -1397,16 +1593,18 @@ gtk_selection_data_set_text (GtkSelectionData *selection_data, * * Gets the contents of the selection data as a UTF-8 string. * - * Return value: if the selection data contained a recognized - * text type and it could be converted to UTF-8, a newly allocated - * string containing the converted text, otherwise %NULL. + * Return value: (type utf8): if the selection data contained a + * recognized text type and it could be converted to UTF-8, a newly + * allocated string containing the converted text, otherwise %NULL. * If the result is non-%NULL it must be freed with g_free(). **/ guchar * -gtk_selection_data_get_text (GtkSelectionData *selection_data) +gtk_selection_data_get_text (const GtkSelectionData *selection_data) { guchar *result = NULL; + g_return_val_if_fail (selection_data != NULL, NULL); + init_atoms (); if (selection_data->length >= 0 && @@ -1423,7 +1621,7 @@ gtk_selection_data_get_text (GtkSelectionData *selection_data) selection_data->length, &list); if (count > 0) - result = list[0]; + result = (guchar *) list[0]; for (i = 1; i < count; i++) g_free (list[i]); @@ -1465,6 +1663,9 @@ gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data, gchar *str, *type; gsize len; + g_return_val_if_fail (selection_data != NULL, FALSE); + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE); + formats = gdk_pixbuf_get_formats (); for (f = formats; f; f = f->next) @@ -1510,7 +1711,7 @@ gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data, * * Gets the contents of the selection data as a #GdkPixbuf. * - * Return value: if the selection data contained a recognized + * Return value: (transfer full): if the selection data contained a recognized * image type and it could be converted to a #GdkPixbuf, a * newly allocated pixbuf is returned, otherwise %NULL. * If the result is non-%NULL it must be freed with g_object_unref(). @@ -1518,11 +1719,13 @@ gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data, * Since: 2.6 **/ GdkPixbuf * -gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data) +gtk_selection_data_get_pixbuf (const GtkSelectionData *selection_data) { GdkPixbufLoader *loader; GdkPixbuf *result = NULL; + g_return_val_if_fail (selection_data != NULL, NULL); + if (selection_data->length > 0) { loader = gdk_pixbuf_loader_new (); @@ -1546,7 +1749,8 @@ gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data) /** * gtk_selection_data_set_uris: * @selection_data: a #GtkSelectionData - * @uris: a %NULL-terminated array of strings hilding URIs + * @uris: (array zero-terminated=1): a %NULL-terminated array of + * strings holding URIs * * Sets the contents of the selection from a list of URIs. * The string is converted to the form determined by @@ -1561,6 +1765,9 @@ gboolean gtk_selection_data_set_uris (GtkSelectionData *selection_data, gchar **uris) { + g_return_val_if_fail (selection_data != NULL, FALSE); + g_return_val_if_fail (uris != NULL, FALSE); + init_atoms (); if (selection_data->target == text_uri_list_atom) @@ -1602,19 +1809,22 @@ gtk_selection_data_set_uris (GtkSelectionData *selection_data, * @selection_data: a #GtkSelectionData * * Gets the contents of the selection data as array of URIs. - * - * Return value: if the selection data contains a list of + * + * Return value: (array zero-terminated=1) (element-type utf8) (transfer full): if + * the selection data contains a list of * URIs, a newly allocated %NULL-terminated string array - * containing the URIs, otherwise %NULL. If the result is + * containing the URIs, otherwise %NULL. If the result is * non-%NULL it must be freed with g_strfreev(). * * Since: 2.6 **/ gchar ** -gtk_selection_data_get_uris (GtkSelectionData *selection_data) +gtk_selection_data_get_uris (const GtkSelectionData *selection_data) { gchar **result = NULL; + g_return_val_if_fail (selection_data != NULL, NULL); + init_atoms (); if (selection_data->length >= 0 && @@ -1640,8 +1850,9 @@ gtk_selection_data_get_uris (GtkSelectionData *selection_data) /** * gtk_selection_data_get_targets: * @selection_data: a #GtkSelectionData object - * @targets: location to store an array of targets. The result - * stored here must be freed with g_free(). + * @targets: (out) (array length=n_atoms) (transfer container): + * location to store an array of targets. The result stored + * here must be freed with g_free(). * @n_atoms: location to store number of items in @targets. * * Gets the contents of @selection_data as an array of targets. @@ -1653,10 +1864,12 @@ gtk_selection_data_get_uris (GtkSelectionData *selection_data) * array of targets, otherwise %FALSE. **/ gboolean -gtk_selection_data_get_targets (GtkSelectionData *selection_data, - GdkAtom **targets, - gint *n_atoms) +gtk_selection_data_get_targets (const GtkSelectionData *selection_data, + GdkAtom **targets, + gint *n_atoms) { + g_return_val_if_fail (selection_data != NULL, FALSE); + if (selection_data->length >= 0 && selection_data->format == 32 && selection_data->type == GDK_SELECTION_TYPE_ATOM) @@ -1681,7 +1894,7 @@ gtk_selection_data_get_targets (GtkSelectionData *selection_data, /** * gtk_targets_include_text: - * @targets: an array of #GdkAtoms + * @targets: (array length=n_targets): an array of #GdkAtoms * @n_targets: the length of @targets * * Determines if any of the targets in @targets can be used to @@ -1694,11 +1907,13 @@ gtk_selection_data_get_targets (GtkSelectionData *selection_data, **/ gboolean gtk_targets_include_text (GdkAtom *targets, - gint n_targets) + gint n_targets) { gint i; gboolean result = FALSE; + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + /* Keep in sync with gtk_target_list_add_text_targets() */ @@ -1724,7 +1939,7 @@ gtk_targets_include_text (GdkAtom *targets, /** * gtk_targets_include_rich_text: - * @targets: an array of #GdkAtoms + * @targets: (array length=n_targets): an array of #GdkAtoms * @n_targets: the length of @targets * @buffer: a #GtkTextBuffer * @@ -1746,6 +1961,7 @@ gtk_targets_include_rich_text (GdkAtom *targets, gint i, j; gboolean result = FALSE; + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); init_atoms (); @@ -1783,12 +1999,14 @@ gtk_targets_include_rich_text (GdkAtom *targets, * and a suitable target for text is included, otherwise %FALSE. **/ gboolean -gtk_selection_data_targets_include_text (GtkSelectionData *selection_data) +gtk_selection_data_targets_include_text (const GtkSelectionData *selection_data) { GdkAtom *targets; gint n_targets; gboolean result = FALSE; + g_return_val_if_fail (selection_data != NULL, FALSE); + init_atoms (); if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) @@ -1816,13 +2034,14 @@ gtk_selection_data_targets_include_text (GtkSelectionData *selection_data) * Since: 2.10 **/ gboolean -gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data, - GtkTextBuffer *buffer) +gtk_selection_data_targets_include_rich_text (const GtkSelectionData *selection_data, + GtkTextBuffer *buffer) { GdkAtom *targets; gint n_targets; gboolean result = FALSE; + g_return_val_if_fail (selection_data != NULL, FALSE); g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); init_atoms (); @@ -1838,7 +2057,7 @@ gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data, /** * gtk_targets_include_image: - * @targets: an array of #GdkAtoms + * @targets: (array length=n_targets): an array of #GdkAtoms * @n_targets: the length of @targets * @writable: whether to accept only targets for which GTK+ knows * how to convert a pixbuf into the format @@ -1861,6 +2080,8 @@ gtk_targets_include_image (GdkAtom *targets, gint i; gboolean result = FALSE; + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + list = gtk_target_list_new (NULL, 0); gtk_target_list_add_image_targets (list, 0, writable); for (i = 0; i < n_targets && !result; i++) @@ -1896,13 +2117,15 @@ gtk_targets_include_image (GdkAtom *targets, * Since: 2.6 **/ gboolean -gtk_selection_data_targets_include_image (GtkSelectionData *selection_data, - gboolean writable) +gtk_selection_data_targets_include_image (const GtkSelectionData *selection_data, + gboolean writable) { GdkAtom *targets; gint n_targets; gboolean result = FALSE; + g_return_val_if_fail (selection_data != NULL, FALSE); + init_atoms (); if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) @@ -1916,7 +2139,7 @@ gtk_selection_data_targets_include_image (GtkSelectionData *selection_data, /** * gtk_targets_include_uri: - * @targets: an array of #GdkAtoms + * @targets: (array length=n_targets): an array of #GdkAtoms * @n_targets: the length of @targets * * Determines if any of the targets in @targets can be used to @@ -1934,6 +2157,8 @@ gtk_targets_include_uri (GdkAtom *targets, gint i; gboolean result = FALSE; + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + /* Keep in sync with gtk_target_list_add_uri_targets() */ @@ -1960,17 +2185,19 @@ gtk_targets_include_uri (GdkAtom *targets, * provide a list or URIs. * * Return value: %TRUE if @selection_data holds a list of targets, - * and a suitable target for text is included, otherwise %FALSE. + * and a suitable target for URI lists is included, otherwise %FALSE. * * Since: 2.10 **/ gboolean -gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data) +gtk_selection_data_targets_include_uri (const GtkSelectionData *selection_data) { GdkAtom *targets; gint n_targets; gboolean result = FALSE; + g_return_val_if_fail (selection_data != NULL, FALSE); + init_atoms (); if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) @@ -1998,28 +2225,23 @@ gtk_selection_init (void) gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE"); gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP"); gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS"); + gtk_selection_atoms[SAVE_TARGETS] = gdk_atom_intern_static_string ("SAVE_TARGETS"); initialize = FALSE; } /** - * gtk_selection_clear: + * _gtk_selection_clear: * @widget: a #GtkWidget * @event: the event * - * The default handler for the GtkWidget::selection_clear_event + * The default handler for the #GtkWidget::selection-clear-event * signal. * * Return value: %TRUE if the event was handled, otherwise false - * - * Since: 2.2 - * - * Deprecated: 2.4: Instead of calling this function, chain up from - * your selection_clear_event handler. Calling this function - * from any other context is illegal. **/ gboolean -gtk_selection_clear (GtkWidget *widget, +_gtk_selection_clear (GtkWidget *widget, GdkEventSelection *event) { /* Note that we filter clear events in gdkselection-x11.c, so @@ -2045,7 +2267,7 @@ gtk_selection_clear (GtkWidget *widget, { current_selections = g_list_remove_link (current_selections, tmp_list); g_list_free (tmp_list); - g_free (selection_info); + g_slice_free (GtkSelectionInfo, selection_info); } return TRUE; @@ -2093,23 +2315,15 @@ _gtk_selection_request (GtkWidget *widget, if (tmp_list == NULL) return FALSE; - info = g_new (GtkIncrInfo, 1); + info = g_slice_new (GtkIncrInfo); g_object_ref (widget); - + info->selection = event->selection; info->num_incrs = 0; - - /* Create GdkWindow structure for the requestor */ - - info->requestor = gdk_window_lookup_for_display (display, - event->requestor); - if (!info->requestor) - info->requestor = gdk_window_foreign_new_for_display (display, - event->requestor); - + info->requestor = g_object_ref (event->requestor); + /* Determine conversions we need to perform */ - if (event->target == gtk_selection_atoms[MULTIPLE]) { GdkAtom type; @@ -2131,10 +2345,11 @@ _gtk_selection_request (GtkWidget *widget, GDK_NONE, event->time); g_free (mult_atoms); - g_free (info); + g_slice_free (GtkIncrInfo, info); + gdk_error_trap_pop_ignored (); return TRUE; } - gdk_error_trap_pop (); + gdk_error_trap_pop_ignored (); /* This is annoying; the ICCCM doesn't specify the property type * used for the property contents, so the autoconversion for @@ -2168,6 +2383,8 @@ _gtk_selection_request (GtkWidget *widget, info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i]; info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1]; } + + g_free (mult_atoms); } } else /* only a single conversion */ @@ -2200,7 +2417,6 @@ _gtk_selection_request (GtkWidget *widget, #endif gtk_selection_invoke_handler (widget, &data, event->time); - if (data.length < 0) { info->conversions[i].property = GDK_NONE; @@ -2306,7 +2522,7 @@ _gtk_selection_request (GtkWidget *widget, if (info->num_incrs == 0) { g_free (info->conversions); - g_free (info); + g_slice_free (GtkIncrInfo, info); } g_object_unref (widget); @@ -2348,7 +2564,7 @@ _gtk_selection_incr_event (GdkWindow *window, g_message ("PropertyDelete, property %ld", event->atom); #endif - selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window)); + selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_window_get_display (window)); /* Now find the appropriate ongoing INCR */ tmp_list = current_incrs; @@ -2398,7 +2614,7 @@ _gtk_selection_incr_event (GdkWindow *window, #ifdef DEBUG_SELECTION g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld", num_bytes, info->conversions[i].offset, - GDK_WINDOW_XWINDOW(info->requestor), event->atom); + GDK_WINDOW_XID(info->requestor), event->atom); #endif bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format); @@ -2474,7 +2690,7 @@ gtk_selection_incr_timeout (GtkIncrInfo *info) /* FIXME: we should check if requestor window is still in use, and if not, remove it? */ - g_free (info); + g_slice_free (GtkIncrInfo, info); retval = FALSE; /* remove timeout */ } @@ -2490,7 +2706,7 @@ gtk_selection_incr_timeout (GtkIncrInfo *info) /************************************************************* * _gtk_selection_notify: - * Handler for "selection_notify_event" signals on windows + * Handler for "selection-notify-event" signals on windows * where a retrieval is currently in process. The selection * owner has responded to our conversion request. * arguments: @@ -2502,21 +2718,24 @@ gtk_selection_incr_timeout (GtkIncrInfo *info) *************************************************************/ gboolean -_gtk_selection_notify (GtkWidget *widget, +_gtk_selection_notify (GtkWidget *widget, GdkEventSelection *event) { GList *tmp_list; GtkRetrievalInfo *info = NULL; + GdkWindow *window; guchar *buffer = NULL; gint length; GdkAtom type; gint format; - + #ifdef DEBUG_SELECTION g_message ("Initial receipt of selection %ld, target %ld (property = %ld)", event->selection, event->target, event->property); #endif - + + window = gtk_widget_get_window (widget); + tmp_list = current_retrievals; while (tmp_list) { @@ -2530,7 +2749,7 @@ _gtk_selection_notify (GtkWidget *widget, return FALSE; if (event->property != GDK_NONE) - length = gdk_selection_property_get (widget->window, &buffer, + length = gdk_selection_property_get (window, &buffer, &type, &format); else length = 0; /* silence gcc */ @@ -2554,8 +2773,8 @@ _gtk_selection_notify (GtkWidget *widget, info->notify_time = event->time; info->idle_time = 0; info->offset = 0; /* Mark as OK to proceed */ - gdk_window_set_events (widget->window, - gdk_window_get_events (widget->window) + gdk_window_set_events (window, + gdk_window_get_events (window) | GDK_PROPERTY_CHANGE_MASK); } else @@ -2569,9 +2788,9 @@ _gtk_selection_notify (GtkWidget *widget, type, format, buffer, length, event->time); } - - gdk_property_delete (widget->window, event->property); - + + gdk_property_delete (window, event->property); + g_free (buffer); return TRUE; @@ -2579,7 +2798,7 @@ _gtk_selection_notify (GtkWidget *widget, /************************************************************* * _gtk_selection_property_notify: - * Handler for "property_notify_event" signals on windows + * Handler for "property-notify-event" signals on windows * where a retrieval is currently in process. The selection * owner has added more data. * arguments: @@ -2596,6 +2815,7 @@ _gtk_selection_property_notify (GtkWidget *widget, { GList *tmp_list; GtkRetrievalInfo *info = NULL; + GdkWindow *window; guchar *new_buffer; int length; GdkAtom type; @@ -2632,11 +2852,12 @@ _gtk_selection_property_notify (GtkWidget *widget, return FALSE; info->idle_time = 0; - - length = gdk_selection_property_get (widget->window, &new_buffer, + + window = gtk_widget_get_window (widget); + length = gdk_selection_property_get (window, &new_buffer, &type, &format); - gdk_property_delete (widget->window, event->atom); - + gdk_property_delete (window, event->atom); + /* We could do a lot better efficiency-wise by paying attention to what length was sent in the initial INCR transaction, instead of doing memory allocation at every step. But its only guaranteed to @@ -2718,7 +2939,7 @@ gtk_selection_retrieval_timeout (GtkRetrievalInfo *info) } g_free (info->buffer); - g_free (info); + g_slice_free (GtkRetrievalInfo, info); retval = FALSE; /* remove timeout */ } @@ -2734,7 +2955,7 @@ gtk_selection_retrieval_timeout (GtkRetrievalInfo *info) /************************************************************* * gtk_selection_retrieval_report: - * Emits a "selection_received" signal. + * Emits a "selection-received" signal. * arguments: * info: information about the retrieval that completed * buffer: buffer containing data (NULL => errror) @@ -2760,7 +2981,7 @@ gtk_selection_retrieval_report (GtkRetrievalInfo *info, data.display = gtk_widget_get_display (info->widget); g_signal_emit_by_name (info->widget, - "selection_received", + "selection-received", &data, time); } @@ -2791,11 +3012,12 @@ gtk_selection_invoke_handler (GtkWidget *widget, g_return_if_fail (widget != NULL); target_list = gtk_selection_target_list_get (widget, data->selection); - if (target_list && + if (data->target != gtk_selection_atoms[SAVE_TARGETS] && + target_list && gtk_target_list_find (target_list, data->target, &info)) { g_signal_emit_by_name (widget, - "selection_get", + "selection-get", data, info, time); } @@ -2884,6 +3106,12 @@ gtk_selection_default_handler (GtkWidget *widget, tmp_list = tmp_list->next; } } + else if (data->target == gtk_selection_atoms[SAVE_TARGETS]) + { + gtk_selection_data_set (data, + gdk_atom_intern_static_string ("NULL"), + 32, NULL, 0); + } else { data->length = -1; @@ -2900,13 +3128,13 @@ gtk_selection_default_handler (GtkWidget *widget, * Return value: a pointer to a copy of @data. **/ GtkSelectionData* -gtk_selection_data_copy (GtkSelectionData *data) +gtk_selection_data_copy (const GtkSelectionData *data) { GtkSelectionData *new_data; g_return_val_if_fail (data != NULL, NULL); - new_data = g_new (GtkSelectionData, 1); + new_data = g_slice_new (GtkSelectionData); *new_data = *data; if (data->data) @@ -2930,39 +3158,86 @@ gtk_selection_data_free (GtkSelectionData *data) { g_return_if_fail (data != NULL); - if (data->data) - g_free (data->data); + g_free (data->data); - g_free (data); + g_slice_free (GtkSelectionData, data); +} + +/** + * gtk_target_entry_new: + * @target: String identifier for target + * @flags: Set of flags, see #GtkTargetFlags + * @info: an ID that will be passed back to the application + * + * Makes a new #GtkTargetEntry structure. + * + * Return value: a pointer to a new GtkTargetEntry structure. + * Free with gtk_target_entry_free() + **/ +GtkTargetEntry * +gtk_target_entry_new (const char *target, + guint flags, + guint info) +{ + GtkTargetEntry entry = { (char *) target, flags, info }; + return gtk_target_entry_copy (&entry); } -GType -gtk_selection_data_get_type (void) +/** + * gtk_target_entry_copy: + * @data: a pointer to a #GtkTargetEntry structure. + * + * Makes a copy of a #GtkTargetEntry structure and its data. + * + * Return value: a pointer to a copy of @data. + * Free with gtk_target_entry_free() + **/ +GtkTargetEntry * +gtk_target_entry_copy (GtkTargetEntry *data) { - static GType our_type = 0; - - if (our_type == 0) - our_type = g_boxed_type_register_static (I_("GtkSelectionData"), - (GBoxedCopyFunc) gtk_selection_data_copy, - (GBoxedFreeFunc) gtk_selection_data_free); + GtkTargetEntry *new_data; + + g_return_val_if_fail (data != NULL, NULL); - return our_type; + new_data = g_slice_new (GtkTargetEntry); + new_data->target = g_strdup (data->target); + new_data->flags = data->flags; + new_data->info = data->info; + + return new_data; } -GType -gtk_target_list_get_type (void) +/** + * gtk_target_entry_free: + * @data: a pointer to a #GtkTargetEntry structure. + * + * Frees a #GtkTargetEntry structure returned from + * gtk_target_entry_new() or gtk_target_entry_copy(). + **/ +void +gtk_target_entry_free (GtkTargetEntry *data) { - static GType our_type = 0; + g_return_if_fail (data != NULL); - if (our_type == 0) - our_type = g_boxed_type_register_static (I_("GtkTargetList"), - (GBoxedCopyFunc) gtk_target_list_ref, - (GBoxedFreeFunc) gtk_target_list_unref); + g_free (data->target); - return our_type; + g_slice_free (GtkTargetEntry, data); } -static int + +G_DEFINE_BOXED_TYPE (GtkSelectionData, gtk_selection_data, + gtk_selection_data_copy, + gtk_selection_data_free) + +G_DEFINE_BOXED_TYPE (GtkTargetList, gtk_target_list, + gtk_target_list_ref, + gtk_target_list_unref) + +G_DEFINE_BOXED_TYPE (GtkTargetEntry, gtk_target_entry, + gtk_target_entry_copy, + gtk_target_entry_free) + +static int gtk_selection_bytes_per_item (gint format) { switch (format) @@ -2981,6 +3256,3 @@ gtk_selection_bytes_per_item (gint format) } return 0; } - -#define __GTK_SELECTION_C__ -#include "gtkaliasdef.c"