* [PATCH 0/4] Add clipboard status notification to VNC
@ 2026-08-18 12:14 Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 1/4] ui/clipboard: add clipboard peer update notification Lukasz Kornicki
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Lukasz Kornicki @ 2026-08-18 12:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Currently, a vnc client has no reliable way of determining if a
guest side clipboard peer is present. Using VNC_ENCODING_CLIPBOARD_EXT
allows the client to try and infer peer presence based on NOTIFY event,
but that is limited to cases where the unregistering peer had ownership
over the clipboard.
This series' goal is to enable vnc clients to determine if a guest side
peer is present, and to be notified of changes to its presence.
This is achieved in 4 commits:
1. Add PEER_UPDATE notification to ui/clipboard and call it on each
register/unregister.
2. Add *guest* field to ClipboardPeer, which indicates that a peer is
guest side. Currently it's only set on vdagent's cbpeer.
3. Factor out vnc peer registration into a separate function.
4. Add the new vnc feature, register the clipboard peer for update
notifications, emit the message on set_encodings and peer updates.
Lukasz Kornicki (4):
ui/clipboard: add clipboard peer update notification
ui/clipboard: keep track of clipboard peer side
ui/vnc-clipboard: factor out clipboard peer registration
ui/vnc: notify client of clipboard peer status
include/ui/clipboard.h | 27 +++++++++++++++++++++
tools/qemu-vnc/clipboard.c | 3 +++
ui/clipboard.c | 33 +++++++++++++++++++++++++
ui/cocoa.m | 3 +++
ui/dbus-clipboard.c | 3 +++
ui/gtk-clipboard.c | 3 +++
ui/trace-events | 2 ++
ui/vdagent.c | 4 ++++
ui/vnc-clipboard.c | 49 +++++++++++++++++++++++++++++++++-----
ui/vnc.c | 6 +++++
ui/vnc.h | 9 +++++++
11 files changed, 136 insertions(+), 6 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] ui/clipboard: add clipboard peer update notification
2026-08-18 12:14 [PATCH 0/4] Add clipboard status notification to VNC Lukasz Kornicki
@ 2026-08-18 12:14 ` Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 2/4] ui/clipboard: keep track of clipboard peer side Lukasz Kornicki
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Lukasz Kornicki @ 2026-08-18 12:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add a new QEMU_CLIPBOARD_PEER_UPDATE notify type which carries
a payload with affected peer and whether it just registered or
unregistered.
All existing notifier handlers are updated to explicitly ignore
the new event so that the enum switch remains exhaustive.
Change-Id: I4b90f50a9b6355bbddb53d21dd6498fc01c0e095
Signed-off-by: Lukasz Kornicki <lucas.kornicki@nutanix.com>
---
include/ui/clipboard.h | 19 +++++++++++++++++++
tools/qemu-vnc/clipboard.c | 3 +++
ui/clipboard.c | 17 +++++++++++++++++
ui/cocoa.m | 3 +++
ui/dbus-clipboard.c | 3 +++
ui/gtk-clipboard.c | 3 +++
ui/trace-events | 1 +
ui/vdagent.c | 3 +++
ui/vnc-clipboard.c | 3 +++
9 files changed, 55 insertions(+)
diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index 62a96ce9ff..6166af5139 100644
--- a/include/ui/clipboard.h
+++ b/include/ui/clipboard.h
@@ -25,6 +25,7 @@ typedef enum QemuClipboardNotifyType QemuClipboardNotifyType;
typedef enum QemuClipboardSelection QemuClipboardSelection;
typedef struct QemuClipboardPeer QemuClipboardPeer;
typedef struct QemuClipboardNotify QemuClipboardNotify;
+typedef struct QemuClipboardPeerUpdate QemuClipboardPeerUpdate;
typedef struct QemuClipboardInfo QemuClipboardInfo;
typedef struct QemuClipboardContent QemuClipboardContent;
@@ -78,12 +79,27 @@ struct QemuClipboardPeer {
*
* @QEMU_CLIPBOARD_UPDATE_INFO: clipboard info update
* @QEMU_CLIPBOARD_RESET_SERIAL: reset clipboard serial
+ * @QEMU_CLIPBOARD_PEER_UPDATE: peer registered/unregistered
*
* Clipboard notify type.
*/
enum QemuClipboardNotifyType {
QEMU_CLIPBOARD_UPDATE_INFO,
QEMU_CLIPBOARD_RESET_SERIAL,
+ QEMU_CLIPBOARD_PEER_UPDATE,
+};
+
+/**
+ * struct QemuClipboardPeerUpdate
+ *
+ * @peer: the peer affected by this event
+ * @registered: whether @peer registered or unregistered.
+ *
+ * Clipboard peer update event data.
+ */
+struct QemuClipboardPeerUpdate {
+ QemuClipboardPeer *peer;
+ bool registered;
};
/**
@@ -91,6 +107,8 @@ enum QemuClipboardNotifyType {
*
* @type: the type of event.
* @info: a QemuClipboardInfo event.
+ * @peer_update: a peer register/unregister event
+ * (valid for QEMU_CLIPBOARD_PEER_UPDATE).
*
* Clipboard notify data.
*/
@@ -98,6 +116,7 @@ struct QemuClipboardNotify {
QemuClipboardNotifyType type;
union {
QemuClipboardInfo *info;
+ QemuClipboardPeerUpdate peer_update;
};
};
diff --git a/tools/qemu-vnc/clipboard.c b/tools/qemu-vnc/clipboard.c
index f62b2f2949..b85a2d8b55 100644
--- a/tools/qemu-vnc/clipboard.c
+++ b/tools/qemu-vnc/clipboard.c
@@ -174,6 +174,9 @@ vnc_dbus_clipboard_notify(Notifier *notifier, void *data)
-1, NULL, NULL, NULL);
}
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
diff --git a/ui/clipboard.c b/ui/clipboard.c
index e3d8a31ba9..beecb40e6f 100644
--- a/ui/clipboard.c
+++ b/ui/clipboard.c
@@ -59,6 +59,21 @@ static void qemu_clipboard_change_state(void *opaque, bool running, RunState sta
}
+static void qemu_clipboard_notify_peer_update(QemuClipboardPeer *peer,
+ bool registered)
+{
+ QemuClipboardNotify notify = {
+ .type = QEMU_CLIPBOARD_PEER_UPDATE,
+ .peer_update = {
+ .peer = peer,
+ .registered = registered,
+ },
+ };
+
+ trace_clipboard_peer_update(peer->name, registered);
+ notifier_list_notify(&clipboard_notifiers, ¬ify);
+}
+
void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
{
if (cb_change_state_entry == NULL) {
@@ -66,6 +81,7 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
}
notifier_list_add(&clipboard_notifiers, &peer->notifier);
+ qemu_clipboard_notify_peer_update(peer, true);
}
void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
@@ -76,6 +92,7 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
qemu_clipboard_peer_release(peer, i);
}
notifier_remove(&peer->notifier);
+ qemu_clipboard_notify_peer_update(peer, false);
}
bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer,
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 3751be3792..4587547c98 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -1860,6 +1860,9 @@ static void cocoa_clipboard_notify(Notifier *notifier, void *data)
case QEMU_CLIPBOARD_RESET_SERIAL:
/* ignore */
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c
index 90318384ee..6940f719ff 100644
--- a/ui/dbus-clipboard.c
+++ b/ui/dbus-clipboard.c
@@ -125,6 +125,9 @@ dbus_clipboard_notify(Notifier *notifier, void *data)
case QEMU_CLIPBOARD_RESET_SERIAL:
dbus_clipboard_reset_serial(dpy);
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index 476e6b8303..6bb3d7f3fc 100644
--- a/ui/gtk-clipboard.c
+++ b/ui/gtk-clipboard.c
@@ -133,6 +133,9 @@ static void gd_clipboard_notify(Notifier *notifier, void *data)
case QEMU_CLIPBOARD_RESET_SERIAL:
/* ignore */
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
diff --git a/ui/trace-events b/ui/trace-events
index 339a61f341..917d116d90 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -171,6 +171,7 @@ xkeymap_keymap(const char *name) "keymap '%s'"
# clipboard.c
clipboard_check_serial(int cur, int recv, bool ok) "cur:%d recv:%d %d"
clipboard_reset_serial(void) ""
+clipboard_peer_update(const char *name, bool registered) "peer '%s' registered=%d"
# vdagent.c
vdagent_fe_open(bool fe_open) "fe_open=%d"
diff --git a/ui/vdagent.c b/ui/vdagent.c
index b9784d4d9b..cc32a94fb9 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -477,6 +477,9 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data)
case QEMU_CLIPBOARD_RESET_SERIAL:
vdagent_clipboard_reset_serial(vd);
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
index fa05d86f42..dfe830f819 100644
--- a/ui/vnc-clipboard.c
+++ b/ui/vnc-clipboard.c
@@ -236,6 +236,9 @@ static void vnc_clipboard_notify(Notifier *notifier, void *data)
case QEMU_CLIPBOARD_RESET_SERIAL:
/* ignore */
return;
+ case QEMU_CLIPBOARD_PEER_UPDATE:
+ /* ignore */
+ return;
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] ui/clipboard: keep track of clipboard peer side
2026-08-18 12:14 [PATCH 0/4] Add clipboard status notification to VNC Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 1/4] ui/clipboard: add clipboard peer update notification Lukasz Kornicki
@ 2026-08-18 12:14 ` Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 3/4] ui/vnc-clipboard: factor out clipboard peer registration Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 4/4] ui/vnc: notify client of clipboard peer status Lukasz Kornicki
3 siblings, 0 replies; 10+ messages in thread
From: Lukasz Kornicki @ 2026-08-18 12:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add a "guest" flag to QemuClipboardPeer and set it on vdagent peer.
Use the flag to keep track of number of registered guest peers and
allow to query for their presence with
qemu_clipboard_guest_peer_present().
This change makes it possible for a clipboard peer to determine if
any guest side peers are present so they can tell whether a guest is
actually able to participate in clipboard exchange.
Change-Id: I6f39b846fb560ea52f19e14cbee34267ba404453
Signed-off-by: Lukasz Kornicki <lucas.kornicki@nutanix.com>
---
include/ui/clipboard.h | 8 ++++++++
ui/clipboard.c | 16 ++++++++++++++++
ui/vdagent.c | 1 +
3 files changed, 25 insertions(+)
diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index 6166af5139..df7fa5e491 100644
--- a/include/ui/clipboard.h
+++ b/include/ui/clipboard.h
@@ -69,6 +69,7 @@ enum QemuClipboardSelection {
*/
struct QemuClipboardPeer {
const char *name;
+ bool guest;
Notifier notifier;
void (*request)(QemuClipboardInfo *info,
QemuClipboardType type);
@@ -179,6 +180,13 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer);
*/
void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer);
+/**
+ * qemu_clipboard_guest_peer_present
+ *
+ * Return TRUE if a guest side clipboard peer is currently registered.
+ */
+bool qemu_clipboard_guest_peer_present(void);
+
/**
* qemu_clipboard_peer_owns
*
diff --git a/ui/clipboard.c b/ui/clipboard.c
index beecb40e6f..928aa435e0 100644
--- a/ui/clipboard.c
+++ b/ui/clipboard.c
@@ -12,6 +12,8 @@ static VMChangeStateEntry *cb_change_state_entry = NULL;
static bool cb_reset_serial_on_resume = false;
+static int guest_peer_count;
+
static const VMStateDescription vmstate_cbcontent = {
.name = "clipboard/content",
.version_id = 0,
@@ -80,6 +82,10 @@ void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
cb_change_state_entry = qemu_add_vm_change_state_handler(qemu_clipboard_change_state, NULL);
}
+ if (peer->guest) {
+ guest_peer_count++;
+ }
+
notifier_list_add(&clipboard_notifiers, &peer->notifier);
qemu_clipboard_notify_peer_update(peer, true);
}
@@ -92,9 +98,19 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
qemu_clipboard_peer_release(peer, i);
}
notifier_remove(&peer->notifier);
+
+ if (peer->guest) {
+ guest_peer_count--;
+ }
+
qemu_clipboard_notify_peer_update(peer, false);
}
+bool qemu_clipboard_guest_peer_present(void)
+{
+ return guest_peer_count > 0;
+}
+
bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer,
QemuClipboardSelection selection)
{
diff --git a/ui/vdagent.c b/ui/vdagent.c
index cc32a94fb9..cdd4cedad2 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -695,6 +695,7 @@ static void vdagent_clipboard_peer_register(VDAgentChardev *vd)
}
vd->cbpeer.name = "vdagent";
+ vd->cbpeer.guest = true;
vd->cbpeer.notifier.notify = vdagent_clipboard_notify;
vd->cbpeer.request = vdagent_clipboard_request;
qemu_clipboard_peer_register(&vd->cbpeer);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] ui/vnc-clipboard: factor out clipboard peer registration
2026-08-18 12:14 [PATCH 0/4] Add clipboard status notification to VNC Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 1/4] ui/clipboard: add clipboard peer update notification Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 2/4] ui/clipboard: keep track of clipboard peer side Lukasz Kornicki
@ 2026-08-18 12:14 ` Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 4/4] ui/vnc: notify client of clipboard peer status Lukasz Kornicki
3 siblings, 0 replies; 10+ messages in thread
From: Lukasz Kornicki @ 2026-08-18 12:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
VNC clipboard peer is registered inline from vnc_server_cut_text_caps.
Move the registration logic into a function so a subsequent change can
register the peer independently of extended clipboard capability.
No functional change.
Change-Id: I96b20e914b3a0e496791a24b33db8a795c2c1690
Signed-off-by: Lukasz Kornicki <lucas.kornicki@nutanix.com>
---
ui/vnc-clipboard.c | 17 +++++++++++------
ui/vnc.h | 1 +
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
index dfe830f819..67f710f6ed 100644
--- a/ui/vnc-clipboard.c
+++ b/ui/vnc-clipboard.c
@@ -325,6 +325,16 @@ void vnc_client_cut_text(VncState *vs, size_t len, uint8_t *text)
qemu_clipboard_info_unref(info);
}
+void vnc_clipboard_peer_register(VncState *vs)
+{
+ if (!vs->cbpeer.notifier.notify) {
+ vs->cbpeer.name = "vnc";
+ vs->cbpeer.notifier.notify = vnc_clipboard_notify;
+ vs->cbpeer.request = vnc_clipboard_request;
+ qemu_clipboard_peer_register(&vs->cbpeer);
+ }
+}
+
void vnc_server_cut_text_caps(VncState *vs)
{
uint32_t caps[2];
@@ -341,10 +351,5 @@ void vnc_server_cut_text_caps(VncState *vs)
caps[1] = 0;
vnc_clipboard_send(vs, 2, caps);
- if (!vs->cbpeer.notifier.notify) {
- vs->cbpeer.name = "vnc";
- vs->cbpeer.notifier.notify = vnc_clipboard_notify;
- vs->cbpeer.request = vnc_clipboard_request;
- qemu_clipboard_peer_register(&vs->cbpeer);
- }
+ vnc_clipboard_peer_register(vs);
}
diff --git a/ui/vnc.h b/ui/vnc.h
index 88293ef497..d8b0070396 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -636,6 +636,7 @@ int vnc_zywrle_send_framebuffer_update(VncState *vs, VncWorker *worker,
void vnc_zrle_clear(VncWorker *worker);
/* vnc-clipboard.c */
+void vnc_clipboard_peer_register(VncState *vs);
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-18 12:14 [PATCH 0/4] Add clipboard status notification to VNC Lukasz Kornicki
` (2 preceding siblings ...)
2026-08-18 12:14 ` [PATCH 3/4] ui/vnc-clipboard: factor out clipboard peer registration Lukasz Kornicki
@ 2026-08-18 12:14 ` Lukasz Kornicki
2026-08-18 13:33 ` Marc-André Lureau
3 siblings, 1 reply; 10+ messages in thread
From: Lukasz Kornicki @ 2026-08-18 12:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
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.
Change-Id: Id0897a24fae103288c399f73e808ed6c07018359
Signed-off-by: Lukasz Kornicki <lucas.kornicki@nutanix.com>
---
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-18 12:14 ` [PATCH 4/4] ui/vnc: notify client of clipboard peer status Lukasz Kornicki
@ 2026-08-18 13:33 ` Marc-André Lureau
2026-08-18 13:55 ` Lucas Kornicki
0 siblings, 1 reply; 10+ messages in thread
From: Marc-André Lureau @ 2026-08-18 13:33 UTC (permalink / raw)
To: Lukasz Kornicki; +Cc: qemu-devel
Hi Lukasz
On Tue, Aug 18, 2026 at 4:15 PM Lukasz Kornicki
<lucas.kornicki@nutanix.com> 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 <lucas.kornicki@nutanix.com>
> ---
> 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
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-18 13:33 ` Marc-André Lureau
@ 2026-08-18 13:55 ` Lucas Kornicki
2026-08-24 12:36 ` Marc-André Lureau
0 siblings, 1 reply; 10+ messages in thread
From: Lucas Kornicki @ 2026-08-18 13:55 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
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
> <lucas.kornicki@nutanix.com> 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 <lucas.kornicki@nutanix.com>
>> ---
>> 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
>>
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-18 13:55 ` Lucas Kornicki
@ 2026-08-24 12:36 ` Marc-André Lureau
2026-08-24 13:09 ` Daniel P. Berrangé
2026-09-01 8:35 ` Lucas Kornicki
0 siblings, 2 replies; 10+ messages in thread
From: Marc-André Lureau @ 2026-08-24 12:36 UTC (permalink / raw)
To: Lucas Kornicki; +Cc: qemu-devel
Hi
On Tue, Aug 18, 2026 at 5:56 PM Lucas Kornicki
<lucas.kornicki@nutanix.com> wrote:
>
> 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
> > <lucas.kornicki@nutanix.com> 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.
I dont think we should take the change until the rfbproto documents it.
thanks
>
> >> 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 <lucas.kornicki@nutanix.com>
> >> ---
> >> 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
> >>
> >>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-24 12:36 ` Marc-André Lureau
@ 2026-08-24 13:09 ` Daniel P. Berrangé
2026-09-01 8:35 ` Lucas Kornicki
1 sibling, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2026-08-24 13:09 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Lucas Kornicki, qemu-devel
On Mon, Aug 24, 2026 at 04:36:12PM +0400, Marc-André Lureau wrote:
> Hi
>
> On Tue, Aug 18, 2026 at 5:56 PM Lucas Kornicki
> <lucas.kornicki@nutanix.com> wrote:
> >
> > 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
> > > <lucas.kornicki@nutanix.com> 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.
>
> I dont think we should take the change until the rfbproto documents it.
Yes, please submit an rfbproto PR for the extension, as we've tried
to ensure everything QEMU implements is specified there to aid in
future interoperability and to spot design mistakes at spec time.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] ui/vnc: notify client of clipboard peer status
2026-08-24 12:36 ` Marc-André Lureau
2026-08-24 13:09 ` Daniel P. Berrangé
@ 2026-09-01 8:35 ` Lucas Kornicki
1 sibling, 0 replies; 10+ messages in thread
From: Lucas Kornicki @ 2026-09-01 8:35 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On 8/24/26 14:36, Marc-André Lureau wrote:
> !-------------------------------------------------------------------|
> CAUTION: External Email
>
> |-------------------------------------------------------------------!
>
> Hi
>
> On Tue, Aug 18, 2026 at 5:56 PM Lucas Kornicki
> <lucas.kornicki@nutanix.com> wrote:
>> 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
>>> <lucas.kornicki@nutanix.com> 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.
> I dont think we should take the change until the rfbproto documents it.
Hi. Just a heads up but this might take some more time as I'm having
trouble convincing legal to allow contribution to rfbproto since it has
no license. Hopefully this will be resolved soon.
> thanks
>
>>>> 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 <lucas.kornicki@nutanix.com>
>>>> ---
>>>> 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
>>>>
>>>>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-09-01 8:36 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 12:14 [PATCH 0/4] Add clipboard status notification to VNC Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 1/4] ui/clipboard: add clipboard peer update notification Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 2/4] ui/clipboard: keep track of clipboard peer side Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 3/4] ui/vnc-clipboard: factor out clipboard peer registration Lukasz Kornicki
2026-08-18 12:14 ` [PATCH 4/4] ui/vnc: notify client of clipboard peer status Lukasz Kornicki
2026-08-18 13:33 ` Marc-André Lureau
2026-08-18 13:55 ` Lucas Kornicki
2026-08-24 12:36 ` Marc-André Lureau
2026-08-24 13:09 ` Daniel P. Berrangé
2026-09-01 8:35 ` Lucas Kornicki
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.