diff mbox series

[RFC,2/3] vdagent: Set up mouse and clipboard after live migration

Message ID 3c9498ef25fd8c5f705a4c6ee2dc46666c322ada.1742527956.git.yong.huang@smartx.com (mailing list archive)
State New
Headers show
Series Support live migration for qemu-vdagent chardev | expand

Commit Message

Yong Huang March 21, 2025, 3:38 a.m. UTC
From: Hyman Huang <yong.huang@smartx.com>

The struct VDAgentChardev's caps, last_serial, and cbpending
fields need to be migrated in order to allow live migration
for vdagent. And the clipboard and mouse should be configured
to correspond with the previously negotiated caps on the
destination.

Signed-off-by: Hyman Huang <yong.huang@smartx.com>
---
 ui/vdagent.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
diff mbox series

Patch

diff --git a/ui/vdagent.c b/ui/vdagent.c
index 7a1cf674d0..4635e8fa56 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -7,6 +7,7 @@ 
 #include "qemu/units.h"
 #include "hw/qdev-core.h"
 #include "migration/blocker.h"
+#include "migration/vmstate.h"
 #include "ui/clipboard.h"
 #include "ui/console.h"
 #include "ui/input.h"
@@ -912,6 +913,72 @@  static void vdagent_chr_parse(QemuOpts *opts, ChardevBackend *backend,
     cfg->clipboard = qemu_opt_get_bool(opts, "clipboard", VDAGENT_CLIPBOARD_DEFAULT);
 }
 
+static void vdagent_release_clipboard_all_types(VDAgentChardev *vd,
+                                                QemuClipboardSelection s)
+{
+    uint32_t type;
+
+    for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) {
+        if (vd->cbpending[s] & (1 << type)) {
+            vd->cbpending[s] &= ~(1 << type);
+            g_autofree VDAgentMessage *msg =
+                g_malloc0(sizeof(VDAgentMessage) + sizeof(uint32_t));
+
+            uint8_t *selection = msg->data;
+            *selection = s;
+            msg->size += sizeof(uint32_t);
+            msg->type = VD_AGENT_CLIPBOARD_RELEASE;
+
+            vdagent_send_msg(vd, msg);
+        }
+    }
+}
+
+static int vdagent_post_load(void *opaque, int version_id)
+{
+    VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(opaque);
+    QemuClipboardSelection s = QEMU_CLIPBOARD_SELECTION_CLIPBOARD;
+
+    if (vd->caps) {
+        if (have_mouse(vd)) {
+            vd->mouse_hs =
+                qemu_input_handler_register(&vd->mouse_dev,
+                                            &vdagent_mouse_handler);
+            if (vd->mouse_hs) {
+                qemu_input_handler_activate(vd->mouse_hs);
+            }
+        }
+
+        if (have_clipboard(vd)) {
+            vdagent_register_to_qemu_clipboard(vd);
+            if (have_selection(vd)) {
+                for (; s < QEMU_CLIPBOARD_SELECTION__COUNT; s++) {
+                    vdagent_release_clipboard_all_types(vd, s);
+                }
+            } else {
+                vdagent_release_clipboard_all_types(vd, s);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_vdagent = {
+    .name = "vdagent",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = vdagent_post_load,
+    .fields = (VMStateField[]){
+        VMSTATE_UINT32(caps, VDAgentChardev),
+        VMSTATE_UINT32_ARRAY(last_serial, VDAgentChardev,
+                QEMU_CLIPBOARD_SELECTION__COUNT),
+        VMSTATE_UINT32_ARRAY(cbpending, VDAgentChardev,
+                QEMU_CLIPBOARD_SELECTION__COUNT),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 /* ------------------------------------------------------------------ */
 
 static void vdagent_chr_class_init(ObjectClass *oc, void *data)
@@ -930,6 +997,7 @@  static void vdagent_chr_init(Object *obj)
     VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
 
     buffer_init(&vd->outbuf, "vdagent-outbuf");
+    vmstate_register(NULL, 0, &vmstate_vdagent, vd);
     error_setg(&vd->migration_blocker,
                "The vdagent chardev doesn't yet support migration");
 }