[PATCH v3 1/2] ui/gtk: Use non-blocking clipboard retrieval

Jindřich Makovička posted 2 patches 2 months, 2 weeks ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
There is a newer version of this series
[PATCH v3 1/2] ui/gtk: Use non-blocking clipboard retrieval
Posted by Jindřich Makovička 2 months, 2 weeks ago
Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
---
 ui/gtk-clipboard.c | 52 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 13 deletions(-)

diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index 65d89ec601..691784697d 100644
--- a/ui/gtk-clipboard.c
+++ b/ui/gtk-clipboard.c
@@ -136,26 +136,54 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
     }
 }
 
+static void
+gd_clipboard_request_text_received_callback(GtkClipboard *clipboard,
+                                            const gchar *text,
+                                            gpointer data)
+{
+    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
+
+    if (text) {
+        qemu_clipboard_set_data(info->owner, info, QEMU_CLIPBOARD_TYPE_TEXT,
+                                strlen(text), text, true);
+    }
+    qemu_clipboard_info_unref(info);
+}
+
 static void gd_clipboard_request(QemuClipboardInfo *info,
                                  QemuClipboardType type)
 {
     GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
-    char *text;
 
     switch (type) {
     case QEMU_CLIPBOARD_TYPE_TEXT:
-        text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
-        if (text) {
-            qemu_clipboard_set_data(&gd->cbpeer, info, type,
-                                    strlen(text), text, true);
-            g_free(text);
-        }
+        qemu_clipboard_info_ref(info);
+        gtk_clipboard_request_text(gd->gtkcb[info->selection],
+                                   gd_clipboard_request_text_received_callback,
+                                   info);
         break;
     default:
         break;
     }
 }
 
+static void gd_clipboard_owner_change_contents_received_callback(
+    GtkClipboard *clipboard,
+    GtkSelectionData *selection_data,
+    gpointer data)
+{
+    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
+
+    if (selection_data) {
+        if (gtk_selection_data_targets_include_text(selection_data)) {
+            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
+        }
+    }
+
+    qemu_clipboard_update(info);
+    qemu_clipboard_info_unref(info);
+}
+
 static void gd_owner_change(GtkClipboard *clipboard,
                             GdkEvent *event,
                             gpointer data)
