]>
Commit | Line | Data |
---|---|---|
660e8d0f GH |
1 | #include "qemu/osdep.h" |
2 | #include "ui/clipboard.h" | |
410840cd | 3 | #include "trace.h" |
660e8d0f GH |
4 | |
5 | static NotifierList clipboard_notifiers = | |
6 | NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); | |
7 | ||
684e64d3 MAL |
8 | static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; |
9 | ||
660e8d0f GH |
10 | void qemu_clipboard_peer_register(QemuClipboardPeer *peer) |
11 | { | |
1b17f1e9 | 12 | notifier_list_add(&clipboard_notifiers, &peer->notifier); |
660e8d0f GH |
13 | } |
14 | ||
15 | void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) | |
16 | { | |
7424bfaa MAL |
17 | int i; |
18 | ||
19 | for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { | |
20 | qemu_clipboard_peer_release(peer, i); | |
21 | } | |
1b17f1e9 | 22 | notifier_remove(&peer->notifier); |
660e8d0f GH |
23 | } |
24 | ||
482bbaf4 MAL |
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 | ||
1387865e MAL |
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 | ||
349504e5 MAL |
45 | bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) |
46 | { | |
410840cd MAL |
47 | bool ok; |
48 | ||
349504e5 MAL |
49 | if (!info->has_serial || |
50 | !cbinfo[info->selection] || | |
51 | !cbinfo[info->selection]->has_serial) { | |
410840cd | 52 | trace_clipboard_check_serial(-1, -1, true); |
349504e5 MAL |
53 | return true; |
54 | } | |
55 | ||
56 | if (client) { | |
0e23ae9c | 57 | ok = info->serial >= cbinfo[info->selection]->serial; |
349504e5 | 58 | } else { |
0e23ae9c | 59 | ok = info->serial > cbinfo[info->selection]->serial; |
349504e5 | 60 | } |
410840cd MAL |
61 | |
62 | trace_clipboard_check_serial(cbinfo[info->selection]->serial, info->serial, ok); | |
63 | return ok; | |
349504e5 MAL |
64 | } |
65 | ||
660e8d0f GH |
66 | void qemu_clipboard_update(QemuClipboardInfo *info) |
67 | { | |
1b17f1e9 MAL |
68 | QemuClipboardNotify notify = { |
69 | .type = QEMU_CLIPBOARD_UPDATE_INFO, | |
70 | .info = info, | |
71 | }; | |
684e64d3 MAL |
72 | assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); |
73 | ||
1b17f1e9 | 74 | notifier_list_notify(&clipboard_notifiers, ¬ify); |
684e64d3 | 75 | |
02a8ee2e MAL |
76 | if (cbinfo[info->selection] != info) { |
77 | qemu_clipboard_info_unref(cbinfo[info->selection]); | |
78 | cbinfo[info->selection] = qemu_clipboard_info_ref(info); | |
79 | } | |
684e64d3 MAL |
80 | } |
81 | ||
82 | QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection) | |
83 | { | |
84 | assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT); | |
85 | ||
86 | return cbinfo[selection]; | |
660e8d0f GH |
87 | } |
88 | ||
89 | QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, | |
90 | QemuClipboardSelection selection) | |
91 | { | |
92 | QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1); | |
93 | ||
94 | info->owner = owner; | |
95 | info->selection = selection; | |
96 | info->refcount = 1; | |
97 | ||
98 | return info; | |
99 | } | |
100 | ||
101 | QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) | |
102 | { | |
103 | info->refcount++; | |
104 | return info; | |
105 | } | |
106 | ||
107 | void qemu_clipboard_info_unref(QemuClipboardInfo *info) | |
108 | { | |
109 | uint32_t type; | |
110 | ||
111 | if (!info) { | |
112 | return; | |
113 | } | |
114 | ||
115 | info->refcount--; | |
116 | if (info->refcount > 0) { | |
117 | return; | |
118 | } | |
119 | ||
120 | for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { | |
121 | g_free(info->types[type].data); | |
122 | } | |
123 | g_free(info); | |
124 | } | |
125 | ||
126 | void qemu_clipboard_request(QemuClipboardInfo *info, | |
127 | QemuClipboardType type) | |
128 | { | |
129 | if (info->types[type].data || | |
130 | info->types[type].requested || | |
131 | !info->types[type].available || | |
132 | !info->owner) | |
133 | return; | |
134 | ||
135 | info->types[type].requested = true; | |
136 | info->owner->request(info, type); | |
137 | } | |
138 | ||
505dbf9b MAL |
139 | void qemu_clipboard_reset_serial(void) |
140 | { | |
141 | QemuClipboardNotify notify = { .type = QEMU_CLIPBOARD_RESET_SERIAL }; | |
72ce36f7 | 142 | int i; |
505dbf9b | 143 | |
72ce36f7 MAL |
144 | for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { |
145 | QemuClipboardInfo *info = qemu_clipboard_info(i); | |
146 | if (info) { | |
147 | info->serial = 0; | |
148 | } | |
149 | } | |
505dbf9b MAL |
150 | notifier_list_notify(&clipboard_notifiers, ¬ify); |
151 | } | |
152 | ||
660e8d0f GH |
153 | void qemu_clipboard_set_data(QemuClipboardPeer *peer, |
154 | QemuClipboardInfo *info, | |
155 | QemuClipboardType type, | |
156 | uint32_t size, | |
7e3e20d8 | 157 | const void *data, |
660e8d0f GH |
158 | bool update) |
159 | { | |
160 | if (!info || | |
161 | info->owner != peer) { | |
162 | return; | |
163 | } | |
164 | ||
165 | g_free(info->types[type].data); | |
166 | info->types[type].data = g_memdup(data, size); | |
167 | info->types[type].size = size; | |
168 | info->types[type].available = true; | |
169 | ||
170 | if (update) { | |
171 | qemu_clipboard_update(info); | |
172 | } | |
173 | } |