diff options
author | kraxel <kraxel> | 2007-05-16 10:12:15 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2007-05-16 10:12:15 +0000 |
commit | 63f9c3be3b98a2c03af38185614cf9ccc1d960f8 (patch) | |
tree | 4a209535e6fbded4fb3dac77883038643dc9d815 | |
parent | 9f355bea4ff551b59f368100e892eeb10eef5c21 (diff) | |
download | xenwatch-63f9c3be3b98a2c03af38185614cf9ccc1d960f8.tar.gz |
opengl support
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | vnc-client.c | 6 | ||||
-rw-r--r-- | vnc.c | 519 | ||||
-rw-r--r-- | vnc.h | 1 |
4 files changed, 432 insertions, 96 deletions
diff --git a/GNUmakefile b/GNUmakefile index 0876691..1e41dfd 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -44,7 +44,7 @@ ifeq ($(HAVE_GTK),yes) TARGETS += $(BUILD_GTK) ifeq ($(HAVE_VNCCLIENT),yes) TARGETS += $(BUILD_VNC) - $(NEEDS_VNC) : LDLIBS += -lvncclient -lz -ljpeg + $(NEEDS_VNC) : LDLIBS += -lvncclient -lz -ljpeg -lGL endif endif diff --git a/vnc-client.c b/vnc-client.c index 577fb45..4f0fdac 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" + " -g Disable OpewnGL.\n" " -o View only.\n" "\n" "-- \n" @@ -43,7 +44,7 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); for (;;) { - if (-1 == (c = getopt(argc, argv, "hdupo"))) + if (-1 == (c = getopt(argc, argv, "hdupgo"))) break; switch (c) { case 'd': @@ -58,6 +59,9 @@ main(int argc, char *argv[]) case 'o': vnc_flags |= VNC_FLAG_VIEW_ONLY; break; + case 'g': + vnc_flags |= VNC_FLAG_NOGL; + break; case 'h': usage(stdout); exit(0); @@ -10,6 +10,9 @@ #include <X11/X.h> #include <X11/Xlib.h> +#include <GL/gl.h> +#include <GL/glx.h> + #include <gdk/gdk.h> #include <gdk/gdkx.h> #include <gtk/gtk.h> @@ -25,26 +28,47 @@ static int debug_libvnc; /* ------------------------------------------------------------------ */ +struct rect { + int w; + int h; +}; + struct vnc_window { /* vnc connection */ char display[128]; rfbClient *client; GIOChannel *ch; guint id, connected; + /* gtk */ GtkWidget *win; GtkWidget *draw; - GtkWidget *line, *res, *kbd, *ptr, *view; + GtkWidget *line, *res, *fs, *kbd, *ptr, *view; GdkCursor *on,*off; int filter_installed; int input_grabbed; + /* x11 */ XImage *ximage; void *shm; GC gc; Display *dpy; unsigned char keydown[32]; + + /* window / vnc display config */ + struct rect window; + struct rect vncdpy; + struct rect texture; + int updates, redraw; + + /* opengl */ + int have_gl; + GLuint tex; + int tex_max; + void *tex_data; + /* config */ + int fullscreen; int viewonly; int standalone; int showpointer; @@ -67,6 +91,218 @@ static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, gpointer data); /* ------------------------------------------------------------------ */ +/* opengl bits */ + +static int gl_error; +static int gl_attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + None }; + +static int +catch_gl_error(Display * dpy, XErrorEvent * event) +{ + fprintf(stderr,"WARNING: Your OpenGL setup is broken.\n"); + gl_error++; + return 0; +} + +static int gl_init(struct vnc_window *vnc) +{ + Window win = gdk_x11_drawable_get_xid(vnc->draw->window); + Screen *scr = DefaultScreenOfDisplay(vnc->dpy); + void *old_handler; + XVisualInfo *visinfo; + GLXContext ctx; + + if (vnc->debug) + fprintf(stderr, "gl: init [window=0x%lx]\n", win); + if (!win) + return -1; + visinfo = glXChooseVisual(vnc->dpy, XScreenNumberOfScreen(scr), + gl_attrib); + if (!visinfo) { + if (vnc->debug) + fprintf(stderr,"gl: can't get visual (rgb,db)\n"); + return -1; + } + ctx = glXCreateContext(vnc->dpy, visinfo, NULL, True); + if (!ctx) { + if (vnc->debug) + fprintf(stderr,"gl: can't create context\n"); + return -1; + } + + /* there is no point in using OpenGL for image scaling if it + * isn't hardware accelerated ... */ + if (vnc->debug) + fprintf(stderr, "gl: DRI=%s\n", + glXIsDirect(vnc->dpy, ctx) ? "Yes" : "No"); + if (!glXIsDirect(vnc->dpy, ctx)) + return -1; + + old_handler = XSetErrorHandler(catch_gl_error); + glXMakeCurrent(vnc->dpy, win, ctx); + XSync(vnc->dpy, False); + XSetErrorHandler(old_handler); + if (gl_error) + return -1; + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &vnc->tex_max); + if (vnc->debug) + fprintf(stderr, "gl: texture max size: %d\n", vnc->tex_max); + return 0; +} + +static void gl_resize_window(struct vnc_window *vnc) +{ + if (!vnc->tex) + return; + + glClearColor (0.0, 0.0, 0.0, 0.0); + glShadeModel(GL_FLAT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glViewport(0, 0, vnc->window.w, vnc->window.h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, vnc->window.w, 0.0, vnc->window.h, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + vnc->redraw++; +} + +static void gl_blit(struct vnc_window *vnc) +{ + Window win = gdk_x11_drawable_get_xid(vnc->draw->window); + float x,y; + unsigned int ww = vnc->window.w, wh = vnc->window.h; + int wx = 0, wy = 0; + + if (!vnc->tex) + return; + glBindTexture(GL_TEXTURE_2D, vnc->tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0,0, vnc->vncdpy.w, vnc->vncdpy.h, + GL_BGRA_EXT /* GL_RGB */, + GL_UNSIGNED_BYTE, + vnc->tex_data); + x = (float)vnc->vncdpy.w / vnc->texture.w; + y = (float)vnc->vncdpy.h / vnc->texture.h; + + glEnable(GL_TEXTURE_2D); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glBegin(GL_QUADS); + glTexCoord2f(0,y); glVertex3f(wx, wy, 0); + glTexCoord2f(0,0); glVertex3f(wx, wy+wh, 0); + glTexCoord2f(x,0); glVertex3f(wx+ww, wy+wh, 0); + glTexCoord2f(x,y); glVertex3f(wx+ww, wy, 0); + glEnd(); + glXSwapBuffers(vnc->dpy, win); + glDisable(GL_TEXTURE_2D); +} + +static void gl_flush(struct vnc_window *vnc) +{ + gl_blit(vnc); + vnc->updates = 0; + vnc->redraw = 0; +} + +/* ------------------------------------------------------------------ */ +/* x11 draw bits */ + +static void x11_update(struct vnc_window *vnc, + int x, int y, int w, int h) +{ + Window win = gdk_x11_drawable_get_xid(vnc->draw->window); + + if (!vnc->gc) { + XGCValues values; + XColor color, dummy; + Colormap cmap; + + cmap = gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(vnc->win)); + XAllocNamedColor(vnc->dpy, cmap, "#404040", &color, &dummy); + values.function = GXcopy; + values.foreground = color.pixel; + vnc->gc = XCreateGC(vnc->dpy, win, + GCForeground|GCFunction, + &values); + } + if (vnc->redraw) + XFillRectangle(vnc->dpy, win, vnc->gc, + 0,0, vnc->window.w, vnc->window.h); + + 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; + + XPUTIMAGE(vnc->dpy, win, vnc->gc, vnc->ximage, x,y, x,y, w,h); +} + +static void x11_flush(struct vnc_window *vnc) +{ + x11_update(vnc, 0, 0, vnc->vncdpy.w, vnc->vncdpy.w); + vnc->updates = 0; + vnc->redraw = 0; +} + +/* ------------------------------------------------------------------ */ +/* x11/gl wrappers */ + +static void dpy_update(struct vnc_window *vnc, + int x, int y, int w, int h) +{ + if (vnc->debug) + fprintf(stderr, "%s: mode%s%s, %dx%d+%d+%d\n", __FUNCTION__, + vnc->tex ? " GL" : "", + vnc->ximage ? " X11" : "", + w, h, x, y); + if (vnc->ximage) + x11_update(vnc, x, y, w, h); + if (vnc->tex) + vnc->updates++; +} + +static void dpy_redraw(struct vnc_window *vnc) +{ + vnc->redraw++; +} + +static void dpy_flush(struct vnc_window *vnc, const char *caller) +{ + if (vnc->debug) + fprintf(stderr, "%s: from %s, mode%s%s, updates %d, redraw %d\n", + __FUNCTION__, caller, + vnc->tex ? " GL" : "", + vnc->ximage ? " X11" : "", + vnc->updates, vnc->redraw); + if (!vnc->updates && !vnc->redraw) + return; + + if (vnc->ximage) + x11_flush(vnc); + if (vnc->tex) + gl_flush(vnc); +} + +static void dpy_resize_window(struct vnc_window *vnc) +{ + if (vnc->tex) + gl_resize_window(vnc); + dpy_redraw(vnc);; +} + +/* ------------------------------------------------------------------ */ /* helper functions */ static void XAddInput(Display *dpy, Window win, long mask) @@ -91,50 +327,35 @@ static GdkCursor* empty_cursor(void) return cursor; } -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 (vnc->debug) - fprintf(stderr, "%s [%s]: %dx%d+%d+%d\n", - __FUNCTION__, reason, w, h, x, y); - 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_texts(struct vnc_window *vnc) { char textline[256]; - if (vnc->client->desktopName && strlen(vnc->client->desktopName)) + if (vnc->client && vnc->client->desktopName && + strlen(vnc->client->desktopName)) { gtk_window_set_title(GTK_WINDOW(vnc->win), vnc->client->desktopName); - else - gtk_window_set_title(GTK_WINDOW(vnc->win), "Untitled VNC session"); + } else { + snprintf(textline, sizeof(textline), "connecting to %s ...", + vnc->display); + gtk_window_set_title(GTK_WINDOW(vnc->win), textline); + } if (vnc->input_grabbed) { gtk_label_set_text(GTK_LABEL(vnc->line), "Press Ctrl-Alt to release input grab."); - } else { + } else if (vnc->client) { snprintf(textline, sizeof(textline), "VNC: \"%s\" at %s", vnc->client->desktopName ?: "", vnc->display); gtk_label_set_text(GTK_LABEL(vnc->line), textline); } - - snprintf(textline, sizeof(textline), "%dx%d", - vnc->client->width, vnc->client->height); - gtk_label_set_text(GTK_LABEL(vnc->res), textline); + + if (vnc->client) { + snprintf(textline, sizeof(textline), "%dx%d", + vnc->vncdpy.w, vnc->vncdpy.h); + 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), @@ -148,13 +369,16 @@ static void vnc_window_conf(struct vnc_window *vnc) if (!vnc->draw) return; vnc_window_texts(vnc); - gtk_widget_set_size_request(vnc->draw, vnc->client->width, vnc->client->height); + if (vnc->client) + gtk_widget_set_size_request(vnc->draw, vnc->vncdpy.w, vnc->vncdpy.h); if (vnc->draw->window) { gdk_window_set_cursor(vnc->draw->window, vnc->showpointer ? vnc->on : vnc->off); + /* FIXME */ XAddInput(vnc->dpy, gdk_x11_drawable_get_xid(vnc->draw->window), KeymapStateMask); } + dpy_resize_window(vnc); } static void vnc_release(struct vnc_window *vnc) @@ -224,39 +448,103 @@ static void ungrab_input(struct vnc_window *vnc, guint32 time) static rfbBool vnc_resize(rfbClient* client) { struct vnc_window *vnc = rfbClientGetClientData(client, vnc_open); + int using_gl = 0; if (vnc->debug) fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, client->width, client->height); + if (vnc->vncdpy.w == client->width && + vnc->vncdpy.h == client->height) { + if (vnc->debug) + fprintf(stderr, "%s: no size change, early exit\n", __FUNCTION__); + return TRUE; + } + /* cleanup */ if (vnc->ximage) { - if (vnc->ximage->width == client->width && - vnc->ximage->height == client->height) { - if (vnc->debug) - fprintf(stderr, "%s: no size change, early exit\n", __FUNCTION__); - return TRUE; - } 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; + if (vnc->tex) { + /* FIXME: release texture */ + vnc->tex = 0; + vnc->vncdpy.w = 0; + vnc->vncdpy.h = 0; + free(vnc->tex_data); + vnc->tex_data = NULL; } - client->width = vnc->ximage->bytes_per_line / (vnc->ximage->bits_per_pixel / 8); - client->frameBuffer = (void*)vnc->ximage->data; + vnc->vncdpy.w = client->width; + vnc->vncdpy.h = client->height; - 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); + /* opengl check */ + if (vnc->have_gl && vnc->vncdpy.w < vnc->tex_max && vnc->vncdpy.h < vnc->tex_max) + using_gl = 1; + if (!using_gl) { + /* init X11 */ + vnc->ximage = x11_create_ximage(vnc->dpy, vnc->vncdpy.w, vnc->vncdpy.h, &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; + } else { + /* init OpenGL */ + void *dummy; + int i; + + /* figure texture size (power of two) */ + for (i = 0; vnc->vncdpy.w >= (1 << i); i++) + ; + vnc->texture.w = (1 << i); + for (i = 0; vnc->vncdpy.h >= (1 << i); i++) + ; + vnc->texture.h = (1 << i); + if (vnc->debug) + fprintf(stderr,"%s: client %dx%d, tex %dx%d\n", __FUNCTION__, + vnc->vncdpy.w, vnc->vncdpy.h, vnc->texture.w, vnc->texture.h); + + /* create texture */ + glGenTextures(1, &vnc->tex); + glBindTexture(GL_TEXTURE_2D, vnc->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + dummy = malloc(vnc->texture.w * vnc->texture.h * 4); + memset(dummy, 128, vnc->texture.w * vnc->texture.h * 4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + vnc->texture.w, vnc->texture.h, 0, + GL_RGB, GL_UNSIGNED_BYTE, + dummy); + free(dummy); + + /* image buffer */ + vnc->tex_data = malloc(vnc->vncdpy.w * vnc->vncdpy.h * 4); + client->frameBuffer = vnc->tex_data; + + client->format.bitsPerPixel = 32; + client->format.redShift = 16; + client->format.greenShift = 8; + client->format.blueShift = 0; + client->format.redMax = 255; + client->format.greenMax = 255; + client->format.blueMax = 255; + } + + if (vnc->debug) + fprintf(stderr, "%s: SetFormatAndEncodings: %s\n", __FUNCTION__, + using_gl ? "GL" : "X11" ); + SetFormatAndEncodings(client); vnc_window_conf(vnc); out: @@ -269,7 +557,7 @@ static void vnc_update(rfbClient* cl, int x, int y, int w, int h) if (!GTK_WIDGET_DRAWABLE(vnc->draw)) return; - vnc_blit(vnc, "update", x,y, w,h); + dpy_update(vnc, x,y, w,h); } #ifdef HAVE_VNC_TEXT @@ -362,8 +650,6 @@ static gboolean vnc_data_cb(GIOChannel *source, GIOCondition condition, { struct vnc_window *vnc = data; - if (vnc->debug) - fprintf(stderr,"%s: called\n", __FUNCTION__); if (!HandleRFBServerMessage(vnc->client)) { /* server closed connection */ g_source_destroy(g_main_context_find_source_by_id @@ -371,6 +657,7 @@ static gboolean vnc_data_cb(GIOChannel *source, GIOCondition condition, vnc->id = 0; gtk_widget_destroy(vnc->win); } + dpy_flush(vnc, __FUNCTION__); return TRUE; } @@ -389,18 +676,37 @@ static gboolean expose_cb(GtkWidget *widget, GdkEventExpose *event, gpointer dat { struct vnc_window *vnc = data; - if (NULL == vnc->ximage) - return FALSE; -#if 0 - vnc_blit(vnc, "expose", event->area.x, event->area.y, - event->area.width, event->area.height); -#else - SendFramebufferUpdateRequest(vnc->client, - event->area.x, event->area.y, - event->area.width, event->area.height, - FALSE); -#endif + dpy_update(vnc, event->area.x, event->area.y, + event->area.width, event->area.height); + if (0 == event->count) + dpy_flush(vnc, __FUNCTION__); + return TRUE; +} + +static gboolean configure_cb(GtkWidget *widget, GdkEventConfigure *event, + gpointer data) +{ + struct vnc_window *vnc = data; + if (vnc->debug) + fprintf(stderr,"%s: %dx%d\n", __FUNCTION__, + event->width, event->height); + vnc->window.w = event->width; + vnc->window.h = event->height; + dpy_resize_window(vnc); + dpy_flush(vnc, __FUNCTION__); + return TRUE; +} + +static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event, + gpointer data) +{ + struct vnc_window *vnc = data; + + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { + vnc->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + vnc_window_texts(vnc); + } return TRUE; } @@ -538,6 +844,17 @@ 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) { struct vnc_window *vnc = data; @@ -627,6 +944,8 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, vnc->viewonly = (flags & VNC_FLAG_VIEW_ONLY); vnc->debug = debug_level; debug_libvnc = debug_level; + snprintf(vnc->display, sizeof(vnc->display), + "%s:%d", hostname, tcpport - 5900); /* x11 */ vnc->dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); @@ -634,33 +953,6 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, if (0 != x11_color_init(vnc->dpy)) goto err; - /* rfb client */ - snprintf(vnc->display, sizeof(vnc->display), - "%s:%d", hostname, tcpport - 5900); - argv[1] = vnc->display; - fprintf(stderr, "%s: connecting to %s\n", __FUNCTION__, vnc->display); - if (8 == x11_red_bits) - vnc->client = rfbGetClient(8,3,4); - else - vnc->client = rfbGetClient(5,3,2); - if (NULL == vnc->client) - goto err; - rfbClientSetClientData(vnc->client, vnc_open, vnc); - vnc->client->MallocFrameBuffer = vnc_resize; - vnc->client->GotFrameBufferUpdate = vnc_update; - 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) - 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); - vnc->connected = 1; - /* gtk toplevel */ vnc->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(vnc->win), "destroy", @@ -692,21 +984,29 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, G_CALLBACK(key_cb), vnc); g_signal_connect(G_OBJECT(vnc->draw), "key-release-event", G_CALLBACK(key_cb), vnc); + g_signal_connect(G_OBJECT(vnc->draw), "configure-event", + G_CALLBACK(configure_cb), vnc); + g_signal_connect(G_OBJECT(vnc->win), "window-state-event", + G_CALLBACK(window_state_cb), vnc); gdk_window_add_filter(NULL, event_filter, vnc); vnc->filter_installed = 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); @@ -729,6 +1029,7 @@ 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); @@ -736,6 +1037,36 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, /* show window */ gtk_widget_show_all(vnc->win); vnc_window_conf(vnc); + + /* opengl */ + if (!(flags & VNC_FLAG_NOGL) && 0 == gl_init(vnc)) + vnc->have_gl = 1; + + /* rfb client */ + argv[1] = vnc->display; + fprintf(stderr, "%s: connecting to %s\n", __FUNCTION__, vnc->display); + if (8 == x11_red_bits) + vnc->client = rfbGetClient(8,3,4); + else + vnc->client = rfbGetClient(5,3,2); + if (NULL == vnc->client) + goto err; + rfbClientSetClientData(vnc->client, vnc_open, vnc); + vnc->client->MallocFrameBuffer = vnc_resize; + vnc->client->GotFrameBufferUpdate = vnc_update; + 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) + 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); + vnc->connected = 1; + return vnc->win; err: @@ -2,6 +2,7 @@ #define VNC_FLAG_US_KBD (1 << 2) #define VNC_FLAG_SHOW_MOUSE (1 << 3) #define VNC_FLAG_VIEW_ONLY (1 << 4) +#define VNC_FLAG_NOGL (1 << 5) GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags, int debug_level); |