aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2007-05-16 10:12:15 +0000
committerkraxel <kraxel>2007-05-16 10:12:15 +0000
commit63f9c3be3b98a2c03af38185614cf9ccc1d960f8 (patch)
tree4a209535e6fbded4fb3dac77883038643dc9d815
parent9f355bea4ff551b59f368100e892eeb10eef5c21 (diff)
downloadxenwatch-63f9c3be3b98a2c03af38185614cf9ccc1d960f8.tar.gz
opengl support
-rw-r--r--GNUmakefile2
-rw-r--r--vnc-client.c6
-rw-r--r--vnc.c519
-rw-r--r--vnc.h1
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);
diff --git a/vnc.c b/vnc.c
index c0be346..10bfaf1 100644
--- a/vnc.c
+++ b/vnc.c
@@ -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:
diff --git a/vnc.h b/vnc.h
index 8bf97e3..839cdf2 100644
--- a/vnc.h
+++ b/vnc.h
@@ -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);