Hi On Thu, Dec 3, 2020 at 3:13 PM Gerd Hoffmann <kra...@redhat.com> wrote:
> The extended desktop resize encoding adds support for (a) clients > sending resize requests to the server, and (b) multihead support. > > This patch implements (a). All resize requests are rejected by qemu. > Qemu can't resize the framebuffer on its own, this is in the hands of > the guest, so all qemu can do is forward the request to the guest. > Should the guest actually resize the framebuffer we can notify the vnc > client later with a separate message. > > This requires support in the display device. Works with virtio-gpu. > > > https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#extendeddesktopsize-pseudo-encoding > > Signed-off-by: Gerd Hoffmann <kra...@redhat.com> > --- > ui/vnc.h | 2 ++ > ui/vnc.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 65 insertions(+), 1 deletion(-) > > diff --git a/ui/vnc.h b/ui/vnc.h > index c8d3ad9ec496..77a310947bd6 100644 > --- a/ui/vnc.h > +++ b/ui/vnc.h > @@ -442,6 +442,7 @@ enum { > > enum VncFeatures { > VNC_FEATURE_RESIZE, > + VNC_FEATURE_RESIZE_EXT, > VNC_FEATURE_HEXTILE, > VNC_FEATURE_POINTER_TYPE_CHANGE, > VNC_FEATURE_WMVI, > @@ -456,6 +457,7 @@ enum VncFeatures { > }; > > #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) > +#define VNC_FEATURE_RESIZE_EXT_MASK (1 << VNC_FEATURE_RESIZE_EXT) > #define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE) > #define VNC_FEATURE_POINTER_TYPE_CHANGE_MASK (1 << > VNC_FEATURE_POINTER_TYPE_CHANGE) > #define VNC_FEATURE_WMVI_MASK (1 << VNC_FEATURE_WMVI) > diff --git a/ui/vnc.c b/ui/vnc.c > index bdaf384f71a4..a15132faa96f 100644 > --- a/ui/vnc.c > +++ b/ui/vnc.c > @@ -663,10 +663,35 @@ void vnc_framebuffer_update(VncState *vs, int x, int > y, int w, int h, > vnc_write_s32(vs, encoding); > } > > +static void vnc_desktop_resize_ext(VncState *vs, bool reject) > +{ > + vnc_lock_output(vs); > + vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); > + vnc_write_u8(vs, 0); > + vnc_write_u16(vs, 1); /* number of rects */ > + vnc_framebuffer_update(vs, > + reject ? 1 : 0, 1 "The client receiving this message requested a change of the screen layout. The change may or may not have happened depending on server policy or available resources. The status code in the *y-position* field must be used to determine which." ok 0 "The screen layout was changed via non-RFB means on the server." ok + reject ? 3 : 0, > 3 "Invalid screen layout" ok + vs->client_width, vs->client_height, > + VNC_ENCODING_DESKTOP_RESIZE_EXT); > + vnc_write_u8(vs, 1); /* number of screens */ > + vnc_write_u8(vs, 0); /* padding */ > + vnc_write_u8(vs, 0); /* padding */ > + vnc_write_u8(vs, 0); /* padding */ > + vnc_write_u32(vs, 0); /* screen id */ > + vnc_write_u16(vs, 0); /* screen x-pos */ > + vnc_write_u16(vs, 0); /* screen y-pos */ > + vnc_write_u16(vs, vs->client_width); > + vnc_write_u16(vs, vs->client_height); > + vnc_write_u32(vs, 0); /* screen flags */ > + vnc_unlock_output(vs); > + vnc_flush(vs); > +} > > static void vnc_desktop_resize(VncState *vs, bool force) > { > - if (vs->ioc == NULL || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { > + if (vs->ioc == NULL || (!vnc_has_feature(vs, VNC_FEATURE_RESIZE) && > + !vnc_has_feature(vs, > VNC_FEATURE_RESIZE_EXT))) { > return; > } > if (vs->client_width == pixman_image_get_width(vs->vd->server) && > @@ -681,6 +706,12 @@ static void vnc_desktop_resize(VncState *vs, bool > force) > pixman_image_get_height(vs->vd->server) >= 0); > vs->client_width = pixman_image_get_width(vs->vd->server); > vs->client_height = pixman_image_get_height(vs->vd->server); > + > + if (vnc_has_feature(vs, VNC_FEATURE_RESIZE_EXT)) { > + vnc_desktop_resize_ext(vs, false); > + return; > + } > + > vnc_lock_output(vs); > vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); > vnc_write_u8(vs, 0); > @@ -2110,6 +2141,9 @@ static void set_encodings(VncState *vs, int32_t > *encodings, size_t n_encodings) > case VNC_ENCODING_DESKTOPRESIZE: > vs->features |= VNC_FEATURE_RESIZE_MASK; > break; > + case VNC_ENCODING_DESKTOP_RESIZE_EXT: > + vs->features |= VNC_FEATURE_RESIZE_EXT_MASK; > + break; > case VNC_ENCODING_POINTER_TYPE_CHANGE: > vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK; > break; > @@ -2431,6 +2465,34 @@ static int protocol_client_msg(VncState *vs, > uint8_t *data, size_t len) > break; > } > break; > + case VNC_MSG_CLIENT_SET_DESKTOP_SIZE: > + { > + size_t size; > + uint8_t screens; > + uint16_t width; > + uint16_t height; > + QemuUIInfo info; > + > + if (len < 8) { > + return 8; > + } > + > + screens = read_u8(data, 6); > + size = 8 + screens * 16; > + if (len < size) { > + return size; > + } > Maybe leave a TODO note for handling multiple screens etc? lgtm Reviewed-by: Marc-André Lureau <marcandre.lur...@redhat.com> + > + width = read_u16(data, 2); > + height = read_u16(data, 4); > + vnc_desktop_resize_ext(vs, true); > + > + memset(&info, 0, sizeof(info)); > + info.width = width; > + info.height = height; > + dpy_set_ui_info(vs->vd->dcl.con, &info); > + break; > + } > default: > VNC_DEBUG("Msg: %d\n", data[0]); > vnc_client_error(vs); > -- > 2.27.0 > > > -- Marc-André Lureau