[gtk-vnc] src: add support for zoom level



commit 06d790b04191f739207593cd6339e0ebf68caa73
Author: Daniel P. Berrangé <dan berrange com>
Date:   Wed Apr 7 17:33:27 2021 +0100

    src: add support for zoom level
    
    This allows the remote desktop be to kept at a fixed scaling
    factor between 10% and 400%.
    
    Signed-off-by: Daniel P. Berrangé <berrange redhat com>

 examples/gvncviewer.c      |  9 +++--
 meson.build                |  2 +-
 src/libgtk-vnc_sym.version |  3 ++
 src/meson.build            |  1 +
 src/vncdisplay.c           | 84 +++++++++++++++++++++++++++++++++++++++++++---
 src/vncdisplay.h           |  3 ++
 6 files changed, 94 insertions(+), 8 deletions(-)
---
diff --git a/examples/gvncviewer.c b/examples/gvncviewer.c
index 50e111f..e1794b5 100644
--- a/examples/gvncviewer.c
+++ b/examples/gvncviewer.c
@@ -82,11 +82,13 @@
 
 
 static gchar **args = NULL;
+int opt_zoom = 100;
 static const GOptionEntry options [] =
     {
-        {
-            G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &args,
-            NULL, "[hostname][:display]" },
+        { "zoom", 'z', 0, G_OPTION_ARG_INT, &opt_zoom,
+          "Zoom level of window, in percentage", "ZOOM" },
+        { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &args,
+          NULL, "[hostname][:display]" },
         { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, 0 }
     };
 
@@ -891,6 +893,7 @@ int main(int argc, char **argv)
     vnc_display_set_scaling(VNC_DISPLAY(vnc), TRUE);
     vnc_display_set_allow_resize(VNC_DISPLAY(vnc), TRUE);
     vnc_display_set_lossy_encoding(VNC_DISPLAY(vnc), TRUE);
+    vnc_display_set_zoom_level(VNC_DISPLAY(vnc), opt_zoom);
 
     g_signal_connect(window, "delete-event",
                      G_CALLBACK(gtk_main_quit), NULL);
diff --git a/meson.build b/meson.build
index d48db12..e2b31d1 100644
--- a/meson.build
+++ b/meson.build
@@ -74,7 +74,7 @@ libpulse_min_version = '11.0'
 # common
 gobject_introspection_min_version = '1.56.0'
 
-
+libm_dep = cc.find_library('m', required : true)
 gobject_dep = dependency('gobject-2.0', version: '>= ' + glib_min_version)
 gio_dep = dependency('gio-2.0', version: '>= ' + glib_min_version)
 gio_unix_dep = dependency('gio-unix-2.0', version: '>= ' + glib_min_version, required: false)
diff --git a/src/libgtk-vnc_sym.version b/src/libgtk-vnc_sym.version
index a235e02..4446b20 100644
--- a/src/libgtk-vnc_sym.version
+++ b/src/libgtk-vnc_sym.version
@@ -97,6 +97,9 @@
     vnc_display_get_keep_aspect_ratio;
     vnc_display_set_keep_aspect_ratio;
 
+    vnc_display_get_zoom_level;
+    vnc_display_set_zoom_level;
+
   local:
       *;
 };
diff --git a/src/meson.build b/src/meson.build
index d3ff69b..5306fb9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -360,6 +360,7 @@ if host_machine.system() == 'linux'
 endif
 
 gtk_vnc_deps = [
+  libm_dep,
   gtk_dep,
   gvnc_dep,
   gtk_vnc_enum_headers_dep,
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 6e98630..f67448a 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -39,6 +39,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <math.h>
 
 #ifdef G_OS_WIN32
 #include <windows.h>
@@ -86,6 +87,7 @@ struct _VncDisplayPrivate
     gboolean allow_resize;
     gboolean smoothing;
     gboolean keep_aspect_ratio;
+    guint zoom_level;
 
     GSList *preferable_auths;
     GSList *preferable_vencrypt_subauths;
@@ -122,6 +124,7 @@ enum
     PROP_SMOOTHING,
     PROP_KEEP_ASPECT_RATIO,
     PROP_DEPTH,
+    PROP_ZOOM_LEVEL,
     PROP_GRAB_KEYS,
     PROP_CONNECTION,
 };
@@ -232,6 +235,9 @@ vnc_display_get_property (GObject    *object,
         case PROP_DEPTH:
             g_value_set_enum (value, vnc->priv->depth);
             break;
+        case PROP_ZOOM_LEVEL:
+            g_value_set_uint (value, vnc->priv->zoom_level);
+            break;
         case PROP_GRAB_KEYS:
             g_value_set_boxed(value, vnc->priv->vncgrabseq);
             break;
@@ -290,6 +296,9 @@ vnc_display_set_property (GObject      *object,
         case PROP_DEPTH:
             vnc_display_set_depth (vnc, g_value_get_enum (value));
             break;
+        case PROP_ZOOM_LEVEL:
+            vnc_display_set_zoom_level (vnc, g_value_get_uint (value));
+            break;
         case PROP_GRAB_KEYS:
             vnc_display_set_grab_keys(vnc, g_value_get_boxed(value));
             break;
@@ -449,8 +458,8 @@ get_render_region_info(GtkWidget *widget,
             *offsety = 0;
             *height = *winheight;
         }
-        *scalex = 1;
-        *scaley = 1;
+        *scalex = round((double)priv->zoom_level / 100.0);
+        *scaley = round((double)priv->zoom_level / 100.0);
     }
 }
 
