[virt-tools-list] [PATCH virt-viewer 3/3] virt-viewer-window: Check for maximum zoom level

Jonathon Jongsma jjongsma at redhat.com
Mon May 18 22:09:17 UTC 2015


Hi Pavel,

To me, it feels a little bit like we're solving the wrong problem here.
I spent a little bit of time testing the bug listed below, and here are
my observations:

- When we use e.g. --zoom=200 at startup, virt-viewer tries to make the
window 2x as big as the guest resolution.
- if this window size would be greater than the size of the client
monitor, gnome-shell will prevent the window from getting that large and
will limit it to the size of the client monitor.
- From here, the behavior between vnc and spice-gtk (with vdagent)
differs:

spice-gtk:
- the window is displayed at the requested zoom level, but the guest
resolution is resized smaller to fit within the client monitor (taking
into account the zoom factor)
- clicking "view > zoom > normal size" will shrink the display to this
smaller size and show it at 100% scale. 
- This doesn't really seem like a bug to me

VNC:
- Since the client cannot resize the resolution of a guest in VNC,
resizing a window is the same as zooming it. If gnome-shell limits the
window to smaller than requested, it is effectively reducing the zoom
level. But the application seems to think its zoom level is still 200%.
- clicking "view > zoom > normal size" shrinks the display and scales it
to a value less than 100% because it unscales the display by 200% (even
though its actual zoom level is really only e.g. 150%).
- In theory this all applies to spice-gtk without a vdagent as well.

So I think that this bug could be fixed by unscaling the display by the
actual effective zoom level (150% in the example above) instead of the
zoom level given on the command line (200%). That seems simpler than
adding new accessors and calculating maximum zoom levels, etc.

What do you think?

Jonathon



On Thu, 2015-05-14 at 16:36 +0200, Pavel Grunt wrote:
> On some desktop environment (e.g. gnome-shell) zooming in can cause
> resizing of the guest's display, because the window manager of DE
> changes the aspect ratio of the window instead when the window could
> exceed the size of the monitor. Other DEs (e.g. GNOME, Xfce) allow
> windows to exceed size of the monitor, so the resize does not happen,
> but part of the guest display is not visible.
> 
> This commit avoids 'zooming in' when it can cause the resizing or
> the exceeding of monitor. The maximum zoom level of the window is
> calculated with respect to dimensions of the monitor where the window
> is placed.
> 
> Resolves: rhbz#1221501
> ---
>  src/virt-viewer-window.c | 49 +++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 44 insertions(+), 5 deletions(-)
> 
> diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c
> index 0ed4b5f..899efc2 100644
> --- a/src/virt-viewer-window.c
> +++ b/src/virt-viewer-window.c
> @@ -71,6 +71,7 @@ static void virt_viewer_window_toolbar_setup(VirtViewerWindow *self);
>  static GtkMenu* virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self);
>  static void virt_viewer_window_get_minimal_dimensions(VirtViewerWindow *self, guint *width, guint *height);
>  static gint virt_viewer_window_get_minimal_zoom_level(VirtViewerWindow *self);
> +static gint virt_viewer_window_get_maximum_zoom_level(VirtViewerWindow *self);
>  static void virt_viewer_window_get_monitor_geometry(VirtViewerWindow *self, GdkRectangle *geometry);
>  
>  G_DEFINE_TYPE (VirtViewerWindow, virt_viewer_window, G_TYPE_OBJECT)
> @@ -1447,7 +1448,6 @@ void
>  virt_viewer_window_set_zoom_level(VirtViewerWindow *self, gint zoom_level)
>  {
>      VirtViewerWindowPrivate *priv;
> -    gint min_zoom;
>  
>      g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self));
>      priv = self->priv;
> @@ -1461,10 +1461,12 @@ virt_viewer_window_set_zoom_level(VirtViewerWindow *self, gint zoom_level)
>      if (!priv->display)
>          return;
>  
> -    min_zoom = virt_viewer_window_get_minimal_zoom_level(self);
> -    if (min_zoom > priv->zoomlevel) {
> -        g_debug("Cannot set zoom level %d, using %d", priv->zoomlevel, min_zoom);
> -        priv->zoomlevel = min_zoom;
> +    zoom_level = CLAMP(priv->zoomlevel,
> +                       virt_viewer_window_get_minimal_zoom_level(self),
> +                       virt_viewer_window_get_maximum_zoom_level(self));
> +    if (zoom_level != priv->zoomlevel) {
> +        g_debug("Cannot set zoom level %d, using %d", priv->zoomlevel, zoom_level);
> +        priv->zoomlevel = zoom_level;
>      }
>  
>      if (priv->zoomlevel == virt_viewer_display_get_zoom_level(priv->display)) {
> @@ -1588,6 +1590,43 @@ virt_viewer_window_get_minimal_zoom_level(VirtViewerWindow *self)
>      return CLAMP(zoom * ZOOM_STEP, MIN_ZOOM_LEVEL, NORMAL_ZOOM_LEVEL);
>  }
>  
> +/**
> + * virt_viewer_window_get_maximum_zoom_level:
> + * @self: a #VirtViewerWindow
> + *
> + * Calculates the zoom level with respect to the size of monitor
> + *
> + * Returns: maximum possible zoom level (multiple of ZOOM_STEP)
> + */
> +static gint
> +virt_viewer_window_get_maximum_zoom_level(VirtViewerWindow *self)
> +{
> +    GdkRectangle monitor;
> +    guint width, height; /* desktop dimensions */
> +    guint menu_height;
> +    gint zoom;
> +    double width_ratio, height_ratio;
> +
> +    g_return_val_if_fail(VIRT_VIEWER_IS_WINDOW(self) &&
> +                         self->priv->display != NULL, MAX_ZOOM_LEVEL);
> +
> +    if (self->priv->fullscreen)
> +        return MAX_ZOOM_LEVEL;
> +
> +    virt_viewer_window_get_monitor_geometry(self, &monitor);
> +    virt_viewer_display_get_desktop_size(virt_viewer_window_get_display(self), &width, &height);
> +    /* it is neccessary to add 'menu_height' to 'height' otherwise window can exceed monitor */
> +    virt_viewer_window_top_menu_dimensions(self, NULL, &menu_height);
> +
> +    width_ratio = (double) monitor.width / width;
> +    height_ratio = (double) monitor.height / (height + menu_height);
> +
> +    zoom = floor(10 * MIN(width_ratio, height_ratio));
> +
> +    /* make sure that the returned zoom level is in the range from NORMAL_ZOOM_LEVEL to MAX_ZOOM_LEVEL */
> +    return CLAMP(zoom * ZOOM_STEP, NORMAL_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
> +}
> +
>  static void
>  virt_viewer_window_get_monitor_geometry(VirtViewerWindow *self, GdkRectangle *geometry)
>  {





More information about the virt-tools-list mailing list