mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/virt-viewer
synced 2025-12-27 14:54:14 +00:00
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:
parent
c8d20b35bd
commit
0d58d9c729
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user