diff options
author | kraxel <kraxel> | 2006-10-31 13:33:31 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-10-31 13:33:31 +0000 |
commit | 0289bad62049061a86ec5eb4185c02ff5807d419 (patch) | |
tree | 3652d03e26fcdfd26f4594a4bd81d677affeb44b /vnc.c | |
parent | 733a1ee52f081c554788accb51d55bb8a9602560 (diff) | |
download | xenwatch-0289bad62049061a86ec5eb4185c02ff5807d419.tar.gz |
KeymapNotify
Diffstat (limited to 'vnc.c')
-rw-r--r-- | vnc.c | 148 |
1 files changed, 73 insertions, 75 deletions
@@ -27,22 +27,23 @@ static int debug_libvnc; struct vnc_window { /* vnc connection */ - rfbClient *client; - GIOChannel *ch; - guint id; + rfbClient *client; + GIOChannel *ch; + guint id; /* gtk */ - GtkWidget *win; - GtkWidget *draw; - GdkCursor *on,*off; - int filter_installed; + GtkWidget *win; + GtkWidget *draw; + GdkCursor *on,*off; + int filter_installed; /* x11 */ - XImage *ximage; - void *shm; - GC gc; - Display *dpy; + XImage *ximage; + void *shm; + GC gc; + Display *dpy; + unsigned char keydown[32]; /* config */ - int standalone; - int debug; + int standalone; + int debug; }; /* ------------------------------------------------------------------ */ @@ -62,6 +63,14 @@ static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, /* ------------------------------------------------------------------ */ /* helper functions */ +static void XAddInput(Display *dpy, Window win, long mask) +{ + XWindowAttributes attr; + + XGetWindowAttributes(dpy, win, &attr); + XSelectInput(dpy, win, attr.your_event_mask | mask); +} + static GdkCursor* empty_cursor(void) { static char bits[32]; @@ -109,8 +118,11 @@ static void vnc_window_conf(struct vnc_window *vnc) 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); - if (vnc->draw->window) + if (vnc->draw->window) { gdk_window_set_cursor(vnc->draw->window, vnc->off); + XAddInput(vnc->dpy, gdk_x11_drawable_get_xid(vnc->draw->window), + KeymapStateMask); + } } static void vnc_release(struct vnc_window *vnc) @@ -315,6 +327,7 @@ static gboolean expose_cb(GtkWidget *widget, GdkEventExpose *event, gpointer dat event->area.width, event->area.height, FALSE); #endif + return TRUE; } @@ -350,12 +363,21 @@ static void send_mouse(struct vnc_window *vnc, int x, int y, SendPointerEvent(vnc->client, x, y, rfbstate); } -#if 0 static gboolean button_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) { struct vnc_window *vnc = data; - send_mouse(vnc, event->x, event->y, event->state); + switch (event->type) { + case GDK_BUTTON_PRESS: + send_mouse(vnc, event->x, event->y, event->state, event->button, 0); + break; + case GDK_BUTTON_RELEASE: + send_mouse(vnc, event->x, event->y, event->state, 0, event->button); + break; + default: + /* keep gcc happy */ + break; + } return TRUE; } @@ -363,10 +385,9 @@ static gboolean motion_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data) { struct vnc_window *vnc = data; - send_mouse(vnc, event->x, event->y, event->state); + send_mouse(vnc, event->x, event->y, event->state, 0, 0); return TRUE; } -#endif static gboolean key_cb_local(GtkWidget *widget, GdkEventKey *event, gpointer data) @@ -390,12 +411,22 @@ static gboolean key_cb_uskbd(GtkWidget *widget, GdkEventKey *event, int shift,keydown; keydown = (8 == event->type); + if (event->hardware_keycode < 256) { + int by = event->hardware_keycode / 8; + int bi = event->hardware_keycode % 8; + if (keydown) + vnc->keydown[by] |= (1 << bi); + else + vnc->keydown[by] &= ~(1 << bi); + } + shift = (event->state & GDK_SHIFT_MASK) ? 1 : 0; if (event->hardware_keycode < linux_uskbd_size) { keysym = linux_uskbd[event->hardware_keycode][shift]; if (0 == keysym) keysym = linux_uskbd[event->hardware_keycode][0]; } + if (vnc->debug || 0 == keysym) fprintf(stderr,"%s[%d]: called: keycode %d => keysym %d\n", __FUNCTION__, event->type, event->hardware_keycode, keysym); @@ -409,46 +440,32 @@ static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent, { struct vnc_window *vnc = data; XEvent *xevent = gdkxevent; + int by, bi, keydown, keycode; + rfbKeySym keysym = 0; 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 2: - case 3: - case 7: - case 8: - case 9: - case 10: - case 15: - case 16: - case 18: - case 21: - - 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; + for (by = 0; by < 32; by++) { + if (vnc->keydown[by] == xevent->xkeymap.key_vector[by]) + continue; + for (bi = 0; bi < 8; bi++) { + if ((vnc->keydown[by] & (1 << bi)) == + (xevent->xkeymap.key_vector[by] & (1 << bi))) + continue; + keydown = xevent->xkeymap.key_vector[by] & (1 << bi); + keycode = by * 8 + bi; + keysym = linux_uskbd[keycode][0]; + if (!keysym) + continue; + if (vnc->debug) + fprintf(stderr,"%s: KeymapNotify: %-7s %3d\n", __FUNCTION__, + keydown ? "press" : "release", keycode); + SendKeyEvent(vnc->client, keysym, keydown ? TRUE : FALSE); + } + } + memcpy(vnc->keydown, xevent->xkeymap.key_vector, 32); + return GDK_FILTER_REMOVE; default: - fprintf(stderr, "%s: unhandled: type %d\n", __FUNCTION__, xevent->type); return GDK_FILTER_CONTINUE; } } @@ -514,7 +531,6 @@ GtkWidget *vnc_open(char *hostname, int displayno, unsigned long flags, vnc->draw = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(vnc->win), vnc->draw); GTK_WIDGET_SET_FLAGS(vnc->draw, GTK_CAN_FOCUS); -#if 1 gtk_widget_add_events(vnc->draw, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | @@ -522,27 +538,23 @@ GtkWidget *vnc_open(char *hostname, int displayno, unsigned long flags, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_EXPOSURE_MASK); -#else - gtk_widget_add_events(vnc->win, GDK_ALL_EVENTS_MASK); - gtk_widget_add_events(vnc->draw, GDK_ALL_EVENTS_MASK); -#endif 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); -#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); -#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", G_CALLBACK(key_cb_uskbd), vnc); + gdk_window_add_filter(NULL, event_filter, vnc); + vnc->filter_installed = 1; } else { g_signal_connect(G_OBJECT(vnc->draw), "key-press-event", G_CALLBACK(key_cb_local), vnc); @@ -553,20 +565,6 @@ GtkWidget *vnc_open(char *hostname, int displayno, unsigned long flags, /* 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); - gdk_window_add_filter(vnc->win->window, event_filter, vnc); -#endif - - gdk_window_add_filter(vnc->draw->window, event_filter, vnc); - vnc->filter_installed = 1; return vnc->win; err: |