@@ -1200,6 +1209,10 @@ static gboolean configure_event(GtkWidget *widget,
 
     fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
     fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
+
+    fbw = round(fbw * (double)priv->zoom_level / 100.0);
+    fbh = round(fbh * (double)priv->zoom_level / 100.0);
+
     if (cfg->width == fbw &&
         cfg->height == fbh) {
         VNC_DEBUG("Framebuffer already matches widget size %dx%d", fbw, fbh);
@@ -1213,8 +1226,8 @@ static gboolean configure_event(GtkWidget *widget,
     }
 
     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;
+    priv->last_resize_reqw = round(cfg->width * 100.0 / (double)priv->zoom_level);
+    priv->last_resize_reqh = round(cfg->height * 100.0 / (double)priv->zoom_level);
 
     if (priv->pending_resize_id) {
         VNC_DEBUG("Cancel pending resize timer %lu", priv->pending_resize_id);
@@ -1260,6 +1273,8 @@ static void get_preferred_width(GtkWidget *widget,
     else
         *defwidth = 0;
 
+    *defwidth = round(*defwidth * (double)priv->zoom_level / 100.0);
+
     if (priv->force_size && !priv->allow_scaling)
         *minwidth = *defwidth;
 }
@@ -1279,6 +1294,8 @@ static void get_preferred_height(GtkWidget *widget,
     else
         *defheight = 0;
 
+    *defheight = round(*defheight * (double)priv->zoom_level / 100.0);
+
     if (priv->force_size && !priv->allow_scaling)
         *minheight = *defheight;
 }
@@ -2466,6 +2483,19 @@ static void vnc_display_class_init(VncDisplayClass *klass)
                                                             G_PARAM_STATIC_NAME |
                                                             G_PARAM_STATIC_NICK |
                                                             G_PARAM_STATIC_BLURB));
+    g_object_class_install_property (object_class,
+                                     PROP_ZOOM_LEVEL,
+                                     g_param_spec_uint ( "zoom-level",
+                                                         "Zoom level",
+                                                         "Zoom percentage level",
+                                                         10,
+                                                         400,
+                                                         100,
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT |
+                                                         G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_NICK |
+                                                         G_PARAM_STATIC_BLURB));
     g_object_class_install_property (object_class,
                                      PROP_GRAB_KEYS,
                                      g_param_spec_boxed( "grab-keys",
@@ -2723,6 +2753,7 @@ static void vnc_display_init(VncDisplay *display)
     priv->allow_resize = FALSE;
     priv->smoothing = TRUE;
     priv->keep_aspect_ratio = FALSE;
+    priv->zoom_level = 100;
     priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L");
     priv->vncactiveseq = g_new0(gboolean, priv->vncgrabseq->nkeysyms);
 
@@ -3483,6 +3514,51 @@ gboolean vnc_display_get_read_only(VncDisplay *obj)
 }
 
 
+/**
+ * vnc_display_set_zoom_level:
+ * @obj: (transfer none): the VNC display widget
+ * @zoom: the zoom percentage level
+ *
+ * Requests a constant scaling factor to be applied to the remote
+ * desktop. The @zoom value is a percentage in the range 10-400.
+ *
+ * If scaling mode is not active, then this results in the remote
+ * desktop always being rendered at the requested zoom level.
+ *
+ * If scaling mode is active, then the remote desktop will be
+ * scaled to fit the widget regardless of the zoom level.
+ *
+ * In both cases, when the remote desktop size changes, the
+ * widget preferred size will reflect the zoom level.
+ */
+void vnc_display_set_zoom_level(VncDisplay *obj, guint zoom)
+{
+    g_return_if_fail (VNC_IS_DISPLAY (obj));
+
+    if (zoom < 10)
+        zoom = 10;
+    if (zoom > 400)
+        zoom = 400;
+
+    obj->priv->zoom_level = zoom;
+}
+
+/**
+ * vnc_display_get_zoom_level:
+ * @obj: (transfer none): the VNC display widget
+ *
+ * Determine the current constant scaling factor.
+ *
+ * Returns: the zoom percentage level between 10-400
+ */
+guint vnc_display_get_zoom_level(VncDisplay *obj)
+{
+    g_return_val_if_fail (VNC_IS_DISPLAY (obj), 100);
+
+    return obj->priv->zoom_level;
+}
+
+
 /**
  * vnc_display_is_pointer_absolute:
  * @obj: (transfer none): the VNC display widget
diff --git a/src/vncdisplay.h b/src/vncdisplay.h
index b6aff2d..0f1120e 100644
--- a/src/vncdisplay.h
+++ b/src/vncdisplay.h
@@ -149,6 +149,9 @@ gboolean vnc_display_get_shared_flag(VncDisplay *obj);
 void vnc_display_set_depth(VncDisplay *obj, VncDisplayDepthColor depth);
 VncDisplayDepthColor vnc_display_get_depth(VncDisplay *obj);
 
+void vnc_display_set_zoom_level(VncDisplay *obj, guint zoom);
+guint vnc_display_get_zoom_level(VncDisplay *obj);
+
 void vnc_display_force_grab(VncDisplay *obj, gboolean enable);
 
 gboolean vnc_display_is_pointer_absolute(VncDisplay *obj);


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