aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2008-09-25 10:49:10 +0000
committerkraxel <kraxel>2008-09-25 10:49:10 +0000
commitebe77c45fa12da6537b4bb903226ced6b7a63288 (patch)
tree288078a759d1cf46651d6e027f0d68321d217ccf
parenta3aa4e1df1e9f67ef8a0944d79666fc307416c00 (diff)
downloadqemu-gtk-ebe77c45fa12da6537b4bb903226ced6b7a63288.tar.gz
- rearrange menu a bit.
- wind up more monitor commands in menu. - add fullscreen mode. - handle password-protected vnc.
-rw-r--r--monitor.c33
-rw-r--r--qemu-gtk.c211
-rw-r--r--qemu-gtk.h7
3 files changed, 211 insertions, 40 deletions
diff --git a/monitor.c b/monitor.c
index 3a4c20a..b4f9c66 100644
--- a/monitor.c
+++ b/monitor.c
@@ -20,6 +20,21 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len)
char *reply, *prompt, *cmd;
int off;
+ if (win->vnc_send_password && win->mrun &&
+ !strcmp(win->mrun->cmd, "change vnc password") &&
+ strstr(buf, "Password: "))
+ {
+ char buf[64];
+ int len;
+
+ if (debug)
+ fprintf(stderr, "%s: password prompt\n", __FUNCTION__);
+ len = snprintf(buf, sizeof(buf), "%s\n", win->vnc_password);
+ write(win->monitor.handle, buf, len);
+ win->vnc_send_password = 0;
+ return 0;
+ }
+
prompt = strstr(buf, "(qemu) ");
if (NULL == prompt) {
return 0;
@@ -54,8 +69,22 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len)
} else if (0 == strcmp(cmd, "info vnc")) {
if (1 == sscanf(reply, "VNC server active on: %127[^\r\n]",
win->vnc_display) &&
- strstr(reply, "No client connected"))
- vnc_connect(win);
+ strstr(reply, "No client connected")) {
+ if (strstr(win->vnc_display, ",password")) {
+ win->vnc_password = malloc(32);
+#if 1
+ /* FIXME: do something less predictable */
+ srand(time(NULL)+getpid());
+ snprintf(win->vnc_password, 32, "%x", rand() & 0xfffffff);
+#endif
+ win->vnc_send_password = 1;
+ monitor_append(win, "change vnc password");
+ } else {
+ vnc_connect(win);
+ }
+ }
+ } else if (0 == strcmp(cmd, "change vnc password")) {
+ vnc_connect(win);
}
out:
diff --git a/qemu-gtk.c b/qemu-gtk.c
index e9ae9c0..80a7780 100644
--- a/qemu-gtk.c
+++ b/qemu-gtk.c
@@ -16,6 +16,8 @@
#include "qemu-gtk.h"
#include "tcp.h"
+#define APPNAME "qemu-gtk"
+
/* ------------------------------------------------------------------ */
static void vte_configure(GtkWidget *vte)
@@ -27,12 +29,19 @@ static void vte_configure(GtkWidget *vte)
static void tabs_configure(struct qemu_window *win)
{
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->tab)) == 1) {
- gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->tab), 0);
- gtk_notebook_set_show_border(GTK_NOTEBOOK(win->tab), 0);
- } else {
+ gboolean showtabs = 1;
+
+ if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->tab)) == 1)
+ showtabs = 0;
+ if (win->fullscreen)
+ showtabs = 0;
+
+ if (showtabs) {
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->tab), 1);
gtk_notebook_set_show_border(GTK_NOTEBOOK(win->tab), 1);
+ } else {
+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->tab), 0);
+ gtk_notebook_set_show_border(GTK_NOTEBOOK(win->tab), 0);
}
}
@@ -51,6 +60,42 @@ static void tabs_add(struct qemu_window *win, GtkWidget *child,
/* ------------------------------------------------------------------ */
+static void menu_cb_fullscreen(GtkToggleAction *action, gpointer userdata)
+{
+ struct qemu_window *win = userdata;
+ gboolean active;
+
+ active = gtk_toggle_action_get_active(action);
+ if (active) {
+ gtk_window_fullscreen(GTK_WINDOW(win->toplevel));
+ } else {
+ gtk_window_unfullscreen(GTK_WINDOW(win->toplevel));
+ }
+}
+
+static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event,
+ gpointer userdata)
+{
+ struct qemu_window *win = userdata;
+ GtkWidget *item;
+
+ if (!(event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN))
+ return TRUE;
+
+ win->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
+ item = gtk_ui_manager_get_widget(win->ui, "/MainMenu/ViewMenu/FullScreen");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), win->fullscreen);
+ tabs_configure(win);
+ if (win->fullscreen) {
+ gtk_widget_hide(win->fstatus);
+ } else {
+ gtk_widget_show(win->fstatus);
+ }
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------ */
+
static void menu_cb_scale_display(GtkToggleAction *action, gpointer userdata)
{
struct qemu_window *win = userdata;
@@ -60,6 +105,22 @@ static void menu_cb_scale_display(GtkToggleAction *action, gpointer userdata)
vnc_display_set_scaling(VNC_DISPLAY(win->vnc), active);
}
+static void menu_cb_about(GtkAction *action, gpointer userdata)
+{
+ static char *comments = "gtk ui for qemu";
+ static char *copyright = "(c) 2008 Gerd Hoffmann";
+ static char *authors[] = { "Gerd Hoffmann <kraxel@redhat.com>", NULL };
+ struct qemu_window *win = userdata;
+
+ gtk_show_about_dialog(GTK_WINDOW(win->toplevel),
+ "authors", authors,
+ "comments", comments,
+ "copyright", copyright,
+ "logo-icon-name", GTK_STOCK_ABOUT,
+ "version", VERSION,
+ NULL);
+}
+
static void menu_cb_close(GtkAction *action, gpointer userdata)
{
struct qemu_window *win = userdata;
@@ -78,6 +139,18 @@ static void menu_cb_monitor_cont(GtkAction *action, gpointer userdata)
monitor_append(win, "cont");
}
+static void menu_cb_monitor_sys_reset(GtkAction *action, gpointer userdata)
+{
+ struct qemu_window *win = userdata;
+ monitor_append(win, "system_reset");
+}
+
+static void menu_cb_monitor_sys_powerdown(GtkAction *action, gpointer userdata)
+{
+ struct qemu_window *win = userdata;
+ monitor_append(win, "system_powerdown");
+}
+
static void menu_cb_run_gdb(GtkAction *action, gpointer userdata)
{
struct qemu_window *win = userdata;
@@ -102,30 +175,39 @@ static void menu_cb_run_gdb(GtkAction *action, gpointer userdata)
void update_status(struct qemu_window *win)
{
- char msg[256];
- int len = 0;
+ char st[256];
+ char ti[256];
+ int tl, sl = 0;
- if (win->vnc_grab) {
- len = snprintf(msg, sizeof(msg), "Press Ctrl-Alt to release input grab.");
+ tl = snprintf(ti, sizeof(ti), "%s", APPNAME);
+
+ if (win->monitor.handle == -1) {
+ sl = snprintf(st, sizeof(st), "Not connected.");
goto out;
}
if (win->vnc_state == VNC_INITIALIZED) {
- len += snprintf(msg+len, sizeof(msg)-len, "VNC display \"%s\", %dx%d",
+ sl += snprintf(st+sl, sizeof(st)-sl, "VNC display \"%s\", %dx%d",
win->vnc_display, win->vnc_width, win->vnc_height);
} else {
- len += snprintf(msg+len, sizeof(msg)-len, "No VNC");
+ sl += snprintf(st+sl, sizeof(st)-sl, "No VNC");
}
-
if (win->version && strlen(win->version))
- len += snprintf(msg+len, sizeof(msg)-len, ", qemu %s", win->version);
- if (win->name && strlen(win->name))
- len += snprintf(msg+len, sizeof(msg)-len, ", name \"%s\"", win->name);
+ sl += snprintf(st+sl, sizeof(st)-sl, ", qemu %s", win->version);
+ if (win->name && strlen(win->name)) {
+ tl = snprintf(ti, sizeof(ti), "%s (%s)", win->name, APPNAME);
+ sl += snprintf(st+sl, sizeof(st)-sl, ", name \"%s\"", win->name);
+ }
+ sl += snprintf(st+sl, sizeof(st)-sl, ".");
- len += snprintf(msg+len, sizeof(msg)-len, ".");
+ if (win->vnc_grab) {
+ sl = snprintf(st, sizeof(st), "Press Ctrl-Alt to release input grab.");
+ goto out;
+ }
out:
- gtk_label_set_text(GTK_LABEL(win->status), msg);
+ gtk_window_set_title(GTK_WINDOW(win->toplevel), ti);
+ gtk_label_set_text(GTK_LABEL(win->status), st);
}
/* ------------------------------------------------------------------ */
@@ -177,8 +259,25 @@ static void vnc_credential(GtkWidget *vncdisplay,
GValueArray *credList,
void *data)
{
-// struct qemu_window *win = data;
- fprintf(stderr, "%s: FIXME\n", __FUNCTION__);
+ struct qemu_window *win = data;
+ char *val;
+ int i;
+
+ for (i = 0 ; i < credList->n_values ; i++) {
+ GValue *cred = g_value_array_get_nth(credList, i);
+ switch (g_value_get_enum(cred)) {
+ case VNC_DISPLAY_CREDENTIAL_PASSWORD:
+ val = win->vnc_password;
+ break;
+ default:
+ fprintf(stderr, "can't handle credential type %d\n",
+ g_value_get_enum(cred));
+ return;
+ }
+ vnc_display_set_credential(VNC_DISPLAY(win->vnc),
+ g_value_get_enum(cred),
+ val);
+ }
}
void vnc_connect(struct qemu_window *win)
@@ -294,26 +393,48 @@ static const GtkActionEntry entries[] = {
.name = "ViewMenu",
.label = "_View",
},{
- .name = "ActionMenu",
- .label = "_Actions",
+ .name = "VMMenu",
+ .label = "_VM",
+ },{
+ .name = "HelpMenu",
+ .label = "_Help",
+
},{
.name = "Close",
.stock_id = GTK_STOCK_CLOSE,
.label = "_Close",
.accelerator = "<control>Q",
.callback = G_CALLBACK(menu_cb_close),
+
},{
.name = "MonitorStop",
- .label = "_Pause VM",
+ .stock_id = GTK_STOCK_MEDIA_PAUSE,
+ .label = "_Pause",
.callback = G_CALLBACK(menu_cb_monitor_stop),
},{
.name = "MonitorCont",
- .label = "_Unpause VM",
+ .stock_id = GTK_STOCK_MEDIA_PLAY,
+ .label = "_Unpause",
.callback = G_CALLBACK(menu_cb_monitor_cont),
},{
+ .name = "MonitorSysReset",
+ .label = "_Reset",
+ .callback = G_CALLBACK(menu_cb_monitor_sys_reset),
+ },{
+ .name = "MonitorSysPowerdown",
+ .label = "_Shutdown",
+ .callback = G_CALLBACK(menu_cb_monitor_sys_powerdown),
+
+ },{
.name = "RunGdb",
.label = "_Debug with gdb",
.callback = G_CALLBACK(menu_cb_run_gdb),
+
+ },{
+ .name = "About",
+ .stock_id = GTK_STOCK_ABOUT,
+ .label = "_About ...",
+ .callback = G_CALLBACK(menu_cb_about),
},
};
@@ -322,6 +443,12 @@ static const GtkToggleActionEntry tentries[] = {
.name = "ScaleDisplay",
.label = "_Scale Display",
.callback = G_CALLBACK(menu_cb_scale_display),
+ },{
+ .name = "FullScreen",
+ .stock_id = GTK_STOCK_FULLSCREEN,
+ .label = "_Fullscreen",
+ .accelerator = "F11",
+ .callback = G_CALLBACK(menu_cb_fullscreen),
}
};
@@ -333,12 +460,20 @@ static char ui_xml[] =
" </menu>"
" <menu action='ViewMenu'>"
" <menuitem action='ScaleDisplay'/>"
+" <menuitem action='FullScreen'/>"
" </menu>"
-" <menu action='ActionMenu'>"
+" <menu action='VMMenu'>"
" <menuitem action='MonitorStop'/>"
" <menuitem action='MonitorCont'/>"
+" <menuitem action='MonitorSysPowerdown'/>"
+" <separator/>"
+" <menuitem action='MonitorSysReset'/>"
+" <separator/>"
" <menuitem action='RunGdb'/>"
" </menu>"
+" <menu action='HelpMenu'>"
+" <menuitem action='About'/>"
+" </menu>"
" </menubar>"
#ifdef WITH_TOOLBAR
" <toolbar action='ToolBar'>"
@@ -355,10 +490,9 @@ static void destroy(GtkWidget *widget, gpointer data)
static struct qemu_window *qemu_create_window(void)
{
struct qemu_window *win;
- GtkWidget *vbox, *menubar, *toolbar, *frame;
+ GtkWidget *vbox, *menubar, *toolbar;
GtkAccelGroup *accel;
GtkActionGroup *ag;
- GtkUIManager *ui;
GError *err;
win = malloc(sizeof(*win));
@@ -367,23 +501,25 @@ static struct qemu_window *qemu_create_window(void)
memset(win,0,sizeof(*win));
win->toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(win->toplevel), "qemu-gtk");
+ gtk_window_set_title(GTK_WINDOW(win->toplevel), APPNAME);
gtk_window_set_default_size(GTK_WINDOW(win->toplevel), 320, 280);
g_signal_connect(G_OBJECT(win->toplevel), "destroy",
G_CALLBACK(destroy), win);
+ g_signal_connect(G_OBJECT(win->toplevel), "window-state-event",
+ G_CALLBACK(window_state_cb), win);
/* menu + toolbar */
- ui = gtk_ui_manager_new();
+ win->ui = gtk_ui_manager_new();
ag = gtk_action_group_new("MenuActions");
gtk_action_group_add_actions(ag, entries, G_N_ELEMENTS(entries), win);
gtk_action_group_add_toggle_actions(ag, tentries,
G_N_ELEMENTS(tentries), win);
- gtk_ui_manager_insert_action_group(ui, ag, 0);
- accel = gtk_ui_manager_get_accel_group(ui);
+ gtk_ui_manager_insert_action_group(win->ui, ag, 0);
+ accel = gtk_ui_manager_get_accel_group(win->ui);
gtk_window_add_accel_group(GTK_WINDOW(win->toplevel), accel);
err = NULL;
- if (!gtk_ui_manager_add_ui_from_string(ui, ui_xml, -1, &err)) {
+ if (!gtk_ui_manager_add_ui_from_string(win->ui, ui_xml, -1, &err)) {
g_message("building menus failed: %s", err->message);
g_error_free(err);
exit(1);
@@ -403,16 +539,16 @@ static struct qemu_window *qemu_create_window(void)
vbox = gtk_vbox_new(FALSE, 1);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 1);
gtk_container_add(GTK_CONTAINER(win->toplevel), vbox);
- menubar = gtk_ui_manager_get_widget(ui, "/MainMenu");
+ menubar = gtk_ui_manager_get_widget(win->ui, "/MainMenu");
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
- toolbar = gtk_ui_manager_get_widget(ui, "/ToolBar");
+ toolbar = gtk_ui_manager_get_widget(win->ui, "/ToolBar");
if (toolbar)
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), win->tab, TRUE, TRUE, 0);
- frame = gtk_frame_new(NULL);
- gtk_box_pack_end(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
- gtk_container_add(GTK_CONTAINER(frame), win->status);
+ win->fstatus = gtk_frame_new(NULL);
+ gtk_box_pack_end(GTK_BOX(vbox), win->fstatus, FALSE, TRUE, 0);
+ gtk_container_add(GTK_CONTAINER(win->fstatus), win->status);
return win;
}
@@ -459,7 +595,7 @@ static void usage(FILE *fp)
fprintf(fp,
"This is a simple qemu gui\n"
"\n"
- "usage: qemu-gtk [ options ] monitor\n"
+ "usage: %s [ options ] monitor\n"
"options:\n"
" -h Print this text.\n"
" -d Raise debug level.\n"
@@ -467,7 +603,8 @@ static void usage(FILE *fp)
" -c <dev> Show serial console.\n"
"\n"
"-- \n"
- "(c) 2008 Gerd Hoffmann <kraxel@redhat.com>\n");
+ "(c) 2008 Gerd Hoffmann <kraxel@redhat.com>\n",
+ APPNAME);
}
int
diff --git a/qemu-gtk.h b/qemu-gtk.h
index aca2565..5cb9848 100644
--- a/qemu-gtk.h
+++ b/qemu-gtk.h
@@ -24,8 +24,11 @@ struct qemu_conn {
struct qemu_window {
/* widgets */
- GtkWidget *toplevel, *status;
+ GtkWidget *toplevel;
+ GtkWidget *status, *fstatus;
GtkWidget *tab, *vnc;
+ GtkUIManager *ui;
+ gboolean fullscreen;
/* vnc (gfx) */
char vnc_display[128];
@@ -35,6 +38,8 @@ struct qemu_window {
int vnc_grab;
int vnc_width;
int vnc_height;
+ char *vnc_password;
+ int vnc_send_password;
/* console (text) */
struct qemu_conn console;