@samitouri / QOSamiQemu / commits / 9a007326e8

ui/gtk: Use non-blocking clipboard retrieval

Signed-off-by: Jindrich Makovicka <makovick@gmail.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260427-gtk-clipboard-v5-1-6968feb31a5d@gmail.com>

Jindřich Makovička committed Apr 27, 2026 at 22:06 UTC 9a007326e83f50185a4d2f1461b380897de0836a
1 file changed +40 -13
ui/gtk-clipboard.c
+40 -13
@@ -136,26 +136,55 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
136 }
137 }
138
139 +static void
140 +gd_clipboard_request_text_received_callback(GtkClipboard *clipboard,
141 + const gchar *text,
142 + gpointer data)
143 +{
144 + QemuClipboardInfo *info = (QemuClipboardInfo *)data;
145 +
146 + if (text) {
147 + qemu_clipboard_set_data(info->owner, info, QEMU_CLIPBOARD_TYPE_TEXT,
148 + strlen(text), text, true);
149 + }
150 + qemu_clipboard_info_unref(info);
151 +}
152 +
153 static void gd_clipboard_request(QemuClipboardInfo *info,
154 QemuClipboardType type)
155 {
156 GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
143 - char *text;
157
158 switch (type) {
159 case QEMU_CLIPBOARD_TYPE_TEXT:
147 - text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
148 - if (text) {
149 - qemu_clipboard_set_data(&gd->cbpeer, info, type,
150 - strlen(text), text, true);
151 - g_free(text);
152 - }
160 + qemu_clipboard_info_ref(info);
161 + gtk_clipboard_request_text(gd->gtkcb[info->selection],
162 + gd_clipboard_request_text_received_callback,
163 + info);
164 break;
165 default:
166 break;
167 }
168 }
169
170 +static void gd_clipboard_owner_change_targets_received_callback(
171 + GtkClipboard *clipboard,
172 + GdkAtom *targets,
173 + gint n_targets,
174 + gpointer data)
175 +{
176 + QemuClipboardInfo *info = (QemuClipboardInfo *)data;
177 +
178 + if (n_targets) {
179 + if (gtk_targets_include_text(targets, n_targets)) {
180 + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
181 + }
182 + }
183 +
184 + qemu_clipboard_update(info);
185 + qemu_clipboard_info_unref(info);
186 +}
187 +
188 static void gd_owner_change(GtkClipboard *clipboard,
189 GdkEvent *event,
190 gpointer data)
@@ -173,12 +202,10 @@ static void gd_owner_change(GtkClipboard *clipboard,
202 switch (event->owner_change.reason) {
203 case GDK_OWNER_CHANGE_NEW_OWNER:
204 info = qemu_clipboard_info_new(&gd->cbpeer, s);
176 - if (gtk_clipboard_wait_is_text_available(clipboard)) {
177 - info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
178 - }
179 -
180 - qemu_clipboard_update(info);
181 - qemu_clipboard_info_unref(info);
205 + gtk_clipboard_request_targets(
206 + clipboard,
207 + gd_clipboard_owner_change_targets_received_callback,
208 + info);
209 break;
210 default:
211 qemu_clipboard_peer_release(&gd->cbpeer, s);