mirror of
https://gitlab.com/virt-viewer/virt-viewer.git
synced 2025-01-10 01:17:47 +03:00
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>
This commit is contained in:
parent
7a54b96dbe
commit
a9ce19f848
@ -12,10 +12,10 @@ AC_CANONICAL_HOST
|
||||
m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
GLIB2_REQUIRED=2.22.0
|
||||
GLIB2_REQUIRED="2.38.0"
|
||||
LIBXML2_REQUIRED="2.6.0"
|
||||
LIBVIRT_REQUIRED="0.10.0"
|
||||
GTK_REQUIRED="3.0"
|
||||
GTK_REQUIRED="3.10"
|
||||
GTK_VNC_REQUIRED="0.4.0"
|
||||
SPICE_GTK_REQUIRED="0.30"
|
||||
SPICE_PROTOCOL_REQUIRED="0.12.7"
|
||||
@ -93,7 +93,7 @@ PKG_PROG_PKG_CONFIG
|
||||
GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
|
||||
AC_SUBST(GLIB_MKENUMS)
|
||||
|
||||
PKG_CHECK_MODULES(GLIB2, glib-2.0 >= $GLIB2_REQUIRED gthread-2.0 gmodule-export-2.0)
|
||||
PKG_CHECK_MODULES(GLIB2, glib-2.0 >= $GLIB2_REQUIRED gio-2.0 gthread-2.0 gmodule-export-2.0)
|
||||
PKG_CHECK_MODULES(LIBXML2, libxml-2.0 >= $LIBXML2_REQUIRED)
|
||||
|
||||
AC_ARG_WITH([libvirt],
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 ()
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user