[virt-tools-list] [PATCH virt-viewer 2/4] spice: implement --fullscreen=auto-conf

Marc-André Lureau marcandre.lureau at gmail.com
Sun Mar 18 18:59:15 UTC 2012


---
 src/remote-viewer-main.c        |   32 +++++++++++++++++--
 src/virt-viewer-app.c           |   30 +++++++++++++++---
 src/virt-viewer-session-spice.c |   62 +++++++++++++++++++++++++++++++++++++-
 src/virt-viewer-session-spice.h |    2 +-
 src/virt-viewer-session.c       |   30 ++++++++++++++++++-
 src/virt-viewer-session.h       |    2 +
 src/virt-viewer-window.c        |   18 ++++++-----
 7 files changed, 155 insertions(+), 21 deletions(-)

diff --git a/src/remote-viewer-main.c b/src/remote-viewer-main.c
index 6d26605..d857e45 100644
--- a/src/remote-viewer-main.c
+++ b/src/remote-viewer-main.c
@@ -43,6 +43,28 @@ remote_viewer_version(void)
     exit(EXIT_SUCCESS);
 }
 
+gboolean fullscreen = FALSE;
+gboolean fullscreen_auto_conf = FALSE;
+
+static gboolean
+option_fullscreen(G_GNUC_UNUSED const gchar *option_name,
+                  const gchar *value,
+                  G_GNUC_UNUSED gpointer data, GError **error)
+{
+    fullscreen = TRUE;
+
+    if (value == NULL)
+        return TRUE;
+
+    if (g_str_equal(value, "auto-conf")) {
+        fullscreen_auto_conf = TRUE;
+        return TRUE;
+    }
+
+    g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Invalid full-screen argument: %s"), value);
+    return FALSE;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -54,7 +76,6 @@ main(int argc, char **argv)
     gboolean verbose = FALSE;
     gboolean debug = FALSE;
     gboolean direct = FALSE;
-    gboolean fullscreen = FALSE;
     RemoteViewer *viewer = NULL;
 #if HAVE_SPICE_GTK
     gboolean controller = FALSE;
@@ -72,8 +93,8 @@ main(int argc, char **argv)
           N_("Zoom level of window, in percentage"), "ZOOM" },
         { "debug", '\0', 0, G_OPTION_ARG_NONE, &debug,
           N_("Display debugging information"), NULL },
-        { "full-screen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen,
-          N_("Open in full screen mode"), NULL },
+        { "full-screen", 'f', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, option_fullscreen,
+          N_("Open in full screen mode (=<auto-conf>)"), NULL },
 #if HAVE_SPICE_GTK
         { "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &controller,
           N_("Open connection using Spice controller communication"), NULL },
@@ -144,7 +165,10 @@ main(int argc, char **argv)
         goto cleanup;
 
     app = VIRT_VIEWER_APP(viewer);
-    g_object_set(app, "fullscreen", fullscreen, NULL);
+    g_object_set(app,
+                 "fullscreen", fullscreen,
+                 "fullscreen-auto-conf", fullscreen_auto_conf,
+                 NULL);
     virt_viewer_window_set_zoom_level(virt_viewer_app_get_main_window(app), zoom);
     virt_viewer_app_set_direct(app, direct);
 
diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c
index e30df85..9cffedb 100644
--- a/src/virt-viewer-app.c
+++ b/src/virt-viewer-app.c
@@ -116,6 +116,7 @@ struct _VirtViewerAppPrivate {
     gboolean authretry;
     gboolean started;
     gboolean fullscreen;
+    gboolean fullscreen_auto_conf;
     gboolean attach;
     gboolean quiting;
 
@@ -157,6 +158,7 @@ enum {
     PROP_TITLE,
     PROP_ENABLE_ACCEL,
     PROP_HAS_FOCUS,
+    PROP_FULLSCREEN_AUTO_CONF,
 };
 
 enum {
@@ -684,7 +686,7 @@ virt_viewer_app_create_session(VirtViewerApp *self, const gchar *type)
         GtkWindow *window = virt_viewer_window_get_window(priv->main_window);
         virt_viewer_app_trace(self, "Guest %s has a %s display\n",
                               priv->guest_name, type);
-        priv->session = virt_viewer_session_spice_new(window);
+        priv->session = virt_viewer_session_spice_new(self, window);
     } else
 #endif
     {
@@ -1170,6 +1172,10 @@ virt_viewer_app_get_property (GObject *object, guint property_id,
         g_value_set_boolean(value, priv->focused > 0);
         break;
 
+    case PROP_FULLSCREEN_AUTO_CONF:
+        g_value_set_boolean(value, priv->fullscreen_auto_conf);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -1218,6 +1224,10 @@ virt_viewer_app_set_property (GObject *object, guint property_id,
         priv->enable_accel = g_value_get_boolean(value);
         break;
 
+    case PROP_FULLSCREEN_AUTO_CONF:
+        priv->fullscreen_auto_conf = g_value_get_boolean(value);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -1377,8 +1387,16 @@ virt_viewer_app_class_init (VirtViewerAppClass *klass)
                                                          "Fullscreen",
                                                          "Fullscreen",
                                                          FALSE,
-                                                         G_PARAM_READABLE |
-                                                         G_PARAM_WRITABLE |
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property(object_class,
+                                    PROP_FULLSCREEN_AUTO_CONF,
+                                    g_param_spec_boolean("fullscreen-auto-conf",
+                                                         "auto conf",
+                                                         "Automatic display configuration in full screen",
+                                                         FALSE,
+                                                         G_PARAM_READWRITE |
                                                          G_PARAM_STATIC_STRINGS));
 
     g_object_class_install_property(object_class,
@@ -1503,7 +1521,7 @@ static void fullscreen_cb(gpointer key,
 
     DEBUG_LOG("fullscreen display %d: %d", nth, options->fullscreen);
     if (options->fullscreen) {
-        GdkScreen *screen = gdk_screen_get_default ();
+        GdkScreen *screen = gdk_screen_get_default();
         GdkRectangle mon;
 
         if (nth >= gdk_screen_get_n_monitors(screen)) {
@@ -1522,12 +1540,14 @@ virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscreen)
     VirtViewerAppPrivate *priv = self->priv;
     FullscreenOptions options  = {
         .fullscreen = fullscreen,
-        .move = virt_viewer_app_get_n_windows_visible(self) > 1,
+        .move = virt_viewer_app_get_n_windows_visible(self) > 1 || self->priv->fullscreen_auto_conf,
     };
 
     /* we iterate unconditionnaly, even if it was set before to update new windows */
     priv->fullscreen = fullscreen;
     g_hash_table_foreach(priv->windows, fullscreen_cb, &options);
+
+    g_object_notify(G_OBJECT(self), "fullscreen");
 }
 
 static void
diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
index a4b3a1f..7d14db4 100644
--- a/src/virt-viewer-session-spice.c
+++ b/src/virt-viewer-session-spice.c
@@ -74,6 +74,7 @@ static void virt_viewer_session_spice_channel_destroy(SpiceSession *s,
                                                       VirtViewerSession *session);
 static void virt_viewer_session_spice_smartcard_insert(VirtViewerSession *session);
 static void virt_viewer_session_spice_smartcard_remove(VirtViewerSession *session);
+static gboolean virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self);
 
 static void
 virt_viewer_session_spice_get_property(GObject *object, guint property_id,
@@ -394,6 +395,15 @@ virt_viewer_session_spice_usb_device_selection(VirtViewerSession *session,
 }
 
 static void
+agent_connected_changed(SpiceChannel *cmain,
+                        GParamSpec *pspec G_GNUC_UNUSED,
+                        VirtViewerSessionSpice *self)
+{
+    if (virt_viewer_session_spice_fullscreen_auto_conf(self))
+        g_signal_handlers_disconnect_by_func(cmain, agent_connected_changed, self);
+}
+
+static void
 virt_viewer_session_spice_channel_new(SpiceSession *s,
                                       SpiceChannel *channel,
                                       VirtViewerSession *session)
@@ -416,6 +426,9 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
         g_signal_connect(channel, "channel-event",
                          G_CALLBACK(virt_viewer_session_spice_main_channel_event), self);
         self->priv->main_channel = SPICE_MAIN_CHANNEL(channel);
+
+        g_signal_connect(channel, "notify::agent-connected", G_CALLBACK(agent_connected_changed),  self);
+        agent_connected_changed(channel, NULL, self);
     }
 
     if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
@@ -447,6 +460,41 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
     self->priv->channel_count++;
 }
 
+static gboolean
+virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self)
+{
+    GdkScreen *screen = gdk_screen_get_default();
+    SpiceMainChannel* cmain = virt_viewer_session_spice_get_main_channel(self);
+    VirtViewerApp *app = NULL;
+    GdkRectangle dest;
+    gboolean auto_conf, agent_connected;
+    gint i;
+
+    app = virt_viewer_session_get_app(VIRT_VIEWER_SESSION(self));
+    g_return_val_if_fail(VIRT_VIEWER_IS_APP(app), TRUE);
+
+    g_object_get(app, "fullscreen-auto-conf", &auto_conf, NULL);
+    if (!auto_conf)
+        return TRUE;
+
+    if (cmain == NULL)
+        return FALSE;
+
+    g_object_get(cmain, "agent-connected", &agent_connected, NULL);
+    if (!agent_connected)
+        return FALSE;
+
+    spice_main_set_display_enabled(cmain, -1, FALSE);
+    for (i = 0; i < gdk_screen_get_n_monitors(screen); i++) {
+        gdk_screen_get_monitor_geometry(screen, i, &dest);
+        spice_main_set_display(cmain, i, dest.x, dest.y, dest.width, dest.height);
+        spice_main_set_display_enabled(cmain, i, TRUE);
+    }
+
+    spice_main_send_monitor_config(cmain);
+    return TRUE;
+}
+
 static void
 virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
                                           SpiceChannel *channel,
@@ -479,16 +527,26 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
         g_signal_emit_by_name(self, "session-disconnected");
 }
 
+static void
+fullscreen_changed(GObject *gobject G_GNUC_UNUSED,
+                   GParamSpec *pspec G_GNUC_UNUSED,
+                   VirtViewerSessionSpice *self)
+{
+    virt_viewer_session_spice_fullscreen_auto_conf(self);
+}
+
 VirtViewerSession *
-virt_viewer_session_spice_new(GtkWindow *main_window)
+virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window)
 {
     VirtViewerSessionSpice *self;
 
-    self = g_object_new(VIRT_VIEWER_TYPE_SESSION_SPICE, NULL);
+    self = g_object_new(VIRT_VIEWER_TYPE_SESSION_SPICE, "app", app, NULL);
 
     create_spice_session(self);
     self->priv->main_window = g_object_ref(main_window);
 
+    g_signal_connect(app, "notify::fullscreen", G_CALLBACK(fullscreen_changed),  self);
+
     return VIRT_VIEWER_SESSION(self);
 }
 
diff --git a/src/virt-viewer-session-spice.h b/src/virt-viewer-session-spice.h
index f0d7e89..95bdcdf 100644
--- a/src/virt-viewer-session-spice.h
+++ b/src/virt-viewer-session-spice.h
@@ -65,7 +65,7 @@ struct _VirtViewerSessionSpiceClass {
 
 GType virt_viewer_session_spice_get_type(void);
 
-VirtViewerSession* virt_viewer_session_spice_new(GtkWindow *main_window);
+VirtViewerSession* virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window);
 SpiceMainChannel* virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self);
 
 G_END_DECLS
