[gtk-vnc] src: add option to keep aspect ratio when scaling the display



commit 23166b946d3dd0de42f1d5f25fd8fc04d38dd2c8
Author: Daniel P. Berrangé <dan berrange com>
Date:   Tue Mar 23 14:50:12 2021 +0000

    src: add option to keep aspect ratio when scaling the display
    
    Currently applications like virt-viewer will apply their own workaround
    to keep the aspect ratio by fixing the widget size. Since applications
    want this behaviour, we should support it directly.
    
    Signed-off-by: Daniel P. Berrangé <berrange redhat com>

 src/libgtk-vnc_sym.version |  3 ++
 src/vncdisplay.c           | 77 ++++++++++++++++++++++++++++++++++++++++++++++
 src/vncdisplay.h           |  3 ++
 3 files changed, 83 insertions(+)
---
diff --git a/src/libgtk-vnc_sym.version b/src/libgtk-vnc_sym.version
index 838b79c..a235e02 100644
--- a/src/libgtk-vnc_sym.version
+++ b/src/libgtk-vnc_sym.version
@@ -94,6 +94,9 @@
 
     vnc_grab_sequence_get_nth;
 
+    vnc_display_get_keep_aspect_ratio;
+    vnc_display_set_keep_aspect_ratio;
+
   local:
       *;
 };
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 0bac3af..cc102b9 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -85,6 +85,7 @@ struct _VncDisplayPrivate
     gboolean force_size;
     gboolean allow_resize;
     gboolean smoothing;
+    gboolean keep_aspect_ratio;
 
     GSList *preferable_auths;
     GSList *preferable_vencrypt_subauths;
@@ -119,6 +120,7 @@ enum
     PROP_FORCE_SIZE,
     PROP_ALLOW_RESIZE,
     PROP_SMOOTHING,
+    PROP_KEEP_ASPECT_RATIO,
     PROP_DEPTH,
     PROP_GRAB_KEYS,
     PROP_CONNECTION,
@@ -224,6 +226,9 @@ vnc_display_get_property (GObject    *object,
         case PROP_SMOOTHING:
             g_value_set_boolean (value, vnc->priv->smoothing);
             break;
+        case PROP_KEEP_ASPECT_RATIO:
+            g_value_set_boolean (value, vnc->priv->keep_aspect_ratio);
+            break;
         case PROP_DEPTH:
             g_value_set_enum (value, vnc->priv->depth);
             break;
@@ -279,6 +284,9 @@ vnc_display_set_property (GObject      *object,
         case PROP_SMOOTHING:
             vnc_display_set_smoothing (vnc, g_value_get_boolean (value));
             break;
+        case PROP_KEEP_ASPECT_RATIO:
+            vnc_display_set_keep_aspect_ratio (vnc, g_value_get_boolean (value));
+            break;
         case PROP_DEPTH:
             vnc_display_set_depth (vnc, g_value_get_enum (value));
             break;
@@ -414,6 +422,18 @@ get_render_region_info(GtkWidget *widget,
         *height = *winheight;
         *scalex = (double)*winwidth / (double)*fbwidth;
         *scaley = (double)*winheight / (double)*fbheight;
+
+        if (priv->keep_aspect_ratio) {
+            if (*scalex > *scaley) {
+                *scalex = *scaley;
+                *width = *fbwidth * *scalex;
+                *offsetx = (*winwidth - *width) / 2;
+            } else if (*scalex < *scaley) {
+                *scaley = *scalex;
+                *height = *fbheight * *scaley;
+                *offsety = (*winheight - *height) / 2;
+            }
+        }
     } else {
         if (*winwidth > *fbwidth) {
             *offsetx = (*winwidth - *fbwidth) / 2;
@@ -2407,6 +2427,18 @@ static void vnc_display_class_init(VncDisplayClass *klass)
                                                             G_PARAM_STATIC_NICK |
                                                             G_PARAM_STATIC_BLURB));
 
+    g_object_class_install_property (object_class,
+                                     PROP_KEEP_ASPECT_RATIO,
+                                     g_param_spec_boolean ( "keep-aspect-ratio",
+                                                            "Keep aspect ratio",
+                                                            "Keep the aspect ratio matching the framebuffer 
when scaling",
+                                                            FALSE,
+                                                            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_DEPTH,
                                      g_param_spec_enum    ( "depth",
@@ -2675,6 +2707,7 @@ static void vnc_display_init(VncDisplay *display)
     priv->force_size = TRUE;
     priv->allow_resize = FALSE;
     priv->smoothing = TRUE;
+    priv->keep_aspect_ratio = FALSE;
     priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L");
     priv->vncactiveseq = g_new0(gboolean, priv->vncgrabseq->nkeysyms);
 
@@ -3180,6 +3213,33 @@ void vnc_display_set_smoothing(VncDisplay *obj, gboolean enabled)
 }
 
 
+/**
+ * vnc_display_keep_aspect_ratio:
+ * @obj: (transfer none): the VNC display widget
+ * @enabled: TRUE to keep aspect ratio, FALSE otherwise
+ *
+ * Set whether the aspect ratio of the framebuffer is preserved
+ * when scaling.
+ */
+void vnc_display_set_keep_aspect_ratio(VncDisplay *obj, gboolean enabled)
+{
+    int ww, wh;
+
+    g_return_if_fail (VNC_IS_DISPLAY (obj));
+    obj->priv->keep_aspect_ratio = enabled;
+
+    if (obj->priv->fb != NULL) {
+        GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(obj));
+
+        if (window != NULL) {
+            ww = gdk_window_get_width(gtk_widget_get_window(GTK_WIDGET(obj)));
+            wh = gdk_window_get_height(gtk_widget_get_window(GTK_WIDGET(obj)));
+            gtk_widget_queue_draw_area(GTK_WIDGET(obj), 0, 0, ww, wh);
+        }
+    }
+}
+
+
 /**
  * vnc_display_set_depth:
  * @obj: (transfer none): the VNC display widget
@@ -3272,6 +3332,23 @@ gboolean vnc_display_get_smoothing(VncDisplay *obj)
 }
 
 
+/**
+ * vnc_display_get_keep_aspect_ratio:
+ * @obj: (transfer none): the VNC display widget
+ *
+ * Determine whether the framebuffer aspect ratio is preserved
+ * when scaling.
+ *
+ * Returns: TRUE if aspect ratio is preserved, FALSE otherwise
+ */
+gboolean vnc_display_get_keep_aspect_ratio(VncDisplay *obj)
+{
+    g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
+
+    return obj->priv->keep_aspect_ratio;
+}
+
+
 /**
  * vnc_display_get_scaling:
  * @obj: (transfer none): the VNC display widget
diff --git a/src/vncdisplay.h b/src/vncdisplay.h
index 8f870b7..b6aff2d 100644
--- a/src/vncdisplay.h
+++ b/src/vncdisplay.h
@@ -140,6 +140,9 @@ gboolean vnc_display_get_allow_resize(VncDisplay *obj);
 void vnc_display_set_smoothing(VncDisplay *obj, gboolean enable);
 gboolean vnc_display_get_smoothing(VncDisplay *obj);
 
+void vnc_display_set_keep_aspect_ratio(VncDisplay *obj, gboolean enable);
+gboolean vnc_display_get_keep_aspect_ratio(VncDisplay *obj);
+
 void vnc_display_set_shared_flag(VncDisplay *obj, gboolean shared);
 gboolean vnc_display_get_shared_flag(VncDisplay *obj);
 


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