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 { 111b17f1e9SMarc-André Lureau notifier_list_add(&clipboard_notifiers, &peer->notifier); 12660e8d0fSGerd Hoffmann } 13660e8d0fSGerd Hoffmann 14660e8d0fSGerd Hoffmann void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) 15660e8d0fSGerd Hoffmann { 167424bfaaSMarc-André Lureau int i; 177424bfaaSMarc-André Lureau 187424bfaaSMarc-André Lureau for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { 197424bfaaSMarc-André Lureau qemu_clipboard_peer_release(peer, i); 207424bfaaSMarc-André Lureau } 211b17f1e9SMarc-André Lureau notifier_remove(&peer->notifier); 22660e8d0fSGerd Hoffmann } 23660e8d0fSGerd Hoffmann 24482bbaf4SMarc-André Lureau bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, 25482bbaf4SMarc-André Lureau QemuClipboardSelection selection) 26482bbaf4SMarc-André Lureau { 27482bbaf4SMarc-André Lureau QemuClipboardInfo *info = qemu_clipboard_info(selection); 28482bbaf4SMarc-André Lureau 29482bbaf4SMarc-André Lureau return info && info->owner == peer; 30482bbaf4SMarc-André Lureau } 31482bbaf4SMarc-André Lureau 321387865eSMarc-André Lureau void qemu_clipboard_peer_release(QemuClipboardPeer *peer, 331387865eSMarc-André Lureau QemuClipboardSelection selection) 341387865eSMarc-André Lureau { 351387865eSMarc-André Lureau g_autoptr(QemuClipboardInfo) info = NULL; 361387865eSMarc-André Lureau 371387865eSMarc-André Lureau if (qemu_clipboard_peer_owns(peer, selection)) { 381387865eSMarc-André Lureau /* set empty clipboard info */ 391387865eSMarc-André Lureau info = qemu_clipboard_info_new(NULL, selection); 401387865eSMarc-André Lureau qemu_clipboard_update(info); 411387865eSMarc-André Lureau } 421387865eSMarc-André Lureau } 431387865eSMarc-André Lureau 44*349504e5SMarc-André Lureau bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) 45*349504e5SMarc-André Lureau { 46*349504e5SMarc-André Lureau if (!info->has_serial || 47*349504e5SMarc-André Lureau !cbinfo[info->selection] || 48*349504e5SMarc-André Lureau !cbinfo[info->selection]->has_serial) { 49*349504e5SMarc-André Lureau return true; 50*349504e5SMarc-André Lureau } 51*349504e5SMarc-André Lureau 52*349504e5SMarc-André Lureau if (client) { 53*349504e5SMarc-André Lureau return cbinfo[info->selection]->serial >= info->serial; 54*349504e5SMarc-André Lureau } else { 55*349504e5SMarc-André Lureau return cbinfo[info->selection]->serial > info->serial; 56*349504e5SMarc-André Lureau } 57*349504e5SMarc-André Lureau } 58*349504e5SMarc-André Lureau 59660e8d0fSGerd Hoffmann void qemu_clipboard_update(QemuClipboardInfo *info) 60660e8d0fSGerd Hoffmann { 611b17f1e9SMarc-André Lureau QemuClipboardNotify notify = { 621b17f1e9SMarc-André Lureau .type = QEMU_CLIPBOARD_UPDATE_INFO, 631b17f1e9SMarc-André Lureau .info = info, 641b17f1e9SMarc-André Lureau }; 65684e64d3SMarc-André Lureau g_autoptr(QemuClipboardInfo) old = NULL; 661b17f1e9SMarc-André Lureau 67684e64d3SMarc-André Lureau assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); 68684e64d3SMarc-André Lureau 691b17f1e9SMarc-André Lureau notifier_list_notify(&clipboard_notifiers, ¬ify); 70684e64d3SMarc-André Lureau 71684e64d3SMarc-André Lureau old = cbinfo[info->selection]; 72684e64d3SMarc-André Lureau cbinfo[info->selection] = qemu_clipboard_info_ref(info); 73684e64d3SMarc-André Lureau } 74684e64d3SMarc-André Lureau 75684e64d3SMarc-André Lureau QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) 76684e64d3SMarc-André Lureau { 77684e64d3SMarc-André Lureau assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); 78684e64d3SMarc-André Lureau 79684e64d3SMarc-André Lureau return cbinfo[selection]; 80660e8d0fSGerd Hoffmann } 81660e8d0fSGerd Hoffmann 82660e8d0fSGerd Hoffmann QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, 83660e8d0fSGerd Hoffmann QemuClipboardSelection selection) 84660e8d0fSGerd Hoffmann { 85660e8d0fSGerd Hoffmann QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1); 86660e8d0fSGerd Hoffmann 87660e8d0fSGerd Hoffmann info->owner = owner; 88660e8d0fSGerd Hoffmann info->selection = selection; 89660e8d0fSGerd Hoffmann info->refcount = 1; 90660e8d0fSGerd Hoffmann 91660e8d0fSGerd Hoffmann return info; 92660e8d0fSGerd Hoffmann } 93660e8d0fSGerd Hoffmann 94660e8d0fSGerd Hoffmann QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) 95660e8d0fSGerd Hoffmann { 96660e8d0fSGerd Hoffmann info->refcount++; 97660e8d0fSGerd Hoffmann return info; 98660e8d0fSGerd Hoffmann } 99660e8d0fSGerd Hoffmann 100660e8d0fSGerd Hoffmann void qemu_clipboard_info_unref(QemuClipboardInfo *info) 101660e8d0fSGerd Hoffmann { 102660e8d0fSGerd Hoffmann uint32_t type; 103660e8d0fSGerd Hoffmann 104660e8d0fSGerd Hoffmann if (!info) { 105660e8d0fSGerd Hoffmann return; 106660e8d0fSGerd Hoffmann } 107660e8d0fSGerd Hoffmann 108660e8d0fSGerd Hoffmann info->refcount--; 109660e8d0fSGerd Hoffmann if (info->refcount > 0) { 110660e8d0fSGerd Hoffmann return; 111660e8d0fSGerd Hoffmann } 112660e8d0fSGerd Hoffmann 113660e8d0fSGerd Hoffmann for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { 114660e8d0fSGerd Hoffmann g_free(info->types[type].data); 115660e8d0fSGerd Hoffmann } 116660e8d0fSGerd Hoffmann g_free(info); 117660e8d0fSGerd Hoffmann } 118660e8d0fSGerd Hoffmann 119660e8d0fSGerd Hoffmann void qemu_clipboard_request(QemuClipboardInfo *info, 120660e8d0fSGerd Hoffmann QemuClipboardType type) 121660e8d0fSGerd Hoffmann { 122660e8d0fSGerd Hoffmann if (info->types[type].data || 123660e8d0fSGerd Hoffmann info->types[type].requested || 124660e8d0fSGerd Hoffmann !info->types[type].available || 125660e8d0fSGerd Hoffmann !info->owner) 126660e8d0fSGerd Hoffmann return; 127660e8d0fSGerd Hoffmann 128660e8d0fSGerd Hoffmann info->types[type].requested = true; 129660e8d0fSGerd Hoffmann info->owner->request(info, type); 130660e8d0fSGerd Hoffmann } 131660e8d0fSGerd Hoffmann 132660e8d0fSGerd Hoffmann void qemu_clipboard_set_data(QemuClipboardPeer *peer, 133660e8d0fSGerd Hoffmann QemuClipboardInfo *info, 134660e8d0fSGerd Hoffmann QemuClipboardType type, 135660e8d0fSGerd Hoffmann uint32_t size, 1367e3e20d8SAkihiko Odaki const void *data, 137660e8d0fSGerd Hoffmann bool update) 138660e8d0fSGerd Hoffmann { 139660e8d0fSGerd Hoffmann if (!info || 140660e8d0fSGerd Hoffmann info->owner != peer) { 141660e8d0fSGerd Hoffmann return; 142660e8d0fSGerd Hoffmann } 143660e8d0fSGerd Hoffmann 144660e8d0fSGerd Hoffmann g_free(info->types[type].data); 145660e8d0fSGerd Hoffmann info->types[type].data = g_memdup(data, size); 146660e8d0fSGerd Hoffmann info->types[type].size = size; 147660e8d0fSGerd Hoffmann info->types[type].available = true; 148660e8d0fSGerd Hoffmann 149660e8d0fSGerd Hoffmann if (update) { 150660e8d0fSGerd Hoffmann qemu_clipboard_update(info); 151660e8d0fSGerd Hoffmann } 152660e8d0fSGerd Hoffmann } 153