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) > { _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list