Signed-off-by: Lukasz Kornicki <[email protected]>
---
ui/trace-events | 1 +
ui/vnc-clipboard.c | 31 ++++++++++++++++++++++++++++++-
ui/vnc.c | 6 ++++++
ui/vnc.h | 8 ++++++++
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/ui/trace-events b/ui/trace-events
index 917d116d90..d2fe153b7d 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -48,6 +48,7 @@ vnc_msg_server_ext_desktop_resize(void *state, void *ioc, int
width, int height,
vnc_msg_client_audio_enable(void *state, void *ioc) "VNC client msg audio enable
state=%p ioc=%p"
vnc_msg_client_audio_disable(void *state, void *ioc) "VNC client msg audio disable
state=%p ioc=%p"
vnc_msg_client_audio_format(void *state, void *ioc, int fmt, int channels, int freq)
"VNC client msg audio format state=%p ioc=%p fmt=%d channels=%d freq=%d"
+vnc_clipboard_peer_status_send(void *state, bool present) "VNC server clipboard
peer status state=%p present=%d"
vnc_msg_client_cut_text(void *state, void *ioc, int len) "VNC client msg cut text
state=%p ioc=%p len=%u"
vnc_msg_client_cut_text_ext(void *state, void *ioc, int len, int flags) "VNC
client msg cut text state=%p ioc=%p len=%u flags=%u"
vnc_msg_client_ext_key_event(void *state, void *ioc, int down, int sym, int keycode)
"VNC client msg ext key event state=%p ioc=%p down=%u sym=%u keycode=%u"
diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
index 67f710f6ed..4ecc4489e4 100644
--- a/ui/vnc-clipboard.c
+++ b/ui/vnc-clipboard.c
@@ -26,6 +26,7 @@
#include "qemu/error-report.h"
#include "vnc.h"
#include "vnc-jobs.h"
+#include "trace.h"
static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
{
@@ -224,6 +225,23 @@ static void vnc_clipboard_update_info(VncState *vs,
QemuClipboardInfo *info)
}
}
+void vnc_clipboard_peer_status_send(VncState *vs, bool present)
+{
+ if (!vnc_has_feature(vs, VNC_FEATURE_CLIPBOARD_STATUS)) {
+ return;
+ }
+
+ trace_vnc_clipboard_peer_status_send(vs, present);
+
+ vnc_lock_output(vs);
+ vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
+ vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_CLIPBOARD_STATUS);
+ vnc_write_u16(vs, present ? VNC_CLIPBOARD_PEER_PRESENT
+ : VNC_CLIPBOARD_PEER_ABSENT);
+ vnc_unlock_output(vs);
+ vnc_flush(vs);
+}
+
static void vnc_clipboard_notify(Notifier *notifier, void *data)
{
VncState *vs = container_of(notifier, VncState, cbpeer.notifier);
@@ -231,13 +249,24 @@ static void vnc_clipboard_notify(Notifier *notifier, void
*data)
switch (notify->type) {
case QEMU_CLIPBOARD_UPDATE_INFO:
+ /* ignore the update if client does not want ext messages */
+ if (!vnc_has_feature(vs, VNC_FEATURE_CLIPBOARD_EXT)) {
+ return;
+ }
+
vnc_clipboard_update_info(vs, notify->info);
return;
case QEMU_CLIPBOARD_RESET_SERIAL:
/* ignore */
return;
case QEMU_CLIPBOARD_PEER_UPDATE:
- /* ignore */
+ /* only guest side peers affect the status we relay to the client */
+ if (!notify->peer_update.peer->guest) {
+ return;
+ }
+
+ vnc_clipboard_peer_status_send(vs,
+ qemu_clipboard_guest_peer_present());
return;
}
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 656768f9c9..9e44a20311 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2191,6 +2191,12 @@ static void set_encodings(VncState *vs, int32_t
*encodings, size_t n_encodings)
vnc_set_feature(vs, VNC_FEATURE_CLIPBOARD_EXT);
vnc_server_cut_text_caps(vs);
break;
+ case VNC_ENCODING_CLIPBOARD_STATUS:
+ vnc_set_feature(vs, VNC_FEATURE_CLIPBOARD_STATUS);
+ vnc_clipboard_peer_register(vs);
+ vnc_clipboard_peer_status_send(vs,
+ qemu_clipboard_guest_peer_present());
+ break;
case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
vc->worker.tight.compression = (enc & 0x0F);
break;
diff --git a/ui/vnc.h b/ui/vnc.h
index d8b0070396..6e8fa66e9c 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -422,6 +422,7 @@ enum {
#define VNC_ENCODING_DESKTOP_RESIZE_EXT 0XFFFFFECC /* -308 */
#define VNC_ENCODING_XVP 0XFFFFFECB /* -309 */
#define VNC_ENCODING_ALPHA_CURSOR 0XFFFFFEC6 /* -314 */
+#define VNC_ENCODING_CLIPBOARD_STATUS 0XFFFFFEC5 /* -315 */
#define VNC_ENCODING_WMVi 0x574D5669
#define VNC_ENCODING_CLIPBOARD_EXT 0xc0a1e5ce
@@ -466,6 +467,7 @@ enum VncFeatures {
VNC_FEATURE_LED_STATE,
VNC_FEATURE_XVP,
VNC_FEATURE_CLIPBOARD_EXT,
+ VNC_FEATURE_CLIPBOARD_STATUS,
VNC_FEATURE_AUDIO,
};
@@ -507,6 +509,7 @@ enum VncFeatures {
/* QEMU server -> client message IDs */
#define VNC_MSG_SERVER_QEMU_AUDIO 1
+#define VNC_MSG_SERVER_QEMU_CLIPBOARD_STATUS 2
@@ -541,6 +544,10 @@ enum VncFeatures {
#define VNC_CLIPBOARD_NOTIFY (1 << 27)
#define VNC_CLIPBOARD_PROVIDE (1 << 28)
+/* guest side clipboard peer status */
+#define VNC_CLIPBOARD_PEER_ABSENT 0
+#define VNC_CLIPBOARD_PEER_PRESENT 1
+
VncDisplay *vnc_display_new(const char *id, Error **errp);
void vnc_display_free(VncDisplay *vd);
@@ -637,6 +644,7 @@ void vnc_zrle_clear(VncWorker *worker);
/* vnc-clipboard.c */
void vnc_clipboard_peer_register(VncState *vs);
+void vnc_clipboard_peer_status_send(VncState *vs, bool present);
void vnc_server_cut_text_caps(VncState *vs);
void vnc_client_cut_text(VncState *vs, size_t len, uint8_t *text);
void vnc_client_cut_text_ext(VncState *vs, int32_t len, uint32_t flags,
uint8_t *data);
--
2.43.0