Hi Lukasz On Tue, Aug 18, 2026 at 4:15 PM Lukasz Kornicki <[email protected]> wrote: > > Introduce a new vnc message (VNC_MSG_SERVER_QEMU_CLIPBOARD_STATUS) and > the corresponding feature/encoding. > > When a client requests this feature, the server will inform the client > whether a guest clipboard peer is present. The server will repeat the > notification each time availability of a guest clipboard peer changes. > > This change enables the VNC client to determine if a guest side > clipboard peer is available for clipboard exchange and react to > changes of its availability. > > Until now the VNC clipboard peer was only registered when > VNC_FEATURE_CLIPBOARD_EXT was enabled. With this change the VNC peer > can be registered just for the purpose of receiving peer status > updates. This requires introducing a VNC_FEATURE_CLIPBOARD_EXT guard > before the QEMU_CLIPBOARD_UPDATE_INFO handler which previously only ran > if VNC_FEATURE_CLIPBOARD_EXT was enabled. >
The series looks good, but this extension is not documented afaict. Can you make a PR for it? https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst > Change-Id: Id0897a24fae103288c399f73e808ed6c07018359 What is this? Is it a gerrit thing? > 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 > >
