[virt-tools-list] [PATCH virt-viewer 15/19] Hook up handling of Monitors

Marc-André Lureau marcandre.lureau at gmail.com
Mon Jul 16 16:57:50 UTC 2012


Rely on spice-gtk display channel monitors property to manage
displays. The same display channel may now provide several monitors,
the SpiceDisplay widget must be told which monitor to display
---
 src/virt-viewer-display-spice.c |   17 +++----
 src/virt-viewer-display-spice.h |    2 +-
 src/virt-viewer-session-spice.c |   98 +++++++++++++++++++++++++++++++++++----
 3 files changed, 98 insertions(+), 19 deletions(-)

diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c
index 53430dd..ca74c1a 100644
--- a/src/virt-viewer-display-spice.c
+++ b/src/virt-viewer-display-spice.c
@@ -172,7 +172,7 @@ virt_viewer_display_spice_size_allocate(VirtViewerDisplaySpice *self,
 {
     gdouble dw = allocation->width, dh = allocation->height;
     guint zoom = 100;
-    guint channelid;
+    guint nth;
 
     if (virt_viewer_display_get_auto_resize(VIRT_VIEWER_DISPLAY(self)) == FALSE)
         return;
@@ -187,13 +187,11 @@ virt_viewer_display_spice_size_allocate(VirtViewerDisplaySpice *self,
         dh /= ((double)zoom / 100.0);
     }
 
-    g_object_get(self->priv->channel, "channel-id", &channelid, NULL);
+    g_object_get(self, "nth-display", &nth, NULL);
 
     SpiceMainChannel *main_channel = virt_viewer_session_spice_get_main_channel(
         VIRT_VIEWER_SESSION_SPICE(virt_viewer_display_get_session(VIRT_VIEWER_DISPLAY(self))));
-    spice_main_set_display(main_channel,
-                           channelid,
-                           0, 0, dw, dh);
+    spice_main_set_display(main_channel, nth, 0, 0, dw, dh);
 }
 
 static void
@@ -212,7 +210,8 @@ enable_accel_changed(VirtViewerApp *app,
 
 GtkWidget *
 virt_viewer_display_spice_new(VirtViewerSessionSpice *session,
-                              SpiceChannel *channel)
+                              SpiceChannel *channel,
+                              gint monitorid)
 {
     VirtViewerDisplaySpice *self;
     VirtViewerApp *app;
@@ -222,15 +221,17 @@ virt_viewer_display_spice_new(VirtViewerSessionSpice *session,
     g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL);
 
     g_object_get(channel, "channel-id", &channelid, NULL);
+    // We don't allow monitorid != 0 && channelid != 0
+    g_return_val_if_fail(channelid == 0 || monitorid == 0, NULL);
 
     self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE,
                         "session", session,
-                        "nth-display", channelid,
+                        "nth-display", channelid + monitorid,
                         NULL);
     self->priv->channel = channel;
 
     g_object_get(session, "spice-session", &s, NULL);
-    self->priv->display = spice_display_new(s, channelid);
+    self->priv->display = spice_display_new_with_monitor(s, channelid, monitorid);
     g_object_unref(s);
 
     virt_viewer_signal_connect_object(self->priv->display, "notify::ready",
diff --git a/src/virt-viewer-display-spice.h b/src/virt-viewer-display-spice.h
index 701ed85..c2013ec 100644
--- a/src/virt-viewer-display-spice.h
+++ b/src/virt-viewer-display-spice.h
@@ -66,7 +66,7 @@ struct _VirtViewerDisplaySpiceClass {
 
 GType virt_viewer_display_spice_get_type(void);
 
-GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, SpiceChannel *channel);
+GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, SpiceChannel *channel, gint monitorid);
 
 G_END_DECLS
 
diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
index 6577237..0df11ef 100644
--- a/src/virt-viewer-session-spice.c
+++ b/src/virt-viewer-session-spice.c
@@ -414,6 +414,80 @@ agent_connected_changed(SpiceChannel *cmain,
 }
 
 static void
+destroy_display(gpointer data)
+{
+    VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(data);
+    VirtViewerSession *session = virt_viewer_display_get_session(display);
+
+    DEBUG_LOG("Destroying spice display %p", display);
+    virt_viewer_session_remove_display(session, display);
+    g_object_unref(display);
+}
+
+static void
+virt_viewer_session_spice_display_monitors(SpiceChannel *channel,
+                                           GParamSpec *pspec G_GNUC_UNUSED,
+                                           VirtViewerSessionSpice *self)
+{
+    GArray *monitors = NULL;
+    GPtrArray *displays = NULL;
+    GtkWidget *display;
+    guint i, monitors_max;
+
+    g_object_get(channel,
+                 "monitors", &monitors,
+                 "monitors-max", &monitors_max,
+                 NULL);
+    g_return_if_fail(monitors != NULL);
+    g_return_if_fail(monitors->len <= monitors_max);
+
+    displays = g_object_get_data(G_OBJECT(channel), "virt-viewer-displays");
+    if (displays == NULL) {
+        displays = g_ptr_array_new();
+#if GLIB_CHECK_VERSION(2, 22, 0)
+        g_ptr_array_set_free_func(displays, destroy_display);
+        g_object_set_data_full(G_OBJECT(channel), "virt-viewer-displays",
+                               displays, (GDestroyNotify)g_ptr_array_unref);
+#endif
+    }
+
+    g_ptr_array_set_size(displays, monitors_max);
+
+    for (i = 0; i < monitors_max; i++) {
+        display = g_ptr_array_index(displays, i);
+        if (display == NULL) {
+            display = virt_viewer_display_spice_new(self, channel, i);
+            DEBUG_LOG("creating spice display (#:%d)", i);
+            g_ptr_array_index(displays, i) = g_object_ref(display);
+        }
+
+        g_object_freeze_notify(G_OBJECT(display));
+        virt_viewer_display_set_enabled(VIRT_VIEWER_DISPLAY(display), FALSE);
+        virt_viewer_session_add_display(VIRT_VIEWER_SESSION(self),
+                                        VIRT_VIEWER_DISPLAY(display));
+    }
+
+    for (i = 0; i < monitors->len; i++) {
+        SpiceDisplayMonitorConfig *c = &g_array_index(monitors, SpiceDisplayMonitorConfig, i);
+        display = g_ptr_array_index(displays, c->id);
+        g_return_if_fail(display != NULL);
+
+        if (c->width == 0 || c->width == 0)
+            continue;
+
+        virt_viewer_display_set_enabled(VIRT_VIEWER_DISPLAY(display), TRUE);
+        virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(display),
+                                             c->width, c->height);
+    }
+
+    for (i = 0; i < monitors_max; i++)
+        g_object_thaw_notify(g_ptr_array_index(displays, i));
+
+    g_clear_pointer(&monitors, g_array_unref);
+
+}
+
+static void
 virt_viewer_session_spice_channel_new(SpiceSession *s,
                                       SpiceChannel *channel,
                                       VirtViewerSession *session)