diff --git a/src/virt-viewer-session.c b/src/virt-viewer-session.c
index c0d6e65..f139c48 100644
--- a/src/virt-viewer-session.c
+++ b/src/virt-viewer-session.c
@@ -35,7 +35,7 @@
 struct _VirtViewerSessionPrivate
 {
     GList *displays;
-
+    VirtViewerApp *app;
     gboolean auto_usbredir;
 };
 
@@ -44,6 +44,7 @@ G_DEFINE_ABSTRACT_TYPE(VirtViewerSession, virt_viewer_session, G_TYPE_OBJECT)
 enum {
     PROP_0,
 
+    PROP_APP,
     PROP_AUTO_USBREDIR,
 };
 
@@ -74,6 +75,11 @@ virt_viewer_session_set_property(GObject *object,
     case PROP_AUTO_USBREDIR:
         virt_viewer_session_set_auto_usbredir(self, g_value_get_boolean(value));
         break;
+
+    case PROP_APP:
+        self->priv->app = g_value_get_object(value);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -92,6 +98,11 @@ virt_viewer_session_get_property(GObject *object,
     case PROP_AUTO_USBREDIR:
         g_value_set_boolean(value, virt_viewer_session_get_auto_usbredir(self));
         break;
+
+    case PROP_APP:
+        g_value_set_object(value, self->priv->app);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -117,6 +128,16 @@ virt_viewer_session_class_init(VirtViewerSessionClass *class)
                                                          G_PARAM_CONSTRUCT |
                                                          G_PARAM_STATIC_STRINGS));
 
