[virt-tools-list] [PATCH virt-viewer 1/3] Adjust zoom level when window is resized and guest cannot be resized

Jonathon Jongsma jjongsma at redhat.com
Thu May 21 21:25:51 UTC 2015


Hi Pavel,

I must apologize. It seems that my cursory analysis of the situation
while reviewing your last patch series was based on an incorrect
assumption. I had assumed that it was caused by not tracking the zoom
level properly. But it appears this is not really the cause. Sorry about
that.

This patch series seems a bit too complex to me, so I spent a little
time debugging some things, and I *think* I understand the root of the
problem now. 

In virt_viewer_window_resize(), we initially get the "desktop size" of
the display, and we scale that by the zoom level to determine how big
the display can be. The implication is that this "desktop size" is equal
to the current resolution of the guest. (These "desktop size" variables
are also used in virt_viewer_display_get_preferred_size() to calculate
what the size request of the widget should be). In other words, the
desktop size should only be changed when we get a notification from the
guest informing us that its resolution has changed. However, later on in
virt_viewer_window_resize(), we call
virt_viewer_display_set_desktop_size() and change the size of the
desktop to the size that we calculated for the display. This seems like
a bug to me. We should not be setting the desktop size without a
notification from the guest.

In my case, while testing a VNC guest with a resolution of 1283x962, the
virt_viewer_window_resize() changed the desktop size to 700x525. Then
when resetting the zoom level to 100%, it used 700x525 as the desktop
size to calculate size request for the display widget. Since the guest
resolution was actually 1283x962, we ended up scaling a 1283x962 display
into a 700x525 widget, resulting in a tiny zoomed-out display. 

When I removed the call to virt_viewer_display_set_desktop_size() in
virt_viewer_window_resize(), things seemed to work properly. But I
didn't test thoroughly so I don't know if it might introduce other
regressions. 

Thoughts?

Jonathon