@@ -441,20 +515,17 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
 
         g_signal_connect(channel, "notify::agent-connected", G_CALLBACK(agent_connected_changed),  self);
         agent_connected_changed(channel, NULL, self);
+
+        g_signal_emit_by_name(session, "session-connected");
     }
 
     if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
-        GtkWidget *display;
-
-        g_signal_emit_by_name(session, "session-connected");
+        g_signal_emit_by_name(session, "session-initialized");
 
-        DEBUG_LOG("new display channel (#%d)", id);
-        display = virt_viewer_display_spice_new(self, channel);
-        g_object_set_data(G_OBJECT(channel), "virt-viewer-display", display);
-        virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session),
-                                        VIRT_VIEWER_DISPLAY(display));
+        g_signal_connect(channel, "notify::monitors",
+                         G_CALLBACK(virt_viewer_session_spice_display_monitors), self);
 
-        g_signal_emit_by_name(session, "session-initialized");
+        spice_channel_connect(channel);
     }
 
     if (SPICE_IS_INPUTS_CHANNEL(channel)) {
@@ -538,7 +609,14 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
     if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
         VirtViewerDisplay *display = g_object_get_data(G_OBJECT(channel), "virt-viewer-display");
         DEBUG_LOG("zap display channel (#%d, %p)", id, display);
-        virt_viewer_session_remove_display(session, display);
+#if !GLIB_CHECK_VERSION(2, 22, 0)
+        GPtrArray *displays = g_object_get_data(G_OBJECT(channel), "virt-viewer-displays");
+        if (displays) {
+            g_ptr_array_foreach(displays, (GFunc)destroy_display, NULL);
+            g_ptr_array_free(displays, TRUE);
+            g_object_set_data(channel, "virt-viewer-displays", NULL);
+        }
+#endif
     }
 
     if (SPICE_IS_PLAYBACK_CHANNEL(channel) && self->priv->audio) {
-- 
1.7.10.4




More information about the virt-tools-list mailing list