From 0341125ca4dd77b58de0d0a580a0bc4515a59332 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Thu, 17 May 2012 18:18:20 +0200 Subject: spice: use weak references to display channel Fix switch-host migration with Spice. spice-gtk doesn't like channels staying around when they should be destroyed/finalized, ie removed from session. spice-gtk should probably learned to handle better the case of non cooperating clients, and be able to dissociate a channel from a session without waiting for it to be disposed, but for now, the relation is quite tight. --- src/virt-viewer-display-spice.c | 17 +++++++++-------- src/virt-viewer-display-spice.h | 4 +--- src/virt-viewer-session-spice.c | 10 +++++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c index f7bb26d..0b6949b 100644 --- a/src/virt-viewer-display-spice.c +++ b/src/virt-viewer-display-spice.c @@ -35,7 +35,7 @@ G_DEFINE_TYPE (VirtViewerDisplaySpice, virt_viewer_display_spice, VIRT_VIEWER_TYPE_DISPLAY) struct _VirtViewerDisplaySpicePrivate { - SpiceChannel *channel; + SpiceChannel *channel; /* weak reference */ SpiceDisplay *display; }; @@ -54,7 +54,6 @@ virt_viewer_display_spice_finalize(GObject *obj) VirtViewerDisplaySpice *spice = VIRT_VIEWER_DISPLAY_SPICE(obj); g_object_unref(spice->priv->display); - g_object_unref(spice->priv->channel); G_OBJECT_CLASS(virt_viewer_display_spice_parent_class)->finalize(obj); } @@ -199,15 +198,14 @@ enable_accel_changed(VirtViewerApp *app, GtkWidget * virt_viewer_display_spice_new(VirtViewerSessionSpice *session, - SpiceChannel *channel, - SpiceDisplay *display) + SpiceChannel *channel) { VirtViewerDisplaySpice *self; VirtViewerApp *app; gint channelid; + SpiceSession *s; g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL); - g_return_val_if_fail(SPICE_IS_DISPLAY(display), NULL); g_object_get(channel, "channel-id", &channelid, NULL); @@ -215,15 +213,18 @@ virt_viewer_display_spice_new(VirtViewerSessionSpice *session, "session", session, "nth-display", channelid, NULL); - self->priv->channel = g_object_ref(channel); - self->priv->display = g_object_ref(display); + self->priv->channel = channel; + + g_object_get(session, "spice-session", &s, NULL); + self->priv->display = spice_display_new(s, channelid); + g_object_unref(s); g_signal_connect(channel, "display-primary-create", G_CALLBACK(primary_create), self); g_signal_connect(channel, "display-mark", G_CALLBACK(display_mark), self); - gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->priv->display)); + gtk_container_add(GTK_CONTAINER(self), g_object_ref(self->priv->display)); gtk_widget_show(GTK_WIDGET(self->priv->display)); g_object_set(self->priv->display, "grab-keyboard", TRUE, diff --git a/src/virt-viewer-display-spice.h b/src/virt-viewer-display-spice.h index eecc03e..701ed85 100644 --- a/src/virt-viewer-display-spice.h +++ b/src/virt-viewer-display-spice.h @@ -66,9 +66,7 @@ struct _VirtViewerDisplaySpiceClass { GType virt_viewer_display_spice_get_type(void); -GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, - SpiceChannel *channel, - SpiceDisplay *display); +GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, SpiceChannel *channel); G_END_DECLS diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c index d11d7a1..4a8c9cf 100644 --- a/src/virt-viewer-session-spice.c +++ b/src/virt-viewer-session-spice.c @@ -448,10 +448,8 @@ virt_viewer_session_spice_channel_new(SpiceSession *s, g_signal_emit_by_name(session, "session-connected"); DEBUG_LOG("new display channel (#%d)", id); - display = virt_viewer_display_spice_new(self, - channel, - spice_display_new(s, 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)); @@ -533,7 +531,9 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s, } if (SPICE_IS_DISPLAY_CHANNEL(channel)) { - DEBUG_LOG("zap session channel (#%d)", id); + 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 (SPICE_IS_PLAYBACK_CHANNEL(channel) && self->priv->audio) { -- cgit