Migrating gtk_clipboard to gdk_clipboard, how?

Hello all,
I’m working on porting my app from GTK3 to GTK4 and I have a small problem with the new GDK Clipboard.
I have the following four functions in my code that I don’t really know how to replace:

gtk_clipboard_request_uris (..);
gtk_clipboard_request_image (..);
gtk_clipboard_wait_is_uris_available (..);
gtk_clipboard_wait_is_image_available (..);

Can someone please point me to the right way of replacing these funcs?

Thanks a lot

There is no 1:1 mapping between the GTK3 and the GTK4 API. If you are implementing copy and paste of URLs and image data, there is a demo doing that in gtk4-demo.

Ah nice, thanks! I’ll have a look into it!

The examples helped a lot! Now I have only one thing left: getting a gdkpixbuf from a gdkpaintable. Is that possible?
In GTK3 there’s a gtk_image_get_pixbuf , but it’s gone in GTK4. How can I convert a gdkpaintable/gtkimage to a gdkpixbuf now?

There’s really no reason to use GdkPixbuf as an intermediate object: GTK4 can automatically copy and paste GdkPaintables directly.

I need to use gdk_pixbuf_save because I have to pass a png file to another library I’m using, so I can’t do everything in memory, unfortunately.
What’s the best way to save a png to disk without using gdkpixbuf then?

Thanks!

If you’re using gtk_image_set_from_pixbuf() then, as the documentation states, you’re telling GTK to create a GdkPaintable out of the GdkPixbuf; the paintable in question is a GdkTexture.

If you want to get the image data out of a GdkTexture then you need to call gdk_texture_download(), which will give you the pixel data and the row stride. You can then create a GdkPixbuf out of that.

To be fair, the reason why it’s not really a good idea to do that is that GTK will try to upload the data to the GPU whenever possible, and remove copies in system memory; if you need to keep GdkPixbuf instances around, you may want to use GDK_TYPE_PIXBUF as the content type for your clipboard operations, instead of going through GDK_TYPE_PAINTABLE.

What I’m actually doing is the following:

Let’s say I have file1.c:

GdkPixbuf *pb;
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
GValue value = G_VALUE_INIT;
g_value_init (&value, GDK_TYPE_PAINTABLE);
if (!gdk_content_provider_get_value (content, &value, NULL)) {
    // it may be text, check and treat data accordingly
} else {
    // it's an image, so get a pixbuf out of it
    GdkPaintable *paintable = GDK_PAINTABLE (g_value_get_object (&value));
    pb = get_pixbuf_from_paintable() //how do I achieve this ?
    g_value_unset (&value);
}
...
another_func(pb);
...

anot

and file2.c with:

void another_func (GdkPixbuf *pb)
{
    ...
    gdk_pixbuf_save (pb, temp_file, "png", &err, NULL);
    ...
}

Basically, I need to check if the clipboard contains a text or an image and, in the first case, I parse and check for an URI, while in the second case I save the image to a temp location and parse the content using an external library.

You can’t. You either check that the GdkPaintable is a GdkTexture, and call gtk_texture_download() to get the texture data, or you cannot get the image data because that is a composite of multiple sources residing on the GPU.

But you don’t strictly need this if you do:

GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
GValue value = G_VALUE_INIT;
GdkPixbuf *pb = NULL;

g_value_init (&value, GDK_TYPE_PIXBUF);

if (!gdk_content_provider_get_value (content, &value, NULL)) {
  // ...
} else {
  pb = g_value_get_object (&value);
}

if (pb != NULL)
  another_func (pb);

g_value_unset (&value);

Ah, right! I was so focused on learning all these new concepts that I completely missed the easy solution of changing g_value_init (&value, GDK_TYPE_PIXBUF); :slight_smile:

Thanks a lot Emmanuele, your help was really super appreciated :+1:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.