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
>
>

Reply via email to