aboutsummaryrefslogtreecommitdiffstats
path: root/vnc.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-10-30 15:50:24 +0000
committerkraxel <kraxel>2006-10-30 15:50:24 +0000
commitb0b7aac6a182502230ecadf0e37f24b220c3b450 (patch)
treeabaef77f9a1b210cc84c050233667102167ebe67 /vnc.c
parent16928d0f1b55cd0adb39450f1fbd122e6aac3f5e (diff)
downloadxenwatch-b0b7aac6a182502230ecadf0e37f24b220c3b450.tar.gz
misc vnc fixes
Diffstat (limited to 'vnc.c')
-rw-r--r--vnc.c108
1 files changed, 101 insertions, 7 deletions
diff --git a/vnc.c b/vnc.c
index 5afdcfc..0d488f0 100644
--- a/vnc.c
+++ b/vnc.c
@@ -7,6 +7,9 @@
#include <locale.h>
#include <signal.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
@@ -31,6 +34,7 @@ struct vnc_window {
GtkWidget *win;
GtkWidget *draw;
GdkCursor *on,*off;
+ int filter_installed;
/* x11 */
XImage *ximage;
void *shm;
@@ -50,6 +54,12 @@ rfbKeySym linux_uskbd[][2] = {
static int linux_uskbd_size = sizeof(linux_uskbd)/sizeof(linux_uskbd[0]);
/* ------------------------------------------------------------------ */
+/* prototypes */
+
+static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent,
+ gpointer data);
+
+/* ------------------------------------------------------------------ */
/* helper functions */
static GdkCursor* empty_cursor(void)
@@ -111,6 +121,8 @@ static void vnc_release(struct vnc_window *vnc)
if (vnc->client)
rfbClientCleanup(vnc->client);
#endif
+ if (vnc->filter_installed)
+ gdk_window_remove_filter(vnc->draw->window, event_filter, vnc);
if (vnc->id)
g_source_destroy(g_main_context_find_source_by_id
(g_main_context_default(), vnc->id));
@@ -133,6 +145,12 @@ static rfbBool vnc_resize(rfbClient* client)
__FUNCTION__, client->width, client->height);
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;
}
@@ -288,12 +306,20 @@ static gboolean expose_cb(GtkWidget *widget, GdkEventExpose *event, gpointer dat
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
return TRUE;
}
-static void send_mouse(struct vnc_window *vnc, int x, int y, int x11state)
+static void send_mouse(struct vnc_window *vnc, int x, int y,
+ int x11state, int x11press, int x11release)
{
int rfbstate = 0;
@@ -304,12 +330,27 @@ static void send_mouse(struct vnc_window *vnc, int x, int y, int x11state)
if (x11state & Button3Mask)
rfbstate |= rfbButton3Mask;
+ if (x11press == Button1)
+ rfbstate |= rfbButton1Mask;
+ if (x11press == Button2)
+ rfbstate |= rfbButton2Mask;
+ if (x11press == Button3)
+ rfbstate |= rfbButton3Mask;
+
+ if (x11release == Button1)
+ rfbstate &= ~rfbButton1Mask;
+ if (x11release == Button2)
+ rfbstate &= ~rfbButton2Mask;
+ if (x11release == Button3)
+ rfbstate &= ~rfbButton3Mask;
+
if (vnc->debug)
fprintf(stderr,"%s: +%d+%d x11state 0x%x rfbstate 0x%x\n",
__FUNCTION__, x, y, x11state, rfbstate);
SendPointerEvent(vnc->client, x, y, rfbstate);
}
+#if 0
static gboolean button_cb(GtkWidget *widget, GdkEventButton *event,
gpointer data)
{
@@ -325,6 +366,7 @@ static gboolean motion_cb(GtkWidget *widget, GdkEventMotion *event,
send_mouse(vnc, event->x, event->y, event->state);
return TRUE;
}
+#endif
static gboolean key_cb_local(GtkWidget *widget, GdkEventKey *event,
gpointer data)
@@ -362,11 +404,49 @@ static gboolean key_cb_uskbd(GtkWidget *widget, GdkEventKey *event,
return TRUE;
}
+static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent,
+ gpointer data)
+{
+ struct vnc_window *vnc = data;
+ XEvent *xevent = gdkxevent;
+
+ switch (xevent->type) {
+ case ButtonPress:
+ send_mouse(vnc, xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.state, xevent->xbutton.button, 0);
+ return GDK_FILTER_REMOVE;
+ case ButtonRelease:
+ send_mouse(vnc, xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.state, 0, xevent->xbutton.button);
+ return GDK_FILTER_REMOVE;
+ case MotionNotify:
+ send_mouse(vnc, xevent->xmotion.x, xevent->xmotion.y,
+ xevent->xmotion.state, 0, 0);
+ return GDK_FILTER_REMOVE;
+
+ case KeymapNotify:
+ fprintf(stderr, "%s: KeymapNotify\n", __FUNCTION__);
+ return GDK_FILTER_REMOVE;
+
+ case Expose: // 12
+ case MapNotify: // 19
+ case ConfigureNotify: // 22
+ case PropertyNotify: // 28
+ case ClientMessage: // 33
+ case 94:
+ /* do not log it */
+ return GDK_FILTER_CONTINUE;
+ default:
+ fprintf(stderr, "%s: unhandled: type %d\n", __FUNCTION__, xevent->type);
+ return GDK_FILTER_CONTINUE;
+ }
+}
+
/* ------------------------------------------------------------------ */
/* public API functions */
-GtkWidget *vnc_open(char *hostname, int displayno,
- int standalone, int uskbd, int debug)
+GtkWidget *vnc_open(char *hostname, int displayno, unsigned long flags,
+ int debug_level)
{
char display[128];
char *argv[] = { "vnc-client", display, NULL };
@@ -378,9 +458,9 @@ GtkWidget *vnc_open(char *hostname, int displayno,
if (NULL == vnc)
goto err;
memset(vnc,0,sizeof(*vnc));
- vnc->standalone = standalone;
- vnc->debug = debug;
- debug_libvnc = debug;
+ vnc->standalone = (flags & VNC_FLAG_STANDALONE);
+ vnc->debug = debug_level;
+ debug_libvnc = debug_level;
/* x11 */
vnc->dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
@@ -434,13 +514,15 @@ GtkWidget *vnc_open(char *hostname, int displayno,
gtk_widget_set_double_buffered(vnc->draw, FALSE);
g_signal_connect(G_OBJECT(vnc->draw), "expose-event",
G_CALLBACK(expose_cb), vnc);
+#if 0
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), "motion-notify-event",
G_CALLBACK(motion_cb), vnc);
- if (uskbd) {
+#endif
+ if (flags & VNC_FLAG_US_KBD) {
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",
@@ -455,6 +537,18 @@ GtkWidget *vnc_open(char *hostname, int displayno,
/* show window */
gtk_widget_show_all(vnc->win);
vnc_window_conf(vnc);
+
+ /* X11 lowlevel stuff (needs window handle) */
+#if 0
+ XSelectInput(vnc->dpy,
+ gdk_x11_drawable_get_xid(vnc->draw->window),
+ ButtonPressMask |
+ ButtonReleaseMask |
+ PointerMotionMask |
+ KeymapStateMask);
+#endif
+ gdk_window_add_filter(vnc->draw->window, event_filter, vnc);
+ vnc->filter_installed = 1;
return vnc->win;
err: