Hook up handling of Monitors

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
This commit is contained in:
Marc-André Lureau 2012-07-09 01:16:31 +02:00
parent c8d20b35bd
commit 0d58d9c729
3 changed files with 93 additions and 20 deletions

View File

@ -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,20 @@ 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,
// either monitorid is always 0 or channelid
// is, we can't have display (0, 2) and (2, 0)
// for example
"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",

View File

@ -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

View File

@ -33,6 +33,7 @@
#include "virt-viewer-session-spice.h"
#include "virt-viewer-display-spice.h"
#include "virt-viewer-auth.h"
#include "virt-glib-compat.h"
#if !GLIB_CHECK_VERSION(2, 26, 0)
#include "gbinding.h"
@ -413,6 +414,78 @@ agent_connected_changed(SpiceChannel *cmain,
g_signal_handlers_disconnect_by_func(cmain, agent_connected_changed, self);
}
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();
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);
}
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 *monitor = &g_array_index(monitors, SpiceDisplayMonitorConfig, i);
display = g_ptr_array_index(displays, monitor->id);
g_return_if_fail(display != NULL);
if (monitor->width == 0 || monitor->width == 0)
continue;
virt_viewer_display_set_enabled(VIRT_VIEWER_DISPLAY(display), TRUE);
virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(display),
monitor->width, monitor->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,
@ -441,20 +514,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");
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_emit_by_name(session, "session-initialized");
g_signal_connect(channel, "notify::monitors",
G_CALLBACK(virt_viewer_session_spice_display_monitors), self);
spice_channel_connect(channel);
}
if (SPICE_IS_INPUTS_CHANNEL(channel)) {
@ -538,7 +608,6 @@ 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 (SPICE_IS_PLAYBACK_CHANNEL(channel) && self->priv->audio) {