Codebase list virt-viewer / 0d58d9c
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 Marc-André Lureau 11 years ago
3 changed file(s) with 93 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
171171 {
172172 gdouble dw = allocation->width, dh = allocation->height;
173173 guint zoom = 100;
174 guint channelid;
174 guint nth;
175175
176176 if (virt_viewer_display_get_auto_resize(VIRT_VIEWER_DISPLAY(self)) == FALSE)
177177 return;
186186 dh /= ((double)zoom / 100.0);
187187 }
188188
189 g_object_get(self->priv->channel, "channel-id", &channelid, NULL);
189 g_object_get(self, "nth-display", &nth, NULL);
190190
191191 SpiceMainChannel *main_channel = virt_viewer_session_spice_get_main_channel(
192192 VIRT_VIEWER_SESSION_SPICE(virt_viewer_display_get_session(VIRT_VIEWER_DISPLAY(self))));
193 spice_main_set_display(main_channel,
194 channelid,
195 0, 0, dw, dh);
193 spice_main_set_display(main_channel, nth, 0, 0, dw, dh);
196194 }
197195
198196 static void
211209
212210 GtkWidget *
213211 virt_viewer_display_spice_new(VirtViewerSessionSpice *session,
214 SpiceChannel *channel)
212 SpiceChannel *channel,
213 gint monitorid)
215214 {
216215 VirtViewerDisplaySpice *self;
217216 VirtViewerApp *app;
221220 g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL);
222221
223222 g_object_get(channel, "channel-id", &channelid, NULL);
223 // We don't allow monitorid != 0 && channelid != 0
224 g_return_val_if_fail(channelid == 0 || monitorid == 0, NULL);
224225
225226 self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE,
226227 "session", session,
227 "nth-display", channelid,
228 // either monitorid is always 0 or channelid
229 // is, we can't have display (0, 2) and (2, 0)
230 // for example
231 "nth-display", channelid + monitorid,
228232 NULL);
229233 self->priv->channel = channel;
230234
231235 g_object_get(session, "spice-session", &s, NULL);
232 self->priv->display = spice_display_new(s, channelid);
236 self->priv->display = spice_display_new_with_monitor(s, channelid, monitorid);
233237 g_object_unref(s);
234238
235239 virt_viewer_signal_connect_object(self->priv->display, "notify::ready",
6565
6666 GType virt_viewer_display_spice_get_type(void);
6767
68 GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, SpiceChannel *channel);
68 GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session, SpiceChannel *channel, gint monitorid);
6969
7070 G_END_DECLS
7171
3232 #include "virt-viewer-session-spice.h"
3333 #include "virt-viewer-display-spice.h"
3434 #include "virt-viewer-auth.h"
35 #include "virt-glib-compat.h"
3536
3637 #if !GLIB_CHECK_VERSION(2, 26, 0)
3738 #include "gbinding.h"
413414 }
414415
415416 static void
417 destroy_display(gpointer data)
418 {
419 VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(data);
420 VirtViewerSession *session = virt_viewer_display_get_session(display);
421
422 DEBUG_LOG("Destroying spice display %p", display);
423 virt_viewer_session_remove_display(session, display);
424 g_object_unref(display);
425 }
426
427 static void
428 virt_viewer_session_spice_display_monitors(SpiceChannel *channel,
429 GParamSpec *pspec G_GNUC_UNUSED,
430 VirtViewerSessionSpice *self)
431 {
432 GArray *monitors = NULL;
433 GPtrArray *displays = NULL;
434 GtkWidget *display;
435 guint i, monitors_max;
436
437 g_object_get(channel,
438 "monitors", &monitors,
439 "monitors-max", &monitors_max,
440 NULL);
441 g_return_if_fail(monitors != NULL);
442 g_return_if_fail(monitors->len <= monitors_max);
443
444 displays = g_object_get_data(G_OBJECT(channel), "virt-viewer-displays");
445 if (displays == NULL) {
446 displays = g_ptr_array_new();
447 g_ptr_array_set_free_func(displays, destroy_display);
448 g_object_set_data_full(G_OBJECT(channel), "virt-viewer-displays",
449 displays, (GDestroyNotify)g_ptr_array_unref);
450 }
451
452 g_ptr_array_set_size(displays, monitors_max);
453
454 for (i = 0; i < monitors_max; i++) {
455 display = g_ptr_array_index(displays, i);
456 if (display == NULL) {
457 display = virt_viewer_display_spice_new(self, channel, i);
458 DEBUG_LOG("creating spice display (#:%d)", i);
459 g_ptr_array_index(displays, i) = g_object_ref(display);
460 }
461
462 g_object_freeze_notify(G_OBJECT(display));
463 virt_viewer_display_set_enabled(VIRT_VIEWER_DISPLAY(display), FALSE);
464 virt_viewer_session_add_display(VIRT_VIEWER_SESSION(self),
465 VIRT_VIEWER_DISPLAY(display));
466 }
467
468 for (i = 0; i < monitors->len; i++) {
469 SpiceDisplayMonitorConfig *monitor = &g_array_index(monitors, SpiceDisplayMonitorConfig, i);
470 display = g_ptr_array_index(displays, monitor->id);
471 g_return_if_fail(display != NULL);
472
473 if (monitor->width == 0 || monitor->width == 0)
474 continue;
475
476 virt_viewer_display_set_enabled(VIRT_VIEWER_DISPLAY(display), TRUE);
477 virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(display),
478 monitor->width, monitor->height);
479 }
480
481 for (i = 0; i < monitors_max; i++)
482 g_object_thaw_notify(g_ptr_array_index(displays, i));
483
484 g_clear_pointer(&monitors, g_array_unref);
485
486 }
487
488 static void
416489 virt_viewer_session_spice_channel_new(SpiceSession *s,
417490 SpiceChannel *channel,
418491 VirtViewerSession *session)
440513
441514 g_signal_connect(channel, "notify::agent-connected", G_CALLBACK(agent_connected_changed), self);
442515 agent_connected_changed(channel, NULL, self);
516
517 g_signal_emit_by_name(session, "session-connected");
443518 }
444519
445520 if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
446 GtkWidget *display;
447
448 g_signal_emit_by_name(session, "session-connected");
449
450 DEBUG_LOG("new display channel (#%d)", id);
451 display = virt_viewer_display_spice_new(self, channel);
452 g_object_set_data(G_OBJECT(channel), "virt-viewer-display", display);
453 virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session),
454 VIRT_VIEWER_DISPLAY(display));
455
456521 g_signal_emit_by_name(session, "session-initialized");
522
523 g_signal_connect(channel, "notify::monitors",
524 G_CALLBACK(virt_viewer_session_spice_display_monitors), self);
525
526 spice_channel_connect(channel);
457527 }
458528
459529 if (SPICE_IS_INPUTS_CHANNEL(channel)) {
537607 if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
538608 VirtViewerDisplay *display = g_object_get_data(G_OBJECT(channel), "virt-viewer-display");
539609 DEBUG_LOG("zap display channel (#%d, %p)", id, display);
540 virt_viewer_session_remove_display(session, display);
541610 }
542611
543612 if (SPICE_IS_PLAYBACK_CHANNEL(channel) && self->priv->audio) {