[virt-tools-list] [PATCH 2/2] Implement SPICE desktop resizing that takes account of zoom level

Daniel P. Berrange berrange at redhat.com
Tue Feb 7 17:10:54 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

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




More information about the virt-tools-list mailing list