Add a notify function to GdkContentProvider

The callback-based content providers need a GDestroyNotify function to
free the data passed to them on construction, otherwise they are going
to leak.
This commit is contained in:
Emmanuele Bassi 2020-02-11 17:24:01 +00:00
parent 47f2a6cafd
commit cdd7e4c5ec
11 changed files with 74 additions and 19 deletions

View File

@ -154,7 +154,7 @@ prepare_drag (GtkDragSource *source,
double y,
GtkWidget *image)
{
return gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
return gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image, NULL);
}
static void

View File

@ -444,7 +444,7 @@ setup_image_dnd (GtkWidget *image)
GtkDragSource *source;
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image, NULL);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
@ -458,7 +458,7 @@ setup_scalable_image_dnd (GtkWidget *image)
GtkDragSource *source;
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image);
content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image, NULL);
gtk_drag_source_set_content (source, content);
g_object_unref (content);

View File

@ -295,6 +295,7 @@ struct _GdkContentProviderCallback
GType type;
GdkContentProviderGetValueFunc func;
gpointer data;
GDestroyNotify notify;
};
struct _GdkContentProviderCallbackClass
@ -330,10 +331,28 @@ gdk_content_provider_callback_get_value (GdkContentProvider *provider,
return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_callback_parent_class)->get_value (provider, value, error);
}
static void
gdk_content_provider_callback_dispose (GObject *gobject)
{
GdkContentProviderCallback *self = GDK_CONTENT_PROVIDER_CALLBACK (gobject);
if (self->notify != NULL)
self->notify (self->data);
self->func = NULL;
self->data = NULL;
self->notify = NULL;
G_OBJECT_CLASS (gdk_content_provider_callback_parent_class)->dispose (gobject);
}
static void
gdk_content_provider_callback_class_init (GdkContentProviderCallbackClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
gobject_class->dispose = gdk_content_provider_callback_dispose;
provider_class->ref_formats = gdk_content_provider_callback_ref_formats;
provider_class->get_value = gdk_content_provider_callback_get_value;
@ -345,10 +364,12 @@ gdk_content_provider_callback_init (GdkContentProviderCallback *content)
}
/**
* gdk_content_provider_new_for_callback:
* gdk_content_provider_new_for_callback: (constructor)
* @type: the type that the callback provides
* @func: callback to populate a #GValue
* @func: (not nullable): callback to populate a #GValue
* @data: (closure): data that gets passed to @func
* @notify: a function to be called to free @data when the content provider
* goes away
*
* Create a content provider that provides data that is provided via a callback.
*
@ -357,14 +378,18 @@ gdk_content_provider_callback_init (GdkContentProviderCallback *content)
GdkContentProvider *
gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data)
gpointer data,
GDestroyNotify notify)
{
GdkContentProviderCallback *content;
g_return_val_if_fail (func != NULL, NULL);
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK, NULL);
content->type = type;
content->func = func;
content->data = data;
content->notify = notify;
return GDK_CONTENT_PROVIDER (content);
}
@ -382,6 +407,7 @@ struct _GdkContentProviderCallback2
GdkContentFormats *formats;
GdkContentProviderGetBytesFunc func;
gpointer data;
GDestroyNotify notify;
};
struct _GdkContentProviderCallback2Class
@ -472,10 +498,28 @@ gdk_content_provider_callback2_write_mime_type_finish (GdkContentProvider *provi
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
gdk_content_provider_callback2_dispose (GObject *gobject)
{
GdkContentProviderCallback2 *self = GDK_CONTENT_PROVIDER_CALLBACK2 (gobject);
if (self->notify != NULL)
self->notify (self->data);
self->notify = NULL;
self->data = NULL;
self->func = NULL;
G_OBJECT_CLASS (gdk_content_provider_callback2_parent_class)->dispose (gobject);
}
static void
gdk_content_provider_callback2_class_init (GdkContentProviderCallback2Class *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
gobject_class->dispose = gdk_content_provider_callback2_dispose;
provider_class->ref_formats = gdk_content_provider_callback2_ref_formats;
provider_class->write_mime_type_async = gdk_content_provider_callback2_write_mime_type_async;
@ -491,7 +535,9 @@ gdk_content_provider_callback2_init (GdkContentProviderCallback2 *content)
* gdk_content_provider_new_with_formats:
* @formats: formats to advertise
* @func: callback to populate a #GValue
* @data: data that gets passed to @func
* @data: (closure func): data that gets passed to @func
* @notify: a function called to free @data when the content provider
* goes away
*
* Create a content provider that provides data that is provided via a callback.
*
@ -500,13 +546,15 @@ gdk_content_provider_callback2_init (GdkContentProviderCallback2 *content)
GdkContentProvider *
gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data)
gpointer data,
GDestroyNotify notify)
{
GdkContentProviderCallback2 *content;
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, NULL);
content->formats = gdk_content_formats_union_serialize_mime_types (gdk_content_formats_ref (formats));
content->func = func;
content->data = data;
content->notify = notify;
return GDK_CONTENT_PROVIDER (content);
}

View File

@ -41,7 +41,8 @@ typedef void (*GdkContentProviderGetValueFunc) (GValue *value,
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data);
gpointer data,
GDestroyNotify notify);
typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type,
gpointer data);
@ -49,7 +50,8 @@ typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type,
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data);
gpointer data,
GDestroyNotify notify);
G_END_DECLS

View File

@ -333,7 +333,7 @@ gtk_color_button_init (GtkColorButton *button)
gdk_content_formats_unref (targets);
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, button);
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, button, NULL);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_button_drag_begin), button);

View File

@ -598,7 +598,7 @@ gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
GtkDragSource *source;
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, swatch);
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, swatch, NULL);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_swatch_drag_begin), swatch);
@ -618,7 +618,6 @@ gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
{
gtk_widget_add_css_class (GTK_WIDGET (swatch), "dark");
gtk_widget_remove_css_class (GTK_WIDGET (swatch), "light");
}
gtk_widget_queue_draw (GTK_WIDGET (swatch));

View File

@ -6055,7 +6055,8 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
content = gdk_content_provider_new_with_formats (icon_view->priv->source_formats,
gtk_icon_view_drag_data_get,
icon_view);
icon_view,
NULL);
drag = gdk_drag_begin (surface,
device,
@ -6064,7 +6065,7 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y);
g_object_unref (content);
g_object_unref (content);
g_signal_connect (drag, "dnd-finished", G_CALLBACK (gtk_icon_view_dnd_finished_cb), icon_view);

View File

@ -2882,7 +2882,8 @@ gtk_notebook_motion (GtkEventController *controller,
content = gdk_content_provider_new_with_formats (priv->source_targets,
gtk_notebook_drag_data_get,
widget);
widget,
NULL);
drag = gdk_drag_begin (surface, device, content, GDK_ACTION_MOVE, priv->drag_begin_x, priv->drag_begin_y);
g_object_unref (content);

View File

@ -3759,7 +3759,8 @@ on_row_dragged (GtkGestureDrag *gesture,
content = gdk_content_provider_new_with_formats (sidebar->source_targets,
drag_data_get_callback,
sidebar);
sidebar,
NULL);
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (sidebar)));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));

View File

@ -7109,7 +7109,10 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view)
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (tree_view)));
device = gtk_gesture_get_device (GTK_GESTURE (tree_view->drag_gesture)),
content = gdk_content_provider_new_with_formats (di->source_formats, gtk_tree_view_drag_data_get, tree_view);
content = gdk_content_provider_new_with_formats (di->source_formats,
gtk_tree_view_drag_data_get,
tree_view,
NULL);
drag = gdk_drag_begin (surface, device, content, di->source_actions, start_x, start_y);

View File

@ -399,7 +399,7 @@ make_image (const gchar *icon_name, int hotspot)
gdk_content_formats_builder_add_gtype (builder, G_TYPE_STRING);
formats = gdk_content_formats_builder_free_to_formats (builder);
content = gdk_content_provider_new_with_formats (formats, get_data, image);
content = gdk_content_provider_new_with_formats (formats, get_data, image, NULL);
source = gtk_drag_source_new ();
gtk_drag_source_set_content (source, content);
gtk_drag_source_set_actions (source, GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_ASK);