[gtk-vnc] src: implement dynamic resize of remote desktop on widget resize



commit 8e86bc76bca7b9c016e23df112be2d05cf34f249
Author: Daniel P. Berrangé <dan berrange com>
Date:   Thu Dec 10 18:23:30 2020 +0000

    src: implement dynamic resize of remote desktop on widget resize
    
    This wires up the widget to send remote desktop resize requests to
    the server when the widget changes size. Resize requests will be
    delayed for 500ms each time a resize is seen, so that when the user
    is resizing the windows we only send a request once they've stopped
    instead of for the 100's of intermediate sizes.
    
    Signed-off-by: Daniel P. Berrangé <berrange redhat com>

 src/vncdisplay.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
---
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index b30e12f..8746010 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -69,6 +69,10 @@ struct _VncDisplayPrivate
     int last_x;
     int last_y;
 
+    int last_resize_reqw;
+    int last_resize_reqh;
+    gulong pending_resize_id;
+
     gboolean absolute;
 
     gboolean grab_pointer;
@@ -1118,6 +1122,62 @@ static gboolean focus_out_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_U
     return TRUE;
 }
 
+static gboolean do_desktop_resize(gpointer opaque)
+{
+    VncDisplay *obj = VNC_DISPLAY(opaque);
+    VncDisplayPrivate *priv = obj->priv;
+    VncConnectionResizeStatus status;
+
+    status = vnc_connection_set_size(priv->conn,
+                                     priv->last_resize_reqw,
+                                     priv->last_resize_reqh);
+    VNC_DEBUG("Made desktop resize req %dx%d status=%d",
+              priv->last_resize_reqw, priv->last_resize_reqh, status);
+
+    priv->pending_resize_id = 0;
+
+    return FALSE;
+}
+
+static gboolean configure_event(GtkWidget *widget,
+                                GdkEventConfigure *cfg)
+{
+    VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
+    int fbw, fbh;
+
+    if (priv->conn == NULL || !vnc_connection_is_initialized(priv->conn))
+        return FALSE;
+
+    if (!priv->allow_resize)
+        return FALSE;
+
+    fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
+    fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
+    if (cfg->width == fbw &&
+        cfg->height == fbh) {
+        VNC_DEBUG("Framebuffer already matches widget size %dx%d", fbw, fbh);
+        return FALSE;
+    }
+
+    if (cfg->width == priv->last_resize_reqw &&
+        cfg->height == priv->last_resize_reqh) {
+        VNC_DEBUG("Already requested resize to %dx%d", fbw, fbh);
+        return FALSE;
+    }
+
+    VNC_DEBUG("Need to try resize to %dx%d", cfg->width, cfg->height);
+    priv->last_resize_reqw = cfg->width;
+    priv->last_resize_reqh = cfg->height;
+
+    if (priv->pending_resize_id) {
+        VNC_DEBUG("Cancel pending resize timer %lu", priv->pending_resize_id);
+        g_source_remove(priv->pending_resize_id);
+    }
+    priv->pending_resize_id = g_timeout_add(500, do_desktop_resize, widget);
+    VNC_DEBUG("Scheduled pending resize timer %lu", priv->pending_resize_id);
+    return FALSE;
+}
+
 
 static void grab_notify(GtkWidget *widget, gboolean was_grabbed)
 {
@@ -1302,6 +1362,9 @@ static void on_desktop_resize(VncConnection *conn G_GNUC_UNUSED,
     VncDisplayPrivate *priv = obj->priv;
     const VncPixelFormat *remoteFormat;
 
+    priv->last_resize_reqw = -1;
+    priv->last_resize_reqh = -1;
+
     remoteFormat = vnc_connection_get_pixel_format(priv->conn);
 
     do_framebuffer_init(opaque, remoteFormat, width, height, FALSE);
@@ -2172,6 +2235,7 @@ static void vnc_display_class_init(VncDisplayClass *klass)
     gtkwidget_class->grab_notify = grab_notify;
     gtkwidget_class->realize = realize_event;
     gtkwidget_class->destroy = vnc_display_destroy;
+    gtkwidget_class->configure_event = configure_event;
 
     object_class->finalize = vnc_display_finalize;
     object_class->get_property = vnc_display_get_property;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]