xref: /qemu/ui/clipboard.c (revision 727385c4)
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