diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c index d3b44b8..f27cbf7 100644 --- a/src/virt-viewer-display-spice.c +++ b/src/virt-viewer-display-spice.c @@ -151,8 +151,35 @@ 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); + + 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); +} + + GtkWidget * -virt_viewer_display_spice_new(SpiceChannel *channel, +virt_viewer_display_spice_new(VirtViewerSessionSpice *session, + SpiceChannel *channel, SpiceDisplay *display) { VirtViewerDisplaySpice *self; @@ -164,6 +191,7 @@ virt_viewer_display_spice_new(SpiceChannel *channel, g_object_get(channel, "channel-id", &channelid, NULL); self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE, + "session", session, "nth-display", channelid, NULL); self->priv->channel = g_object_ref(channel); @@ -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..eecc03e 100644 --- a/src/virt-viewer-display-spice.h +++ b/src/virt-viewer-display-spice.h @@ -29,6 +29,7 @@ #include #include "virt-viewer-display.h" +#include "virt-viewer-session-spice.h" G_BEGIN_DECLS @@ -65,7 +66,8 @@ struct _VirtViewerDisplaySpiceClass { GType virt_viewer_display_spice_get_type(void); -GtkWidget* virt_viewer_display_spice_new(SpiceChannel *channel, +GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, + SpiceChannel *channel, SpiceDisplay *display); G_END_DECLS diff --git a/src/virt-viewer-display.c b/src/virt-viewer-display.c index 1d2ade2..a62c289 100644 --- a/src/virt-viewer-display.c +++ b/src/virt-viewer-display.c @@ -26,6 +26,7 @@ #include +#include "virt-viewer-session.h" #include "virt-viewer-display.h" #include "virt-viewer-util.h" @@ -40,6 +41,7 @@ struct _VirtViewerDisplayPrivate gboolean zoom; gint nth_display; gint show_hint; + VirtViewerSession *session; }; static void virt_viewer_display_size_request(GtkWidget *widget, @@ -75,6 +77,7 @@ enum { PROP_ZOOM, PROP_ZOOM_LEVEL, PROP_SHOW_HINT, + PROP_SESSION, }; static void @@ -154,6 +157,15 @@ virt_viewer_display_class_init(VirtViewerDisplayClass *class) 0, G_PARAM_READABLE)); + g_object_class_install_property(object_class, + PROP_SESSION, + g_param_spec_object("session", + "Session", + "VirtSession", + VIRT_VIEWER_TYPE_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_signal_new("display-pointer-grab", G_OBJECT_CLASS_TYPE(object_class), @@ -252,6 +264,11 @@ virt_viewer_display_set_property(GObject *object, case PROP_NTH_DISPLAY: priv->nth_display = g_value_get_int(value); break; + case PROP_SESSION: + g_warn_if_fail(priv->session == NULL); + priv->session = g_value_dup_object(value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -280,6 +297,9 @@ virt_viewer_display_get_property(GObject *object, case PROP_SHOW_HINT: g_value_set_int(value, priv->show_hint); break; + case PROP_SESSION: + g_value_set_object(value, virt_viewer_display_get_session(display)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -468,6 +488,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 +508,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) { @@ -509,6 +544,13 @@ void virt_viewer_display_set_show_hint(VirtViewerDisplay *self, gint hint) g_object_notify(G_OBJECT(self), "show-hint"); } +VirtViewerSession* virt_viewer_display_get_session(VirtViewerDisplay *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), NULL); + + return self->priv->session; +} + /* * Local variables: * c-indent-level: 4 diff --git a/src/virt-viewer-display.h b/src/virt-viewer-display.h index 5deb923..b5a3266 100644 --- a/src/virt-viewer-display.h +++ b/src/virt-viewer-display.h @@ -45,6 +45,9 @@ G_BEGIN_DECLS #define VIRT_VIEWER_DISPLAY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_DISPLAY, VirtViewerDisplayClass)) +typedef struct _VirtViewerSession VirtViewerSession; +typedef struct _VirtViewerSessionClass VirtViewerSessionClass; + typedef struct _VirtViewerDisplay VirtViewerDisplay; typedef struct _VirtViewerDisplayClass VirtViewerDisplayClass; typedef struct _VirtViewerDisplayPrivate VirtViewerDisplayPrivate; @@ -94,13 +97,16 @@ 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); GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay *display); void virt_viewer_display_set_show_hint(VirtViewerDisplay *display, gint hint); +VirtViewerSession* virt_viewer_display_get_session(VirtViewerDisplay *display); G_END_DECLS diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c index 7d8e2b0..66eabbb 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); } @@ -370,8 +373,16 @@ virt_viewer_session_spice_channel_new(SpiceSession *s, g_object_get(channel, "channel-id", &id, NULL); if (SPICE_IS_MAIN_CHANNEL(channel)) { + if (self->priv->main_channel != NULL) { + /* FIXME: use telepathy-glib g_signal_connect_object to automatically disconnect.. */ + g_signal_handlers_disconnect_by_func(self->priv->main_channel, + virt_viewer_session_spice_main_channel_event, self); + g_object_unref(self->priv->main_channel); + } + g_signal_connect(channel, "channel-event", G_CALLBACK(virt_viewer_session_spice_main_channel_event), self); + self->priv->main_channel = g_object_ref(channel); } if (SPICE_IS_DISPLAY_CHANNEL(channel)) { @@ -380,7 +391,8 @@ virt_viewer_session_spice_channel_new(SpiceSession *s, g_signal_emit_by_name(session, "session-connected"); DEBUG_LOG("new session channel (#%d)", id); - display = virt_viewer_display_spice_new(channel, + display = virt_viewer_display_spice_new(self, + channel, spice_display_new(s, id)); virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session), @@ -414,6 +426,10 @@ 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"); + if (channel == SPICE_CHANNEL(self->priv->main_channel)) { + g_object_unref(self->priv->main_channel); + self->priv->main_channel = NULL; + } } if (SPICE_IS_DISPLAY_CHANNEL(channel)) { @@ -439,6 +455,14 @@ virt_viewer_session_spice_new(void) return VIRT_VIEWER_SESSION(self); } +SpiceMainChannel* +virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_SESSION_SPICE(self), NULL); + + return self->priv->main_channel; +} + /* * Local variables: * c-indent-level: 4 diff --git a/src/virt-viewer-session-spice.h b/src/virt-viewer-session-spice.h index 49f18d2..19941a0 100644 --- a/src/virt-viewer-session-spice.h +++ b/src/virt-viewer-session-spice.h @@ -66,6 +66,7 @@ struct _VirtViewerSessionSpiceClass { GType virt_viewer_session_spice_get_type(void); VirtViewerSession* virt_viewer_session_spice_new(void); +SpiceMainChannel* virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self); G_END_DECLS diff --git a/src/virt-viewer-session.h b/src/virt-viewer-session.h index b10e2e2..9a4933e 100644 --- a/src/virt-viewer-session.h +++ b/src/virt-viewer-session.h @@ -47,8 +47,6 @@ G_BEGIN_DECLS #define VIRT_VIEWER_SESSION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_SESSION, VirtViewerSessionClass)) -typedef struct _VirtViewerSession VirtViewerSession; -typedef struct _VirtViewerSessionClass VirtViewerSessionClass; typedef struct _VirtViewerSessionPrivate VirtViewerSessionPrivate; typedef struct _VirtViewerSessionChannel VirtViewerSessionChannel;