Blob Blame Raw
From 3fa0b44ff46eccd3c22729a6e5d4ed044d22ab8a Mon Sep 17 00:00:00 2001
From: "Daniel P. Berrange" <berrange@redhat.com>
Date: Thu, 8 Feb 2018 17:50:28 +0100
Subject: [PATCH 14/27] ui: fix refresh of VNC server surface

RH-Author: Daniel P. Berrange <berrange@redhat.com>
Message-id: <20180208175041.5634-15-berrange@redhat.com>
Patchwork-id: 78948
O-Subject: [RHEL-7.5 qemu-kvm PATCH v1 14/27] ui: fix refresh of VNC server surface
Bugzilla: 1527405
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>

From: "Daniel P. Berrange" <berrange@redhat.com>

In previous commit

  commit c7628bff4138ce906a3620d12e0820c1cf6c140d
  Author: Gerd Hoffmann <kraxel@redhat.com>
  Date:   Fri Oct 30 12:10:09 2015 +0100

    vnc: only alloc server surface with clients connected

the VNC server was changed so that the 'vd->server' pixman
image was only allocated when a client is connected.

Since then if a client disconnects and then reconnects to
the VNC server all they will see is a black screen until
they do something that triggers a refresh. On a graphical
desktop this is not often noticed since there's many things
going on which cause a refresh. On a plain text console it
is really obvious since nothing refreshes frequently.

The problem is that the VNC server didn't update the guest
dirty bitmap, so still believes its server image is in sync
with the guest contents.

To fix this we must explicitly mark the entire guest desktop
as dirty after re-creating the server surface. Move this
logic into vnc_update_server_surface() so it is guaranteed
to be call in all code paths that re-create the surface
instead of only in vnc_dpy_switch()

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Peter Lieven <pl@kamp.de>
Tested-by: Peter Lieven <pl@kamp.de>
Message-id: 1471365032-18096-1-git-send-email-berrange@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit b69a553b4af9bc87a8b2e0a7b7a7de4cc7f0557e)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 ui/vnc.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index dc09089..ec7bb0c 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -617,6 +617,8 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
 
 static void vnc_update_server_surface(VncDisplay *vd)
 {
+    int width, height;
+
     qemu_pixman_image_unref(vd->server);
     vd->server = NULL;
 
@@ -624,10 +626,15 @@ static void vnc_update_server_surface(VncDisplay *vd)
         return;
     }
 
+    width = vnc_width(vd);
+    height = vnc_height(vd);
     vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
-                                          vnc_width(vd),
-                                          vnc_height(vd),
+                                          width, height,
                                           NULL, 0);
+
+    memset(vd->guest.dirty, 0x00, sizeof(vd->guest.dirty));
+    vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0,
+                       width, height);
 }
 
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
@@ -635,7 +642,6 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
 {
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs;
-    int width, height;
 
     vnc_abort_display_jobs(vd);
     vd->ds = surface;
@@ -647,11 +653,6 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
     qemu_pixman_image_unref(vd->guest.fb);
     vd->guest.fb = pixman_image_ref(surface->image);
     vd->guest.format = surface->format;
-    width = vnc_width(vd);
-    height = vnc_height(vd);
-    memset(vd->guest.dirty, 0x00, sizeof(vd->guest.dirty));
-    vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0,
-                       width, height);
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
         vnc_colordepth(vs);
@@ -661,7 +662,8 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
         }
         memset(vs->dirty, 0x00, sizeof(vs->dirty));
         vnc_set_area_dirty(vs->dirty, vd, 0, 0,
-                           width, height);
+                           vnc_width(vd),
+                           vnc_height(vd));
     }
 }
 
-- 
1.8.3.1