1 #include "qemu/osdep.h" 2 #include "ui/clipboard.h" 3 4 static NotifierList clipboard_notifiers = 5 NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); 6 7 static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; 8 9 void qemu_clipboard_peer_register(QemuClipboardPeer *peer) 10 { 11 notifier_list_add(&clipboard_notifiers, &peer->update); 12 } 13 14 void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) 15 { 16 int i; 17 18 for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { 19 qemu_clipboard_peer_release(peer, i); 20 } 21 22 notifier_remove(&peer->update); 23 } 24 25 bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, 26 QemuClipboardSelection selection) 27 { 28 QemuClipboardInfo *info = qemu_clipboard_info(selection); 29 30 return info && info->owner == peer; 31 } 32 33 void qemu_clipboard_peer_release(QemuClipboardPeer *peer, 34 QemuClipboardSelection selection) 35 { 36 g_autoptr(QemuClipboardInfo) info = NULL; 37 38 if (qemu_clipboard_peer_owns(peer, selection)) { 39 /* set empty clipboard info */ 40 info = qemu_clipboard_info_new(NULL, selection); 41 qemu_clipboard_update(info); 42 } 43 } 44 45 void qemu_clipboard_update(QemuClipboardInfo *info) 46 { 47 g_autoptr(QemuClipboardInfo) old = NULL; 48 assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); 49 50 notifier_list_notify(&clipboard_notifiers, info); 51 52 old = cbinfo[info->selection]; 53 cbinfo[info->selection] = qemu_clipboard_info_ref(info); 54 } 55 56 QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) 57 { 58 assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); 59 60 return cbinfo[selection]; 61 } 62 63 QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, 64 QemuClipboardSelection selection) 65 { 66 QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1); 67 68 info->owner = owner; 69 info->selection = selection; 70 info->refcount = 1; 71 72 return info; 73 } 74 75 QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) 76 { 77 info->refcount++; 78 return info; 79 } 80 81 void qemu_clipboard_info_unref(QemuClipboardInfo *info) 82 { 83 uint32_t type; 84 85 if (!info) { 86 return; 87 } 88 89 info->refcount--; 90 if (info->refcount > 0) { 91 return; 92 } 93 94 for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { 95 g_free(info->types[type].data); 96 } 97 g_free(info); 98 } 99 100 void qemu_clipboard_request(QemuClipboardInfo *info, 101 QemuClipboardType type) 102 { 103 if (info->types[type].data || 104 info->types[type].requested || 105 !info->types[type].available || 106 !info->owner) 107 return; 108 109 info->types[type].requested = true; 110 info->owner->request(info, type); 111 } 112 113 void qemu_clipboard_set_data(QemuClipboardPeer *peer, 114 QemuClipboardInfo *info, 115 QemuClipboardType type, 116 uint32_t size, 117 const void *data, 118 bool update) 119 { 120 if (!info || 121 info->owner != peer) { 122 return; 123 } 124 125 g_free(info->types[type].data); 126 info->types[type].data = g_memdup(data, size); 127 info->types[type].size = size; 128 info->types[type].available = true; 129 130 if (update) { 131 qemu_clipboard_update(info); 132 } 133 } 134