ui: generalize clipboard notifier

Use a QemuClipboardNotify union type for extendable clipboard events.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Marc-André Lureau 2021-07-19 19:42:15 +04:00
parent 5912745288
commit 1b17f1e9f9
7 changed files with 101 additions and 29 deletions

View File

@ -20,8 +20,10 @@
*/ */
typedef enum QemuClipboardType QemuClipboardType; typedef enum QemuClipboardType QemuClipboardType;
typedef enum QemuClipboardNotifyType QemuClipboardNotifyType;
typedef enum QemuClipboardSelection QemuClipboardSelection; typedef enum QemuClipboardSelection QemuClipboardSelection;
typedef struct QemuClipboardPeer QemuClipboardPeer; typedef struct QemuClipboardPeer QemuClipboardPeer;
typedef struct QemuClipboardNotify QemuClipboardNotify;
typedef struct QemuClipboardInfo QemuClipboardInfo; typedef struct QemuClipboardInfo QemuClipboardInfo;
/** /**
@ -55,18 +57,44 @@ enum QemuClipboardSelection {
* struct QemuClipboardPeer * struct QemuClipboardPeer
* *
* @name: peer name. * @name: peer name.
* @update: notifier for clipboard updates. * @notifier: notifier for clipboard updates.
* @request: callback for clipboard data requests. * @request: callback for clipboard data requests.
* *
* Clipboard peer description. * Clipboard peer description.
*/ */
struct QemuClipboardPeer { struct QemuClipboardPeer {
const char *name; const char *name;
Notifier update; Notifier notifier;
void (*request)(QemuClipboardInfo *info, void (*request)(QemuClipboardInfo *info,
QemuClipboardType type); QemuClipboardType type);
}; };
/**
* enum QemuClipboardNotifyType
*
* @QEMU_CLIPBOARD_UPDATE_INFO: clipboard info update
*
* Clipboard notify type.
*/
enum QemuClipboardNotifyType {
QEMU_CLIPBOARD_UPDATE_INFO,
};
/**
* struct QemuClipboardNotify
*
* @type: the type of event.
* @info: a QemuClipboardInfo event.
*
* Clipboard notify data.
*/
struct QemuClipboardNotify {
QemuClipboardNotifyType type;
union {
QemuClipboardInfo *info;
};
};
/** /**
* struct QemuClipboardInfo * struct QemuClipboardInfo
* *

View File

@ -8,7 +8,7 @@ static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT];
void qemu_clipboard_peer_register(QemuClipboardPeer *peer) void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
{ {
notifier_list_add(&clipboard_notifiers, &peer->update); notifier_list_add(&clipboard_notifiers, &peer->notifier);
} }
void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
@ -18,8 +18,7 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) {
qemu_clipboard_peer_release(peer, i); qemu_clipboard_peer_release(peer, i);
} }
notifier_remove(&peer->notifier);
notifier_remove(&peer->update);
} }
bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer,
@ -44,10 +43,15 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer,
void qemu_clipboard_update(QemuClipboardInfo *info) void qemu_clipboard_update(QemuClipboardInfo *info)
{ {
QemuClipboardNotify notify = {
.type = QEMU_CLIPBOARD_UPDATE_INFO,
.info = info,
};
g_autoptr(QemuClipboardInfo) old = NULL; g_autoptr(QemuClipboardInfo) old = NULL;
assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT);
notifier_list_notify(&clipboard_notifiers, info); notifier_list_notify(&clipboard_notifiers, &notify);
old = cbinfo[info->selection]; old = cbinfo[info->selection];
cbinfo[info->selection] = qemu_clipboard_info_ref(info); cbinfo[info->selection] = qemu_clipboard_info_ref(info);

View File

@ -1808,14 +1808,12 @@ static void cocoa_clipboard_request(QemuClipboardInfo *info,
static QemuClipboardPeer cbpeer = { static QemuClipboardPeer cbpeer = {
.name = "cocoa", .name = "cocoa",
.update = { .notify = cocoa_clipboard_notify }, .notifier = { .notify = cocoa_clipboard_notify },
.request = cocoa_clipboard_request .request = cocoa_clipboard_request
}; };
static void cocoa_clipboard_notify(Notifier *notifier, void *data) static void cocoa_clipboard_update_info(QemuClipboardInfo *info)
{ {
QemuClipboardInfo *info = data;
if (info->owner == &cbpeer || info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { if (info->owner == &cbpeer || info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) {
return; return;
} }
@ -1831,6 +1829,17 @@ static void cocoa_clipboard_notify(Notifier *notifier, void *data)
qemu_event_set(&cbevent); qemu_event_set(&cbevent);
} }
static void cocoa_clipboard_notify(Notifier *notifier, void *data)
{
QemuClipboardNotify *notify = data;
switch (notify->type) {
case QEMU_CLIPBOARD_UPDATE_INFO:
cocoa_clipboard_update_info(notify->info);
return;
}
}
static void cocoa_clipboard_request(QemuClipboardInfo *info, static void cocoa_clipboard_request(QemuClipboardInfo *info,
QemuClipboardType type) QemuClipboardType type)
{ {

View File

@ -74,10 +74,9 @@ static void gd_clipboard_clear(GtkClipboard *clipboard,
gd->cbowner[s] = false; gd->cbowner[s] = false;
} }
static void gd_clipboard_notify(Notifier *notifier, void *data) static void gd_clipboard_update_info(GtkDisplayState *gd,
QemuClipboardInfo *info)
{ {
GtkDisplayState *gd = container_of(notifier, GtkDisplayState, cbpeer.update);
QemuClipboardInfo *info = data;
QemuClipboardSelection s = info->selection; QemuClipboardSelection s = info->selection;
bool self_update = info->owner == &gd->cbpeer; bool self_update = info->owner == &gd->cbpeer;
@ -118,6 +117,19 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
*/ */
} }
static void gd_clipboard_notify(Notifier *notifier, void *data)
{
GtkDisplayState *gd =
container_of(notifier, GtkDisplayState, cbpeer.notifier);
QemuClipboardNotify *notify = data;
switch (notify->type) {
case QEMU_CLIPBOARD_UPDATE_INFO:
gd_clipboard_update_info(gd, notify->info);
return;
}
}
static void gd_clipboard_request(QemuClipboardInfo *info, static void gd_clipboard_request(QemuClipboardInfo *info,
QemuClipboardType type) QemuClipboardType type)
{ {
@ -172,7 +184,7 @@ static void gd_owner_change(GtkClipboard *clipboard,
void gd_clipboard_init(GtkDisplayState *gd) void gd_clipboard_init(GtkDisplayState *gd)
{ {
gd->cbpeer.name = "gtk"; gd->cbpeer.name = "gtk";
gd->cbpeer.update.notify = gd_clipboard_notify; gd->cbpeer.notifier.notify = gd_clipboard_notify;
gd->cbpeer.request = gd_clipboard_request; gd->cbpeer.request = gd_clipboard_request;
qemu_clipboard_peer_register(&gd->cbpeer); qemu_clipboard_peer_register(&gd->cbpeer);

View File

@ -417,10 +417,9 @@ static void vdagent_send_empty_clipboard_data(VDAgentChardev *vd,
vdagent_send_clipboard_data(vd, info, type); vdagent_send_clipboard_data(vd, info, type);
} }
static void vdagent_clipboard_notify(Notifier *notifier, void *data) static void vdagent_clipboard_update_info(VDAgentChardev *vd,
QemuClipboardInfo *info)
{ {
VDAgentChardev *vd = container_of(notifier, VDAgentChardev, cbpeer.update);
QemuClipboardInfo *info = data;
QemuClipboardSelection s = info->selection; QemuClipboardSelection s = info->selection;
QemuClipboardType type; QemuClipboardType type;
bool self_update = info->owner == &vd->cbpeer; bool self_update = info->owner == &vd->cbpeer;
@ -449,6 +448,19 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data)
} }
} }
static void vdagent_clipboard_notify(Notifier *notifier, void *data)
{
VDAgentChardev *vd =
container_of(notifier, VDAgentChardev, cbpeer.notifier);
QemuClipboardNotify *notify = data;
switch (notify->type) {
case QEMU_CLIPBOARD_UPDATE_INFO:
vdagent_clipboard_update_info(vd, notify->info);
return;
}
}
static void vdagent_clipboard_request(QemuClipboardInfo *info, static void vdagent_clipboard_request(QemuClipboardInfo *info,
QemuClipboardType qtype) QemuClipboardType qtype)
{ {
@ -658,9 +670,9 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg)
if (have_mouse(vd) && vd->mouse_hs) { if (have_mouse(vd) && vd->mouse_hs) {
qemu_input_handler_activate(vd->mouse_hs); qemu_input_handler_activate(vd->mouse_hs);
} }
if (have_clipboard(vd) && vd->cbpeer.update.notify == NULL) { if (have_clipboard(vd) && vd->cbpeer.notifier.notify == NULL) {
vd->cbpeer.name = "vdagent"; vd->cbpeer.name = "vdagent";
vd->cbpeer.update.notify = vdagent_clipboard_notify; vd->cbpeer.notifier.notify = vdagent_clipboard_notify;
vd->cbpeer.request = vdagent_clipboard_request; vd->cbpeer.request = vdagent_clipboard_request;
qemu_clipboard_peer_register(&vd->cbpeer); qemu_clipboard_peer_register(&vd->cbpeer);
} }
@ -799,7 +811,7 @@ static void vdagent_disconnect(VDAgentChardev *vd)
if (vd->mouse_hs) { if (vd->mouse_hs) {
qemu_input_handler_deactivate(vd->mouse_hs); qemu_input_handler_deactivate(vd->mouse_hs);
} }
if (vd->cbpeer.update.notify) { if (vd->cbpeer.notifier.notify) {
qemu_clipboard_peer_unregister(&vd->cbpeer); qemu_clipboard_peer_unregister(&vd->cbpeer);
memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); memset(&vd->cbpeer, 0, sizeof(vd->cbpeer));
} }
@ -807,11 +819,8 @@ static void vdagent_disconnect(VDAgentChardev *vd)
static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open)
{ {
VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(chr);
if (!fe_open) { if (!fe_open) {
trace_vdagent_close(); trace_vdagent_close();
vdagent_disconnect(vd);
return; return;
} }

View File

@ -189,10 +189,8 @@ static void vnc_clipboard_provide(VncState *vs,
vnc_flush(vs); vnc_flush(vs);
} }
static void vnc_clipboard_notify(Notifier *notifier, void *data) static void vnc_clipboard_update_info(VncState *vs, QemuClipboardInfo *info)
{ {
VncState *vs = container_of(notifier, VncState, cbpeer.update);
QemuClipboardInfo *info = data;
QemuClipboardType type; QemuClipboardType type;
bool self_update = info->owner == &vs->cbpeer; bool self_update = info->owner == &vs->cbpeer;
uint32_t flags = 0; uint32_t flags = 0;
@ -223,6 +221,18 @@ static void vnc_clipboard_notify(Notifier *notifier, void *data)
} }
} }
static void vnc_clipboard_notify(Notifier *notifier, void *data)
{
VncState *vs = container_of(notifier, VncState, cbpeer.notifier);
QemuClipboardNotify *notify = data;
switch (notify->type) {
case QEMU_CLIPBOARD_UPDATE_INFO:
vnc_clipboard_update_info(vs, notify->info);
return;
}
}
static void vnc_clipboard_request(QemuClipboardInfo *info, static void vnc_clipboard_request(QemuClipboardInfo *info,
QemuClipboardType type) QemuClipboardType type)
{ {
@ -316,9 +326,9 @@ void vnc_server_cut_text_caps(VncState *vs)
caps[1] = 0; caps[1] = 0;
vnc_clipboard_send(vs, 2, caps); vnc_clipboard_send(vs, 2, caps);
if (!vs->cbpeer.update.notify) { if (!vs->cbpeer.notifier.notify) {
vs->cbpeer.name = "vnc"; vs->cbpeer.name = "vnc";
vs->cbpeer.update.notify = vnc_clipboard_notify; vs->cbpeer.notifier.notify = vnc_clipboard_notify;
vs->cbpeer.request = vnc_clipboard_request; vs->cbpeer.request = vnc_clipboard_request;
qemu_clipboard_peer_register(&vs->cbpeer); qemu_clipboard_peer_register(&vs->cbpeer);
} }

View File

@ -1354,7 +1354,7 @@ void vnc_disconnect_finish(VncState *vs)
/* last client gone */ /* last client gone */
vnc_update_server_surface(vs->vd); vnc_update_server_surface(vs->vd);
} }
if (vs->cbpeer.update.notify) { if (vs->cbpeer.notifier.notify) {
qemu_clipboard_peer_unregister(&vs->cbpeer); qemu_clipboard_peer_unregister(&vs->cbpeer);
} }