summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEduardo Lima (Etrunko) <etrunko@redhat.com>2015-12-09 18:11:37 -0200
committerFabiano FidĂȘncio <fidencio@redhat.com>2016-02-18 21:45:56 +0100
commita9ce19f84864cc402ea1b4682a94fe53895bb13f (patch)
tree167a3de3998be59443ec506944d06f9eb675d4d2 /src
parent7a54b96dbebfeb44f73a3e48e11f32006763a3b6 (diff)
downloadvirt-viewer-a9ce19f84864cc402ea1b4682a94fe53895bb13f.tar.gz
virt-viewer-a9ce19f84864cc402ea1b4682a94fe53895bb13f.tar.xz
virt-viewer-a9ce19f84864cc402ea1b4682a94fe53895bb13f.zip
Port to GtkApplication API's
Most of this patch consists in code being shuffled around to fit the expected flow while using the new APIs. I tried my best to make this patch the less intrusive as possible. Main changes are: - Updated build requirements * glib version 2.38 * gtk+ version 3.10 * gio - VirtViewerApp is now a subclass of GtkApplication. Some mainloop calls were replaced: * gtk_main() -> g_application_run() * gtk_quit() -> g_application_quit() - Unified command line option handling. The logic has moved from the main functions and split in common options, and specific ones for each application. With this, the main functions were highly simplified, and now basically responsible for instantiating the App object and running the main loop. - All Window objects must be associated with the Application. With this, there is no need to emit our own 'window-added'/'window- removed' signals, as those will be emited by GtkApplication whenever gtk_application_add_window() and gtk_application_remove_window() are called. Also, 'window-removed' was not being used anywhere. Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/remote-viewer-main.c170
-rw-r--r--src/remote-viewer.c182
-rw-r--r--src/remote-viewer.h3
-rw-r--r--src/virt-viewer-app.c158
-rw-r--r--src/virt-viewer-app.h11
-rw-r--r--src/virt-viewer-main.c110
-rw-r--r--src/virt-viewer-util.h2
-rw-r--r--src/virt-viewer.c117
-rw-r--r--src/virt-viewer.h8
-rw-r--r--src/virt-viewer.xml2
10 files changed, 361 insertions, 402 deletions
diff --git a/src/remote-viewer-main.c b/src/remote-viewer-main.c
index 81cf736..4ed74fb 100644
--- a/src/remote-viewer-main.c
+++ b/src/remote-viewer-main.c
@@ -22,184 +22,24 @@
#include <config.h>
#include <locale.h>
+#include <gio/gio.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <stdlib.h>
-#ifdef G_OS_WIN32
-#include <windows.h>
-#include <io.h>
-#endif
-
-#ifdef HAVE_GTK_VNC
-#include <vncdisplay.h>
-#endif
-#ifdef HAVE_SPICE_GTK
-#include <spice-option.h>
-#endif
-#ifdef HAVE_OVIRT
-#include <govirt/ovirt-options.h>
-#endif
#include "remote-viewer.h"
-#include "virt-viewer-app.h"
-#include "virt-viewer-session.h"
-
-static void
-remote_viewer_version(void)
-{
- g_print(_("remote-viewer version %s"), VERSION BUILDID);
-#ifdef REMOTE_VIEWER_OS_ID
- g_print(" (OS ID: %s)", REMOTE_VIEWER_OS_ID);
-#endif
- g_print("\n");
- exit(EXIT_SUCCESS);
-}
-
-static void
-recent_add(gchar *uri, const gchar *mime_type)
-{
- GtkRecentManager *recent;
- GtkRecentData meta = {
- .app_name = (char*)"remote-viewer",
- .app_exec = (char*)"remote-viewer %u",
- .mime_type = (char*)mime_type,
- };
-
- if (uri == NULL)
- return;
-
- recent = gtk_recent_manager_get_default();
- meta.display_name = uri;
- if (!gtk_recent_manager_add_full(recent, uri, &meta))
- g_warning("Recent item couldn't be added");
-}
-
-static void connected(VirtViewerSession *session,
- VirtViewerApp *self G_GNUC_UNUSED)
-{
- gchar *uri = virt_viewer_session_get_uri(session);
- const gchar *mime = virt_viewer_session_mime_type(session);
-
- recent_add(uri, mime);
- g_free(uri);
-}
int
main(int argc, char **argv)
{
- GOptionContext *context;
- GError *error = NULL;
int ret = 1;
- gchar **args = NULL;
- gchar *uri = NULL;
- char *title = NULL;
- RemoteViewer *viewer = NULL;
-#ifdef HAVE_SPICE_GTK
- gboolean controller = FALSE;
-#endif
- VirtViewerApp *app;
- const GOptionEntry options [] = {
- { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- remote_viewer_version, N_("Display version information"), NULL },
- { "title", 't', 0, G_OPTION_ARG_STRING, &title,
- N_("Set window title"), NULL },
-#ifdef HAVE_SPICE_GTK
- { "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &controller,
- N_("Open connection using Spice controller communication"), NULL },
-#endif
- { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &args,
- NULL, "URI|VV-FILE" },
- { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
- };
- GOptionGroup *app_options = NULL;
+ GApplication *app = NULL;
virt_viewer_util_init(_("Remote Viewer"));
+ app = G_APPLICATION(remote_viewer_new());
- /* Setup command line options */
- context = g_option_context_new (NULL);
- g_option_context_set_summary(context, _("Remote viewer client"));
- app_options = virt_viewer_app_get_option_group();
- g_option_group_add_entries (app_options, options);
- g_option_context_set_main_group (context, app_options);
- g_option_context_add_group (context, gtk_get_option_group (TRUE));
-#ifdef HAVE_GTK_VNC
- g_option_context_add_group (context, vnc_display_get_option_group ());
-#endif
-#ifdef HAVE_SPICE_GTK
- g_option_context_add_group (context, spice_get_option_group ());
-#endif
-#ifdef HAVE_OVIRT
- g_option_context_add_group (context, ovirt_get_option_group ());
-#endif
- g_option_context_parse (context, &argc, &argv, &error);
- if (error) {
- char *base_name;
- base_name = g_path_get_basename(argv[0]);
- g_printerr(_("%s\nRun '%s --help' to see a full list of available command line options\n"),
- error->message, base_name);
- g_free(base_name);
- goto cleanup;
- }
-
- g_option_context_free(context);
-
-#ifdef HAVE_SPICE_GTK
- if (controller) {
- if (args) {
- g_printerr(_("Error: extra arguments given while using Spice controller\n"));
- goto cleanup;
- }
- } else
-#endif
- if (args) {
- if (g_strv_length(args) > 1) {
- g_printerr(_("Error: can't handle multiple URIs\n"));
- goto cleanup;
- } else if (g_strv_length(args) == 1) {
- uri = g_strdup(args[0]);
- }
- }
-
-#ifdef HAVE_SPICE_GTK
- if (controller) {
- viewer = remote_viewer_new_with_controller();
- g_object_set(viewer, "guest-name", "defined by Spice controller", NULL);
- } else {
-#endif
- viewer = remote_viewer_new(uri);
- if (title)
- g_object_set(viewer, "title", title, NULL);
-#ifdef HAVE_SPICE_GTK
- }
-#endif
- if (viewer == NULL)
- goto cleanup;
-
- app = VIRT_VIEWER_APP(viewer);
-
- if (!virt_viewer_app_start(app, &error)) {
- if (g_error_matches(error, VIRT_VIEWER_ERROR, VIRT_VIEWER_ERROR_CANCELLED))
- ret = 0;
- else if (error) {
- virt_viewer_app_simple_message_dialog(app, error->message);
- }
- goto cleanup;
- }
-
- g_signal_connect(virt_viewer_app_get_session(app), "session-connected",
- G_CALLBACK(connected), app);
-
- gtk_main();
-
- ret = 0;
-
- cleanup:
- g_free(uri);
- if (viewer)
- g_object_unref(viewer);
- g_strfreev(args);
- g_clear_error(&error);
-
+ ret = g_application_run(app, argc, argv);
+ g_object_unref(app);
return ret;
}
diff --git a/src/remote-viewer.c b/src/remote-viewer.c
index e712d61..5f8be6b 100644
--- a/src/remote-viewer.c
+++ b/src/remote-viewer.c
@@ -23,6 +23,7 @@
*/
#include <config.h>
+#include <gio/gio.h>
#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include <glib/gi18n.h>
@@ -84,8 +85,9 @@ static OvirtVm * choose_vm(GtkWindow *main_window,
static gboolean remote_viewer_start(VirtViewerApp *self, GError **error);
#ifdef HAVE_SPICE_GTK
static gboolean remote_viewer_activate(VirtViewerApp *self, GError **error);
-static void remote_viewer_window_added(VirtViewerApp *self, VirtViewerWindow *win);
+static void remote_viewer_window_added(GtkApplication *app, GtkWindow *w);
static void spice_foreign_menu_updated(RemoteViewer *self);
+static void foreign_menu_title_changed(SpiceCtrlForeignMenu *menu, GParamSpec *pspec, RemoteViewer *self);
#endif
static void
@@ -183,11 +185,104 @@ remote_viewer_deactivated(VirtViewerApp *app, gboolean connect_error)
VIRT_VIEWER_APP_CLASS(remote_viewer_parent_class)->deactivated(app, connect_error);
}
+static gchar **opt_args = NULL;
+static char *opt_title = NULL;
+static gboolean opt_controller = FALSE;
+
+static void
+remote_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group)
+{
+ static const GOptionEntry options[] = {
+ { "title", 't', 0, G_OPTION_ARG_STRING, &opt_title,
+ N_("Set window title"), NULL },
+#ifdef HAVE_SPICE_GTK
+ { "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &opt_controller,
+ N_("Open connection using Spice controller communication"), NULL },
+#endif
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_args,
+ NULL, "URI|VV-FILE" },
+ { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
+ };
+
+ VIRT_VIEWER_APP_CLASS(remote_viewer_parent_class)->add_option_entries(self, context, group);
+ g_option_context_set_summary(context, _("Remote viewer client"));
+ g_option_group_add_entries(group, options);
+
+#ifdef HAVE_OVIRT
+ g_option_context_add_group (context, ovirt_get_option_group ());
+#endif
+}
+
+static gboolean
+remote_viewer_local_command_line (GApplication *gapp,
+ gchar ***args,
+ int *status)
+{
+ gboolean ret = FALSE;
+ VirtViewerApp *app = VIRT_VIEWER_APP(gapp);
+ RemoteViewer *self = REMOTE_VIEWER(app);
+
+ ret = G_APPLICATION_CLASS(remote_viewer_parent_class)->local_command_line(gapp, args, status);
+ if (ret)
+ goto end;
+
+ if (!opt_args) {
+ self->priv->open_recent_dialog = TRUE;
+ } else {
+ if (g_strv_length(opt_args) > 1) {
+ g_printerr(_("\nError: can't handle multiple URIs\n\n"));
+ ret = TRUE;
+ *status = 1;
+ goto end;
+ }
+
+ g_object_set(app, "guri", opt_args[0], NULL);
+ }
+
+#ifdef HAVE_SPICE_GTK
+ if (opt_controller) {
+ if (opt_args) {
+ g_printerr(_("\nError: extra arguments given while using Spice controller\n\n"));
+ ret = TRUE;
+ *status = 1;
+ goto end;
+ }
+
+ SpiceCtrlController *ctrl = spice_ctrl_controller_new();
+ SpiceCtrlForeignMenu *menu = spice_ctrl_foreign_menu_new();
+
+ g_object_set(self, "guest-name", "defined by Spice controller",
+ "controller", ctrl,
+ "foreign-menu", menu,
+ NULL);
+
+ g_signal_connect(menu, "notify::title",
+ G_CALLBACK(foreign_menu_title_changed),
+ self);
+
+ g_object_unref(ctrl);
+ g_object_unref(menu);
+ }
+#endif
+
+ if (opt_title && !opt_controller)
+ g_object_set(app, "title", opt_title, NULL);
+
+end:
+ if (ret && *status)
+ g_printerr(_("Run '%s --help' to see a full list of available command line options\n"), g_get_prgname());
+
+ g_strfreev(opt_args);
+ return ret;
+}
+
static void
remote_viewer_class_init (RemoteViewerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkApplicationClass *gtk_app_class = GTK_APPLICATION_CLASS(klass);
VirtViewerAppClass *app_class = VIRT_VIEWER_APP_CLASS (klass);
+ GApplicationClass *g_app_class = G_APPLICATION_CLASS(klass);
g_type_class_add_private (klass, sizeof (RemoteViewerPrivate));
@@ -195,11 +290,15 @@ remote_viewer_class_init (RemoteViewerClass *klass)
object_class->set_property = remote_viewer_set_property;
object_class->dispose = remote_viewer_dispose;
+ g_app_class->local_command_line = remote_viewer_local_command_line;
+
app_class->start = remote_viewer_start;
app_class->deactivated = remote_viewer_deactivated;
+ app_class->add_option_entries = remote_viewer_add_option_entries;
#ifdef HAVE_SPICE_GTK
app_class->activate = remote_viewer_activate;
- app_class->window_added = remote_viewer_window_added;
+
+ gtk_app_class->window_added = remote_viewer_window_added;
g_object_class_install_property(object_class,
PROP_CONTROLLER,
@@ -208,7 +307,6 @@ remote_viewer_class_init (RemoteViewerClass *klass)
"Spice controller",
SPICE_CTRL_TYPE_CONTROLLER,
G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property(object_class,
PROP_CTRL_FOREIGN_MENU,
@@ -217,8 +315,9 @@ remote_viewer_class_init (RemoteViewerClass *klass)
"Spice foreign menu",
SPICE_CTRL_TYPE_FOREIGN_MENU,
G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
+#else
+ (void) gtk_app_class;
#endif
g_object_class_install_property(object_class,
PROP_OPEN_RECENT_DIALOG,
@@ -227,7 +326,6 @@ remote_viewer_class_init (RemoteViewerClass *klass)
"Open recent dialog",
FALSE,
G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
@@ -238,11 +336,11 @@ remote_viewer_init(RemoteViewer *self)
}
RemoteViewer *
-remote_viewer_new(const gchar *uri)
+remote_viewer_new(void)
{
return g_object_new(REMOTE_VIEWER_TYPE,
- "guri", uri,
- "open-recent-dialog", uri == NULL,
+ "application-id", "org.virt-manager.remote-viewer",
+ "flags", G_APPLICATION_NON_UNIQUE,
NULL);
}
@@ -265,26 +363,6 @@ foreign_menu_title_changed(SpiceCtrlForeignMenu *menu G_GNUC_UNUSED,
spice_foreign_menu_updated(self);
}
-RemoteViewer *
-remote_viewer_new_with_controller(void)
-{
- RemoteViewer *self;
- SpiceCtrlController *ctrl = spice_ctrl_controller_new();
- SpiceCtrlForeignMenu *menu = spice_ctrl_foreign_menu_new();
-
- self = g_object_new(REMOTE_VIEWER_TYPE,
- "controller", ctrl,
- "foreign-menu", menu,
- NULL);
- g_signal_connect(menu, "notify::title",
- G_CALLBACK(foreign_menu_title_changed),
- self);
- g_object_unref(ctrl);
- g_object_unref(menu);
-
- return self;
-}
-
static void
spice_ctrl_do_connect(SpiceCtrlController *ctrl G_GNUC_UNUSED,
VirtViewerApp *self)
@@ -634,9 +712,11 @@ remote_viewer_activate(VirtViewerApp *app, GError **error)
}
static void
-remote_viewer_window_added(VirtViewerApp *app,
- VirtViewerWindow *win)
+remote_viewer_window_added(GtkApplication *app,
+ GtkWindow *w)
{
+ VirtViewerWindow *win = VIRT_VIEWER_WINDOW(
+ g_object_get_data(G_OBJECT(w), "virt-viewer-window"));
spice_menu_update(REMOTE_VIEWER(app), win);
spice_foreign_menu_update(REMOTE_VIEWER(app), win);
}
@@ -742,8 +822,10 @@ authenticate_cb(RestProxy *proxy, G_GNUC_UNUSED RestProxyAuth *auth,
}
static void
-ovirt_foreign_menu_update(RemoteViewer *app, VirtViewerWindow *win)
+ovirt_foreign_menu_update(GtkApplication *gtkapp, GtkWindow *gtkwin, G_GNUC_UNUSED gpointer data)
{
+ RemoteViewer *app = REMOTE_VIEWER(gtkapp);
+ VirtViewerWindow *win = g_object_get_data(G_OBJECT(gtkwin), "virt-viewer-window");
GtkWidget *menu = g_object_get_data(G_OBJECT(win), "foreign-menu");
GtkWidget *submenu;
GtkMenuShell *shell = GTK_MENU_SHELL(gtk_builder_get_object(virt_viewer_window_get_builder(win), "top-menu"));
@@ -776,8 +858,9 @@ static void
ovirt_foreign_menu_update_each(gpointer value,
gpointer user_data)
{
- ovirt_foreign_menu_update(REMOTE_VIEWER(user_data),
- VIRT_VIEWER_WINDOW(value));
+ ovirt_foreign_menu_update(GTK_APPLICATION(user_data),
+ virt_viewer_window_get_window(VIRT_VIEWER_WINDOW(value)),
+ NULL);
}
static void
@@ -1059,6 +1142,36 @@ choose_vm(GtkWindow *main_window,
}
#endif
+static void
+remote_viewer_recent_add(gchar *uri, const gchar *mime_type)
+{
+ GtkRecentManager *recent;
+ GtkRecentData meta = {
+ .app_name = (char*)"remote-viewer",
+ .app_exec = (char*)"remote-viewer %u",
+ .mime_type = (char*)mime_type,
+ };
+
+ if (uri == NULL)
+ return;
+
+ recent = gtk_recent_manager_get_default();
+ meta.display_name = uri;
+ if (!gtk_recent_manager_add_full(recent, uri, &meta))
+ g_warning("Recent item couldn't be added");
+}
+
+static void
+remote_viewer_session_connected(VirtViewerSession *session,
+ VirtViewerApp *self G_GNUC_UNUSED)
+{
+ gchar *uri = virt_viewer_session_get_uri(session);
+ const gchar *mime = virt_viewer_session_mime_type(session);
+
+ remote_viewer_recent_add(uri, mime);
+ g_free(uri);
+}
+
static gboolean
remote_viewer_start(VirtViewerApp *app, GError **err)
{
@@ -1142,6 +1255,9 @@ retry_dialog:
goto cleanup;
}
+ g_signal_connect(virt_viewer_app_get_session(app), "session-connected",
+ G_CALLBACK(remote_viewer_session_connected), app);
+
virt_viewer_session_set_file(virt_viewer_app_get_session(app), vvfile);
#ifdef HAVE_OVIRT
if (vvfile != NULL) {
diff --git a/src/remote-viewer.h b/src/remote-viewer.h
index 6d445ca..53566fc 100644
--- a/src/remote-viewer.h
+++ b/src/remote-viewer.h
@@ -48,8 +48,7 @@ typedef struct {
GType remote_viewer_get_type (void);
-RemoteViewer* remote_viewer_new(const gchar *uri);
-RemoteViewer* remote_viewer_new_with_controller(void);
+RemoteViewer *remote_viewer_new (void);
G_END_DECLS
diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c
index 7f7fed3..aa5e905 100644
--- a/src/virt-viewer-app.c
+++ b/src/virt-viewer-app.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <unistd.h>
#include <locale.h>
+#include <gio/gio.h>
#include <glib/gprintf.h>
#include <glib/gi18n.h>
@@ -102,6 +103,7 @@ static void virt_viewer_app_update_pretty_address(VirtViewerApp *self);
static void virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscreen);
static void virt_viewer_app_update_menu_displays(VirtViewerApp *self);
static void virt_viewer_update_smartcard_accels(VirtViewerApp *self);
+static void virt_viewer_app_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group);
struct _VirtViewerAppPrivate {
@@ -154,7 +156,7 @@ struct _VirtViewerAppPrivate {
};
-G_DEFINE_ABSTRACT_TYPE(VirtViewerApp, virt_viewer_app, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE(VirtViewerApp, virt_viewer_app, GTK_TYPE_APPLICATION)
#define GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE_APP, VirtViewerAppPrivate))
@@ -173,14 +175,6 @@ enum {
PROP_UUID,
};
-enum {
- SIGNAL_WINDOW_ADDED,
- SIGNAL_WINDOW_REMOVED,
- SIGNAL_LAST,
-};
-
-static guint signals[SIGNAL_LAST];
-
void
virt_viewer_app_set_debug(gboolean debug)
{
@@ -297,7 +291,7 @@ virt_viewer_app_quit(VirtViewerApp *self)
}
}
- gtk_main_quit();
+ g_application_quit(G_APPLICATION(self));
}
static gint
@@ -948,12 +942,13 @@ virt_viewer_app_window_new(VirtViewerApp *self, gint nth)
virt_viewer_app_update_menu_displays(self);
virt_viewer_window_set_usb_options_sensitive(window, virt_viewer_app_has_usbredir(self));
- g_signal_emit(self, signals[SIGNAL_WINDOW_ADDED], 0, window);
+ w = virt_viewer_window_get_window(window);
+ g_object_set_data(G_OBJECT(w), "virt-viewer-window", window);
+ gtk_application_add_window(GTK_APPLICATION(self), w);
if (self->priv->fullscreen)
app_window_try_fullscreen(self, window, nth);
- w = virt_viewer_window_get_window(window);
g_signal_connect(w, "hide", G_CALLBACK(viewer_window_visible_cb), self);
g_signal_connect(w, "show", G_CALLBACK(viewer_window_visible_cb), self);
g_signal_connect(w, "focus-in-event", G_CALLBACK(viewer_window_focus_in_cb), self);
@@ -1068,8 +1063,6 @@ static void virt_viewer_app_remove_nth_window(VirtViewerApp *self,
g_debug("Remove window %d %p", nth, win);
self->priv->windows = g_list_remove(self->priv->windows, win);
- g_signal_emit(self, signals[SIGNAL_WINDOW_REMOVED], 0, win);
-
g_object_unref(win);
}
@@ -1423,7 +1416,7 @@ virt_viewer_app_default_deactivated(VirtViewerApp *self, gboolean connect_error)
}
if (self->priv->quit_on_disconnect)
- gtk_main_quit();
+ g_application_quit(G_APPLICATION(self));
}
static void
@@ -1501,7 +1494,7 @@ virt_viewer_app_disconnected(VirtViewerSession *session G_GNUC_UNUSED, const gch
virt_viewer_app_hide_all_windows(self);
if (priv->quitting)
- gtk_main_quit();
+ g_application_quit(G_APPLICATION(self));
if (connect_error) {
GtkWidget *dialog = virt_viewer_app_make_message_dialog(self,
@@ -1768,6 +1761,7 @@ gboolean virt_viewer_app_start(VirtViewerApp *self, GError **error)
static int opt_zoom = NORMAL_ZOOM_LEVEL;
static gchar *opt_hotkeys = NULL;
+static gboolean opt_version = FALSE;
static gboolean opt_verbose = FALSE;
static gboolean opt_debug = FALSE;
static gboolean opt_fullscreen = FALSE;
@@ -1787,8 +1781,6 @@ virt_viewer_app_init(VirtViewerApp *self)
self->priv = GET_PRIVATE(self);
gtk_window_set_default_icon_name("virt-viewer");
- virt_viewer_app_set_debug(opt_debug);
- virt_viewer_app_set_fullscreen(self, opt_fullscreen);
self->priv->displays = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
self->priv->config = g_key_file_new();
@@ -1804,14 +1796,7 @@ virt_viewer_app_init(VirtViewerApp *self)
g_clear_error(&error);
- if (opt_zoom < MIN_ZOOM_LEVEL || opt_zoom > MAX_ZOOM_LEVEL) {
- g_printerr(_("Zoom level must be within %d-%d\n"), MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
- opt_zoom = NORMAL_ZOOM_LEVEL;
- }
-
self->priv->initial_display_map = virt_viewer_app_get_monitor_mapping_for_section(self, "fallback");
- self->priv->verbose = opt_verbose;
- self->priv->quit_on_disconnect = opt_kiosk ? opt_kiosk_quit : TRUE;
g_signal_connect(self, "notify::guest-name", G_CALLBACK(title_maybe_changed), NULL);
g_signal_connect(self, "notify::title", G_CALLBACK(title_maybe_changed), NULL);
g_signal_connect(self, "notify::guri", G_CALLBACK(title_maybe_changed), NULL);
@@ -1870,9 +1855,18 @@ virt_viewer_update_smartcard_accels(VirtViewerApp *self)
}
static void
-virt_viewer_app_constructed(GObject *object)
+virt_viewer_app_on_application_startup(GApplication *app)
{
- VirtViewerApp *self = VIRT_VIEWER_APP(object);
+ VirtViewerApp *self = VIRT_VIEWER_APP(app);
+ GError *error = NULL;
+
+ G_APPLICATION_CLASS(virt_viewer_app_parent_class)->startup(app);
+
+ virt_viewer_app_set_debug(opt_debug);
+ virt_viewer_app_set_fullscreen(self, opt_fullscreen);
+
+ self->priv->verbose = opt_verbose;
+ self->priv->quit_on_disconnect = opt_kiosk ? opt_kiosk_quit : TRUE;
self->priv->main_window = virt_viewer_app_window_new(self,
virt_viewer_app_get_first_monitor(self));
@@ -1880,6 +1874,12 @@ virt_viewer_app_constructed(GObject *object)
virt_viewer_app_set_kiosk(self, opt_kiosk);
virt_viewer_app_set_hotkeys(self, opt_hotkeys);
+
+ if (opt_zoom < MIN_ZOOM_LEVEL || opt_zoom > MAX_ZOOM_LEVEL) {
+ g_printerr(_("Zoom level must be within %d-%d\n"), MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
+ opt_zoom = NORMAL_ZOOM_LEVEL;
+ }
+
virt_viewer_window_set_zoom_level(self->priv->main_window, opt_zoom);
virt_viewer_set_insert_smartcard_accel(self, GDK_KEY_F8, GDK_SHIFT_MASK);
@@ -1890,25 +1890,92 @@ virt_viewer_app_constructed(GObject *object)
gtk_accel_map_add_entry("<virt-viewer>/view/zoom-out", GDK_KEY_minus, GDK_CONTROL_MASK);
gtk_accel_map_add_entry("<virt-viewer>/view/zoom-in", GDK_KEY_plus, GDK_CONTROL_MASK);
gtk_accel_map_add_entry("<virt-viewer>/send/secure-attention", GDK_KEY_End, GDK_CONTROL_MASK | GDK_MOD1_MASK);
+
+ if (!virt_viewer_app_start(self, &error)) {
+ if (error && !g_error_matches(error, VIRT_VIEWER_ERROR, VIRT_VIEWER_ERROR_CANCELLED))
+ virt_viewer_app_simple_message_dialog(self, error->message);
+
+ g_clear_error(&error);
+ g_application_quit(app);
+ return;
+ }
+
+ g_application_hold(app);
+}
+
+static gboolean
+virt_viewer_app_local_command_line (GApplication *gapp,
+ gchar ***args,
+ int *status)
+{
+ VirtViewerApp *self = VIRT_VIEWER_APP(gapp);
+ gboolean ret = FALSE;
+ gint argc = g_strv_length(*args);
+ GError *error = NULL;
+ GOptionContext *context = g_option_context_new(NULL);
+ GOptionGroup *group = g_option_group_new("virt-viewer", NULL, NULL, gapp, NULL);
+
+ *status = 0;
+ g_option_context_set_main_group(context, group);
+ VIRT_VIEWER_APP_GET_CLASS(self)->add_option_entries(self, context, group);
+
+ g_option_context_add_group(context, gtk_get_option_group(TRUE));
+
+#ifdef HAVE_GTK_VNC
+ g_option_context_add_group(context, vnc_display_get_option_group());
+#endif
+
+#ifdef HAVE_SPICE_GTK
+ g_option_context_add_group(context, spice_get_option_group());
+#endif
+
+ if (!g_option_context_parse(context, &argc, args, &error)) {
+ if (error != NULL) {
+ g_printerr(_("%s\n"), error->message);
+ g_error_free(error);
+ }
+
+ *status = 1;
+ ret = TRUE;
+ goto end;
+ }
+
+ if (opt_version) {
+ g_print(_("%s version %s"), g_get_prgname(), VERSION BUILDID);
+#ifdef REMOTE_VIEWER_OS_ID
+ g_print(" (OS ID: %s)", REMOTE_VIEWER_OS_ID);
+#endif
+ g_print("\n");
+ ret = TRUE;
+ }
+
+end:
+ g_option_context_free(context);
+ return ret;
}
static void
virt_viewer_app_class_init (VirtViewerAppClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GApplicationClass *g_app_class = G_APPLICATION_CLASS(klass);
g_type_class_add_private (klass, sizeof (VirtViewerAppPrivate));
- object_class->constructed = virt_viewer_app_constructed;
object_class->get_property = virt_viewer_app_get_property;
object_class->set_property = virt_viewer_app_set_property;
object_class->dispose = virt_viewer_app_dispose;
+ g_app_class->local_command_line = virt_viewer_app_local_command_line;
+ g_app_class->startup = virt_viewer_app_on_application_startup;
+ g_app_class->command_line = NULL; /* inhibit GApplication default handler */
+
klass->start = virt_viewer_app_default_start;
klass->initial_connect = virt_viewer_app_default_initial_connect;
klass->activate = virt_viewer_app_default_activate;
klass->deactivated = virt_viewer_app_default_deactivated;
klass->open_connection = virt_viewer_app_default_open_connection;
+ klass->add_option_entries = virt_viewer_app_add_option_entries;
g_object_class_install_property(object_class,
PROP_VERBOSE,
@@ -2014,28 +2081,6 @@ virt_viewer_app_class_init (VirtViewerAppClass *klass)
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_STATIC_STRINGS));
-
- signals[SIGNAL_WINDOW_ADDED] =
- g_signal_new("window-added",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(VirtViewerAppClass, window_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
- G_TYPE_OBJECT);
-
- signals[SIGNAL_WINDOW_REMOVED] =
- g_signal_new("window-removed",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(VirtViewerAppClass, window_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
- G_TYPE_OBJECT);
}
void
@@ -2575,10 +2620,14 @@ option_kiosk_quit(G_GNUC_UNUSED const gchar *option_name,
return FALSE;
}
-GOptionGroup*
-virt_viewer_app_get_option_group(void)
+static void
+virt_viewer_app_add_option_entries(G_GNUC_UNUSED VirtViewerApp *self,
+ G_GNUC_UNUSED GOptionContext *context,
+ GOptionGroup *group)
{
static const GOptionEntry options [] = {
+ { "version", 'V', 0, G_OPTION_ARG_NONE, &opt_version,
+ N_("Display version information"), NULL },
{ "zoom", 'z', 0, G_OPTION_ARG_INT, &opt_zoom,
N_("Zoom level of window, in percentage"), "ZOOM" },
{ "full-screen", 'f', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
@@ -2595,11 +2644,8 @@ virt_viewer_app_get_option_group(void)
N_("Display debugging information"), NULL },
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
};
- GOptionGroup *group;
- group = g_option_group_new("virt-viewer", NULL, NULL, NULL, NULL);
- g_option_group_add_entries(group, options);
- return group;
+ g_option_group_add_entries(group, options);
}
gboolean virt_viewer_app_get_session_cancelled(VirtViewerApp *self)
diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h
index bbbc9b4..7f6c401 100644
--- a/src/virt-viewer-app.h
+++ b/src/virt-viewer-app.h
@@ -24,6 +24,7 @@
#define VIRT_VIEWER_APP_H
#include <glib-object.h>
+#include <gtk/gtk.h>
#include "virt-viewer-util.h"
#include "virt-viewer-window.h"
@@ -39,16 +40,12 @@ G_BEGIN_DECLS
typedef struct _VirtViewerAppPrivate VirtViewerAppPrivate;
typedef struct {
- GObject parent;
+ GtkApplication parent;
VirtViewerAppPrivate *priv;
} VirtViewerApp;
typedef struct {
- GObjectClass parent_class;
-
- /* signals */
- void (*window_added) (VirtViewerApp *self, VirtViewerWindow *window);
- void (*window_removed) (VirtViewerApp *self, VirtViewerWindow *window);
+ GtkApplicationClass parent_class;
/*< private >*/
gboolean (*start) (VirtViewerApp *self, GError **error);
@@ -56,6 +53,7 @@ typedef struct {
gboolean (*activate) (VirtViewerApp *self, GError **error);
void (*deactivated) (VirtViewerApp *self, gboolean connect_error);
gboolean (*open_connection)(VirtViewerApp *self, int *fd);
+ void (*add_option_entries)(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group);
} VirtViewerAppClass;
GType virt_viewer_app_get_type (void);
@@ -95,7 +93,6 @@ GList* virt_viewer_app_get_windows(VirtViewerApp *self);
gboolean virt_viewer_app_get_enable_accel(VirtViewerApp *self);
VirtViewerSession* virt_viewer_app_get_session(VirtViewerApp *self);
gboolean virt_viewer_app_get_fullscreen(VirtViewerApp *app);
-GOptionGroup* virt_viewer_app_get_option_group(void);
void virt_viewer_app_clear_hotkeys(VirtViewerApp *app);
GList* virt_viewer_app_get_initial_displays(VirtViewerApp* self);
gint virt_viewer_app_get_initial_monitor_for_display(VirtViewerApp* self, gint display);
diff --git a/src/virt-viewer-main.c b/src/virt-viewer-main.c
index 505b472..56521f2 100644
--- a/src/virt-viewer-main.c
+++ b/src/virt-viewer-main.c
@@ -22,121 +22,23 @@
#include <config.h>
#include <locale.h>
+#include <gio/gio.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <stdlib.h>
-#ifdef HAVE_GTK_VNC
-#include <vncdisplay.h>
-#endif
-#ifdef HAVE_SPICE_GTK
-#include <spice-option.h>
-#endif
-#include "virt-viewer.h"
-
-static void virt_viewer_version(void)
-{
- g_print(_("%s version %s\n"), PACKAGE, VERSION BUILDID);
-
- exit(EXIT_SUCCESS);
-}
+#include "virt-viewer.h"
int main(int argc, char **argv)
{
- GOptionContext *context;
- GError *error = NULL;
int ret = 1;
- char *uri = NULL;
- gchar **args = NULL;
- gboolean direct = FALSE;
- gboolean attach = FALSE;
- gboolean waitvm = FALSE;
- gboolean reconnect = FALSE;
- VirtViewer *viewer = NULL;
- char *base_name;
- char *help_msg = NULL;
- const GOptionEntry options [] = {
- { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- virt_viewer_version, N_("Display version information"), NULL },
- { "direct", 'd', 0, G_OPTION_ARG_NONE, &direct,
- N_("Direct connection with no automatic tunnels"), NULL },
- { "attach", 'a', 0, G_OPTION_ARG_NONE, &attach,
- N_("Attach to the local display using libvirt"), NULL },
- { "connect", 'c', 0, G_OPTION_ARG_STRING, &uri,
- N_("Connect to hypervisor"), "URI"},
- { "wait", 'w', 0, G_OPTION_ARG_NONE, &waitvm,
- N_("Wait for domain to start"), NULL },
- { "reconnect", 'r', 0, G_OPTION_ARG_NONE, &reconnect,
- N_("Reconnect to domain upon restart"), NULL },
- { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &args,
- NULL, "-- DOMAIN-NAME|ID|UUID" },
- { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
- };
- GOptionGroup* app_options = NULL;
+ GApplication *app= NULL;
virt_viewer_util_init(_("Virt Viewer"));
+ app = G_APPLICATION(virt_viewer_new());
- base_name = g_path_get_basename(argv[0]);
- help_msg = g_strdup_printf(_("Run '%s --help' to see a full list of available command line options"),
- base_name);
- g_free(base_name);
-
- /* Setup command line options */
- context = g_option_context_new (NULL);
- g_option_context_set_summary (context, _("Virtual machine graphical console"));
- app_options = virt_viewer_app_get_option_group();
- g_option_group_add_entries (app_options, options);
- g_option_context_set_main_group (context, app_options);
- g_option_context_add_group (context, gtk_get_option_group (TRUE));
-#ifdef HAVE_GTK_VNC
- g_option_context_add_group (context, vnc_display_get_option_group ());
-#endif
-#ifdef HAVE_SPICE_GTK
- g_option_context_add_group (context, spice_get_option_group ());
-#endif
- g_option_context_parse (context, &argc, &argv, &error);
- if (error) {
- g_printerr("%s\n%s\n",
- error->message, help_msg);
- goto cleanup;
- }
-
- g_option_context_free(context);
-
- if (args && (g_strv_length(args) != 1)) {
- g_printerr(_("\nUsage: %s [OPTIONS] [DOMAIN-NAME|ID|UUID]\n\n%s\n\n"), argv[0], help_msg);
- goto cleanup;
- }
-
- if (args == NULL && waitvm) {
- g_printerr(_("\nNo DOMAIN-NAME|ID|UUID was specified for '--wait'\n\n"));
- goto cleanup;
- }
-
- viewer = virt_viewer_new(uri, (args) ? args[0] : NULL, direct, attach, waitvm, reconnect);
- if (viewer == NULL)
- goto cleanup;
-
- if (!virt_viewer_app_start(VIRT_VIEWER_APP(viewer), &error)) {
- if (g_error_matches(error, VIRT_VIEWER_ERROR, VIRT_VIEWER_ERROR_CANCELLED))
- ret = 0;
- else if (error) {
- virt_viewer_app_simple_message_dialog(VIRT_VIEWER_APP(viewer), error->message);
- }
- goto cleanup;
- }
-
- gtk_main();
-
- ret = 0;
-
- cleanup:
- if (viewer)
- g_object_unref(viewer);
- g_free(uri);
- g_strfreev(args);
- g_free(help_msg);
- g_clear_error(&error);
+ ret = g_application_run(app, argc, argv);
+ g_object_unref(app);
return ret;
}
diff --git a/src/virt-viewer-util.h b/src/virt-viewer-util.h
index f1cb08b..0a7dd97 100644
--- a/src/virt-viewer-util.h
+++ b/src/virt-viewer-util.h
@@ -30,7 +30,7 @@ extern gboolean doDebug;
enum {
VIRT_VIEWER_ERROR_FAILED,
- VIRT_VIEWER_ERROR_CANCELLED,
+ VIRT_VIEWER_ERROR_CANCELLED
};
#define VIRT_VIEWER_ERROR virt_viewer_error_quark ()
diff --git a/src/virt-viewer.c b/src/virt-viewer.c
index 10f624d..647c76a 100644
--- a/src/virt-viewer.c
+++ b/src/virt-viewer.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <unistd.h>
#include <locale.h>
+#include <gio/gio.h>
#include <glib/gprintf.h>
#include <glib/gi18n.h>
@@ -73,11 +74,93 @@ static gboolean virt_viewer_start(VirtViewerApp *self, GError **error);
static void virt_viewer_dispose (GObject *object);
static int virt_viewer_connect(VirtViewerApp *app, GError **error);
+static gchar **opt_args = NULL;
+static gchar *opt_uri = NULL;
+static gboolean opt_direct = FALSE;
+static gboolean opt_attach = FALSE;
+static gboolean opt_waitvm = FALSE;
+static gboolean opt_reconnect = FALSE;
+
+static void
+virt_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group)
+{
+ static const GOptionEntry options[] = {
+ { "direct", 'd', 0, G_OPTION_ARG_NONE, &opt_direct,
+ N_("Direct connection with no automatic tunnels"), NULL },
+ { "attach", 'a', 0, G_OPTION_ARG_NONE, &opt_attach,
+ N_("Attach to the local display using libvirt"), NULL },
+ { "connect", 'c', 0, G_OPTION_ARG_STRING, &opt_uri,
+ N_("Connect to hypervisor"), "URI"},
+ { "wait", 'w', 0, G_OPTION_ARG_NONE, &opt_waitvm,
+ N_("Wait for domain to start"), NULL },
+ { "reconnect", 'r', 0, G_OPTION_ARG_NONE, &opt_reconnect,
+ N_("Reconnect to domain upon restart"), NULL },
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_args,
+ NULL, "-- DOMAIN-NAME|ID|UUID" },
+ { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
+ };
+
+ VIRT_VIEWER_APP_CLASS(virt_viewer_parent_class)->add_option_entries(self, context, group);
+ g_option_context_set_summary(context, _("Virtual machine graphical console"));
+ g_option_group_add_entries(group, options);
+}
+
+static gboolean
+virt_viewer_local_command_line (GApplication *gapp,
+ gchar ***args,
+ int *status)
+{
+ gboolean ret = FALSE;
+ VirtViewer *self = VIRT_VIEWER(gapp);
+ VirtViewerApp *app = VIRT_VIEWER_APP(gapp);
+
+ ret = G_APPLICATION_CLASS(virt_viewer_parent_class)->local_command_line(gapp, args, status);
+ if (ret)
+ goto end;
+
+ if (opt_args) {
+ if (g_strv_length(opt_args) != 1) {
+ g_printerr(_("\nUsage: %s [OPTIONS] [DOMAIN-NAME|ID|UUID]\n\n"), PACKAGE);
+ ret = TRUE;
+ *status = 1;
+ goto end;
+ }
+
+ self->priv->domkey = g_strdup(opt_args[0]);
+ }
+
+
+ if (opt_waitvm) {
+ if (!self->priv->domkey) {
+ g_printerr(_("\nNo DOMAIN-NAME|ID|UUID was specified for '--wait'\n\n"));
+ ret = TRUE;
+ *status = 1;
+ goto end;
+ }
+
+ self->priv->waitvm = TRUE;
+ }
+
+ virt_viewer_app_set_direct(app, opt_direct);
+ virt_viewer_app_set_attach(app, opt_attach);
+ self->priv->reconnect = opt_reconnect;
+ self->priv->uri = g_strdup(opt_uri);
+
+end:
+ if (ret && *status)
+ g_printerr(_("Run '%s --help' to see a full list of available command line options\n"), g_get_prgname());
+
+ g_strfreev(opt_args);
+ g_free(opt_uri);
+ return ret;
+}
+
static void
virt_viewer_class_init (VirtViewerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
VirtViewerAppClass *app_class = VIRT_VIEWER_APP_CLASS (klass);
+ GApplicationClass *g_app_class = G_APPLICATION_CLASS(klass);
g_type_class_add_private (klass, sizeof (VirtViewerPrivate));
@@ -87,6 +170,9 @@ virt_viewer_class_init (VirtViewerClass *klass)
app_class->deactivated = virt_viewer_deactivated;
app_class->open_connection = virt_viewer_open_connection;
app_class->start = virt_viewer_start;
+ app_class->add_option_entries = virt_viewer_add_option_entries;
+
+ g_app_class->local_command_line = virt_viewer_local_command_line;
}
static void
@@ -106,7 +192,7 @@ virt_viewer_connect_timer(void *opaque)
if (!virt_viewer_app_is_active(app) &&
!virt_viewer_app_initial_connect(app, NULL))
- gtk_main_quit();
+ g_application_quit(G_APPLICATION(app));
if (virt_viewer_app_is_active(app)) {
self->priv->reconnect_poll = 0;
@@ -976,33 +1062,12 @@ virt_viewer_start(VirtViewerApp *app, GError **error)
}
VirtViewer *
-virt_viewer_new(const char *uri,
- const char *name,
- gboolean direct,
- gboolean attach,
- gboolean waitvm,
- gboolean reconnect)
+virt_viewer_new(void)
{
- VirtViewer *self;
- VirtViewerApp *app;
- VirtViewerPrivate *priv;
-
- self = g_object_new(VIRT_VIEWER_TYPE,
- "guest-name", name,
+ return g_object_new(VIRT_VIEWER_TYPE,
+ "application-id", "org.virt-manager.virt-viewer",
+ "flags", G_APPLICATION_NON_UNIQUE,
NULL);
- app = VIRT_VIEWER_APP(self);
- priv = self->priv;
-
- virt_viewer_app_set_direct(app, direct);
- virt_viewer_app_set_attach(app, attach);
-
- /* should probably be properties instead */
- priv->uri = g_strdup(uri);
- priv->domkey = g_strdup(name);
- priv->waitvm = waitvm;
- priv->reconnect = reconnect;
-
- return self;
}
/*
diff --git a/src/virt-viewer.h b/src/virt-viewer.h
index c962615..5aeacb0 100644
--- a/src/virt-viewer.h
+++ b/src/virt-viewer.h
@@ -48,13 +48,7 @@ typedef struct {
GType virt_viewer_get_type (void);
-VirtViewer *
-virt_viewer_new(const char *uri,
- const char *name,
- gboolean direct,
- gboolean attach,
- gboolean waitvm,
- gboolean reconnect);
+VirtViewer *virt_viewer_new (void);
G_END_DECLS
diff --git a/src/virt-viewer.xml b/src/virt-viewer.xml
index 07948bd..03f2f84 100644
--- a/src/virt-viewer.xml
+++ b/src/virt-viewer.xml
@@ -2,7 +2,7 @@
<interface>
<!-- interface-requires gtk+ 2.6 -->
<object class="GtkAccelGroup" id="accelgroup"/>
- <object class="GtkWindow" id="viewer">
+ <object class="GtkApplicationWindow" id="viewer">
<property name="can_focus">False</property>
<property name="default_width">1024</property>
<property name="default_height">768</property>