Costales
Costales

Reputation: 2873

How to get clipboard content with Python3 & GDK 4?

GTK4 doens't manage the Clipboard anymore, now it's done from GDK4.

I was not lucky migrating this code from GTK3 to GDK4?

from gi.repository import Gtk, Gdk
cb = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
content = cb.wait_for_text()

Any idea please? Thanks in advance!

Upvotes: 5

Views: 765

Answers (2)

Reece
Reece

Reputation: 8108

I finally figured this out. Here's a complete function to copy the clipboard to a file in a Nautilus plugin (see nautilus-image-copypaste):

def get_clipboard():
    clipboard = Gdk.Display().get_default().get_clipboard()
    _logger.warning("Clipboard: " + clipboard.get_formats().to_string())
    return clipboard

def copy_clipboard_to_file_image(self, menuitem: Nautilus.MenuItem, dir):
    clipboard = get_clipboard()

    def update_cb(so, res, user_data):
        texture = clipboard.read_texture_finish(res)
        pixbuf = Gdk.pixbuf_get_from_texture(texture)
        ts = datetime.datetime.utcnow().strftime("%FT%T")
        filename = os.path.join(dir, f"Clipboard {ts}.png")
        pixbuf.savev(filename, "png", (), ())
        _logger.warning(f"Pasted to {filename}")

    clipboard.read_texture_async(
        cancellable=None, callback=update_cb, user_data=None
    )

This is for textures, but there are similar mechanisms for text or other content. Clipboard handling changed immensely between Gtk/Gdk 3 and 4. The major changes: 1) Clipboard moved from Gtk to Gdk, 2) The Gdk 4 clipboard requires callbacks.

I did not figure out how to do the reverse, i.e., set the clipboard from a texture. For that, I opened How do I set the clipboard with a Texture in Gdk4 using Python?.

Upvotes: 5

Dodezv
Dodezv

Reputation: 316

Gtk.Widget has a method get_clipboard() to get the clipboard.

The clipboard has a method read_text_async, which is called with a callback that is supposed to call read_text_finished.

widget: Gtk.Widget = ...
clipboard = widget.get_clipboard()

def callback(cb, res):
    try:
        text = cb.read_text_finished(cb, res)
    except GLib.GError:  # Errors occur often
        pass
    else:
        ...
clipboard.read_text_async(None, callback)

The suggested method in the migration guide is Gdk.Clipboard.get_content(), which returns a GdkContentProvider, but this content is empty if the copied text does not come from within the application. Furthermore, I have not gotten it to work with Python, maybe because the method GdkContentProvider.get_value has an in-out-parameter.

Upvotes: 0

Related Questions