diff options
author | kraxel <kraxel> | 2006-10-25 14:47:11 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-10-25 14:47:11 +0000 |
commit | 397fcd38d34e02a73dc0d05e41562a82e608e203 (patch) | |
tree | 051bfb9d033634e8d6832cfb754a1be6a777c2e6 | |
parent | 75e722fc76c56c56a14546ba2dc7418fec08a558 (diff) | |
download | xenwatch-397fcd38d34e02a73dc0d05e41562a82e608e203.tar.gz |
add cvs viewer
-rw-r--r-- | .cvsignore | 1 | ||||
-rw-r--r-- | GNUmakefile | 13 | ||||
-rw-r--r-- | vnc-client.c | 64 | ||||
-rw-r--r-- | vnc.c | 410 | ||||
-rw-r--r-- | vnc.h | 21 | ||||
-rw-r--r-- | x11.c | 226 | ||||
-rw-r--r-- | x11.h | 27 | ||||
-rw-r--r-- | xd_view.c | 5 |
8 files changed, 765 insertions, 2 deletions
@@ -5,3 +5,4 @@ xenscreenrc xenwatch mdns-browser mdns-publish-xendom +vnc-client diff --git a/GNUmakefile b/GNUmakefile index 37dfbe5..8cb6a52 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -9,10 +9,12 @@ CFLAGS += -DVERSION='"$(VERSION)"' -DLIB='"$(LIB)"' TARGETS := xenlog xenscreen xenscreenrc BUILD_GTK := xenwatch mdns-browser BUILD_MDNS := mdns-publish-xendom +BUILD_VNC := vnc-client NEEDS_XENSTORE := xenlog xenscreen xenwatch mdns-publish-xendom -NEEDS_GTK := xenwatch mdns-browser +NEEDS_GTK := xenwatch mdns-browser vnc-client NEEDS_MDNS := xenwatch mdns-browser mdns-publish-xendom +NEEDS_VNC := xenwatch vnc-client # default target all: build @@ -27,6 +29,7 @@ define make-config LIB := $(LIB) HAVE_GTK := $(call ac_pkg_config,gtk+-x11-2.0) HAVE_AVAHI := $(call ac_pkg_config,avahi-glib) +HAVE_VNCCLIENT := $(call ac_lib,rfbGetClient,vncclient,-lz -ljpeg) endef # gtk stuff @@ -34,6 +37,11 @@ ifeq ($(HAVE_GTK),yes) $(NEEDS_GTK) : CFLAGS += -Wno-strict-prototypes $(NEEDS_GTK) : pkglst += gtk+-x11-2.0 TARGETS += $(BUILD_GTK) + ifeq ($(HAVE_VNCCLIENT),yes) + TARGETS += $(BUILD_VNC) + $(NEEDS_VNC) : CFLAGS += -DHAVE_VNC=1 + $(NEEDS_VNC) : LDLIBS += -lvncclient -lz -ljpeg + endif endif # avahi stuff @@ -78,9 +86,10 @@ realclean distclean: clean xenlog: xenlog.o xenstore.o xenscreen: xenscreen.o xenstore.o apps.o xenwatch: xenwatch.o xs_view.o xs_store.o xd_view.o xd_store.o \ - apps.o apps-x11.o tcp.o mdns.o + apps.o apps-x11.o tcp.o mdns.o vnc.o x11.o mdns-browser: mdns-browser.o mdns.o apps.o apps-x11.o mdns-publish-xendom: mdns-publish-xendom.o +vnc-client: vnc-client.o vnc.o x11.o xenscreenrc: xenscreen ./xenscreen -b > $@ diff --git a/vnc-client.c b/vnc-client.c new file mode 100644 index 0000000..a8012cb --- /dev/null +++ b/vnc-client.c @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <locale.h> +#include <signal.h> + +#include <gdk/gdk.h> +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + +#include "vnc.h" + +/* ------------------------------------------------------------------ */ + + +/* ------------------------------------------------------------------ */ + +static void usage(FILE *fp) +{ + fprintf(fp, + "This is a vnc client\n" + "\n" + "usage: vnc-client [options] hostname displayno\n" + "options:\n" + " -h print this text\n" + "\n" + "-- \n" + "(c) 2006 Gerd Hoffmann <kraxel@suse.de>\n"); +} + +int +main(int argc, char *argv[]) +{ + int c; + + gtk_init(&argc, &argv); + for (;;) { + if (-1 == (c = getopt(argc, argv, "h"))) + break; + switch (c) { + case 'h': + usage(stdout); + exit(0); + default: + usage(stderr); + exit(1); + } + } + + if (optind+2 > argc) { + usage(stderr); + exit(1); + } + + if (NULL == vnc_open(argv[optind], atoi(argv[optind+1]), 1)) + exit(1); + + gtk_main(); + fprintf(stderr,"bye...\n"); + exit(0); +} @@ -0,0 +1,410 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <locale.h> +#include <signal.h> + +#include <gdk/gdk.h> +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + +#include "x11.h" +#include "vnc.h" + +#ifdef HAVE_VNC + +/* ------------------------------------------------------------------ */ +/* data tables */ + +rfbKeySym linux_us_kbd[] = { + [ 9 ] = XK_Escape, + [ 10 ] = XK_1, + [ 11 ] = XK_2, + [ 12 ] = XK_3, + [ 13 ] = XK_4, + [ 14 ] = XK_5, + [ 15 ] = XK_6, + [ 16 ] = XK_7, + [ 17 ] = XK_8, + [ 18 ] = XK_9, + [ 19 ] = XK_0, + [ 20 ] = XK_minus, + [ 21 ] = XK_equal, + [ 22 ] = XK_BackSpace, + [ 23 ] = XK_Tab, + [ 24 ] = XK_q, + [ 25 ] = XK_w, + [ 26 ] = XK_e, + [ 27 ] = XK_r, + [ 28 ] = XK_t, + [ 29 ] = XK_y, + [ 30 ] = XK_u, + [ 31 ] = XK_i, + [ 32 ] = XK_o, + [ 33 ] = XK_p, + [ 34 ] = XK_bracketleft, + [ 35 ] = XK_bracketright, + [ 36 ] = XK_Return, + [ 37 ] = XK_Control_L, + [ 38 ] = XK_a, + [ 39 ] = XK_s, + [ 40 ] = XK_d, + [ 41 ] = XK_f, + [ 42 ] = XK_g, + [ 43 ] = XK_h, + [ 44 ] = XK_j, + [ 45 ] = XK_k, + [ 46 ] = XK_l, + [ 47 ] = XK_semicolon, + [ 48 ] = XK_apostrophe, + [ 49 ] = XK_grave, + [ 50 ] = XK_Shift_L, + [ 51 ] = XK_backslash, + [ 52 ] = XK_z, + [ 53 ] = XK_x, + [ 54 ] = XK_c, + [ 55 ] = XK_v, + [ 56 ] = XK_b, + [ 57 ] = XK_n, + [ 58 ] = XK_m, + [ 59 ] = XK_comma, + [ 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, + [ 70 ] = XK_F4, + [ 71 ] = XK_F5, + [ 72 ] = XK_F6, + [ 73 ] = XK_F7, + [ 74 ] = XK_F8, + [ 75 ] = XK_F9, + [ 76 ] = XK_F10, + [ 77 ] = XK_Num_Lock, + [ 78 ] = XK_Scroll_Lock, + [ 79 ] = XK_KP_Home, + [ 80 ] = XK_KP_Up, + [ 81 ] = XK_KP_Prior, + [ 82 ] = XK_KP_Subtract, + [ 83 ] = XK_KP_Left, + [ 84 ] = XK_KP_Begin, + [ 85 ] = XK_KP_Right, + [ 86 ] = XK_KP_Add, + [ 87 ] = XK_KP_End, + [ 88 ] = XK_KP_Down, + [ 89 ] = XK_KP_Next, + [ 90 ] = XK_KP_Insert, + [ 91 ] = XK_KP_Delete, + [ 93 ] = XK_Mode_switch, + [ 94 ] = XK_less, + [ 95 ] = XK_F11, + [ 96 ] = XK_F12, + [ 97 ] = XK_Home, + [ 98 ] = XK_Up, + [ 99 ] = XK_Prior, + [ 100 ] = XK_Left, + [ 102 ] = XK_Right, + [ 103 ] = XK_End, + [ 104 ] = XK_Down, + [ 105 ] = XK_Next, + [ 106 ] = XK_Insert, + [ 107 ] = XK_Delete, + [ 108 ] = XK_KP_Enter, + [ 109 ] = XK_Control_R, + [ 110 ] = XK_Pause, + [ 111 ] = XK_Print, + [ 112 ] = XK_KP_Divide, + [ 113 ] = XK_Alt_R, + [ 115 ] = XK_Super_L, + [ 116 ] = XK_Super_R, + [ 117 ] = XK_Menu, + [ 124 ] = XK_ISO_Level3_Shift, + [ 126 ] = XK_KP_Equal, +}; +static int linux_us_kbd_size = sizeof(linux_us_kbd)/sizeof(linux_us_kbd[0]); + +/* ------------------------------------------------------------------ */ +/* helper functions */ + +static void vnc_blit(char *reason, struct vnc_window *vnc, int x, int y, int w, int h) +{ + Window win = gdk_x11_drawable_get_xid(vnc->draw->window); + XGCValues values; + +#if 0 + fprintf(stderr, "%s [%s]: %dx%d+%d+%d\n", + __FUNCTION__, reason, w, h, x, y); +#endif + if (x > vnc->ximage->width) + return; + if (y > vnc->ximage->height) + return; + if (x+w > vnc->ximage->width) + w = vnc->ximage->width - x; + if (y+h > vnc->ximage->height) + h = vnc->ximage->height - y; + + if (!vnc->gc) + vnc->gc = XCreateGC(vnc->dpy, win, 0, &values); + XPUTIMAGE(vnc->dpy, win, vnc->gc, vnc->ximage, x,y, x,y, w,h); +} + +static void vnc_window_conf(struct vnc_window *vnc) +{ + char title[256]; + + if (!vnc->draw) + return; + snprintf(title, sizeof(title), "%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); +} + +/* ------------------------------------------------------------------ */ +/* libvncclient callbacks */ + +static rfbBool vnc_resize(rfbClient* client) +{ + struct vnc_window *vnc = rfbClientGetClientData(client, vnc_open); + + fprintf(stderr, "%s: %dx%d\n", + __FUNCTION__, client->width, client->height); + + if (vnc->ximage) { + x11_destroy_ximage(vnc->dpy, vnc->ximage, vnc->shm); + vnc->ximage = NULL; + } + vnc->ximage = x11_create_ximage(vnc->dpy, client->width, client->height, &vnc->shm); + if (NULL == vnc->ximage) { + fprintf(stderr, "Oops: creating ximage failed\n"); + goto out; + } + + client->width = vnc->ximage->bytes_per_line / (vnc->ximage->bits_per_pixel / 8); + client->frameBuffer = (void*)vnc->ximage->data; + + client->format.bitsPerPixel = vnc->ximage->bits_per_pixel; + client->format.redShift = x11_red_shift; + client->format.greenShift = x11_green_shift; + client->format.blueShift = x11_blue_shift; + client->format.redMax = (1 << x11_red_bits) - 1; + client->format.greenMax = (1 << x11_green_bits) - 1; + client->format.blueMax = (1 << x11_blue_bits) - 1; + SetFormatAndEncodings(client); + + vnc_window_conf(vnc); + + out: + return TRUE; +} + +static void vnc_update(rfbClient* cl, int x, int y, int w, int h) +{ + struct vnc_window *vnc = rfbClientGetClientData(cl, vnc_open); + + if (!GTK_WIDGET_DRAWABLE(vnc->draw)) + return; + vnc_blit("update", vnc, x,y, w,h); +} + +#if 0 +static void vnc_textchat(rfbClient* cl, int value, char *text) +{ + switch(value) { + case rfbTextChatOpen: + fprintf(stderr,"TextChat: Open\n"); + break; + case rfbTextChatClose: + case rfbTextChatFinished: + fprintf(stderr,"TextChat: Close/Finished\n"); + break; + default: + fprintf(stderr,"TextChat: \"%s\"\n", text); + break; + } +} +#endif + +/* ------------------------------------------------------------------ */ +/* glib/gtk callbacks */ + +static gboolean vnc_data_cb(GIOChannel *source, GIOCondition condition, + gpointer data) +{ + struct vnc_window *vnc = data; + + if (!HandleRFBServerMessage(vnc->client)) { + /* server closed connection */ + g_source_destroy(g_main_context_find_source_by_id + (g_main_context_default(), vnc->id)); + vnc->id = 0; + gtk_widget_destroy(vnc->win); + } + return TRUE; +} + +static void destroy_cb(GtkWidget *widget, gpointer data) +{ + struct vnc_window *vnc = data; + + if (vnc->standalone) + gtk_main_quit(); + vnc_release(vnc); +} + +static gboolean expose_cb(GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + struct vnc_window *vnc = data; + + if (NULL == vnc->ximage) + return FALSE; + vnc_blit("expose", vnc, event->area.x, event->area.y, + event->area.width, event->area.height); + return TRUE; +} + +static gboolean button_cb(GtkWidget *widget, GdkEventButton *event, + gpointer data) +{ + struct vnc_window *vnc = data; + + SendPointerEvent(vnc->client, event->x, event->y, event->state); + return TRUE; +} + +static gboolean key_cb(GtkWidget *widget, GdkEventKey *event, + gpointer data) +{ + struct vnc_window *vnc = data; + rfbKeySym keysym = 0; + int keydown; + + keydown = (8 == event->type); + 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 + 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) +{ + char display[128]; + char *argv[] = { "vnc-client", display, NULL }; + int argc = sizeof(argv)/sizeof(argv[0]) -1; + struct vnc_window *vnc; + int rc; + + vnc = malloc(sizeof(*vnc)); + if (NULL == vnc) + goto err; + memset(vnc,0,sizeof(*vnc)); + vnc->standalone = standalone; + + /* x11 */ + vnc->dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); + if (NULL == x11_info) + x11_color_init(vnc->dpy); + + /* rfb client */ + snprintf(display, sizeof(display), "%s:%d", hostname, displayno); + fprintf(stderr, "%s: connecting to %s:%d\n", __FUNCTION__, hostname, displayno); + vnc->client = rfbGetClient(8,3,3); + if (NULL == vnc->client) + 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; + rc = rfbInitClient(vnc->client, &argc, argv); + if (0 == rc) + goto err; + vnc->ch = g_io_channel_unix_new(vnc->client->sock); + vnc->id = g_io_add_watch(vnc->ch, G_IO_IN, vnc_data_cb, vnc); + + /* gtk toplevel */ + vnc->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect(G_OBJECT(vnc->win), "destroy", + G_CALLBACK(destroy_cb), vnc); + + /* gtk drawing area */ + vnc->draw = gtk_drawing_area_new(); + gtk_container_add(GTK_CONTAINER(vnc->win), vnc->draw); + GTK_WIDGET_SET_FLAGS(vnc->draw, GTK_CAN_FOCUS); + gtk_widget_add_events(vnc->draw, + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_KEY_PRESS_MASK | + GDK_KEY_RELEASE_MASK | + GDK_EXPOSURE_MASK); + gtk_widget_set_app_paintable(vnc->draw, TRUE); + gtk_widget_set_double_buffered(vnc->draw, FALSE); + g_signal_connect(G_OBJECT(vnc->draw), "expose-event", + G_CALLBACK(expose_cb), vnc); + g_signal_connect(G_OBJECT(vnc->draw), "button-press-event", + 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); + + /* show window */ + vnc_window_conf(vnc); + gtk_widget_show_all(vnc->win); + return vnc; + + 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 + +struct vnc_window* vnc_open(char *hostname, int displayno, int standalone) +{ + fprintf(stderr, "compiled without VNC support, sorry\n"); + return NULL; +} + +void vnc_release(struct vnc_window *vnc) +{ + /* nothing */ +} + +#endif @@ -0,0 +1,21 @@ +#include <X11/Xlib.h> +#include <rfb/rfbclient.h> + +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; + /* misc */ + int standalone; +}; + +void vnc_release(struct vnc_window*); +struct vnc_window* vnc_open(char *hostname, int displayno, int standalone); @@ -0,0 +1,226 @@ +/* + * some X11 ximage / pixmaps rotines + * + * (c) 2006 Gerd Hoffmann <kraxel@suse.de> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#include "x11.h" + +/* ------------------------------------------------------------------------ */ + +XVisualInfo *x11_info; +int have_shmem = 0; + +int x11_red_bits = 0; +int x11_red_shift = 0; +int x11_green_bits = 0; +int x11_green_shift = 0; +int x11_blue_bits = 0; +int x11_blue_shift = 0; + +static void +x11_find_bits(unsigned long red_mask, + unsigned long green_mask, + unsigned long blue_mask) +{ + int i; + unsigned long mask; + + for (i = 0; i < 24; i++) { + mask = (1 << i); + if (red_mask & mask) + x11_red_bits++; + else if (!x11_red_bits) + x11_red_shift++; + if (green_mask & mask) + x11_green_bits++; + else if (!x11_green_bits) + x11_green_shift++; + if (blue_mask & mask) + x11_blue_bits++; + else if (!x11_blue_bits) + x11_blue_shift++; + } + +#if 1 + printf("color: bits shift\n"); + printf("red : %04i %05i\n", x11_red_bits, x11_red_shift); + printf("green: %04i %05i\n", x11_green_bits, x11_green_shift); + printf("blue : %04i %05i\n", x11_blue_bits, x11_blue_shift); +#endif +} + +int x11_color_init(Display *dpy) +{ + Screen *scr; + XVisualInfo template; + int found; + + scr = DefaultScreenOfDisplay(dpy); + + /* Ask for visual type */ + template.screen = XDefaultScreen(dpy); + template.visualid = + XVisualIDFromVisual(DefaultVisualOfScreen(scr)); + x11_info = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &template, + &found); + if (XShmQueryExtension(dpy)) + have_shmem = 1; + + if (x11_info->class != TrueColor) { + fprintf(stderr, "sorry, can't handle visual\n"); + return -1; + } + x11_find_bits(x11_info->red_mask, x11_info->green_mask, x11_info->blue_mask); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int mitshm_bang = 0; + +static int x11_error_dev_null(Display *dpy, XErrorEvent *event) +{ + mitshm_bang = 1; + return 0; +} + +XImage* x11_create_ximage(Display *dpy, int width, int height, void **shm) +{ + XImage *ximage = NULL; + char *ximage_data; + XShmSegmentInfo *shminfo = NULL; + void *old_handler; + Screen *scr = DefaultScreenOfDisplay(dpy); + + if (have_shmem) { + old_handler = XSetErrorHandler(x11_error_dev_null); + (*shm) = shminfo = malloc(sizeof(XShmSegmentInfo)); + memset(shminfo, 0, sizeof(XShmSegmentInfo)); + ximage = XShmCreateImage(dpy, + DefaultVisualOfScreen(scr), + DefaultDepthOfScreen(scr), + ZPixmap, NULL, + shminfo, width, height); + if (ximage) { + shminfo->shmid = shmget(IPC_PRIVATE, + ximage->bytes_per_line * ximage->height, + IPC_CREAT | 0777); + if (-1 == shminfo->shmid) { + fprintf(stderr,"shmget(%dMB): %s\n", + ximage->bytes_per_line * ximage->height / 1024 / 1024, + strerror(errno)); + goto oom; + } + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + if ((void *) -1 == shminfo->shmaddr) { + perror("shmat"); + goto oom; + } + ximage->data = shminfo->shmaddr; + shminfo->readOnly = False; + + XShmAttach(dpy, shminfo); + XSync(dpy, False); + shmctl(shminfo->shmid, IPC_RMID, 0); + if (mitshm_bang) { + have_shmem = 0; + shmdt(shminfo->shmaddr); + free(shminfo); + shminfo = *shm = NULL; + XDestroyImage(ximage); + ximage = NULL; + } + } else { + have_shmem = 0; + free(shminfo); + shminfo = *shm = NULL; + } + XSetErrorHandler(old_handler); + } + + if (ximage == NULL) { + (*shm) = NULL; + if (NULL == (ximage_data = malloc(width * height * 4))) { + fprintf(stderr,"Oops: out of memory\n"); + goto oom; + } + ximage = XCreateImage(dpy, + DefaultVisualOfScreen(scr), + DefaultDepthOfScreen(scr), + ZPixmap, 0, ximage_data, + width, height, + 8, 0); + } + memset(ximage->data, 0, ximage->bytes_per_line * ximage->height); + + return ximage; + + oom: + if (shminfo) { + if (shminfo->shmid && shminfo->shmid != -1) + shmctl(shminfo->shmid, IPC_RMID, 0); + free(shminfo); + } + if (ximage) + XDestroyImage(ximage); + return NULL; +} + +void x11_destroy_ximage(Display *dpy, XImage *ximage, void *shm) +{ + XShmSegmentInfo *shminfo = shm; + + if (shminfo) { + XShmDetach(dpy, shminfo); + XDestroyImage(ximage); + shmdt(shminfo->shmaddr); + free(shminfo); + } else + XDestroyImage(ximage); +} + +Pixmap x11_create_pixmap(Display *dpy, unsigned char *byte_data, + int width, int height) +{ + Pixmap pixmap; + XImage *ximage; + XGCValues values; + GC gc; + unsigned long *long_data = (unsigned long *)byte_data; + int x, y; + void *shm; + + Screen *scr = DefaultScreenOfDisplay(dpy); + + pixmap = XCreatePixmap(dpy, + RootWindowOfScreen(scr), + width, height, + DefaultDepthOfScreen(scr)); + gc = XCreateGC(dpy, pixmap, 0, &values); + + if (NULL == (ximage = x11_create_ximage(dpy, width, height, &shm))) { + XFreePixmap(dpy, pixmap); + XFreeGC(dpy, gc); + return 0; + } + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + XPutPixel(ximage, x, y, *(long_data++)); + + XPUTIMAGE(dpy, pixmap, gc, ximage, 0, 0, 0, 0, width, height); + + x11_destroy_ximage(dpy, ximage, shm); + XFreeGC(dpy, gc); + return pixmap; +} @@ -0,0 +1,27 @@ +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> + +extern XVisualInfo *x11_info; +extern int have_shmem; + +extern int x11_red_bits; +extern int x11_red_shift; +extern int x11_green_bits; +extern int x11_green_shift; +extern int x11_blue_bits; +extern int x11_blue_shift; + +int x11_color_init(Display *dpy); + +XImage *x11_create_ximage(Display *dpy, int width, int height, void **shm); +void x11_destroy_ximage(Display *dpy, XImage * ximage, void *shm); +Pixmap x11_create_pixmap(Display *dpy, unsigned char *data, + int width, int height); + +#define XPUTIMAGE(dpy,dr,gc,xi,a,b,c,d,w,h) \ + if (have_shmem) \ + XShmPutImage(dpy,dr,gc,xi,a,b,c,d,w,h,True); \ + else \ + XPutImage(dpy,dr,gc,xi,a,b,c,d,w,h) @@ -19,6 +19,7 @@ #include "tcp.h" #include "mdns.h" #include "apps.h" +#include "vnc.h" #define array_size(x) (sizeof(x)/sizeof(*x)) @@ -134,8 +135,12 @@ static void open_vnc(gint id, char *name, char *ostype) { if (0 == strcmp(ostype, "hvm")) { /* works for hvm ... */ +#ifdef HAVE_VNC + vnc_open("localhost", id, 0); +#else if (-1 == open_vnc_session("localhost", id)) gtk_message(GTK_MESSAGE_ERROR, app_error); +#endif } else { gtk_message(GTK_MESSAGE_ERROR, "VNC works for hvm domains only.\n"); } |