On Fri, Apr 23, 2021 at 12:34 PM Gerd Hoffmann <kra...@redhat.com> wrote:
> Add some infrastructure to manage the clipboard in qemu. > > Signed-off-by: Gerd Hoffmann <kra...@redhat.com> > --- > include/ui/clipboard.h | 62 ++++++++++++++++++++++++++++ > ui/clipboard.c | 92 ++++++++++++++++++++++++++++++++++++++++++ > ui/meson.build | 1 + > 3 files changed, 155 insertions(+) > create mode 100644 include/ui/clipboard.h > create mode 100644 ui/clipboard.c > > diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h > new file mode 100644 > index 000000000000..b2354a4162db > --- /dev/null > +++ b/include/ui/clipboard.h > @@ -0,0 +1,62 @@ > +#ifndef QEMU_CLIPBOARD_H > +#define QEMU_CLIPBOARD_H > + > +#include "qemu/notify.h" > + > +typedef enum QemuClipboardType QemuClipboardType; > +typedef enum QemuClipboardSelection QemuClipboardSelection; > +typedef struct QemuClipboardPeer QemuClipboardPeer; > +typedef struct QemuClipboardInfo QemuClipboardInfo; > + > +enum QemuClipboardType { > + QEMU_CLIPBOARD_TYPE_TEXT, /* text/plain; charset=utf-8 */ > + QEMU_CLIPBOARD_TYPE__COUNT, > +}; > + > +/* same as VD_AGENT_CLIPBOARD_SELECTION_* */ > +enum QemuClipboardSelection { > + QEMU_CLIPBOARD_SELECTION_CLIPBOARD, > + QEMU_CLIPBOARD_SELECTION_PRIMARY, > + QEMU_CLIPBOARD_SELECTION_SECONDARY, > + QEMU_CLIPBOARD_SELECTION__COUNT, > +}; > + > +struct QemuClipboardPeer { > + const char *name; > + Notifier update; > + void (*request)(QemuClipboardInfo *info, > + QemuClipboardType type); > +}; > + > +struct QemuClipboardInfo { > + uint32_t refcount; > + QemuClipboardPeer *owner; > + QemuClipboardSelection selection; > + struct { > + bool available; > + bool requested; > + size_t size; > + void *data; > + } types[QEMU_CLIPBOARD_TYPE__COUNT]; > +}; > + > +void qemu_clipboard_peer_register(QemuClipboardPeer *peer); > +void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); > + > +QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, > + QemuClipboardSelection > selection); > +QemuClipboardInfo *qemu_clipboard_info_get(QemuClipboardInfo *info); > +void qemu_clipboard_info_put(QemuClipboardInfo *info); > Generally, we follow the glib-style _ref/unref in qemu rather than kernel-style, but ymmv. For new types, it might be worth adding G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuClipboardInfo, qemu_clipboard_info_{put/unref}) ? + > +void qemu_clipboard_update(QemuClipboardInfo *info); > +void qemu_clipboard_request(QemuClipboardInfo *info, > + QemuClipboardType type); > + > +void qemu_clipboard_set_data(QemuClipboardPeer *peer, > + QemuClipboardInfo *info, > + QemuClipboardType type, > + uint32_t size, > + void *data, > + bool update); > + > +#endif /* QEMU_CLIPBOARD_H */ > diff --git a/ui/clipboard.c b/ui/clipboard.c > new file mode 100644 > index 000000000000..556531c578a1 > --- /dev/null > +++ b/ui/clipboard.c > @@ -0,0 +1,92 @@ > +#include "qemu/osdep.h" > +#include "ui/clipboard.h" > + > +static NotifierList clipboard_notifiers = > + NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); > + > +void qemu_clipboard_peer_register(QemuClipboardPeer *peer) > +{ > + notifier_list_add(&clipboard_notifiers, &peer->update); > +} > + > +void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) > +{ > + notifier_remove(&peer->update); > +} > + > +void qemu_clipboard_update(QemuClipboardInfo *info) > +{ > + notifier_list_notify(&clipboard_notifiers, info); > +} > + > +QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, > + QemuClipboardSelection > selection) > +{ > + QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1); > + > + info->owner = owner; > + info->selection = selection; > + info->refcount = 1; > + > + return info; > +} > + > +QemuClipboardInfo *qemu_clipboard_info_get(QemuClipboardInfo *info) > +{ > + info->refcount++; > + return info; > +} > + > +void qemu_clipboard_info_put(QemuClipboardInfo *info) > +{ > + uint32_t type; > + > + if (!info) { > + return; > + } > + > + info->refcount--; > + if (info->refcount > 0) { > + return; > + } > + > + for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { > + g_free(info->types[type].data); > + } > + g_free(info); > +} > + > +void qemu_clipboard_request(QemuClipboardInfo *info, > + QemuClipboardType type) > +{ > + if (info->types[type].data || > + info->types[type].requested || > + !info->types[type].available || > + !info->owner) > + return; > + > + info->types[type].requested = true; > + info->owner->request(info, type); > +} > + > +void qemu_clipboard_set_data(QemuClipboardPeer *peer, > + QemuClipboardInfo *info, > + QemuClipboardType type, > + uint32_t size, > + void *data, > + bool update) > +{ > + if (!info || > + info->owner != peer) { > + return; > + } > + > + g_free(info->types[type].data); > + info->types[type].data = g_memdup(data, size); > + info->types[type].size = size; > + info->types[type].available = true; > + > + if (update) { > + qemu_clipboard_update(info); > + } > +} > diff --git a/ui/meson.build b/ui/meson.build > index e8d3ff41b905..fc4fb75c2869 100644 > --- a/ui/meson.build > +++ b/ui/meson.build > @@ -2,6 +2,7 @@ softmmu_ss.add(pixman) > specific_ss.add(when: ['CONFIG_SOFTMMU'], if_true: pixman) # for the > include path > > softmmu_ss.add(files( > + 'clipboard.c', > 'console.c', > 'cursor.c', > 'input-keymap.c', > -- > 2.30.2 > > the above is minor suggestion, so: Reviewed-by: Marc-André Lureau <marcandre.lur...@redhat.com>