From 248c50b2bd31ab7bb8220cd1d7eca3a0d6463aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:56:58 +0400 Subject: [PATCH 01/18] ui/vdagent: fix leak on error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "info" was leaked when more than 10 entries. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-2-marcandre.lureau@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 2 ++ ui/vdagent.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index b45b984c9f..eb789a285a 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -190,4 +190,6 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, const void *data, bool update); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuClipboardInfo, qemu_clipboard_info_unref) + #endif /* QEMU_CLIPBOARD_H */ diff --git a/ui/vdagent.c b/ui/vdagent.c index a253a8fe63..f6ef8d1993 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -438,7 +438,7 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) uint8_t s = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; uint32_t size = msg->size; void *data = msg->data; - QemuClipboardInfo *info; + g_autoptr(QemuClipboardInfo) info = NULL; QemuClipboardType type; if (have_selection(vd)) { @@ -477,7 +477,6 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) size -= sizeof(uint32_t); } qemu_clipboard_update(info); - qemu_clipboard_info_unref(info); break; case VD_AGENT_CLIPBOARD_REQUEST: if (size < sizeof(uint32_t)) { @@ -523,7 +522,6 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) /* set empty clipboard info */ info = qemu_clipboard_info_new(NULL, s); qemu_clipboard_update(info); - qemu_clipboard_info_unref(info); } break; } From e7c55746f1eab99429ac1505536f3bbcab20df8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:56:59 +0400 Subject: [PATCH 02/18] ui/vdagent: remove copy-pasta comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-3-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index f6ef8d1993..5ae5734c81 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -516,7 +516,7 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) qemu_clipboard_set_data(&vd->cbpeer, vd->cbinfo[s], type, size, data, true); break; - case VD_AGENT_CLIPBOARD_RELEASE: /* data */ + case VD_AGENT_CLIPBOARD_RELEASE: if (vd->cbinfo[s] && vd->cbinfo[s]->owner == &vd->cbpeer) { /* set empty clipboard info */ From c311e8d7ff62ddabd474898815e8c122c484a88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:00 +0400 Subject: [PATCH 03/18] ui/gtk-clipboard: use existing macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardcoding strings is error prone, use dedicated macros instead. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-4-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/gtk-clipboard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index bff28d2030..5e817ae55c 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -177,11 +177,11 @@ void gd_clipboard_init(GtkDisplayState *gd) qemu_clipboard_peer_register(&gd->cbpeer); gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD] = - gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)); + gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY] = - gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE)); + gtk_clipboard_get(GDK_SELECTION_PRIMARY); gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY] = - gtk_clipboard_get(gdk_atom_intern("SECONDARY", FALSE)); + gtk_clipboard_get(GDK_SELECTION_SECONDARY); g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD], "owner-change", G_CALLBACK(gd_owner_change), gd); From 6b32aef09a7d592491a8e25ce1714cb0503a3d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:01 +0400 Subject: [PATCH 04/18] ui/gtk-clipboard: fix clipboard enum typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-5-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/gtk-clipboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index 5e817ae55c..2c78de9500 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -155,7 +155,7 @@ static void gd_owner_change(GtkClipboard *clipboard, switch (event->owner_change.reason) { - case GDK_SETTING_ACTION_NEW: + 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; From 684e64d36d139c1473dd029661c20ba968c0fe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:02 +0400 Subject: [PATCH 05/18] ui/clipboard: add helper to retrieve current clipboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-6-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 9 +++++++++ ui/clipboard.c | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index eb789a285a..e9fcb15c66 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -109,6 +109,15 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer); */ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); +/** + * qemu_clipboard_info + * + * @selection: clipboard selection. + * + * Return the current clipboard data & owner informations. + */ +QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection); + /** * qemu_clipboard_info_new * diff --git a/ui/clipboard.c b/ui/clipboard.c index 3525b30178..56c14509fe 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -4,6 +4,8 @@ static NotifierList clipboard_notifiers = NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); +static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; + void qemu_clipboard_peer_register(QemuClipboardPeer *peer) { notifier_list_add(&clipboard_notifiers, &peer->update); @@ -16,7 +18,20 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) void qemu_clipboard_update(QemuClipboardInfo *info) { + g_autoptr(QemuClipboardInfo) old = NULL; + assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); + notifier_list_notify(&clipboard_notifiers, info); + + old = cbinfo[info->selection]; + cbinfo[info->selection] = qemu_clipboard_info_ref(info); +} + +QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) +{ + assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); + + return cbinfo[selection]; } QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, From 482bbaf4776d223971ec68ddd4d31d8861d31f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:03 +0400 Subject: [PATCH 06/18] ui/clipboard: add qemu_clipboard_peer_owns() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-7-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 11 +++++++++++ ui/clipboard.c | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index e9fcb15c66..25e0b470c8 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -109,6 +109,17 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer); */ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); +/** + * qemu_clipboard_peer_owns + * + * @peer: peer information. + * @selection: clipboard selection. + * + * Return TRUE if the peer owns the clipboard. + */ +bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, + QemuClipboardSelection selection); + /** * qemu_clipboard_info * diff --git a/ui/clipboard.c b/ui/clipboard.c index 56c14509fe..490c3220f4 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -16,6 +16,14 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) notifier_remove(&peer->update); } +bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, + QemuClipboardSelection selection) +{ + QemuClipboardInfo *info = qemu_clipboard_info(selection); + + return info && info->owner == peer; +} + void qemu_clipboard_update(QemuClipboardInfo *info) { g_autoptr(QemuClipboardInfo) old = NULL; From 1387865eca16984fc6d57702ac9e999527681b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:04 +0400 Subject: [PATCH 07/18] ui/clipboard: add qemu_clipboard_peer_release() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-8-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 11 +++++++++++ ui/clipboard.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index 25e0b470c8..6298986b15 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -120,6 +120,17 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, QemuClipboardSelection selection); +/** + * qemu_clipboard_peer_release + * + * @peer: peer information. + * @selection: clipboard selection. + * + * If the peer owns the clipboard, release it. + */ +void qemu_clipboard_peer_release(QemuClipboardPeer *peer, + QemuClipboardSelection selection); + /** * qemu_clipboard_info * diff --git a/ui/clipboard.c b/ui/clipboard.c index 490c3220f4..c277247a7f 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -24,6 +24,18 @@ bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, return info && info->owner == peer; } +void qemu_clipboard_peer_release(QemuClipboardPeer *peer, + QemuClipboardSelection selection) +{ + g_autoptr(QemuClipboardInfo) info = NULL; + + if (qemu_clipboard_peer_owns(peer, selection)) { + /* set empty clipboard info */ + info = qemu_clipboard_info_new(NULL, selection); + qemu_clipboard_update(info); + } +} + void qemu_clipboard_update(QemuClipboardInfo *info) { g_autoptr(QemuClipboardInfo) old = NULL; From 7424bfaa99b629e243bf05debd3eeb69c1dd670f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:05 +0400 Subject: [PATCH 08/18] ui/clipboard: release owned grabs on unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-9-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/clipboard.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/clipboard.c b/ui/clipboard.c index c277247a7f..d7b008d62a 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -13,6 +13,12 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer) void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) { + int i; + + for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { + qemu_clipboard_peer_release(peer, i); + } + notifier_remove(&peer->update); } From 5e0a24e8685892f52826567b216fe34f98bc9d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:06 +0400 Subject: [PATCH 09/18] ui/vdagent: disconnect handlers and reset state on finalize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid handlers being called with dangling pointers when the object is freed. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-10-marcandre.lureau@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Acked-by: Gerd Hoffmann --- ui/vdagent.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 5ae5734c81..1a29016e07 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -721,22 +721,26 @@ static void vdagent_chr_accept_input(Chardev *chr) vdagent_send_buf(vd); } +static void vdagent_disconnect(VDAgentChardev *vd) +{ + vdagent_reset_bufs(vd); + vd->caps = 0; + if (vd->mouse_hs) { + qemu_input_handler_deactivate(vd->mouse_hs); + } + if (vd->cbpeer.update.notify) { + qemu_clipboard_peer_unregister(&vd->cbpeer); + memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); + } +} + static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) { VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(chr); if (!fe_open) { trace_vdagent_close(); - /* reset state */ - vdagent_reset_bufs(vd); - vd->caps = 0; - if (vd->mouse_hs) { - qemu_input_handler_deactivate(vd->mouse_hs); - } - if (vd->cbpeer.update.notify) { - qemu_clipboard_peer_unregister(&vd->cbpeer); - memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); - } + vdagent_disconnect(vd); return; } @@ -781,6 +785,7 @@ static void vdagent_chr_fini(Object *obj) { VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj); + vdagent_disconnect(vd); buffer_free(&vd->outbuf); } From 5fb2e8d99bdba89efeaae7d9752a6edb7b3f4ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:07 +0400 Subject: [PATCH 10/18] ui/vdagent: reset outbuf on disconnect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-11-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/vdagent.c b/ui/vdagent.c index 1a29016e07..3770c58b6c 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -723,6 +723,7 @@ static void vdagent_chr_accept_input(Chardev *chr) static void vdagent_disconnect(VDAgentChardev *vd) { + buffer_reset(&vd->outbuf); vdagent_reset_bufs(vd); vd->caps = 0; if (vd->mouse_hs) { From 3b99bb4c3ae2cdc445defa243988ceebc7a8378b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:08 +0400 Subject: [PATCH 11/18] ui/vdagent: split clipboard recv message handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-12-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 157 +++++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 68 deletions(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 3770c58b6c..362064213c 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -433,13 +433,94 @@ static void vdagent_clipboard_request(QemuClipboardInfo *info, vdagent_send_msg(vd, msg); } +static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t size, void *data) +{ + g_autoptr(QemuClipboardInfo) info = NULL; + + trace_vdagent_cb_grab_selection(GET_NAME(sel_name, s)); + info = qemu_clipboard_info_new(&vd->cbpeer, s); + if (size > sizeof(uint32_t) * 10) { + /* + * spice has 6 types as of 2021. Limiting to 10 entries + * so we we have some wiggle room. + */ + return; + } + while (size >= sizeof(uint32_t)) { + trace_vdagent_cb_grab_type(GET_NAME(type_name, *(uint32_t *)data)); + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true; + break; + default: + break; + } + data += sizeof(uint32_t); + size -= sizeof(uint32_t); + } + qemu_clipboard_update(info); +} + +static void vdagent_clipboard_recv_request(VDAgentChardev *vd, uint8_t s, uint32_t size, void *data) +{ + QemuClipboardType type; + + if (size < sizeof(uint32_t)) { + return; + } + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + type = QEMU_CLIPBOARD_TYPE_TEXT; + break; + default: + return; + } + if (vd->cbinfo[s] && vd->cbinfo[s]->types[type].available && + vd->cbinfo[s]->owner != &vd->cbpeer) { + if (vd->cbinfo[s]->types[type].data) { + vdagent_send_clipboard_data(vd, vd->cbinfo[s], type); + } else { + vd->cbpending[s] |= (1 << type); + qemu_clipboard_request(vd->cbinfo[s], type); + } + } +} + +static void vdagent_clipboard_recv_data(VDAgentChardev *vd, uint8_t s, uint32_t size, void *data) +{ + QemuClipboardType type; + + if (size < sizeof(uint32_t)) { + return; + } + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + type = QEMU_CLIPBOARD_TYPE_TEXT; + break; + default: + return; + } + data += 4; + size -= 4; + qemu_clipboard_set_data(&vd->cbpeer, vd->cbinfo[s], type, size, data, true); +} + +static void vdagent_clipboard_recv_release(VDAgentChardev *vd, uint8_t s) +{ + g_autoptr(QemuClipboardInfo) info = NULL; + + if (vd->cbinfo[s] && vd->cbinfo[s]->owner == &vd->cbpeer) { + /* set empty clipboard info */ + info = qemu_clipboard_info_new(NULL, s); + qemu_clipboard_update(info); + } +} + static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) { uint8_t s = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; uint32_t size = msg->size; void *data = msg->data; - g_autoptr(QemuClipboardInfo) info = NULL; - QemuClipboardType type; if (have_selection(vd)) { if (size < 4) { @@ -455,75 +536,15 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) switch (msg->type) { case VD_AGENT_CLIPBOARD_GRAB: - trace_vdagent_cb_grab_selection(GET_NAME(sel_name, s)); - info = qemu_clipboard_info_new(&vd->cbpeer, s); - if (size > sizeof(uint32_t) * 10) { - /* - * spice has 6 types as of 2021. Limiting to 10 entries - * so we we have some wiggle room. - */ - return; - } - while (size >= sizeof(uint32_t)) { - trace_vdagent_cb_grab_type(GET_NAME(type_name, *(uint32_t *)data)); - switch (*(uint32_t *)data) { - case VD_AGENT_CLIPBOARD_UTF8_TEXT: - info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true; - break; - default: - break; - } - data += sizeof(uint32_t); - size -= sizeof(uint32_t); - } - qemu_clipboard_update(info); - break; + return vdagent_clipboard_recv_grab(vd, s, size, data); case VD_AGENT_CLIPBOARD_REQUEST: - if (size < sizeof(uint32_t)) { - return; - } - switch (*(uint32_t *)data) { - case VD_AGENT_CLIPBOARD_UTF8_TEXT: - type = QEMU_CLIPBOARD_TYPE_TEXT; - break; - default: - return; - } - if (vd->cbinfo[s] && - vd->cbinfo[s]->types[type].available && - vd->cbinfo[s]->owner != &vd->cbpeer) { - if (vd->cbinfo[s]->types[type].data) { - vdagent_send_clipboard_data(vd, vd->cbinfo[s], type); - } else { - vd->cbpending[s] |= (1 << type); - qemu_clipboard_request(vd->cbinfo[s], type); - } - } - break; + return vdagent_clipboard_recv_request(vd, s, size, data); case VD_AGENT_CLIPBOARD: /* data */ - if (size < sizeof(uint32_t)) { - return; - } - switch (*(uint32_t *)data) { - case VD_AGENT_CLIPBOARD_UTF8_TEXT: - type = QEMU_CLIPBOARD_TYPE_TEXT; - break; - default: - return; - } - data += 4; - size -= 4; - qemu_clipboard_set_data(&vd->cbpeer, vd->cbinfo[s], type, - size, data, true); - break; + return vdagent_clipboard_recv_data(vd, s, size, data); case VD_AGENT_CLIPBOARD_RELEASE: - if (vd->cbinfo[s] && - vd->cbinfo[s]->owner == &vd->cbpeer) { - /* set empty clipboard info */ - info = qemu_clipboard_info_new(NULL, s); - qemu_clipboard_update(info); - } - break; + return vdagent_clipboard_recv_release(vd, s); + default: + g_assert_not_reached(); } } From c98c50de7c4de5f90e978b54b400480689eb2455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:09 +0400 Subject: [PATCH 12/18] ui/vdagent: use qemu_clipboard_peer_release helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-13-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 362064213c..99ba34646f 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -507,13 +507,7 @@ static void vdagent_clipboard_recv_data(VDAgentChardev *vd, uint8_t s, uint32_t static void vdagent_clipboard_recv_release(VDAgentChardev *vd, uint8_t s) { - g_autoptr(QemuClipboardInfo) info = NULL; - - if (vd->cbinfo[s] && vd->cbinfo[s]->owner == &vd->cbpeer) { - /* set empty clipboard info */ - info = qemu_clipboard_info_new(NULL, s); - qemu_clipboard_update(info); - } + qemu_clipboard_peer_release(&vd->cbpeer, s); } static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage *msg) From d2ed2c01c20d739f0ffaa7b178f9020c7ab880b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:10 +0400 Subject: [PATCH 13/18] ui/vdagent: use qemu_clipboard_info helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clipboard unit now tracks the current clipboard grab, no need to duplicate this work. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-14-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 99ba34646f..cd07937a4b 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -47,7 +47,6 @@ struct VDAgentChardev { /* clipboard */ QemuClipboardPeer cbpeer; - QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; uint32_t cbpending[QEMU_CLIPBOARD_SELECTION__COUNT]; }; typedef struct VDAgentChardev VDAgentChardev; @@ -384,9 +383,7 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data) QemuClipboardType type; bool self_update = info->owner == &vd->cbpeer; - if (info != vd->cbinfo[s]) { - qemu_clipboard_info_unref(vd->cbinfo[s]); - vd->cbinfo[s] = qemu_clipboard_info_ref(info); + if (info != qemu_clipboard_info(s)) { vd->cbpending[s] = 0; if (!self_update) { vdagent_send_clipboard_grab(vd, info); @@ -464,6 +461,7 @@ static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t static void vdagent_clipboard_recv_request(VDAgentChardev *vd, uint8_t s, uint32_t size, void *data) { QemuClipboardType type; + QemuClipboardInfo *info; if (size < sizeof(uint32_t)) { return; @@ -475,13 +473,14 @@ static void vdagent_clipboard_recv_request(VDAgentChardev *vd, uint8_t s, uint32 default: return; } - if (vd->cbinfo[s] && vd->cbinfo[s]->types[type].available && - vd->cbinfo[s]->owner != &vd->cbpeer) { - if (vd->cbinfo[s]->types[type].data) { - vdagent_send_clipboard_data(vd, vd->cbinfo[s], type); + + info = qemu_clipboard_info(s); + if (info && info->types[type].available && info->owner != &vd->cbpeer) { + if (info->types[type].data) { + vdagent_send_clipboard_data(vd, info, type); } else { vd->cbpending[s] |= (1 << type); - qemu_clipboard_request(vd->cbinfo[s], type); + qemu_clipboard_request(info, type); } } } @@ -502,7 +501,11 @@ static void vdagent_clipboard_recv_data(VDAgentChardev *vd, uint8_t s, uint32_t } data += 4; size -= 4; - qemu_clipboard_set_data(&vd->cbpeer, vd->cbinfo[s], type, size, data, true); + + if (qemu_clipboard_peer_owns(&vd->cbpeer, s)) { + qemu_clipboard_set_data(&vd->cbpeer, qemu_clipboard_info(s), + type, size, data, true); + } } static void vdagent_clipboard_recv_release(VDAgentChardev *vd, uint8_t s) From 3d3f0bc3f7d5d74a7ae14f7336c9c3c209cdb71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:11 +0400 Subject: [PATCH 14/18] ui/vdagent: send empty clipboard when unhandled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than leaving the agent timing out or hanging, reply to it with an empty result. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-15-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/trace-events | 1 + ui/vdagent.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/ui/trace-events b/ui/trace-events index 1b5f87bc09..b9c0dd0fa1 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -129,6 +129,7 @@ xkeymap_keymap(const char *name) "keymap '%s'" vdagent_open(void) "" vdagent_close(void) "" vdagent_send(const char *name) "msg %s" +vdagent_send_empty_clipboard(void) "" vdagent_recv_chunk(uint32_t size) "size %d" vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d" vdagent_peer_cap(const char *name) "cap %s" diff --git a/ui/vdagent.c b/ui/vdagent.c index cd07937a4b..cd49da1ffa 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -375,6 +375,16 @@ static void vdagent_send_clipboard_data(VDAgentChardev *vd, vdagent_send_msg(vd, msg); } +static void vdagent_send_empty_clipboard_data(VDAgentChardev *vd, + QemuClipboardSelection selection, + QemuClipboardType type) +{ + g_autoptr(QemuClipboardInfo) info = qemu_clipboard_info_new(&vd->cbpeer, selection); + + trace_vdagent_send_empty_clipboard(); + vdagent_send_clipboard_data(vd, info, type); +} + static void vdagent_clipboard_notify(Notifier *notifier, void *data) { VDAgentChardev *vd = container_of(notifier, VDAgentChardev, cbpeer.update); @@ -482,6 +492,8 @@ static void vdagent_clipboard_recv_request(VDAgentChardev *vd, uint8_t s, uint32 vd->cbpending[s] |= (1 << type); qemu_clipboard_request(info, type); } + } else { + vdagent_send_empty_clipboard_data(vd, s, type); } } From b702c863bfaf590e00e3cc9d599f3bbdd955d099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:12 +0400 Subject: [PATCH 15/18] ui/gtk-clipboard: use qemu_clipboard_info helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-16-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- include/ui/gtk.h | 1 - ui/gtk-clipboard.c | 14 ++++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 80d6bbd9b5..7835ef1a71 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -143,7 +143,6 @@ struct GtkDisplayState { bool external_pause_update; QemuClipboardPeer cbpeer; - QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; uint32_t cbpending[QEMU_CLIPBOARD_SELECTION__COUNT]; GtkClipboard *gtkcb[QEMU_CLIPBOARD_SELECTION__COUNT]; bool cbowner[QEMU_CLIPBOARD_SELECTION__COUNT]; diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index 2c78de9500..4e4b3c52bb 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -45,24 +45,24 @@ static void gd_clipboard_get_data(GtkClipboard *clipboard, GtkDisplayState *gd = data; QemuClipboardSelection s = gd_find_selection(gd, clipboard); QemuClipboardType type = QEMU_CLIPBOARD_TYPE_TEXT; - QemuClipboardInfo *info = qemu_clipboard_info_ref(gd->cbinfo[s]); + g_autoptr(QemuClipboardInfo) info = NULL; + + info = qemu_clipboard_info_ref(qemu_clipboard_info(s)); qemu_clipboard_request(info, type); - while (info == gd->cbinfo[s] && + while (info == qemu_clipboard_info(s) && info->types[type].available && info->types[type].data == NULL) { main_loop_wait(false); } - if (info == gd->cbinfo[s] && gd->cbowner[s]) { + if (info == qemu_clipboard_info(s) && gd->cbowner[s]) { gtk_selection_data_set_text(selection_data, info->types[type].data, info->types[type].size); } else { /* clipboard owner changed while waiting for the data */ } - - qemu_clipboard_info_unref(info); } static void gd_clipboard_clear(GtkClipboard *clipboard, @@ -81,9 +81,7 @@ static void gd_clipboard_notify(Notifier *notifier, void *data) QemuClipboardSelection s = info->selection; bool self_update = info->owner == &gd->cbpeer; - if (info != gd->cbinfo[s]) { - qemu_clipboard_info_unref(gd->cbinfo[s]); - gd->cbinfo[s] = qemu_clipboard_info_ref(info); + if (info != qemu_clipboard_info(s)) { gd->cbpending[s] = 0; if (!self_update) { GtkTargetList *list; From 314bf50086d8b7d057f980cb1cd6ed5c87640980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:13 +0400 Subject: [PATCH 16/18] ui/vdagent: send release when no clipboard owner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-17-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index cd49da1ffa..7d8cb963ff 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -345,6 +345,24 @@ static void vdagent_send_clipboard_grab(VDAgentChardev *vd, vdagent_send_msg(vd, msg); } +static void vdagent_send_clipboard_release(VDAgentChardev *vd, + QemuClipboardInfo *info) +{ + g_autofree VDAgentMessage *msg = g_malloc0(sizeof(VDAgentMessage) + + sizeof(uint32_t)); + + if (have_selection(vd)) { + uint8_t *s = msg->data; + *s = info->selection; + msg->size += sizeof(uint32_t); + } else if (info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { + return; + } + + msg->type = VD_AGENT_CLIPBOARD_RELEASE; + vdagent_send_msg(vd, msg); +} + static void vdagent_send_clipboard_data(VDAgentChardev *vd, QemuClipboardInfo *info, QemuClipboardType type) @@ -396,7 +414,11 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data) if (info != qemu_clipboard_info(s)) { vd->cbpending[s] = 0; if (!self_update) { - vdagent_send_clipboard_grab(vd, info); + if (info->owner) { + vdagent_send_clipboard_grab(vd, info); + } else { + vdagent_send_clipboard_release(vd, info); + } } return; } From 8038c5b64649b2d8ed9bf3dd7fac4bb2536524c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:14 +0400 Subject: [PATCH 17/18] ui/gtk-clipboard: emit release clipboard events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-18-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/gtk-clipboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index 4e4b3c52bb..35b7a2c228 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -163,6 +163,8 @@ static void gd_owner_change(GtkClipboard *clipboard, qemu_clipboard_info_unref(info); break; default: + qemu_clipboard_peer_release(&gd->cbpeer, s); + gd->cbowner[s] = false; break; } } From 90208bc9657b7e0f8a6bc6af82b69c65c97b2d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 5 Aug 2021 17:57:15 +0400 Subject: [PATCH 18/18] ui/vdagent: add a migration blocker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation lacks migration support. After migration, vdagent support will be broken (even after a restart of the daemons). Let's try to fix it in 6.2. Signed-off-by: Marc-André Lureau Message-Id: <20210805135715.857938-19-marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann --- ui/vdagent.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ui/vdagent.c b/ui/vdagent.c index 7d8cb963ff..19e8fbfc96 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -6,6 +6,7 @@ #include "qemu/option.h" #include "qemu/units.h" #include "hw/qdev-core.h" +#include "migration/blocker.h" #include "ui/clipboard.h" #include "ui/console.h" #include "ui/input.h" @@ -23,6 +24,9 @@ struct VDAgentChardev { Chardev parent; + /* TODO: migration isn't yet supported */ + Error *migration_blocker; + /* config */ bool mouse; bool clipboard; @@ -599,6 +603,10 @@ static void vdagent_chr_open(Chardev *chr, return; #endif + if (migrate_add_blocker(vd->migration_blocker, errp) != 0) { + return; + } + vd->mouse = VDAGENT_MOUSE_DEFAULT; if (cfg->has_mouse) { vd->mouse = cfg->mouse; @@ -832,14 +840,18 @@ static void vdagent_chr_init(Object *obj) VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj); buffer_init(&vd->outbuf, "vdagent-outbuf"); + error_setg(&vd->migration_blocker, + "The vdagent chardev doesn't yet support migration"); } static void vdagent_chr_fini(Object *obj) { VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj); + migrate_del_blocker(vd->migration_blocker); vdagent_disconnect(vd); buffer_free(&vd->outbuf); + error_free(vd->migration_blocker); } static const TypeInfo vdagent_chr_type_info = {