@@ -173,12 +201,10 @@ static void gd_owner_change(GtkClipboard *clipboard,
     switch (event->owner_change.reason) {
     case GDK_OWNER_CHANGE_NEW_OWNER:
         info = qemu_clipboard_info_new(&gd->cbpeer, s);
-        if (gtk_clipboard_wait_is_text_available(clipboard)) {
-            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
-        }
-
-        qemu_clipboard_update(info);
-        qemu_clipboard_info_unref(info);
+        gtk_clipboard_request_contents(
+            clipboard, gdk_atom_intern_static_string("TARGETS"),
+            gd_clipboard_owner_change_contents_received_callback,
+            info);
         break;
     default:
         qemu_clipboard_peer_release(&gd->cbpeer, s);

-- 
2.53.0
Re: [PATCH v3 1/2] ui/gtk: Use non-blocking clipboard retrieval
Posted by Marc-André Lureau 2 months, 2 weeks ago
Hi Jindřich

On Sun, Apr 26, 2026 at 11:53 AM Jindřich Makovička <makovick@gmail.com> wrote:
>

Could you review & compare with the previous lost patch ("[PATCH v4]
ui/gtk-clipboard: async owner_change clipboard_request")

https://patchew.org/QEMU/20231206142243.510068-1-edmund.raile@proton.me/

thanks

> Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
> ---
>  ui/gtk-clipboard.c | 52 +++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 39 insertions(+), 13 deletions(-)
>
> diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
> index 65d89ec601..691784697d 100644
> --- a/ui/gtk-clipboard.c
> +++ b/ui/gtk-clipboard.c
> @@ -136,26 +136,54 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
>      }
>  }
>
> +static void
> +gd_clipboard_request_text_received_callback(GtkClipboard *clipboard,
> +                                            const gchar *text,
> +                                            gpointer data)
> +{
> +    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
> +
> +    if (text) {
> +        qemu_clipboard_set_data(info->owner, info, QEMU_CLIPBOARD_TYPE_TEXT,
> +                                strlen(text), text, true);
> +    }
> +    qemu_clipboard_info_unref(info);
> +}
> +
>  static void gd_clipboard_request(QemuClipboardInfo *info,
>                                   QemuClipboardType type)
>  {
>      GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
> -    char *text;
>
>      switch (type) {
>      case QEMU_CLIPBOARD_TYPE_TEXT:
> -        text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
> -        if (text) {
> -            qemu_clipboard_set_data(&gd->cbpeer, info, type,
> -                                    strlen(text), text, true);
> -            g_free(text);
> -        }
> +        qemu_clipboard_info_ref(info);
> +        gtk_clipboard_request_text(gd->gtkcb[info->selection],
> +                                   gd_clipboard_request_text_received_callback,
> +                                   info);
>          break;
>      default:
>          break;
>      }
>  }
>
> +static void gd_clipboard_owner_change_contents_received_callback(
> +    GtkClipboard *clipboard,
> +    GtkSelectionData *selection_data,
> +    gpointer data)
> +{
> +    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
> +
> +    if (selection_data) {
> +        if (gtk_selection_data_targets_include_text(selection_data)) {
> +            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
> +        }
> +    }
> +
> +    qemu_clipboard_update(info);
> +    qemu_clipboard_info_unref(info);
> +}
> +
>  static void gd_owner_change(GtkClipboard *clipboard,
>                              GdkEvent *event,
>                              gpointer data)
> @@ -173,12 +201,10 @@ static void gd_owner_change(GtkClipboard *clipboard,
>      switch (event->owner_change.reason) {
>      case GDK_OWNER_CHANGE_NEW_OWNER:
>          info = qemu_clipboard_info_new(&gd->cbpeer, s);
> -        if (gtk_clipboard_wait_is_text_available(clipboard)) {
> -            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
> -        }
> -
> -        qemu_clipboard_update(info);
> -        qemu_clipboard_info_unref(info);
> +        gtk_clipboard_request_contents(
> +            clipboard, gdk_atom_intern_static_string("TARGETS"),
> +            gd_clipboard_owner_change_contents_received_callback,
> +            info);
>          break;
>      default:
>          qemu_clipboard_peer_release(&gd->cbpeer, s);
>
> --
> 2.53.0
>
>
Re: [PATCH v3 1/2] ui/gtk: Use non-blocking clipboard retrieval
Posted by Marc-André Lureau 2 months, 2 weeks ago
Hi

On Sun, Apr 26, 2026 at 11:52 AM Jindřich Makovička <makovick@gmail.com> wrote:
>
> Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
> ---
>  ui/gtk-clipboard.c | 52 +++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 39 insertions(+), 13 deletions(-)
>
> diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
> index 65d89ec601..691784697d 100644
> --- a/ui/gtk-clipboard.c
> +++ b/ui/gtk-clipboard.c
> @@ -136,26 +136,54 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
>      }
>  }
>
> +static void
> +gd_clipboard_request_text_received_callback(GtkClipboard *clipboard,
> +                                            const gchar *text,
> +                                            gpointer data)
> +{
> +    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
> +
> +    if (text) {
> +        qemu_clipboard_set_data(info->owner, info, QEMU_CLIPBOARD_TYPE_TEXT,
> +                                strlen(text), text, true);
> +    }
> +    qemu_clipboard_info_unref(info);
> +}
> +
>  static void gd_clipboard_request(QemuClipboardInfo *info,
>                                   QemuClipboardType type)
>  {
>      GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
> -    char *text;
>
>      switch (type) {
>      case QEMU_CLIPBOARD_TYPE_TEXT:
> -        text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
> -        if (text) {
> -            qemu_clipboard_set_data(&gd->cbpeer, info, type,
> -                                    strlen(text), text, true);
> -            g_free(text);
> -        }
> +        qemu_clipboard_info_ref(info);
> +        gtk_clipboard_request_text(gd->gtkcb[info->selection],
> +                                   gd_clipboard_request_text_received_callback,
> +                                   info);
>          break;
>      default:
>          break;
>      }
>  }
>
> +static void gd_clipboard_owner_change_contents_received_callback(
> +    GtkClipboard *clipboard,
> +    GtkSelectionData *selection_data,
> +    gpointer data)
> +{
> +    QemuClipboardInfo *info = (QemuClipboardInfo *)data;
> +
> +    if (selection_data) {
> +        if (gtk_selection_data_targets_include_text(selection_data)) {
> +            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
> +        }
> +    }
> +
> +    qemu_clipboard_update(info);
> +    qemu_clipboard_info_unref(info);
> +}
> +
>  static void gd_owner_change(GtkClipboard *clipboard,
>                              GdkEvent *event,
>                              gpointer data)
> @@ -173,12 +201,10 @@ static void gd_owner_change(GtkClipboard *clipboard,
>      switch (event->owner_change.reason) {
>      case GDK_OWNER_CHANGE_NEW_OWNER:
>          info = qemu_clipboard_info_new(&gd->cbpeer, s);
> -        if (gtk_clipboard_wait_is_text_available(clipboard)) {
> -            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
> -        }
> -
> -        qemu_clipboard_update(info);
> -        qemu_clipboard_info_unref(info);
> +        gtk_clipboard_request_contents(
> +            clipboard, gdk_atom_intern_static_string("TARGETS"),
> +            gd_clipboard_owner_change_contents_received_callback,
> +            info);

could you use gtk_clipboard_request_targets instead?

lgtm otherwise

>          break;
>      default:
>          qemu_clipboard_peer_release(&gd->cbpeer, s);
>
> --
> 2.53.0
>