diff options
author | kraxel <kraxel> | 2008-09-25 10:49:10 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2008-09-25 10:49:10 +0000 |
commit | ebe77c45fa12da6537b4bb903226ced6b7a63288 (patch) | |
tree | 288078a759d1cf46651d6e027f0d68321d217ccf | |
parent | a3aa4e1df1e9f67ef8a0944d79666fc307416c00 (diff) | |
download | qemu-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.c | 33 | ||||
-rw-r--r-- | qemu-gtk.c | 211 | ||||
-rw-r--r-- | qemu-gtk.h | 7 |
3 files changed, 211 insertions, 40 deletions
@@ -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: @@ -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 @@ -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; |