Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status

Marc-André Lureau <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <CAJ+F1CKuDAzTz2iC+acOKf2j1vW3iFE6jinTKL=AwWCu3-1KGg@mail.gmail.com>
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
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.