1660e8d0fSGerd Hoffmann #include "qemu/osdep.h" 2660e8d0fSGerd Hoffmann #include "ui/clipboard.h" 3660e8d0fSGerd Hoffmann 4660e8d0fSGerd Hoffmann static NotifierList clipboard_notifiers = 5660e8d0fSGerd Hoffmann NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); 6660e8d0fSGerd Hoffmann 7684e64d3SMarc-André Lureau static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; 8684e64d3SMarc-André Lureau 9660e8d0fSGerd Hoffmann void qemu_clipboard_peer_register(QemuClipboardPeer *peer) 10660e8d0fSGerd Hoffmann { 11660e8d0fSGerd Hoffmann notifier_list_add(&clipboard_notifiers, &peer->update); 12660e8d0fSGerd Hoffmann } 13660e8d0fSGerd Hoffmann 14660e8d0fSGerd Hoffmann void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) 15660e8d0fSGerd Hoffmann { 16660e8d0fSGerd Hoffmann notifier_remove(&peer->update); 17660e8d0fSGerd Hoffmann } 18660e8d0fSGerd Hoffmann 19*482bbaf4SMarc-André Lureau bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, 20*482bbaf4SMarc-André Lureau QemuClipboardSelection selection) 21*482bbaf4SMarc-André Lureau { 22*482bbaf4SMarc-André Lureau QemuClipboardInfo *info = qemu_clipboard_info(selection); 23*482bbaf4SMarc-André Lureau 24*482bbaf4SMarc-André Lureau return info && info->owner == peer; 25*482bbaf4SMarc-André Lureau } 26*482bbaf4SMarc-André Lureau 27660e8d0fSGerd Hoffmann void qemu_clipboard_update(QemuClipboardInfo *info) 28660e8d0fSGerd Hoffmann { 29684e64d3SMarc-André Lureau g_autoptr(QemuClipboardInfo) old = NULL; 30684e64d3SMarc-André Lureau assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); 31684e64d3SMarc-André Lureau 32660e8d0fSGerd Hoffmann notifier_list_notify(&clipboard_notifiers, info); 33684e64d3SMarc-André Lureau 34684e64d3SMarc-André Lureau old = cbinfo[info->selection]; 35684e64d3SMarc-André Lureau cbinfo[info->selection] = qemu_clipboard_info_ref(info); 36684e64d3SMarc-André Lureau } 37684e64d3SMarc-André Lureau 38684e64d3SMarc-André Lureau QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) 39684e64d3SMarc-André Lureau { 40684e64d3SMarc-André Lureau assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); 41684e64d3SMarc-André Lureau 42684e64d3SMarc-André Lureau return cbinfo[selection]; 43660e8d0fSGerd Hoffmann } 44660e8d0fSGerd Hoffmann 45660e8d0fSGerd Hoffmann QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, 46660e8d0fSGerd Hoffmann QemuClipboardSelection selection) 47660e8d0fSGerd Hoffmann { 48660e8d0fSGerd Hoffmann QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1); 49660e8d0fSGerd Hoffmann 50660e8d0fSGerd Hoffmann info->owner = owner; 51660e8d0fSGerd Hoffmann info->selection = selection; 52660e8d0fSGerd Hoffmann info->refcount = 1; 53660e8d0fSGerd Hoffmann 54660e8d0fSGerd Hoffmann return info; 55660e8d0fSGerd Hoffmann } 56660e8d0fSGerd Hoffmann 57660e8d0fSGerd Hoffmann QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) 58660e8d0fSGerd Hoffmann { 59660e8d0fSGerd Hoffmann info->refcount++; 60660e8d0fSGerd Hoffmann return info; 61660e8d0fSGerd Hoffmann } 62660e8d0fSGerd Hoffmann 63660e8d0fSGerd Hoffmann void qemu_clipboard_info_unref(QemuClipboardInfo *info) 64660e8d0fSGerd Hoffmann { 65660e8d0fSGerd Hoffmann uint32_t type; 66660e8d0fSGerd Hoffmann 67660e8d0fSGerd Hoffmann if (!info) { 68660e8d0fSGerd Hoffmann return; 69660e8d0fSGerd Hoffmann } 70660e8d0fSGerd Hoffmann 71660e8d0fSGerd Hoffmann info->refcount--; 72660e8d0fSGerd Hoffmann if (info->refcount > 0) { 73660e8d0fSGerd Hoffmann return; 74660e8d0fSGerd Hoffmann } 75660e8d0fSGerd Hoffmann 76660e8d0fSGerd Hoffmann for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { 77660e8d0fSGerd Hoffmann g_free(info->types[type].data); 78660e8d0fSGerd Hoffmann } 79660e8d0fSGerd Hoffmann g_free(info); 80660e8d0fSGerd Hoffmann } 81660e8d0fSGerd Hoffmann 82660e8d0fSGerd Hoffmann void qemu_clipboard_request(QemuClipboardInfo *info, 83660e8d0fSGerd Hoffmann QemuClipboardType type) 84660e8d0fSGerd Hoffmann { 85660e8d0fSGerd Hoffmann if (info->types[type].data || 86660e8d0fSGerd Hoffmann info->types[type].requested || 87660e8d0fSGerd Hoffmann !info->types[type].available || 88660e8d0fSGerd Hoffmann !info->owner) 89660e8d0fSGerd Hoffmann return; 90660e8d0fSGerd Hoffmann 91660e8d0fSGerd Hoffmann info->types[type].requested = true; 92660e8d0fSGerd Hoffmann info->owner->request(info, type); 93660e8d0fSGerd Hoffmann } 94660e8d0fSGerd Hoffmann 95660e8d0fSGerd Hoffmann void qemu_clipboard_set_data(QemuClipboardPeer *peer, 96660e8d0fSGerd Hoffmann QemuClipboardInfo *info, 97660e8d0fSGerd Hoffmann QemuClipboardType type, 98660e8d0fSGerd Hoffmann uint32_t size, 997e3e20d8SAkihiko Odaki const void *data, 100660e8d0fSGerd Hoffmann bool update) 101660e8d0fSGerd Hoffmann { 102660e8d0fSGerd Hoffmann if (!info || 103660e8d0fSGerd Hoffmann info->owner != peer) { 104660e8d0fSGerd Hoffmann return; 105660e8d0fSGerd Hoffmann } 106660e8d0fSGerd Hoffmann 107660e8d0fSGerd Hoffmann g_free(info->types[type].data); 108660e8d0fSGerd Hoffmann info->types[type].data = g_memdup(data, size); 109660e8d0fSGerd Hoffmann info->types[type].size = size; 110660e8d0fSGerd Hoffmann info->types[type].available = true; 111660e8d0fSGerd Hoffmann 112660e8d0fSGerd Hoffmann if (update) { 113660e8d0fSGerd Hoffmann qemu_clipboard_update(info); 114660e8d0fSGerd Hoffmann } 115660e8d0fSGerd Hoffmann } 116