summaryrefslogtreecommitdiffstats
path: root/x11vnc/uinput.c
diff options
context:
space:
mode:
authorrunge <runge>2006-07-09 01:48:31 +0000
committerrunge <runge>2006-07-09 01:48:31 +0000
commit079528470d8a1dfeab321ebdc2ab6c42943ed296 (patch)
treeaaa83a4d318c1c72a7698c3b8a6b5318397688d3 /x11vnc/uinput.c
parent8cda60969b6d2df88e0f4fc0fd267dc26adb3872 (diff)
downloadlibtdevnc-079528470d8a1dfeab321ebdc2ab6c42943ed296.tar.gz
libtdevnc-079528470d8a1dfeab321ebdc2ab6c42943ed296.zip
x11vnc: add uinput support for full input into linux fb device (e.g. qt-embed).
Diffstat (limited to 'x11vnc/uinput.c')
-rw-r--r--x11vnc/uinput.c1097
1 files changed, 1097 insertions, 0 deletions
diff --git a/x11vnc/uinput.c b/x11vnc/uinput.c
new file mode 100644
index 0000000..1c3f1b2
--- /dev/null
+++ b/x11vnc/uinput.c
@@ -0,0 +1,1097 @@
+/* -- uinput.c -- */
+
+#include "x11vnc.h"
+#include "cleanup.h"
+#include "scan.h"
+#include "xinerama.h"
+#include "screen.h"
+#include "pointer.h"
+#include "allowed_input_t.h"
+
+#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
+#if LIBVNCSERVER_HAVE_LINUX_INPUT_H
+#if LIBVNCSERVER_HAVE_LINUX_UINPUT_H
+#define UINPUT_OK
+#endif
+#endif
+#endif
+
+#ifdef UINPUT_OK
+#include <sys/ioctl.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+#endif
+
+int check_uinput(void);
+int initialize_uinput(void);
+int set_uinput_accel(char *str);
+void set_uinput_reset(int ms);
+char *get_uinput_accel();
+int get_uinput_reset();
+void parse_uinput_str(char *str);
+void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client);
+void uinput_key_command(int down, int keysym, rfbClientPtr client);
+
+static void set_uinput_accel_xy(double fx, double fy);
+static void shutdown_uinput(void);
+static void ptr_move(int dx, int dy);
+static void ptr_rel(int dx, int dy);
+static void button_click(int down, int btn);
+static int lookup_code(int keysym);
+
+static int fd = -1;
+static int db = 1;
+static int bmask = 0;
+
+static char *injectable = NULL;
+static char *uinput_dev = NULL;
+
+static char *devs[] = {
+ "/dev/misc/uinput",
+ "/dev/input/uinput",
+ "/dev/uinput",
+ NULL
+};
+
+
+/*
+ * User may need to do:
+ modprode uinput
+ mknod /dev/input/uinput c 10 223
+ */
+
+int check_uinput(void) {
+ int i;
+#ifndef UINPUT_OK
+ return 0;
+#else
+ if (UT.release) {
+ int maj, min;
+ /* guard against linux 2.4 */
+ if (sscanf(UT.release, "%d.%d.", &maj, &min) == 2) {
+ if (maj < 2) {
+ return 0;
+ } else if (maj == 2) {
+ if (min < 6) {
+ return 0;
+ }
+ }
+ }
+ }
+ fd = -1;
+ i = 0;
+ while (devs[i] != NULL) {
+ if ( (fd = open(devs[i++], O_RDWR)) >= 0) {
+ break;
+ }
+ }
+ if (fd < 0) {
+ return 0;
+ }
+ close(fd);
+ fd = -1;
+ return 1;
+#endif
+}
+
+static void shutdown_uinput(void) {
+#ifdef UINPUT_OK
+ ioctl(fd, UI_DEV_DESTROY);
+#endif
+}
+
+int initialize_uinput(void) {
+#ifndef UINPUT_OK
+ return 0;
+#else
+ int i;
+ struct uinput_user_dev udev;
+
+ if (fd >= 0) {
+ shutdown_uinput();
+ close(fd);
+ fd = -1;
+ }
+
+ if (uinput_dev) {
+ fd = open(uinput_dev, O_RDWR);
+ rfbLog("initialize_uinput: using: %s %d\n", uinput_dev, fd);
+ } else {
+ i = 0;
+ while (devs[i] != NULL) {
+ if ( (fd = open(devs[i], O_RDWR)) >= 0) {
+ rfbLog("initialize_uinput: using: %s %d\n",
+ devs[i], fd);
+ break;
+ }
+ i++;
+ }
+ }
+ if (fd < 0) {
+ rfbLog("initialize_uinput: could not open an uinput device.\n");
+ rfbLogPerror("open");
+ clean_up_exit(1);
+ }
+
+ memset(&udev, 0, sizeof(udev));
+
+ strncpy(udev.name, "x11vnc injector", UINPUT_MAX_NAME_SIZE);
+
+ udev.id.bustype = BUS_USB; /* Matters? */
+ udev.id.version = 4;
+
+ ioctl(fd, UI_SET_EVBIT, EV_REL);
+ ioctl(fd, UI_SET_RELBIT, REL_X);
+ ioctl(fd, UI_SET_RELBIT, REL_Y);
+
+ ioctl(fd, UI_SET_EVBIT, EV_KEY);
+
+ for (i=0; i < 256; i++) {
+ ioctl(fd, UI_SET_KEYBIT, i);
+ }
+
+ ioctl(fd, UI_SET_KEYBIT, BTN_MOUSE);
+ ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
+ ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE);
+ ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
+ ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD);
+ ioctl(fd, UI_SET_KEYBIT, BTN_BACK);
+
+ write(fd, &udev, sizeof(udev));
+
+ if (ioctl(fd, UI_DEV_CREATE) != 0) {
+ rfbLog("ioctl(fd, UI_DEV_CREATE) failed.\n");
+ rfbLogPerror("ioctl");
+ close(fd);
+ clean_up_exit(1);
+ }
+ return 1;
+#endif
+}
+
+static double fudge_x = 0.5; /* accel=2.0 */
+static double fudge_y = 0.5;
+
+static double resid_x = 0.0;
+static double resid_y = 0.0;
+
+static double zero_delay = 0.5;
+
+static void set_uinput_accel_xy(double fx, double fy) {
+ fudge_x = 1.0/fx;
+ fudge_y = 1.0/fy;
+ rfbLog("set_uinput_accel: fx=%.5f fy=%.5f\n", fx, fy);
+ rfbLog("set_uinput_accel: ix=%.5f iy=%.5f\n", fudge_x, fudge_y);
+}
+
+static char *uinput_accel_str = NULL;
+
+int set_uinput_accel(char *str) {
+ double fx, fy;
+ rfbLog("set_uinput_accel: str=%s\n", str);
+ if (sscanf(str, "%lf+%lf", &fx, &fy) == 2) {
+ set_uinput_accel_xy(fx, fy);
+ } else if (sscanf(str, "%lf", &fx) == 1) {
+ set_uinput_accel_xy(fx, fx);
+ } else {
+ rfbLog("invalid UINPUT accel= option: %s\n", str);
+ return 0;
+ }
+ if (uinput_accel_str) {
+ free(uinput_accel_str);
+ }
+ uinput_accel_str = strdup(str);
+ return 1;
+}
+
+void set_uinput_reset(int ms) {
+ zero_delay = (double) ms/1000.;
+ rfbLog("set_uinput_reset: %d\n", ms);
+}
+
+char *get_uinput_accel(void) {
+ return uinput_accel_str;
+}
+int get_uinput_reset(void) {
+ return (int) (1000 * zero_delay);
+}
+
+void parse_uinput_str(char *in) {
+ char *p, *q, *str = strdup(in);
+
+ if (injectable) {
+ free(injectable);
+ injectable = strdup("KMB");
+ }
+
+ p = strtok(str, ",");
+ while (p) {
+ if (p[0] == '/') {
+ if (uinput_dev) {
+ free(uinput_dev);
+ }
+ uinput_dev = strdup(p);
+ } else if (strstr(p, "accel=") == p) {
+ double fx, fy;
+ q = p + strlen("accel=");
+ if (! set_uinput_accel(q)) {
+ clean_up_exit(1);
+ }
+
+ } else if (strstr(p, "reset=") == p) {
+ int n = atoi(p + strlen("reset="));
+ set_uinput_reset(n);
+ } else if (strpbrk(p, "KMB") == p) {
+ if (injectable) {
+ free(injectable);
+ }
+ injectable = strdup(p);
+ } else {
+ rfbLog("invalid UINPUT option: %s\n", p);
+ clean_up_exit(1);
+ }
+ p = strtok(NULL, ",");
+ }
+ free(str);
+}
+
+static void ptr_move(int dx, int dy) {
+#ifdef UINPUT_OK
+ struct input_event ev;
+
+ if (injectable && strchr(injectable, 'M') == NULL) {
+ return;
+ }
+if (0) fprintf(stderr, "ptr_move: %d %d\n", dx, dy);
+
+ memset(&ev, 0, sizeof(ev));
+
+ gettimeofday(&ev.time, NULL);
+ ev.type = EV_REL;
+ ev.code = REL_X;
+ ev.value = dx;
+ write(fd, &ev, sizeof(ev));
+
+ ev.type = EV_REL;
+ ev.code = REL_Y;
+ ev.value = dy;
+ write(fd, &ev, sizeof(ev));
+
+ ev.type = EV_SYN;
+ ev.code = SYN_REPORT;
+ ev.value = 0;
+ write(fd, &ev, sizeof(ev));
+#endif
+}
+
+static void ptr_rel(int dx, int dy) {
+ int dxf, dyf;
+
+ dxf = (int) (fudge_x * (double) dx);
+ dyf = (int) (fudge_y * (double) dy);
+
+ if (db > 1) fprintf(stderr, "old dx dy: %d %d\n", dx, dy);
+ if (db > 1) fprintf(stderr, "new dx dy: %d %d\n", dxf, dyf);
+
+ ptr_move(dxf, dyf);
+
+ resid_x += fudge_x * (double) dx - dxf;
+ resid_y += fudge_y * (double) dy - dyf;
+
+ if (resid_x < -1.0 || resid_x > 1.0 || resid_y < -1.0 || resid_y > 1.0) {
+ dxf = 0;
+ dyf = 0;
+ if (resid_x > 1.0) {
+ dxf = (int) resid_x;
+ } else if (resid_x < -1.0) {
+ dxf = -((int) (-resid_x));
+ }
+ resid_x -= dxf;
+ if (resid_y > 1.0) {
+ dyf = (int) resid_y;
+ } else if (resid_y < -1.0) {
+ dyf = -((int) (-resid_y));
+ }
+ resid_y -= dyf;
+ ptr_move(dxf, dyf);
+ }
+}
+
+static void button_click(int down, int btn) {
+#ifdef UINPUT_OK
+ struct input_event ev;
+
+ if (injectable && strchr(injectable, 'B') == NULL) {
+ return;
+ }
+
+ if (db) fprintf(stderr, "down %d btn %d\n", down, btn);
+
+ memset(&ev, 0, sizeof(ev));
+ gettimeofday(&ev.time, NULL);
+ ev.type = EV_KEY;
+ ev.value = down;
+
+ if (btn == 1) {
+ ev.code = BTN_LEFT;
+ } else if (btn == 2) {
+ ev.code = BTN_MIDDLE;
+ } else if (btn == 3) {
+ ev.code = BTN_RIGHT;
+ } else if (btn == 4) {
+ ev.code = BTN_FORWARD;
+ } else if (btn == 5) {
+ ev.code = BTN_BACK;
+ } else {
+ return;
+ }
+
+ write(fd, &ev, sizeof(ev));
+
+ ev.type = EV_SYN;
+ ev.code = SYN_REPORT;
+ ev.value = 0;
+ write(fd, &ev, sizeof(ev));
+
+#endif
+}
+
+
+void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) {
+ static int last_x = -1, last_y = -1, last_mask = -1;
+ static double last_zero = 0.0;
+ allowed_input_t input;
+
+ if (db) fprintf(stderr, "uinput_pointer_command: %d %d - %d\n", x, y, mask);
+
+ if (view_only) {
+ return;
+ }
+ get_allowed_input(client, &input);
+
+ if (!bmask && dnow() >= last_zero + zero_delay && input.motion) {
+ static int first = 1;
+
+ if (zero_delay > 0.0 || first) {
+ /* try to push it to 0,0 */
+ int tx = fudge_x * last_x;
+ int ty = fudge_y * last_y;
+ int bigjump = 1;
+
+ if (bigjump) {
+ ptr_move(-tx, -ty);
+ ptr_move(-tx, -ty);
+ } else {
+ int i, step, n = 20;
+ step = dpy_x / n;
+ if (step < 100) step = 100;
+ for (i=0; i < n; i++) {
+ ptr_move(-step, -step);
+ }
+ for (i=0; i < n; i++) {
+ ptr_move(-1, -1);
+ }
+ }
+ if (db) fprintf(stderr, "uinput_pointer_command: reset\n");
+
+ /* rest a bit for system to absorb the change */
+ usleep(30*1000);
+
+ /* now jump back out */
+ ptr_rel(x, y);
+
+ last_x = x;
+ last_y = y;
+ resid_x = 0.0;
+ resid_y = 0.0;
+
+ first = 0;
+ }
+ last_zero = dnow();
+ }
+
+ if (input.motion) {
+ if (x != last_x || y != last_y) {
+ ptr_rel(x - last_x, y - last_y);
+ last_x = x;
+ last_y = y;
+ }
+ }
+
+ if (! input.button) {
+ return;
+ }
+
+ if (last_mask < 0) {
+ last_mask = mask;
+ }
+
+#if 0
+fprintf(stderr, "mask: %s\n", bitprint(mask, 16));
+fprintf(stderr, "bmask: %s\n", bitprint(bmask, 16));
+fprintf(stderr, "last_mask: %s\n", bitprint(last_mask, 16));
+fprintf(stderr, "button_mask: %s\n", bitprint(button_mask, 16));
+#endif
+
+ if (mask != last_mask) {
+ int i;
+ for (i=1; i <= MAX_BUTTONS; i++) {
+ int down, b = 1 << (i-1);
+ if ( (last_mask & b) == (mask & b)) {
+ continue;
+ }
+ if (mask & b) {
+ down = 1;
+ } else {
+ down = 0;
+ }
+ button_click(down, i);
+ }
+ last_mask = mask;
+ }
+ bmask = mask;
+}
+
+void uinput_key_command(int down, int keysym, rfbClientPtr client) {
+#ifdef UINPUT_OK
+ struct input_event ev;
+ int scancode;
+ allowed_input_t input;
+
+ if (injectable && strchr(injectable, 'K') == NULL) {
+ return;
+ }
+ if (view_only) {
+ return;
+ }
+ get_allowed_input(client, &input);
+ if (! input.keystroke) {
+ return;
+ }
+
+ scancode = lookup_code(keysym);
+
+ if (scancode < 0) {
+ return;
+ }
+ if (db) fprintf(stderr, "uinput_key_command: %d -> %d\n", keysym, scancode);
+
+ memset(&ev, 0, sizeof(ev));
+ gettimeofday(&ev.time, NULL);
+ ev.type = EV_KEY;
+ ev.code = (unsigned char) scancode;
+ ev.value = down;
+
+ write(fd, &ev, sizeof(ev));
+
+ ev.type = EV_SYN;
+ ev.code = SYN_REPORT;
+ ev.value = 0;
+ write(fd, &ev, sizeof(ev));
+#endif
+}
+
+static int lookup_code(int keysym) {
+
+ if (keysym == NoSymbol) {
+ return -1;
+ }
+
+ switch(keysym) {
+#ifdef UINPUT_OK
+ case XK_Escape: return KEY_ESC;
+ case XK_1: return KEY_1;
+ case XK_2: return KEY_2;
+ case XK_3: return KEY_3;
+ case XK_4: return KEY_4;
+ case XK_5: return KEY_5;
+ case XK_6: return KEY_6;
+ case XK_7: return KEY_7;
+ case XK_8: return KEY_8;
+ case XK_9: return KEY_9;
+ case XK_0: return KEY_0;
+ case XK_exclam: return KEY_1;
+ case XK_at: return KEY_2;
+ case XK_numbersign: return KEY_3;
+ case XK_dollar: return KEY_4;
+ case XK_percent: return KEY_5;
+ case XK_asciicircum: return KEY_6;
+ case XK_ampersand: return KEY_7;
+ case XK_asterisk: return KEY_8;
+ case XK_parenleft: return KEY_9;
+ case XK_parenright: return KEY_0;
+ case XK_minus: return KEY_MINUS;
+ case XK_underscore: return KEY_MINUS;
+ case XK_equal: return KEY_EQUAL;
+ case XK_plus: return KEY_EQUAL;
+ case XK_BackSpace: return KEY_BACKSPACE;
+ case XK_Tab: return KEY_TAB;
+ case XK_q: return KEY_Q;
+ case XK_Q: return KEY_Q;
+ case XK_w: return KEY_W;
+ case XK_W: return KEY_W;
+ case XK_e: return KEY_E;
+ case XK_E: return KEY_E;
+ case XK_r: return KEY_R;
+ case XK_R: return KEY_R;
+ case XK_t: return KEY_T;
+ case XK_T: return KEY_T;
+ case XK_y: return KEY_Y;
+ case XK_Y: return KEY_Y;
+ case XK_u: return KEY_U;
+ case XK_U: return KEY_U;
+ case XK_i: return KEY_I;
+ case XK_I: return KEY_I;
+ case XK_o: return KEY_O;
+ case XK_O: return KEY_O;
+ case XK_p: return KEY_P;
+ case XK_P: return KEY_P;
+ case XK_braceleft: return KEY_LEFTBRACE;
+ case XK_braceright: return KEY_RIGHTBRACE;
+ case XK_bracketleft: return KEY_LEFTBRACE;
+ case XK_bracketright: return KEY_RIGHTBRACE;
+ case XK_Return: return KEY_ENTER;
+ case XK_Control_L: return KEY_LEFTCTRL;
+ case XK_a: return KEY_A;
+ case XK_A: return KEY_A;
+ case XK_s: return KEY_S;
+ case XK_S: return KEY_S;
+ case XK_d: return KEY_D;
+ case XK_D: return KEY_D;
+ case XK_f: return KEY_F;
+ case XK_F: return KEY_F;
+ case XK_g: return KEY_G;
+ case XK_G: return KEY_G;
+ case XK_h: return KEY_H;
+ case XK_H: return KEY_H;
+ case XK_j: return KEY_J;
+ case XK_J: return KEY_J;
+ case XK_k: return KEY_K;
+ case XK_K: return KEY_K;
+ case XK_l: return KEY_L;
+ case XK_L: return KEY_L;
+ case XK_semicolon: return KEY_SEMICOLON;
+ case XK_colon: return KEY_SEMICOLON;
+ case XK_apostrophe: return KEY_APOSTROPHE;
+ case XK_quotedbl: return KEY_APOSTROPHE;
+ case XK_grave: return KEY_GRAVE;
+ case XK_asciitilde: return KEY_GRAVE;
+ case XK_Shift_L: return KEY_LEFTSHIFT;
+ case XK_backslash: return KEY_BACKSLASH;
+ case XK_bar: return KEY_BACKSLASH;
+ case XK_z: return KEY_Z;
+ case XK_Z: return KEY_Z;
+ case XK_x: return KEY_X;
+ case XK_X: return KEY_X;
+ case XK_c: return KEY_C;
+ case XK_C: return KEY_C;
+ case XK_v: return KEY_V;
+ case XK_V: return KEY_V;
+ case XK_b: return KEY_B;
+ case XK_B: return KEY_B;
+ case XK_n: return KEY_N;
+ case XK_N: return KEY_N;
+ case XK_m: return KEY_M;
+ case XK_M: return KEY_M;
+ case XK_comma: return KEY_COMMA;
+ case XK_less: return KEY_COMMA;
+ case XK_period: return KEY_DOT;
+ case XK_greater: return KEY_DOT;
+ case XK_slash: return KEY_SLASH;
+ case XK_question: return KEY_SLASH;
+ case XK_Shift_R: return KEY_RIGHTSHIFT;
+ case XK_KP_Multiply: return KEY_KPASTERISK;
+ case XK_Alt_L: return KEY_LEFTALT;
+ case XK_space: return KEY_SPACE;
+ case XK_Caps_Lock: return KEY_CAPSLOCK;
+ case XK_F1: return KEY_F1;
+ case XK_F2: return KEY_F2;
+ case XK_F3: return KEY_F3;
+ case XK_F4: return KEY_F4;
+ case XK_F5: return KEY_F5;
+ case XK_F6: return KEY_F6;
+ case XK_F7: return KEY_F7;
+ case XK_F8: return KEY_F8;
+ case XK_F9: return KEY_F9;
+ case XK_F10: return KEY_F10;
+ case XK_Num_Lock: return KEY_NUMLOCK;
+ case XK_Scroll_Lock: return KEY_SCROLLLOCK;
+ case XK_KP_7: return KEY_KP7;
+ case XK_KP_8: return KEY_KP8;
+ case XK_KP_9: return KEY_KP9;
+ case XK_KP_Subtract: return KEY_KPMINUS;
+ case XK_KP_4: return KEY_KP4;
+ case XK_KP_5: return KEY_KP5;
+ case XK_KP_6: return KEY_KP6;
+ case XK_KP_Add: return KEY_KPPLUS;
+ case XK_KP_1: return KEY_KP1;
+ case XK_KP_2: return KEY_KP2;
+ case XK_KP_3: return KEY_KP3;
+ case XK_KP_0: return KEY_KP0;
+ case XK_KP_Decimal: return KEY_KPDOT;
+ case XK_F13: return KEY_F13;
+ case XK_F11: return KEY_F11;
+ case XK_F12: return KEY_F12;
+ case XK_F14: return KEY_F14;
+ case XK_F15: return KEY_F15;
+ case XK_F16: return KEY_F16;
+ case XK_F17: return KEY_F17;
+ case XK_F18: return KEY_F18;
+ case XK_F19: return KEY_F19;
+ case XK_F20: return KEY_F20;
+ case XK_KP_Enter: return KEY_KPENTER;
+ case XK_Control_R: return KEY_RIGHTCTRL;
+ case XK_KP_Divide: return KEY_KPSLASH;
+ case XK_Sys_Req: return KEY_SYSRQ;
+ case XK_Alt_R: return KEY_RIGHTALT;
+ case XK_Linefeed: return KEY_LINEFEED;
+ case XK_Home: return KEY_HOME;
+ case XK_Up: return KEY_UP;
+ case XK_Page_Up: return KEY_PAGEUP;
+ case XK_Left: return KEY_LEFT;
+ case XK_Right: return KEY_RIGHT;
+ case XK_End: return KEY_END;
+ case XK_Down: return KEY_DOWN;
+ case XK_Page_Down: return KEY_PAGEDOWN;
+ case XK_Insert: return KEY_INSERT;
+ case XK_Delete: return KEY_DELETE;
+ case XK_KP_Equal: return KEY_KPEQUAL;
+ case XK_Pause: return KEY_PAUSE;
+ case XK_F21: return KEY_F21;
+ case XK_F22: return KEY_F22;
+ case XK_F23: return KEY_F23;
+ case XK_F24: return KEY_F24;
+ case XK_KP_Separator: return KEY_KPCOMMA;
+ case XK_Meta_L: return KEY_LEFTMETA;
+ case XK_Meta_R: return KEY_RIGHTMETA;
+ case XK_Multi_key: return KEY_COMPOSE;
+#endif
+ default: return -1;
+ }
+}
+
+#if 0
+
+From /usr/include/linux/input.h
+
+We maintain it here since it is such a painful mess.
+
+Here is a little script to make it easier:
+
+#!/usr/bin/perl
+while (<>) {
+ $_ =~ s/-XK_/XK_/;
+ next unless /^XK_/;
+ chomp;
+ if (/^(\S+)(\s+)(\S+)/) {
+ $a = $1;
+ $t = $2;
+ $b = $3;
+ print "\tcase $a:${t}return $b;\n";
+ if ($a =~ /XK_[a-z]$/) {
+ $a = uc($a);
+ print "\tcase $a:${t}return $b;\n";
+ }
+ }
+}
+
+This only handles us kbd, we would need a kbd database in general...
+
+XK_Escape KEY_ESC
+XK_1 KEY_1
+XK_2 KEY_2
+XK_3 KEY_3
+XK_4 KEY_4
+XK_5 KEY_5
+XK_6 KEY_6
+XK_7 KEY_7
+XK_8 KEY_8
+XK_9 KEY_9
+XK_0 KEY_0
+-XK_exclam KEY_1
+-XK_at KEY_2
+-XK_numbersign KEY_3
+-XK_dollar KEY_4
+-XK_percent KEY_5
+-XK_asciicircum KEY_6
+-XK_ampersand KEY_7
+-XK_asterisk KEY_8
+-XK_parenleft KEY_9
+-XK_parenright KEY_0
+XK_minus KEY_MINUS
+-XK_underscore KEY_MINUS
+XK_equal KEY_EQUAL
+-XK_plus KEY_EQUAL
+XK_BackSpace KEY_BACKSPACE
+XK_Tab KEY_TAB
+XK_q KEY_Q
+XK_w KEY_W
+XK_e KEY_E
+XK_r KEY_R
+XK_t KEY_T
+XK_y KEY_Y
+XK_u KEY_U
+XK_i KEY_I
+XK_o KEY_O
+XK_p KEY_P
+XK_braceleft KEY_LEFTBRACE
+XK_braceright KEY_RIGHTBRACE
+-XK_bracketleft KEY_LEFTBRACE
+-XK_bracketright KEY_RIGHTBRACE
+XK_Return KEY_ENTER
+XK_Control_L KEY_LEFTCTRL
+XK_a KEY_A
+XK_s KEY_S
+XK_d KEY_D
+XK_f KEY_F
+XK_g KEY_G
+XK_h KEY_H
+XK_j KEY_J
+XK_k KEY_K
+XK_l KEY_L
+XK_semicolon KEY_SEMICOLON
+-XK_colon KEY_SEMICOLON
+XK_apostrophe KEY_APOSTROPHE
+-XK_quotedbl KEY_APOSTROPHE
+XK_grave KEY_GRAVE
+-XK_asciitilde KEY_GRAVE
+XK_Shift_L KEY_LEFTSHIFT
+XK_backslash KEY_BACKSLASH
+-XK_bar KEY_BACKSLASH
+XK_z KEY_Z
+XK_x KEY_X
+XK_c KEY_C
+XK_v KEY_V
+XK_b KEY_B
+XK_n KEY_N
+XK_m KEY_M
+XK_comma KEY_COMMA
+-XK_less KEY_COMMA
+XK_period KEY_DOT
+-XK_greater KEY_DOT
+XK_slash KEY_SLASH
+-XK_question KEY_SLASH
+XK_Shift_R KEY_RIGHTSHIFT
+XK_KP_Multiply KEY_KPASTERISK
+XK_Alt_L KEY_LEFTALT
+XK_space KEY_SPACE
+XK_Caps_Lock KEY_CAPSLOCK
+XK_F1 KEY_F1
+XK_F2 KEY_F2
+XK_F3 KEY_F3
+XK_F4 KEY_F4
+XK_F5 KEY_F5
+XK_F6 KEY_F6
+XK_F7 KEY_F7
+XK_F8 KEY_F8
+XK_F9 KEY_F9
+XK_F10 KEY_F10
+XK_Num_Lock KEY_NUMLOCK
+XK_Scroll_Lock KEY_SCROLLLOCK
+XK_KP_7 KEY_KP7
+XK_KP_8 KEY_KP8
+XK_KP_9 KEY_KP9
+XK_KP_Subtract KEY_KPMINUS
+XK_KP_4 KEY_KP4
+XK_KP_5 KEY_KP5
+XK_KP_6 KEY_KP6
+XK_KP_Add KEY_KPPLUS
+XK_KP_1 KEY_KP1
+XK_KP_2 KEY_KP2
+XK_KP_3 KEY_KP3
+XK_KP_0 KEY_KP0
+XK_KP_Decimal KEY_KPDOT
+NoSymbol KEY_103RD
+XK_F13 KEY_F13
+NoSymbol KEY_102ND
+XK_F11 KEY_F11
+XK_F12 KEY_F12
+XK_F14 KEY_F14
+XK_F15 KEY_F15
+XK_F16 KEY_F16
+XK_F17 KEY_F17
+XK_F18 KEY_F18
+XK_F19 KEY_F19
+XK_F20 KEY_F20
+XK_KP_Enter KEY_KPENTER
+XK_Control_R KEY_RIGHTCTRL
+XK_KP_Divide KEY_KPSLASH
+XK_Sys_Req KEY_SYSRQ
+XK_Alt_R KEY_RIGHTALT
+XK_Linefeed KEY_LINEFEED
+XK_Home KEY_HOME
+XK_Up KEY_UP
+XK_Page_Up KEY_PAGEUP
+XK_Left KEY_LEFT
+XK_Right KEY_RIGHT
+XK_End KEY_END
+XK_Down KEY_DOWN
+XK_Page_Down KEY_PAGEDOWN
+XK_Insert KEY_INSERT
+XK_Delete KEY_DELETE
+NoSymbol KEY_MACRO
+NoSymbol KEY_MUTE
+NoSymbol KEY_VOLUMEDOWN
+NoSymbol KEY_VOLUMEUP
+NoSymbol KEY_POWER
+XK_KP_Equal KEY_KPEQUAL
+NoSymbol KEY_KPPLUSMINUS
+XK_Pause KEY_PAUSE
+XK_F21 KEY_F21
+XK_F22 KEY_F22
+XK_F23 KEY_F23
+XK_F24 KEY_F24
+XK_KP_Separator KEY_KPCOMMA
+XK_Meta_L KEY_LEFTMETA
+XK_Meta_R KEY_RIGHTMETA
+XK_Multi_key KEY_COMPOSE
+
+NoSymbol KEY_STOP
+NoSymbol KEY_AGAIN
+NoSymbol KEY_PROPS
+NoSymbol KEY_UNDO
+NoSymbol KEY_FRONT
+NoSymbol KEY_COPY
+NoSymbol KEY_OPEN
+NoSymbol KEY_PASTE
+NoSymbol KEY_FIND
+NoSymbol KEY_CUT
+NoSymbol KEY_HELP
+NoSymbol KEY_MENU
+NoSymbol KEY_CALC
+NoSymbol KEY_SETUP
+NoSymbol KEY_SLEEP
+NoSymbol KEY_WAKEUP
+NoSymbol KEY_FILE
+NoSymbol KEY_SENDFILE
+NoSymbol KEY_DELETEFILE
+NoSymbol KEY_XFER
+NoSymbol KEY_PROG1
+NoSymbol KEY_PROG2
+NoSymbol KEY_WWW
+NoSymbol KEY_MSDOS
+NoSymbol KEY_COFFEE
+NoSymbol KEY_DIRECTION
+NoSymbol KEY_CYCLEWINDOWS
+NoSymbol KEY_MAIL
+NoSymbol KEY_BOOKMARKS
+NoSymbol KEY_COMPUTER
+NoSymbol KEY_BACK
+NoSymbol KEY_FORWARD
+NoSymbol KEY_CLOSECD
+NoSymbol KEY_EJECTCD
+NoSymbol KEY_EJECTCLOSECD
+NoSymbol KEY_NEXTSONG
+NoSymbol KEY_PLAYPAUSE
+NoSymbol KEY_PREVIOUSSONG
+NoSymbol KEY_STOPCD
+NoSymbol KEY_RECORD
+NoSymbol KEY_REWIND
+NoSymbol KEY_PHONE
+NoSymbol KEY_ISO
+NoSymbol KEY_CONFIG
+NoSymbol KEY_HOMEPAGE
+NoSymbol KEY_REFRESH
+NoSymbol KEY_EXIT
+NoSymbol KEY_MOVE
+NoSymbol KEY_EDIT
+NoSymbol KEY_SCROLLUP
+NoSymbol KEY_SCROLLDOWN
+NoSymbol KEY_KPLEFTPAREN
+NoSymbol KEY_KPRIGHTPAREN
+
+NoSymbol KEY_INTL1
+NoSymbol KEY_INTL2
+NoSymbol KEY_INTL3
+NoSymbol KEY_INTL4
+NoSymbol KEY_INTL5
+NoSymbol KEY_INTL6
+NoSymbol KEY_INTL7
+NoSymbol KEY_INTL8
+NoSymbol KEY_INTL9
+NoSymbol KEY_LANG1
+NoSymbol KEY_LANG2
+NoSymbol KEY_LANG3
+NoSymbol KEY_LANG4
+NoSymbol KEY_LANG5
+NoSymbol KEY_LANG6
+NoSymbol KEY_LANG7
+NoSymbol KEY_LANG8
+NoSymbol KEY_LANG9
+
+NoSymbol KEY_PLAYCD
+NoSymbol KEY_PAUSECD
+NoSymbol KEY_PROG3
+NoSymbol KEY_PROG4
+NoSymbol KEY_SUSPEND
+NoSymbol KEY_CLOSE
+NoSymbol KEY_PLAY
+NoSymbol KEY_FASTFORWARD
+NoSymbol KEY_BASSBOOST
+NoSymbol KEY_PRINT
+NoSymbol KEY_HP
+NoSymbol KEY_CAMERA
+NoSymbol KEY_SOUND
+NoSymbol KEY_QUESTION
+NoSymbol KEY_EMAIL
+NoSymbol KEY_CHAT
+NoSymbol KEY_SEARCH
+NoSymbol KEY_CONNECT
+NoSymbol KEY_FINANCE
+NoSymbol KEY_SPORT
+NoSymbol KEY_SHOP
+NoSymbol KEY_ALTERASE
+NoSymbol KEY_CANCEL
+NoSymbol KEY_BRIGHTNESSDOWN
+NoSymbol KEY_BRIGHTNESSUP
+NoSymbol KEY_MEDIA
+
+NoSymbol KEY_UNKNOWN
+NoSymbol
+NoSymbol BTN_MISC
+NoSymbol BTN_0
+NoSymbol BTN_1
+NoSymbol BTN_2
+NoSymbol BTN_3
+NoSymbol BTN_4
+NoSymbol BTN_5
+NoSymbol BTN_6
+NoSymbol BTN_7
+NoSymbol BTN_8
+NoSymbol BTN_9
+NoSymbol
+NoSymbol BTN_MOUSE
+NoSymbol BTN_LEFT
+NoSymbol BTN_RIGHT
+NoSymbol BTN_MIDDLE
+NoSymbol BTN_SIDE
+NoSymbol BTN_EXTRA
+NoSymbol BTN_FORWARD
+NoSymbol BTN_BACK
+NoSymbol BTN_TASK
+NoSymbol
+NoSymbol BTN_JOYSTICK
+NoSymbol BTN_TRIGGER
+NoSymbol BTN_THUMB
+NoSymbol BTN_THUMB2
+NoSymbol BTN_TOP
+NoSymbol BTN_TOP2
+NoSymbol BTN_PINKIE
+NoSymbol BTN_BASE
+NoSymbol BTN_BASE2
+NoSymbol BTN_BASE3
+NoSymbol BTN_BASE4
+NoSymbol BTN_BASE5
+NoSymbol BTN_BASE6
+NoSymbol BTN_DEAD
+
+NoSymbol BTN_GAMEPAD
+NoSymbol BTN_A
+NoSymbol BTN_B
+NoSymbol BTN_C
+NoSymbol BTN_X
+NoSymbol BTN_Y
+NoSymbol BTN_Z
+NoSymbol BTN_TL
+NoSymbol BTN_TR
+NoSymbol BTN_TL2
+NoSymbol BTN_TR2
+NoSymbol BTN_SELECT
+NoSymbol BTN_START
+NoSymbol BTN_MODE
+NoSymbol BTN_THUMBL
+NoSymbol BTN_THUMBR
+
+NoSymbol BTN_DIGI
+NoSymbol BTN_TOOL_PEN
+NoSymbol BTN_TOOL_RUBBER
+NoSymbol BTN_TOOL_BRUSH
+NoSymbol BTN_TOOL_PENCIL
+NoSymbol BTN_TOOL_AIRBRUSH
+NoSymbol BTN_TOOL_FINGER
+NoSymbol BTN_TOOL_MOUSE
+NoSymbol BTN_TOOL_LENS
+NoSymbol BTN_TOUCH
+NoSymbol BTN_STYLUS
+NoSymbol BTN_STYLUS2
+NoSymbol BTN_TOOL_DOUBLETAP
+NoSymbol BTN_TOOL_TRIPLETAP
+
+NoSymbol BTN_WHEEL
+NoSymbol BTN_GEAR_DOWN
+NoSymbol BTN_GEAR_UP
+
+NoSymbol KEY_OK
+NoSymbol KEY_SELECT
+NoSymbol KEY_GOTO
+NoSymbol KEY_CLEAR
+NoSymbol KEY_POWER2
+NoSymbol KEY_OPTION
+NoSymbol KEY_INFO
+NoSymbol KEY_TIME
+NoSymbol KEY_VENDOR
+NoSymbol KEY_ARCHIVE
+NoSymbol KEY_PROGRAM
+NoSymbol KEY_CHANNEL
+NoSymbol KEY_FAVORITES
+NoSymbol KEY_EPG
+NoSymbol KEY_PVR
+NoSymbol KEY_MHP
+NoSymbol KEY_LANGUAGE
+NoSymbol KEY_TITLE
+NoSymbol KEY_SUBTITLE
+NoSymbol KEY_ANGLE
+NoSymbol KEY_ZOOM
+NoSymbol KEY_MODE
+NoSymbol KEY_KEYBOARD
+NoSymbol KEY_SCREEN
+NoSymbol KEY_PC
+NoSymbol KEY_TV
+NoSymbol KEY_TV2
+NoSymbol KEY_VCR
+NoSymbol KEY_VCR2
+NoSymbol KEY_SAT
+NoSymbol KEY_SAT2
+NoSymbol KEY_CD
+NoSymbol KEY_TAPE
+NoSymbol KEY_RADIO
+NoSymbol KEY_TUNER
+NoSymbol KEY_PLAYER
+NoSymbol KEY_TEXT
+NoSymbol KEY_DVD
+NoSymbol KEY_AUX
+NoSymbol KEY_MP3
+NoSymbol KEY_AUDIO
+NoSymbol KEY_VIDEO
+NoSymbol KEY_DIRECTORY
+NoSymbol KEY_LIST
+NoSymbol KEY_MEMO
+NoSymbol KEY_CALENDAR
+NoSymbol KEY_RED
+NoSymbol KEY_GREEN
+NoSymbol KEY_YELLOW
+NoSymbol KEY_BLUE
+NoSymbol KEY_CHANNELUP
+NoSymbol KEY_CHANNELDOWN
+NoSymbol KEY_FIRST
+NoSymbol KEY_LAST
+NoSymbol KEY_AB
+NoSymbol KEY_NEXT
+NoSymbol KEY_RESTART
+NoSymbol KEY_SLOW
+NoSymbol KEY_SHUFFLE
+NoSymbol KEY_BREAK
+NoSymbol KEY_PREVIOUS
+NoSymbol KEY_DIGITS
+NoSymbol KEY_TEEN
+NoSymbol KEY_TWEN
+
+NoSymbol KEY_DEL_EOL
+NoSymbol KEY_DEL_EOS
+NoSymbol KEY_INS_LINE
+NoSymbol KEY_DEL_LINE
+NoSymbol KEY_MAX
+
+#endif
+
+