1 #include "qemu/osdep.h"
2 #include "ui/clipboard.h"
5 static NotifierList clipboard_notifiers
=
6 NOTIFIER_LIST_INITIALIZER(clipboard_notifiers
);
8 static QemuClipboardInfo
*cbinfo
[QEMU_CLIPBOARD_SELECTION__COUNT
];
10 void qemu_clipboard_peer_register(QemuClipboardPeer
*peer
)
12 notifier_list_add(&clipboard_notifiers
, &peer
->notifier
);
15 void qemu_clipboard_peer_unregister(QemuClipboardPeer
*peer
)
19 for (i
= 0; i
< QEMU_CLIPBOARD_SELECTION__COUNT
; i
++) {
20 qemu_clipboard_peer_release(peer
, i
);
22 notifier_remove(&peer
->notifier
);
25 bool qemu_clipboard_peer_owns(QemuClipboardPeer
*peer
,
26 QemuClipboardSelection selection
)
28 QemuClipboardInfo
*info
= qemu_clipboard_info(selection
);
30 return info
&& info
->owner
== peer
;
33 void qemu_clipboard_peer_release(QemuClipboardPeer
*peer
,
34 QemuClipboardSelection selection
)
36 g_autoptr(QemuClipboardInfo
) info
= NULL
;
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
);
45 bool qemu_clipboard_check_serial(QemuClipboardInfo
*info
, bool client
)
49 if (!info
->has_serial
||
50 !cbinfo
[info
->selection
] ||
51 !cbinfo
[info
->selection
]->has_serial
) {
52 trace_clipboard_check_serial(-1, -1, true);
57 ok
= info
->serial
>= cbinfo
[info
->selection
]->serial
;
59 ok
= info
->serial
> cbinfo
[info
->selection
]->serial
;
62 trace_clipboard_check_serial(cbinfo
[info
->selection
]->serial
, info
->serial
, ok
);
66 void qemu_clipboard_update(QemuClipboardInfo
*info
)
69 QemuClipboardNotify notify
= {
70 .type
= QEMU_CLIPBOARD_UPDATE_INFO
,
73 assert(info
->selection
< QEMU_CLIPBOARD_SELECTION__COUNT
);
75 for (type
= 0; type
< QEMU_CLIPBOARD_TYPE__COUNT
; type
++) {
77 * If data is missing, the clipboard owner's 'request' callback needs to
78 * be set. Otherwise, there is no way to get the clipboard data and
79 * qemu_clipboard_request() cannot be called.
81 if (info
->types
[type
].available
&& !info
->types
[type
].data
) {
82 assert(info
->owner
&& info
->owner
->request
);
86 notifier_list_notify(&clipboard_notifiers
, ¬ify
);
88 if (cbinfo
[info
->selection
] != info
) {
89 qemu_clipboard_info_unref(cbinfo
[info
->selection
]);
90 cbinfo
[info
->selection
] = qemu_clipboard_info_ref(info
);
94 QemuClipboardInfo
*qemu_clipboard_info(QemuClipboardSelection selection
)
96 assert(selection
< QEMU_CLIPBOARD_SELECTION__COUNT
);
98 return cbinfo
[selection
];
101 QemuClipboardInfo
*qemu_clipboard_info_new(QemuClipboardPeer
*owner
,
102 QemuClipboardSelection selection
)
104 QemuClipboardInfo
*info
= g_new0(QemuClipboardInfo
, 1);
107 info
->selection
= selection
;
113 QemuClipboardInfo
*qemu_clipboard_info_ref(QemuClipboardInfo
*info
)
119 void qemu_clipboard_info_unref(QemuClipboardInfo
*info
)
128 if (info
->refcount
> 0) {
132 for (type
= 0; type
< QEMU_CLIPBOARD_TYPE__COUNT
; type
++) {
133 g_free(info
->types
[type
].data
);
138 void qemu_clipboard_request(QemuClipboardInfo
*info
,
139 QemuClipboardType type
)
141 if (info
->types
[type
].data
||
142 info
->types
[type
].requested
||
143 !info
->types
[type
].available
||
147 assert(info
->owner
->request
);
149 info
->types
[type
].requested
= true;
150 info
->owner
->request(info
, type
);
153 void qemu_clipboard_reset_serial(void)
155 QemuClipboardNotify notify
= { .type
= QEMU_CLIPBOARD_RESET_SERIAL
};
158 for (i
= 0; i
< QEMU_CLIPBOARD_SELECTION__COUNT
; i
++) {
159 QemuClipboardInfo
*info
= qemu_clipboard_info(i
);
164 notifier_list_notify(&clipboard_notifiers
, ¬ify
);
167 void qemu_clipboard_set_data(QemuClipboardPeer
*peer
,
168 QemuClipboardInfo
*info
,
169 QemuClipboardType type
,
175 info
->owner
!= peer
) {
179 g_free(info
->types
[type
].data
);
181 info
->types
[type
].data
= g_memdup2(data
, size
);
182 info
->types
[type
].size
= size
;
183 info
->types
[type
].available
= true;
185 info
->types
[type
].data
= NULL
;
186 info
->types
[type
].size
= 0;
187 info
->types
[type
].available
= false;
191 qemu_clipboard_update(info
);