Hi Marc-Andre

I quickly became aware of the shortcomings of my v1 series and I've already drafted a v2 where the cover is a bit more detailed and the commits were fixed to remove the Change-IDs.

On 8/18/26 15:33, Marc-André Lureau wrote:
!-------------------------------------------------------------------|
   CAUTION: External Email

|-------------------------------------------------------------------!

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?

Sure. I've found this repo before but was not aware that it functions in any official capacity.

Change-Id: Id0897a24fae103288c399f73e808ed6c07018359
What is this? Is it a gerrit thing?
Yes, I forgot to remove the commit-msg hook and they got regenerated right after I removed them :)
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