Hi,
I’m migrating a GTK3 application to GTK4, but I’m failing to get text from the clipboard. This is my current minimal script:
#!/usr/bin/env python
"""Display the current textual content from the clipboard.
Usage:
1. Select some text in any application and copy it (e.g. Ctrl+C).
2. Run this program in a terminal.
Result:
The program displays the text you copied on screen."""
import gi
gi.require_version("Gdk", "4.0")
gi.require_version("Gtk", "4.0")
from gi.repository import Gdk, GObject, Gtk
# FUNCTIONS
def get_text():
"""Return text from the clipboard."""
def read_text(clipboard, result, user_data):
value = clipboard.read_value_finish(result)
print(value)
return value.get_string()
display = Gdk.Display.get_default()
clipboard = display.get_clipboard()
# clipboard.set("yellow")
formats = clipboard.get_formats() # FIXME: Always empty ↓ Unless set ↑
print("Formats:", formats.to_string()) # Just checking...
if formats.contain_gtype(GObject.TYPE_STRING):
text = clipboard.read_value_async(
GObject.TYPE_STRING,
0, # I/O Priority
None, # Cancellable
read_text, # Callback
None # User data
)
else:
text = "N/A"
return text
# RUN
Gtk.init()
print("TEXT:", get_text())
Running the program as is, it seems the clipboard is always empty, even though I have copied text from the web browser or another application.
Also, if I uncomment the line clipboard.set("yellow")
, the clipboard formats report that there is plain text, but reading the value returns None
instead of "yellow"
.
NOTE: The Clipboard
example from gtk4-demo
reads text from the clipboard and it actually works. That is, I can copy text from the web browser, for example, and when I click the Paste
button in the demo, it pastes the right text. But the demo is written in C, and although the script above is actually a translation of the relevant parts of the Clipboard demo, it doesn’t work. I can’t see what I’m missing…
This is the relevant C code:
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <string.h>
#include "demoimage.h"
static void
present_value (GtkStack *dest_stack,
const GValue *value)
{
GtkWidget *child;
// ...
if (G_VALUE_HOLDS (value, G_TYPE_STRING))
{
gtk_stack_set_visible_child_name (dest_stack, "Text");
child = gtk_stack_get_visible_child (dest_stack);
gtk_label_set_label (GTK_LABEL (child), g_value_get_string (value));
}
}
static void
paste_received (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
GtkStack *dest_stack = user_data;
GdkClipboard *clipboard;
const GValue *value;
GError *error = NULL;
clipboard = GDK_CLIPBOARD (source_object);
value = gdk_clipboard_read_value_finish (clipboard, result, &error);
if (value)
{
present_value (dest_stack, value);
}
else
{
g_print ("%s\n", error->message);
g_error_free (error);
}
}
static void
paste_button_clicked (GtkStack *dest_stack,
gpointer user_data)
{
GdkClipboard *clipboard;
GdkContentFormats *formats;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (dest_stack));
formats = gdk_clipboard_get_formats (clipboard);
// ...
if (gdk_content_formats_contain_gtype (formats, G_TYPE_STRING))
gdk_clipboard_read_value_async (clipboard, G_TYPE_STRING, 0, NULL, paste_received, dest_stack);
}