On Thu, 2015-05-21 at 19:19 +0200, Pavel Grunt wrote:
> When resizing the window and it is not possible to resize the guest
> desktop, VirtViewerDisplay acts like the zoom level was changed.
> Because this change is not stored anywhere, zoom operations are not
> working correctly (e.g. 'zooming in' decreases the zoom level).
> 
> This commit solves the problem by dynamically adjusting the zoom level
> when it is not possible to resize the guest display.
> 
> Related: rhbz#1221501
> ---
>  src/virt-viewer-display.c       |  9 +++++++++
>  src/virt-viewer-session-spice.c | 15 +++++++++++++++
>  src/virt-viewer-session.c       | 11 +++++++++++
>  src/virt-viewer-session.h       |  2 ++
>  src/virt-viewer-window.c        | 11 +++++++++++
>  5 files changed, 48 insertions(+)
> 
> diff --git a/src/virt-viewer-display.c b/src/virt-viewer-display.c
> index 3efe24c..3bdc9b8 100644
> --- a/src/virt-viewer-display.c
> +++ b/src/virt-viewer-display.c
> @@ -519,6 +519,7 @@ virt_viewer_display_size_allocate(GtkWidget *widget,
>      desktopAspect = (double)priv->desktopWidth / (double)priv->desktopHeight;
>  
>      if (child && gtk_widget_get_visible(child)) {
> +        guint new_zoom;
>          border_width = gtk_container_get_border_width(GTK_CONTAINER(display));
>  
>          width  = MAX(1, allocation->width - 2 * border_width);
> @@ -532,6 +533,14 @@ virt_viewer_display_size_allocate(GtkWidget *widget,
>              child_allocation.width = width;
>              child_allocation.height = round(width / desktopAspect);
>          }
> +        new_zoom = round((double) NORMAL_ZOOM_LEVEL * child_allocation.width / priv->desktopWidth);
> +
> +        if (!virt_viewer_session_can_resize_guest(priv->session) && new_zoom != priv->zoom_level) {
> +            g_debug("cannot resize guest, changing zoom level from %d to %d",
> +                    priv->zoom_level, new_zoom);
> +            priv->zoom_level = new_zoom;
> +            g_object_notify(G_OBJECT(display), "zoom-level");
> +        }
>  
>          child_allocation.x = 0.5 * (width - child_allocation.width) + allocation->x + border_width;
>          child_allocation.y = 0.5 * (height - child_allocation.height) + allocation->y + border_width;
> diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
> index b69faa6..4256d4c 100644
> --- a/src/virt-viewer-session-spice.c
> +++ b/src/virt-viewer-session-spice.c
> @@ -165,6 +165,20 @@ virt_viewer_session_spice_can_share_folder(VirtViewerSession *session)
>      return spice_session_has_channel_type(self->priv->session, SPICE_CHANNEL_WEBDAV);
>  }
>  
> +static gboolean
> +virt_viewer_session_spice_can_resize_guest(VirtViewerSession *session)
> +{
> +    gboolean agent_connected;
> +
> +    g_return_val_if_fail(VIRT_VIEWER_IS_SESSION_SPICE(session), FALSE);
> +
> +    g_object_get(virt_viewer_session_spice_get_main_channel(VIRT_VIEWER_SESSION_SPICE(session)),
> +                 "agent-connected", &agent_connected,
> +                 NULL);
> +
> +    return agent_connected;
> +}
> +
>  static void
>  virt_viewer_session_spice_class_init(VirtViewerSessionSpiceClass *klass)
>  {
> @@ -186,6 +200,7 @@ virt_viewer_session_spice_class_init(VirtViewerSessionSpiceClass *klass)
>      dclass->mime_type = virt_viewer_session_spice_mime_type;
>      dclass->apply_monitor_geometry = virt_viewer_session_spice_apply_monitor_geometry;
>      dclass->can_share_folder = virt_viewer_session_spice_can_share_folder;
> +    dclass->can_resize_guest = virt_viewer_session_spice_can_resize_guest;
>  
>      g_type_class_add_private(klass, sizeof(VirtViewerSessionSpicePrivate));
>  
> diff --git a/src/virt-viewer-session.c b/src/virt-viewer-session.c
> index 131a500..fccaa19 100644
> --- a/src/virt-viewer-session.c
> +++ b/src/virt-viewer-session.c
> @@ -678,6 +678,17 @@ gboolean virt_viewer_session_can_share_folder(VirtViewerSession *self)
>      return klass->can_share_folder ? klass->can_share_folder(self) : FALSE;
>  }
>  
> +gboolean virt_viewer_session_can_resize_guest(VirtViewerSession *self)
> +{
> +    VirtViewerSessionClass *klass;
> +
> +    g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
> +
> +    klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
> +
> +    return klass->can_resize_guest ? klass->can_resize_guest(self) : FALSE;
> +}
> +
>  /*
>   * Local variables:
>   *  c-indent-level: 4
> diff --git a/src/virt-viewer-session.h b/src/virt-viewer-session.h
> index 533d79a..4afc176 100644
> --- a/src/virt-viewer-session.h
> +++ b/src/virt-viewer-session.h
> @@ -74,6 +74,7 @@ struct _VirtViewerSessionClass {
>      void (* smartcard_insert) (VirtViewerSession* session);
>      void (* smartcard_remove) (VirtViewerSession* session);
>      const gchar* (* mime_type) (VirtViewerSession* session);
> +    gboolean (*can_resize_guest)(VirtViewerSession *session);
>  
>      /* signals */
>      void (*session_connected)(VirtViewerSession *session);
> @@ -132,6 +133,7 @@ gchar* virt_viewer_session_get_uri(VirtViewerSession *self);
>  void virt_viewer_session_set_file(VirtViewerSession *self, VirtViewerFile *file);
>  VirtViewerFile* virt_viewer_session_get_file(VirtViewerSession *self);
>  gboolean virt_viewer_session_can_share_folder(VirtViewerSession *self);
> +gboolean virt_viewer_session_can_resize_guest(VirtViewerSession *self);
>  
>  G_END_DECLS
>  
> diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c
> index d67fbc1..2a72207 100644
> --- a/src/virt-viewer-window.c
> +++ b/src/virt-viewer-window.c
> @@ -1327,6 +1327,15 @@ display_show_hint(VirtViewerDisplay *display,
>  
>      gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(self->priv->builder, "menu-file-screenshot")), hint);
>  }
> +
> +static void
> +display_zoom_changed(VirtViewerDisplay *display,
> +                     GParamSpec *pspec G_GNUC_UNUSED,
> +                     VirtViewerWindow *self)
> +{
> +    self->priv->zoomlevel = virt_viewer_display_get_zoom_level(display);
> +}
> +
>  static gboolean
>  window_key_pressed (GtkWidget *widget G_GNUC_UNUSED,
>                      GdkEvent  *event,
> @@ -1381,6 +1390,8 @@ virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *displa
>                                            G_CALLBACK(virt_viewer_window_desktop_resize), self, 0);
>          virt_viewer_signal_connect_object(display, "notify::show-hint",
>                                            G_CALLBACK(display_show_hint), self, 0);
> +        virt_viewer_signal_connect_object(display, "notify::zoom-level",
> +                                          G_CALLBACK(display_zoom_changed), self, 0);
>  
>          display_show_hint(display, NULL, self);
>  





More information about the virt-tools-list mailing list