Commit bcd94dccb1 for qemu.org
commit bcd94dccb1aab3416981bff89dc97a4f60d4e9ee
Author: Lukasz Kornicki <lucas.kornicki@nutanix.com>
Date: Fri Oct 30 15:14:40 2026 +0100
ui/clipboard: keep track of clipboard peer side
Add a "guest" flag to QemuClipboardPeer and set it on vdagent peer.
Use the flag to keep track of number of registered guest peers and
allow to query for their presence with
qemu_clipboard_guest_peer_present().
This change makes it possible for a clipboard peer to determine if
any guest side peers are present so they can tell whether a guest is
actually able to participate in clipboard exchange.
Signed-off-by: Lukasz Kornicki <lucas.kornicki@nutanix.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20261030141442.264308-3-lucas.kornicki@nutanix.com>
diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index 6166af5139..250f1d8ea5 100644
--- a/include/ui/clipboard.h
+++ b/include/ui/clipboard.h
@@ -62,6 +62,7 @@ enum QemuClipboardSelection {
* struct QemuClipboardPeer
*
* @name: peer name.
+ * @guest: is peer guest side.
* @notifier: notifier for clipboard updates.
* @request: callback for clipboard data requests.
*
@@ -69,6 +70,7 @@ enum QemuClipboardSelection {
*/
struct QemuClipboardPeer {
const char *name;
+ bool guest;
Notifier notifier;
void (*request)(QemuClipboardInfo *info,
QemuClipboardType type);
@@ -179,6 +181,13 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer);
*/
void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer);
+/**
+ * qemu_clipboard_guest_peer_present
+ *
+ * Return TRUE if a guest side clipboard peer is currently registered.
+ */
+bool qemu_clipboard_guest_peer_present(void);
+
/**
* qemu_clipboard_peer_owns
*
diff --git a/ui/clipboard.c b/ui/clipboard.c
index 3d8f58a855..f750b494eb 100644
--- a/ui/clipboard.c
+++ b/ui/clipboard.c
@@ -12,6 +12,8 @@ static VMChangeStateEntry *cb_change_state_entry = NULL;
static bool cb_reset_serial_on_resume = false;
+static int guest_peer_count;
+
static const VMStateDescription vmstate_cbcontent = {
.name = "clipboard/content",
.version_id = 0,
@@ -80,6 +82,10 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
cb_change_state_entry = qemu_add_vm_change_state_handler(qemu_clipboard_change_state, NULL);
}
+ if (peer->guest) {
+ guest_peer_count++;
+ }
+
notifier_list_add(&clipboard_notifiers, &peer->notifier);
qemu_clipboard_notify_peer_update(peer, true);
}
@@ -92,6 +98,12 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
qemu_clipboard_peer_release(peer, i);
}
notifier_remove(&peer->notifier);
+
+ if (peer->guest) {
+ assert(guest_peer_count > 0);
+ guest_peer_count--;
+ }
+
qemu_clipboard_notify_peer_update(peer, false);
if (QLIST_EMPTY(&clipboard_notifiers.notifiers)) {
@@ -100,6 +112,11 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
}
}
+bool qemu_clipboard_guest_peer_present(void)
+{
+ return guest_peer_count > 0;
+}
+
bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer,
QemuClipboardSelection selection)
{
diff --git a/ui/vdagent.c b/ui/vdagent.c
index cc32a94fb9..cdd4cedad2 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -695,6 +695,7 @@ static void vdagent_clipboard_peer_register(VDAgentChardev *vd)
}
vd->cbpeer.name = "vdagent";
+ vd->cbpeer.guest = true;
vd->cbpeer.notifier.notify = vdagent_clipboard_notify;
vd->cbpeer.request = vdagent_clipboard_request;
qemu_clipboard_peer_register(&vd->cbpeer);