diff options
author | kraxel <kraxel> | 2006-10-26 09:53:23 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-10-26 09:53:23 +0000 |
commit | 07acecedbfa72393fd550115abca23ddb31e309d (patch) | |
tree | 990160ed6504180bcc5ed3071b3649bd0aa92016 /vnc.c | |
parent | 5b5e06bc639f478daf1828df71bceac12697042c (diff) | |
download | xenwatch-07acecedbfa72393fd550115abca23ddb31e309d.tar.gz |
cvs stuff
Diffstat (limited to 'vnc.c')
-rw-r--r-- | vnc.c | 232 |
1 files changed, 163 insertions, 69 deletions
@@ -11,17 +11,36 @@ #include <gdk/gdkx.h> #include <gtk/gtk.h> +#include <rfb/rfbclient.h> + #include "x11.h" #include "vnc.h" -#ifdef HAVE_VNC +#ifdef HAVE_VNCCLIENT -static int debug = 0; +/* ------------------------------------------------------------------ */ + +struct vnc_window { + /* vnc connection */ + rfbClient *client; + GIOChannel *ch; + guint id; + /* gtk windows */ + GtkWidget *win; + GtkWidget *draw; + XImage *ximage; + void *shm; + GC gc; + Display *dpy; + /* config */ + int standalone; + int debug; +}; /* ------------------------------------------------------------------ */ /* data tables */ -rfbKeySym linux_us_kbd[] = { +rfbKeySym linux_uskbd[] = { [ 9 ] = XK_Escape, [ 10 ] = XK_1, [ 11 ] = XK_2, @@ -36,6 +55,7 @@ rfbKeySym linux_us_kbd[] = { [ 20 ] = XK_minus, [ 21 ] = XK_equal, [ 22 ] = XK_BackSpace, + [ 23 ] = XK_Tab, [ 24 ] = XK_q, [ 25 ] = XK_w, @@ -50,6 +70,7 @@ rfbKeySym linux_us_kbd[] = { [ 34 ] = XK_bracketleft, [ 35 ] = XK_bracketright, [ 36 ] = XK_Return, + [ 37 ] = XK_Control_L, [ 38 ] = XK_a, [ 39 ] = XK_s, @@ -63,6 +84,7 @@ rfbKeySym linux_us_kbd[] = { [ 47 ] = XK_semicolon, [ 48 ] = XK_apostrophe, [ 49 ] = XK_grave, + [ 50 ] = XK_Shift_L, [ 51 ] = XK_backslash, [ 52 ] = XK_z, @@ -76,10 +98,12 @@ rfbKeySym linux_us_kbd[] = { [ 60 ] = XK_period, [ 61 ] = XK_slash, [ 62 ] = XK_Shift_R, + [ 63 ] = XK_KP_Multiply, [ 64 ] = XK_Alt_L, [ 65 ] = XK_space, [ 66 ] = XK_Caps_Lock, + [ 67 ] = XK_F1, [ 68 ] = XK_F2, [ 69 ] = XK_F3, @@ -92,6 +116,7 @@ rfbKeySym linux_us_kbd[] = { [ 76 ] = XK_F10, [ 77 ] = XK_Num_Lock, [ 78 ] = XK_Scroll_Lock, + [ 79 ] = XK_KP_Home, [ 80 ] = XK_KP_Up, [ 81 ] = XK_KP_Prior, @@ -105,8 +130,12 @@ rfbKeySym linux_us_kbd[] = { [ 89 ] = XK_KP_Next, [ 90 ] = XK_KP_Insert, [ 91 ] = XK_KP_Delete, + [ 93 ] = XK_Mode_switch, - [ 94 ] = XK_less, +#if 0 + [ 94 ] = XK_FIXME, /* Hmm, the intl kbd 105 th key ... */ +#endif + [ 95 ] = XK_F11, [ 96 ] = XK_F12, [ 97 ] = XK_Home, @@ -119,6 +148,7 @@ rfbKeySym linux_us_kbd[] = { [ 105 ] = XK_Next, [ 106 ] = XK_Insert, [ 107 ] = XK_Delete, + [ 108 ] = XK_KP_Enter, [ 109 ] = XK_Control_R, [ 110 ] = XK_Pause, @@ -131,17 +161,18 @@ rfbKeySym linux_us_kbd[] = { [ 124 ] = XK_ISO_Level3_Shift, [ 126 ] = XK_KP_Equal, }; -static int linux_us_kbd_size = sizeof(linux_us_kbd)/sizeof(linux_us_kbd[0]); +static int linux_uskbd_size = sizeof(linux_uskbd)/sizeof(linux_uskbd[0]); /* ------------------------------------------------------------------ */ /* helper functions */ -static void vnc_blit(char *reason, struct vnc_window *vnc, int x, int y, int w, int h) +static void vnc_blit(struct vnc_window *vnc, char *reason, + int x, int y, int w, int h) { Window win = gdk_x11_drawable_get_xid(vnc->draw->window); XGCValues values; - if (debug) + if (vnc->debug) fprintf(stderr, "%s [%s]: %dx%d+%d+%d\n", __FUNCTION__, reason, w, h, x, y); if (x > vnc->ximage->width) @@ -164,12 +195,30 @@ static void vnc_window_conf(struct vnc_window *vnc) if (!vnc->draw) return; - snprintf(title, sizeof(title), "%s (%dx%d)", vnc->client->desktopName, + snprintf(title, sizeof(title), "VNC: %s (%dx%d)", vnc->client->desktopName, vnc->client->width, vnc->client->height); gtk_window_set_title(GTK_WINDOW(vnc->win), title); gtk_widget_set_size_request(vnc->draw, vnc->client->width, vnc->client->height); } +static void vnc_release(struct vnc_window *vnc) +{ + if (NULL == vnc) + return; +#if 0 /* FIXME: segfaults ??? */ + if (vnc->client) + rfbClientCleanup(vnc->client); +#endif + if (vnc->id) + g_source_destroy(g_main_context_find_source_by_id + (g_main_context_default(), vnc->id)); + if (vnc->ximage) + x11_destroy_ximage(vnc->dpy, vnc->ximage, vnc->shm); + if (vnc->gc) + XFreeGC(vnc->dpy, vnc->gc); + free(vnc); +} + /* ------------------------------------------------------------------ */ /* libvncclient callbacks */ @@ -177,7 +226,7 @@ static rfbBool vnc_resize(rfbClient* client) { struct vnc_window *vnc = rfbClientGetClientData(client, vnc_open); - if (debug) + if (vnc->debug) fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, client->width, client->height); @@ -215,33 +264,83 @@ static void vnc_update(rfbClient* cl, int x, int y, int w, int h) if (!GTK_WIDGET_DRAWABLE(vnc->draw)) return; - vnc_blit("update", vnc, x,y, w,h); + vnc_blit(vnc, "update", x,y, w,h); } -#if 0 +#ifdef HAVE_VNC_TEXT static void vnc_textchat(rfbClient* cl, int value, char *text) { switch(value) { case rfbTextChatOpen: - fprintf(stderr,"TextChat: Open\n"); + fprintf(stderr,"%s: Open\n", __FUNCTION__); break; case rfbTextChatClose: case rfbTextChatFinished: - fprintf(stderr,"TextChat: Close/Finished\n"); + fprintf(stderr,"%s: Close/Finished\n", __FUNCTION__); break; default: - fprintf(stderr,"TextChat: \"%s\"\n", text); + fprintf(stderr,"%s: \"%s\"\n", __FUNCTION__, text); break; } } #endif +static char *vnc_passwd(rfbClient* cl) +{ + struct vnc_window *vnc = rfbClientGetClientData(cl, vnc_open); + GtkWidget *dialog, *label, *entry; + const char *passwd = ""; + char message[256]; + + if (vnc->debug) + fprintf(stderr,"%s: called\n", __FUNCTION__); + + /* Create the widgets */ + dialog = gtk_dialog_new_with_buttons("Password needed", + vnc->win ? GTK_WINDOW(vnc->win) : NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + NULL); + + snprintf(message, sizeof(message), + "Please enter vnc screen password for \"%s\".", + vnc->client->desktopName ? : "unknown"); + label = gtk_label_new(message); + entry = gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 10); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + + /* show and wait for response */ + gtk_widget_show_all(dialog); + switch (gtk_dialog_run(GTK_DIALOG(dialog))) { + case GTK_RESPONSE_ACCEPT: + passwd = gtk_entry_get_text(GTK_ENTRY(entry)); + if (vnc->debug) + fprintf(stderr,"%s: OK\n", __FUNCTION__); + break; + default: + if (vnc->debug) + fprintf(stderr,"%s: canceled\n", __FUNCTION__); + break; + } + gtk_widget_destroy(dialog); + + return strdup(passwd); +} + static void vnc_log(const char *format, ...) { va_list args; - if (!debug) - return; + if (1) + return; va_start(args, format); vfprintf(stderr, format, args); va_end(args); @@ -255,7 +354,7 @@ static gboolean vnc_data_cb(GIOChannel *source, GIOCondition condition, { struct vnc_window *vnc = data; - if (debug) + if (vnc->debug) fprintf(stderr,"%s: called\n", __FUNCTION__); if (!HandleRFBServerMessage(vnc->client)) { /* server closed connection */ @@ -271,7 +370,7 @@ static void destroy_cb(GtkWidget *widget, gpointer data) { struct vnc_window *vnc = data; - if (debug) + if (vnc->debug) fprintf(stderr,"%s: called\n", __FUNCTION__); if (vnc->standalone) gtk_main_quit(); @@ -284,7 +383,7 @@ static gboolean expose_cb(GtkWidget *widget, GdkEventExpose *event, gpointer dat if (NULL == vnc->ximage) return FALSE; - vnc_blit("expose", vnc, event->area.x, event->area.y, + vnc_blit(vnc, "expose", event->area.x, event->area.y, event->area.width, event->area.height); return TRUE; } @@ -294,41 +393,50 @@ static gboolean button_cb(GtkWidget *widget, GdkEventButton *event, { struct vnc_window *vnc = data; - if (debug) + if (vnc->debug) fprintf(stderr,"%s: called\n", __FUNCTION__); SendPointerEvent(vnc->client, event->x, event->y, event->state); return TRUE; } -static gboolean key_cb(GtkWidget *widget, GdkEventKey *event, - gpointer data) +static gboolean key_cb_local(GtkWidget *widget, GdkEventKey *event, + gpointer data) +{ + struct vnc_window *vnc = data; + int keydown; + + if (vnc->debug) + fprintf(stderr,"%s[%d]: called: keysym %d\n", __FUNCTION__, + event->type, event->keyval); + keydown = (8 == event->type); + SendKeyEvent(vnc->client, event->keyval, keydown ? TRUE : FALSE); + return TRUE; +} + +static gboolean key_cb_uskbd(GtkWidget *widget, GdkEventKey *event, + gpointer data) { struct vnc_window *vnc = data; rfbKeySym keysym = 0; int keydown; - if (debug) - fprintf(stderr,"%s[%d]: called: sym %d, code %d\n", __FUNCTION__, - event->type, event->keyval, event->hardware_keycode); + if (event->hardware_keycode < linux_uskbd_size) + keysym = linux_uskbd[event->hardware_keycode]; + if (vnc->debug || 0 == keysym) + fprintf(stderr,"%s[%d]: called: keycode %d => keysym %d\n", __FUNCTION__, + event->type, event->hardware_keycode, keysym); keydown = (8 == event->type); - if (vnc->keysyms) - keysym = event->keyval; - else if (event->hardware_keycode < linux_us_kbd_size) - keysym = linux_us_kbd[event->hardware_keycode]; if (keysym) SendKeyEvent(vnc->client, keysym, keydown ? TRUE : FALSE); - else if (!vnc->keysyms) - fprintf(stderr, "%s: unknown keycode: %d\n", - __FUNCTION__, event->hardware_keycode); return TRUE; } /* ------------------------------------------------------------------ */ /* public API functions */ -struct vnc_window* vnc_open(char *hostname, int displayno, - int standalone, int keysyms) +GtkWidget *vnc_open(char *hostname, int displayno, + int standalone, int keysyms) { char display[128]; char *argv[] = { "vnc-client", display, NULL }; @@ -341,7 +449,6 @@ struct vnc_window* vnc_open(char *hostname, int displayno, goto err; memset(vnc,0,sizeof(*vnc)); vnc->standalone = standalone; - vnc->keysyms = keysyms; /* x11 */ vnc->dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); @@ -360,9 +467,12 @@ struct vnc_window* vnc_open(char *hostname, int displayno, goto err; rfbClientSetClientData(vnc->client, vnc_open, vnc); vnc->client->MallocFrameBuffer = vnc_resize; -// vnc->client->canHandleNewFBSize = TRUE; vnc->client->GotFrameBufferUpdate = vnc_update; -// vnc->client->HandleTextChat = vnc_textchat; + vnc->client->GetPassword = vnc_passwd; +#ifdef HAVE_VNC_TEXT + vnc->client->canHandleNewFBSize = TRUE; /* was added before textchat */ + vnc->client->HandleTextChat = vnc_textchat; +#endif rfbClientLog = vnc_log; rc = rfbInitClient(vnc->client, &argc, argv); if (0 == rc) @@ -393,51 +503,35 @@ struct vnc_window* vnc_open(char *hostname, int displayno, G_CALLBACK(button_cb), vnc); g_signal_connect(G_OBJECT(vnc->draw), "button-release-event", G_CALLBACK(button_cb), vnc); - g_signal_connect(G_OBJECT(vnc->draw), "key-press-event", - G_CALLBACK(key_cb), vnc); - g_signal_connect(G_OBJECT(vnc->draw), "key-release-event", - G_CALLBACK(key_cb), vnc); + if (keysyms) { + g_signal_connect(G_OBJECT(vnc->draw), "key-press-event", + G_CALLBACK(key_cb_local), vnc); + g_signal_connect(G_OBJECT(vnc->draw), "key-release-event", + G_CALLBACK(key_cb_local), vnc); + } else { + g_signal_connect(G_OBJECT(vnc->draw), "key-press-event", + G_CALLBACK(key_cb_uskbd), vnc); + g_signal_connect(G_OBJECT(vnc->draw), "key-release-event", + G_CALLBACK(key_cb_uskbd), vnc); + } /* show window */ vnc_window_conf(vnc); gtk_widget_show_all(vnc->win); - return vnc; + return vnc->win; err: vnc_release(vnc); return NULL; } -void vnc_release(struct vnc_window *vnc) -{ - if (NULL == vnc) - return; -#if 0 /* FIXME: segfaults ??? */ - if (vnc->client) - rfbClientCleanup(vnc->client); -#endif - if (vnc->id) - g_source_destroy(g_main_context_find_source_by_id - (g_main_context_default(), vnc->id)); - if (vnc->ximage) - x11_destroy_ximage(vnc->dpy, vnc->ximage, vnc->shm); - if (vnc->gc) - XFreeGC(vnc->dpy, vnc->gc); - free(vnc); -} - -#else +#else /* HAVE_VNCCLIENT */ -struct vnc_window* vnc_open(char *hostname, int displayno, - int standalone, int keysyms) +GtkWidget *vnc_open(char *hostname, int displayno, + int standalone, int keysyms) { fprintf(stderr, "compiled without VNC support, sorry\n"); return NULL; } -void vnc_release(struct vnc_window *vnc) -{ - /* nothing */ -} - -#endif +#endif /* HAVE_VNCCLIENT */ |