aboutsummaryrefslogtreecommitdiffstats
path: root/vnc.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-10-31 13:33:31 +0000
committerkraxel <kraxel>2006-10-31 13:33:31 +0000
commit0289bad62049061a86ec5eb4185c02ff5807d419 (patch)
tree3652d03e26fcdfd26f4594a4bd81d677affeb44b /vnc.c
parent733a1ee52f081c554788accb51d55bb8a9602560 (diff)
downloadxenwatch-0289bad62049061a86ec5eb4185c02ff5807d419.tar.gz
KeymapNotify
Diffstat (limited to 'vnc.c')
-rw-r--r--vnc.c148
1 files changed, 73 insertions, 75 deletions
diff --git a/vnc.c b/vnc.c
index 9b4bab9..c30143e 100644
--- a/vnc.c
+++ b/vnc.c
@@ -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: