diff options
author | kraxel <kraxel> | 2007-07-18 08:19:06 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2007-07-18 08:19:06 +0000 |
commit | 1abb391559d2a32ada784390952abd2536786312 (patch) | |
tree | 3769c332ce7efb4a8dbcf50b1941177b7b0ae6ed | |
parent | 490c34d9eb570a9e21d9a984491411e6bde6e433 (diff) | |
download | xenwatch-1abb391559d2a32ada784390952abd2536786312.tar.gz |
vnc polishing
-rw-r--r-- | vnc-client.c | 6 | ||||
-rw-r--r-- | vnc.c | 317 | ||||
-rw-r--r-- | vnc.h | 1 |
3 files changed, 254 insertions, 70 deletions
diff --git a/vnc-client.c b/vnc-client.c index 331fc86..56599f6 100644 --- a/vnc-client.c +++ b/vnc-client.c @@ -26,6 +26,7 @@ static void usage(FILE *fp) " -d Enable debug output.\n" " -u Send us kbd layout keysyms.\n" " -p Show mouse pointer.\n" + " -f Start in fullscreen mode.\n" " -g Enable OpenGL for fullscreen mode.\n" " -G Enable OpenGL unconditionally.\n" " -o View only.\n" @@ -45,7 +46,7 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); for (;;) { - if (-1 == (c = getopt(argc, argv, "hdupgGo"))) + if (-1 == (c = getopt(argc, argv, "hdupfgGo"))) break; switch (c) { case 'd': @@ -66,6 +67,9 @@ main(int argc, char *argv[]) case 'G': vnc_flags |= VNC_FLAG_GL_ALLWAYS; break; + case 'f': + vnc_flags |= VNC_FLAG_FULLSCREEN; + break; case 'h': usage(stdout); exit(0); @@ -46,9 +46,12 @@ struct vnc_window { guint id, connected; /* gtk */ + GtkAccelGroup *ac; + GtkActionGroup *ag; + GtkUIManager *ui; GtkWidget *win; GtkWidget *draw; - GtkWidget *line, *res, *fs, *kbd, *ptr, *view; + GtkWidget *line, *res, *mbutton, *popup; GdkCursor *on,*off; int filter_installed; int input_grabbed; @@ -99,6 +102,7 @@ static int linux_uskbd_size = sizeof(linux_uskbd)/sizeof(linux_uskbd[0]); static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, gpointer data); static void vnc_window_conf(struct vnc_window *vnc); +static void vnc_window_texts(struct vnc_window *vnc); /* ------------------------------------------------------------------ */ /* opengl bits */ @@ -470,6 +474,8 @@ static void dpy_setup(struct vnc_window *vnc, int width, int height, int using_g fprintf(stderr, "%s: SetFormatAndEncodings: %s\n", __FUNCTION__, using_gl ? "GL" : "X11" ); SetFormatAndEncodings(vnc->client); + SendFramebufferUpdateRequest(vnc->client, 0, 0, + vnc->vncdpy.w, vnc->vncdpy.h, False); vnc_window_conf(vnc); } @@ -491,6 +497,7 @@ static void dpy_resize_window(struct vnc_window *vnc) gl_resize_window(vnc); dpy_redraw(vnc); } + vnc_window_texts(vnc); } /* ------------------------------------------------------------------ */ @@ -521,6 +528,7 @@ static GdkCursor* empty_cursor(void) static void vnc_window_texts(struct vnc_window *vnc) { char textline[256]; + int pos; if (vnc->client && vnc->client->desktopName && strlen(vnc->client->desktopName)) { @@ -541,25 +549,23 @@ static void vnc_window_texts(struct vnc_window *vnc) } if (vnc->client) { - snprintf(textline, sizeof(textline), "%dx%d", - vnc->vncdpy.w, vnc->vncdpy.h); + pos = 0; + pos += snprintf(textline+pos, sizeof(textline)-pos, "%dx%d", + vnc->vncdpy.w, vnc->vncdpy.h); + if (vnc->vncdpy.w != vnc->window.w || + vnc->vncdpy.h != vnc->window.h) + pos += snprintf(textline+pos, sizeof(textline)-pos, " @ %dx%d", + vnc->window.w, vnc->window.h); + pos += snprintf(textline+pos, sizeof(textline)-pos, " (%s)", + vnc->ximage ? "X11" : "GL"); gtk_label_set_text(GTK_LABEL(vnc->res), textline); } - gtk_button_set_label(GTK_BUTTON(vnc->fs), - vnc->fullscreen ? "FS: on" : "FS: off"); - gtk_button_set_label(GTK_BUTTON(vnc->kbd), - vnc->uskbd ? "kbd: us" : "kbd: local"); - gtk_button_set_label(GTK_BUTTON(vnc->ptr), - vnc->showpointer ? "ptr: visible" : "ptr: hidden"); - gtk_button_set_label(GTK_BUTTON(vnc->view), - vnc->viewonly ? "viewonly" : "input ok"); } static void vnc_window_conf(struct vnc_window *vnc) { if (!vnc->draw) return; - vnc_window_texts(vnc); if (vnc->client) gtk_widget_set_size_request(vnc->draw, vnc->vncdpy.w, vnc->vncdpy.h); if (vnc->draw->window) { @@ -805,13 +811,15 @@ static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event, gpointer data) { struct vnc_window *vnc = data; + GtkWidget *item; if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { vnc->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; if (vnc->debug) fprintf(stderr, "%s: fullscreen %s\n", __FUNCTION__, vnc->fullscreen ? "on" : "off"); - vnc_window_texts(vnc); + item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/FullScreen"); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->fullscreen); } return TRUE; } @@ -860,7 +868,21 @@ static void send_mouse(struct vnc_window *vnc, int x, int y, rfbstate &= ~buttons[i].rfbmask; } - /* FIXME: fixup mouse coordinates */ + /* fixup mouse coordinates */ + x -= vnc->vncoff.x; + y -= vnc->vncoff.y; + if (vnc->tex) { + x = x * vnc->window.w / vnc->vncdpy.w; + y = y * vnc->window.h / vnc->vncdpy.h; + } + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (x >= vnc->vncdpy.w) + x = vnc->vncdpy.w -1; + if (y >= vnc->vncdpy.h) + y = vnc->vncdpy.h -1; if (vnc->debug) fprintf(stderr,"%s: +%d+%d x11state 0x%x rfbstate 0x%x\n", @@ -952,42 +974,12 @@ static gboolean key_cb(GtkWidget *widget, GdkEventKey *event, return TRUE; } -static void fs_btn(GtkWidget *widget, gpointer data) -{ - struct vnc_window *vnc = data; - - vnc->fullscreen = !vnc->fullscreen; - if (vnc->fullscreen) - gtk_window_fullscreen(GTK_WINDOW(vnc->win)); - else - gtk_window_unfullscreen(GTK_WINDOW(vnc->win)); -} - -static void kbd_btn(GtkWidget *widget, gpointer data) +static void menu_btn(GtkWidget *widget, gpointer data) { struct vnc_window *vnc = data; - vnc->uskbd = !vnc->uskbd; - vnc_window_texts(vnc); -} - -static void ptr_btn(GtkWidget *widget, gpointer data) -{ - struct vnc_window *vnc = data; - - vnc->showpointer = !vnc->showpointer; - if (vnc->draw->window) - gdk_window_set_cursor(vnc->draw->window, - vnc->showpointer ? vnc->on : vnc->off); - vnc_window_texts(vnc); -} - -static void view_btn(GtkWidget *widget, gpointer data) -{ - struct vnc_window *vnc = data; - - vnc->viewonly = !vnc->viewonly; - vnc_window_texts(vnc); + gtk_menu_popup(GTK_MENU(vnc->popup), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time()); } static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, @@ -1031,12 +1023,174 @@ static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, } /* ------------------------------------------------------------------ */ + +static void menu_cb_full_screen(GtkToggleAction *action, gpointer user_data) +{ + struct vnc_window *vnc = user_data; + + vnc->fullscreen = gtk_toggle_action_get_active(action); + if (vnc->fullscreen) + gtk_window_fullscreen(GTK_WINDOW(vnc->win)); + else + gtk_window_unfullscreen(GTK_WINDOW(vnc->win)); +} + +static void menu_cb_us_keyboard(GtkToggleAction *action, gpointer user_data) +{ + struct vnc_window *vnc = user_data; + + vnc->uskbd = gtk_toggle_action_get_active(action); +} + +static void menu_cb_show_pointer(GtkToggleAction *action, gpointer user_data) +{ + struct vnc_window *vnc = user_data; + + vnc->showpointer = gtk_toggle_action_get_active(action); + if (vnc->draw->window) + gdk_window_set_cursor(vnc->draw->window, + vnc->showpointer ? vnc->on : vnc->off); +} + +static void menu_cb_view_only(GtkToggleAction *action, gpointer user_data) +{ + struct vnc_window *vnc = user_data; + + vnc->viewonly = gtk_toggle_action_get_active(action); +} + +static void menu_cb_gl(GtkRadioAction *action, GtkRadioAction *current, + gpointer user_data) +{ + struct vnc_window *vnc = user_data; + int value = gtk_radio_action_get_current_value(action); + + switch (value) { + case 1: /* OFF */ + vnc->gl_fullscreen = 0; + vnc->gl_allways = 0; + break; + case 2: /* fullscreen ON */ + vnc->gl_fullscreen = 1; + vnc->gl_allways = 0; + break; + case 3: /* allways ON */ + vnc->gl_fullscreen = 1; + vnc->gl_allways = 1; + break; + } + dpy_resize_window(vnc); +} + +static void menu_cb_about(GtkMenuItem *item, void *user_data) +{ + static char *comments = "simple vnc client"; + static char *copyright = "(c) 2005-2007 Gerd Hoffmann"; + static char *authors[] = { "Gerd Hoffmann <kraxel@redhat.com>", NULL }; + struct vnc_window *vnc = user_data; + + gtk_show_about_dialog(GTK_WINDOW(vnc->win), + "authors", authors, + "comments", comments, + "copyright", copyright, + "logo-icon-name", GTK_STOCK_ABOUT, + "version", VERSION, + NULL); +} + +static void menu_cb_quit(GtkMenuItem *item, void *user_data) +{ + struct vnc_window *vnc = user_data; + + gtk_widget_destroy(vnc->win); +} + +/* ------------------------------------------------------------------ */ + +static const GtkActionEntry entries[] = { + { + /* popup menu */ + .name = "ConfMenu", + .label = "Config", + },{ + /* menu items */ + .name = "About", + .stock_id = GTK_STOCK_ABOUT, + .label = "_About ...", + .callback = G_CALLBACK(menu_cb_about), + },{ + .name = "Close", + .stock_id = GTK_STOCK_QUIT, + .label = "_Close", +// .accelerator = "<control>Q", + .tooltip = "Quit the job", + .callback = G_CALLBACK(menu_cb_quit), + } +}; + +static const GtkToggleActionEntry tentries[] = { + { + .name = "FullScreen", + .label = "_Fullscreen", + .accelerator = "F11", + .callback = G_CALLBACK(menu_cb_full_screen), + },{ + .name = "USKbd", + .label = "US _Keyboard", + .callback = G_CALLBACK(menu_cb_us_keyboard), + },{ + .name = "ShowPointer", + .label = "Show _Pointer", + .callback = G_CALLBACK(menu_cb_show_pointer), + },{ + .name = "ViewOnly", + .label = "_View only", + .callback = G_CALLBACK(menu_cb_view_only), + } +}; + +static const GtkRadioActionEntry rentries[] = { + { + .name = "GL_OFF", + .label = "_Disable OpenGL scaling", + .value = 1, + },{ + .name = "GL_FSonly", + .label = "OpenGL scaling for fullscreen", + .value = 2, + },{ + .name = "GL_ON", + .label = "Allways scale using _OpenGL", + .value = 3, + } +}; + +static char ui_xml[] = +"<ui>" +" <popup action='ConfMenu'>" +" <menuitem action='FullScreen'/>" +" <menuitem action='USKbd'/>" +" <menuitem action='ShowPointer'/>" +" <menuitem action='ViewOnly'/>" +" <separator/>" +" <menuitem action='GL_OFF'/>" +" <menuitem action='GL_FSonly'/>" +" <menuitem action='GL_ON'/>" +" <separator/>" +" <menuitem action='About'/>" +" <menuitem action='Close'/>" +" </popup>" +"</ui>"; + +/* ------------------------------------------------------------------ */ /* public API functions */ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, int debug_level) { - GtkWidget *vbox, *hbox, *frame; + GtkWidget *vbox, *hbox, *frame, *item; + GtkAction *action; + GError *err; char *argv[] = { "vnc-client", NULL, NULL }; int argc = sizeof(argv)/sizeof(argv[0]) -1; struct vnc_window *vnc; @@ -1104,25 +1258,51 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, gdk_window_add_filter(NULL, event_filter, vnc); vnc->filter_installed = 1; + /* popup menu */ + vnc->ui = gtk_ui_manager_new(); + vnc->ag = gtk_action_group_new("MenuActions"); + gtk_action_group_add_actions(vnc->ag, entries, G_N_ELEMENTS(entries), vnc); + gtk_action_group_add_toggle_actions(vnc->ag, tentries, + G_N_ELEMENTS(tentries), vnc); + gtk_action_group_add_radio_actions(vnc->ag, rentries, + G_N_ELEMENTS(rentries), + 0, G_CALLBACK(menu_cb_gl), vnc); + gtk_ui_manager_insert_action_group(vnc->ui, vnc->ag, 0); + vnc->ac = gtk_ui_manager_get_accel_group(vnc->ui); + gtk_window_add_accel_group(GTK_WINDOW(vnc->win), vnc->ac); + + err = NULL; + if (!gtk_ui_manager_add_ui_from_string(vnc->ui, ui_xml, -1, &err)) { + g_message("building menus failed: %s", err->message); + g_error_free(err); + exit(1); + } + vnc->popup = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu"); + gtk_menu_set_title(GTK_MENU(vnc->popup), "Config"); + + /* popup menu: initial state */ + item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/USKbd"); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->uskbd); + item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/ShowPointer"); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->showpointer); + item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/ViewOnly"); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->viewonly); + + action = gtk_ui_manager_get_action(vnc->ui, "/ConfMenu/GL_ON"); + if (vnc->gl_allways) + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 3); + else if (vnc->gl_fullscreen) + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 2); + else + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 1); + /* labels for the status line */ vnc->line = gtk_label_new("status line"); vnc->res = gtk_label_new("vnc screen resolution"); - vnc->fs = gtk_button_new_with_label("FS"); - vnc->kbd = gtk_button_new_with_label("keyboard mode"); - vnc->ptr = gtk_button_new_with_label("mouse mode"); - vnc->view = gtk_button_new_with_label("input mode"); - g_signal_connect(G_OBJECT(vnc->fs), "clicked", - G_CALLBACK(fs_btn), vnc); - g_signal_connect(G_OBJECT(vnc->kbd), "clicked", - G_CALLBACK(kbd_btn), vnc); - g_signal_connect(G_OBJECT(vnc->ptr), "clicked", - G_CALLBACK(ptr_btn), vnc); - g_signal_connect(G_OBJECT(vnc->view), "clicked", - G_CALLBACK(view_btn), vnc); - GTK_WIDGET_UNSET_FLAGS(vnc->fs, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(vnc->kbd, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(vnc->ptr, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(vnc->view, GTK_CAN_FOCUS); + vnc->mbutton = gtk_button_new_with_label("config"); + g_signal_connect(G_OBJECT(vnc->mbutton), "clicked", + G_CALLBACK(menu_btn), vnc); + GTK_WIDGET_UNSET_FLAGS(vnc->mbutton, GTK_CAN_FOCUS); /* packing */ vbox = gtk_vbox_new(FALSE, 0); @@ -1142,17 +1322,16 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, gtk_container_add(GTK_CONTAINER(frame), vnc->res); gtk_misc_set_padding(GTK_MISC(vnc->res), 3, 1); - gtk_box_pack_start(GTK_BOX(hbox), vnc->fs, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vnc->kbd, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vnc->ptr, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vnc->view, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), vnc->mbutton, FALSE, TRUE, 0); /* show window */ gtk_widget_show_all(vnc->win); vnc_window_conf(vnc); + if (flags & VNC_FLAG_FULLSCREEN) + gtk_window_fullscreen(GTK_WINDOW(vnc->win)); /* opengl */ - if ((vnc->gl_allways || vnc->gl_fullscreen) && 0 == gl_init(vnc)) + if (0 == gl_init(vnc)) vnc->have_gl = 1; /* rfb client */ @@ -4,6 +4,7 @@ #define VNC_FLAG_VIEW_ONLY (1 << 4) #define VNC_FLAG_GL_ALLWAYS (1 << 5) #define VNC_FLAG_GL_FULLSCR (1 << 6) +#define VNC_FLAG_FULLSCREEN (1 << 7) GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, int debug_level); |