clipboard.c (3325B)
1#include "qemu/osdep.h" 2#include "ui/clipboard.h" 3 4static NotifierList clipboard_notifiers = 5 NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); 6 7static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; 8 9void qemu_clipboard_peer_register(QemuClipboardPeer *peer) 10{ 11 notifier_list_add(&clipboard_notifiers, &peer->update); 12} 13 14void 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 25bool 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 33void 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 45void 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 56QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) 57{ 58 assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); 59 60 return cbinfo[selection]; 61} 62 63QemuClipboardInfo *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 75QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) 76{ 77 info->refcount++; 78 return info; 79} 80 81void 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 100void 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 113void 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}