+    g_object_class_install_property(object_class,
+                                    PROP_APP,
+                                    g_param_spec_object("app",
+                                                         "VirtViewerApp",
+                                                         "VirtViewerApp",
+                                                         VIRT_VIEWER_TYPE_APP,
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT |
+                                                         G_PARAM_STATIC_STRINGS));
+
     g_signal_new("session-connected",
                  G_OBJECT_CLASS_TYPE(object_class),
                  G_SIGNAL_RUN_FIRST,
@@ -408,6 +429,13 @@ void virt_viewer_session_smartcard_remove(VirtViewerSession *self)
     klass->smartcard_remove(self);
 }
 
+VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self)
+{
+    g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), NULL);
+
+    return self->priv->app;
+}
+
 /*
  * Local variables:
  *  c-indent-level: 4
diff --git a/src/virt-viewer-session.h b/src/virt-viewer-session.h
index c20f23d..c53c8b5 100644
--- a/src/virt-viewer-session.h
+++ b/src/virt-viewer-session.h
@@ -26,6 +26,7 @@
 
 #include <gtk/gtk.h>
 
+#include "virt-viewer-app.h"
 #include "virt-viewer-display.h"
 
 G_BEGIN_DECLS
@@ -118,6 +119,7 @@ gboolean virt_viewer_session_has_usb(VirtViewerSession *self);
 void virt_viewer_session_usb_device_selection(VirtViewerSession *self, GtkWindow *parent);
 void virt_viewer_session_smartcard_insert(VirtViewerSession *self);
 void virt_viewer_session_smartcard_remove(VirtViewerSession *self);
+VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self);
 
 G_END_DECLS
 
diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c
index f539fb5..62b6052 100644
--- a/src/virt-viewer-window.c
+++ b/src/virt-viewer-window.c
@@ -493,15 +493,17 @@ virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gboolean move, gint
         priv->before_saved = TRUE;
     }
 
-    if (!priv->fullscreen) {
-        gtk_check_menu_item_set_active(check, TRUE);
-        priv->fullscreen = TRUE;
-        gtk_widget_hide(menu);
-        gtk_widget_show(priv->toolbar);
-        ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), TRUE);
-        ViewAutoDrawer_Close(VIEW_AUTODRAWER(priv->layout));
-    }
+    if (priv->fullscreen)
+        return;
+    priv->fullscreen = TRUE;
+
+    gtk_check_menu_item_set_active(check, TRUE);
+    gtk_widget_hide(menu);
+    gtk_widget_show(priv->toolbar);
+    ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), TRUE);
+    ViewAutoDrawer_Close(VIEW_AUTODRAWER(priv->layout));
 
+    /* g_debug("enter fullscreen move:%d %d+%d", move, x, y); */
     if (move)
         gtk_window_move(GTK_WINDOW(priv->window), x, y);
 
-- 
1.7.7.6




More information about the virt-tools-list mailing list