From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> The standard SPICE widget guest resize implementation does not take into account the zoom level settings in virt-viewer, because it has no knowledge of this functionality. The guest resize can, however, be done by calling spice_main_set_display() directly. This allows virt-viewer to resize the guest taking into account zoom levels. ie, if virt-viewer is run with --zoom 50 and the window is resized to 400x300, then the guest agent should be told to set its resolution to 800x600 --- src/virt-viewer-display-spice.c | 32 ++++++++++++++++++++++++++++++++ src/virt-viewer-display-spice.h | 1 + src/virt-viewer-display.c | 15 +++++++++++++++ src/virt-viewer-display.h | 2 ++ src/virt-viewer-session-spice.c | 9 +++++++++ 5 files changed, 59 insertions(+), 0 deletions(-) diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c index d3b44b8..2121105 100644 --- a/src/virt-viewer-display-spice.c +++ b/src/virt-viewer-display-spice.c @@ -36,6 +36,7 @@ G_DEFINE_TYPE (VirtViewerDisplaySpice, virt_viewer_display_spice, VIRT_VIEWER_TY struct _VirtViewerDisplaySpicePrivate { SpiceChannel *channel; + SpiceMainChannel *main_channel; SpiceDisplay *display; }; @@ -53,6 +54,7 @@ virt_viewer_display_spice_finalize(GObject *obj) g_object_unref(spice->priv->display); g_object_unref(spice->priv->channel); + g_object_unref(spice->priv->main_channel); G_OBJECT_CLASS(virt_viewer_display_spice_parent_class)->finalize(obj); } @@ -151,8 +153,33 @@ virt_viewer_display_spice_mouse_grab(SpiceDisplay *display G_GNUC_UNUSED, } +static void +virt_viewer_display_spice_size_allocate(SpiceDisplay *display G_GNUC_UNUSED, + GtkAllocation *allocation, + VirtViewerDisplaySpice *self G_GNUC_UNUSED) +{ + gdouble dw = allocation->width, dh = allocation->height; + guint zoom = 100; + guint channelid; + + if (virt_viewer_display_get_zoom(VIRT_VIEWER_DISPLAY(self))) { + zoom = virt_viewer_display_get_zoom_level(VIRT_VIEWER_DISPLAY(self)); + + dw /= ((double)zoom / 100.0); + dh /= ((double)zoom / 100.0); + } + + g_object_get(self->priv->channel, "channel-id", &channelid, NULL); + + spice_main_set_display(self->priv->main_channel, + channelid, + 0, 0, dw, dh); +} + + GtkWidget * virt_viewer_display_spice_new(SpiceChannel *channel, + SpiceMainChannel *main_channel, SpiceDisplay *display) { VirtViewerDisplaySpice *self; @@ -167,6 +194,7 @@ virt_viewer_display_spice_new(SpiceChannel *channel, "nth-display", channelid, NULL); self->priv->channel = g_object_ref(channel); + self->priv->main_channel = g_object_ref(main_channel); self->priv->display = g_object_ref(display); g_signal_connect(channel, "display-primary-create", @@ -189,6 +217,10 @@ virt_viewer_display_spice_new(SpiceChannel *channel, g_signal_connect(self->priv->display, "mouse-grab", G_CALLBACK(virt_viewer_display_spice_mouse_grab), self); + g_signal_connect(self->priv->display, + "size-allocate", + G_CALLBACK(virt_viewer_display_spice_size_allocate), self); + return GTK_WIDGET(self); } diff --git a/src/virt-viewer-display-spice.h b/src/virt-viewer-display-spice.h index 3b4e8e6..ee412a1 100644 --- a/src/virt-viewer-display-spice.h +++ b/src/virt-viewer-display-spice.h @@ -66,6 +66,7 @@ struct _VirtViewerDisplaySpiceClass { GType virt_viewer_display_spice_get_type(void); GtkWidget* virt_viewer_display_spice_new(SpiceChannel *channel, + SpiceMainChannel *main_channel, SpiceDisplay *display); G_END_DECLS diff --git a/src/virt-viewer-display.c b/src/virt-viewer-display.c index 1d2ade2..cdddc32 100644 --- a/src/virt-viewer-display.c +++ b/src/virt-viewer-display.c @@ -468,6 +468,13 @@ void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display, } +guint virt_viewer_display_get_zoom_level(VirtViewerDisplay *display) +{ + VirtViewerDisplayPrivate *priv = display->priv; + return priv->zoom_level; +} + + void virt_viewer_display_set_zoom(VirtViewerDisplay *display, gboolean zoom) { @@ -481,6 +488,14 @@ void virt_viewer_display_set_zoom(VirtViewerDisplay *display, } } + +gboolean virt_viewer_display_get_zoom(VirtViewerDisplay *display) +{ + VirtViewerDisplayPrivate *priv = display->priv; + return priv->zoom; +} + + void virt_viewer_display_send_keys(VirtViewerDisplay *display, const guint *keyvals, int nkeyvals) { diff --git a/src/virt-viewer-display.h b/src/virt-viewer-display.h index 5deb923..f7b61f6 100644 --- a/src/virt-viewer-display.h +++ b/src/virt-viewer-display.h @@ -94,8 +94,10 @@ void virt_viewer_display_get_desktop_size(VirtViewerDisplay *display, void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display, guint zoom); +guint virt_viewer_display_get_zoom_level(VirtViewerDisplay *display); void virt_viewer_display_set_zoom(VirtViewerDisplay *display, gboolean zoom); +gboolean virt_viewer_display_get_zoom(VirtViewerDisplay *display); void virt_viewer_display_send_keys(VirtViewerDisplay *display, const guint *keyvals, int nkeyvals); diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c index 7d8e2b0..200a75c 100644 --- a/src/virt-viewer-session-spice.c +++ b/src/virt-viewer-session-spice.c @@ -40,6 +40,7 @@ G_DEFINE_TYPE (VirtViewerSessionSpice, virt_viewer_session_spice, VIRT_VIEWER_TY struct _VirtViewerSessionSpicePrivate { SpiceSession *session; SpiceGtkSession *gtk_session; + SpiceMainChannel *main_channel; SpiceAudio *audio; }; @@ -103,6 +104,8 @@ virt_viewer_session_spice_dispose(GObject *obj) } if (spice->priv->audio) g_object_unref(spice->priv->audio); + if (spice->priv->main_channel) + g_object_unref(spice->priv->main_channel); G_OBJECT_CLASS(virt_viewer_session_spice_parent_class)->finalize(obj); } @@ -372,6 +375,9 @@ virt_viewer_session_spice_channel_new(SpiceSession *s, if (SPICE_IS_MAIN_CHANNEL(channel)) { g_signal_connect(channel, "channel-event", G_CALLBACK(virt_viewer_session_spice_main_channel_event), self); + if (self->priv->main_channel != NULL) + return; + self->priv->main_channel = g_object_ref(channel); } if (SPICE_IS_DISPLAY_CHANNEL(channel)) { @@ -381,6 +387,7 @@ virt_viewer_session_spice_channel_new(SpiceSession *s, DEBUG_LOG("new session channel (#%d)", id); display = virt_viewer_display_spice_new(channel, + self->priv->main_channel, spice_display_new(s, id)); virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session), @@ -414,6 +421,8 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s, g_object_get(channel, "channel-id", &id, NULL); if (SPICE_IS_MAIN_CHANNEL(channel)) { DEBUG_LOG("zap main channel"); + g_object_unref(self->priv->main_channel); + self->priv->main_channel = NULL; } if (SPICE_IS_DISPLAY_CHANNEL(channel)) { -- 1.7.7.6