joy2key
ジョイパッドの入力をキーボードのキーコードに変換するjoy2keyを試していたけど、window名の指定が面倒なのでフォーカスがあたったところ限定にしたオリジナル版を作ってみました。Shift, Control, Metaなどのmodifierがない簡易的なものです。
joy2keyのソースコードを見ればわかりますが、はっきりいっていまいちです。sleep(0.2)とか使い方間違ってるし。
はまっている方もいらっしゃるようです。
http://d.hatena.ne.jp/n9d/20080210/1202648836
$ ./myjoy2key -b "d c x s NoSymbol NoSymbol NoSymbol NoSymbol space Return a z" \ -a "Left Right Up Down"
#include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #if !defined(MYJOY2KEY_DEBUG) #include <linux/joystick.h> #include <X11/Xlib.h> #include <X11/keysymdef.h> #else #include "myjoy2key_debug.h" #endif typedef struct { int pos_on; int neg_on; KeySym pos; KeySym neg; } Axis; typedef struct { char name[128]; int fd; int naxes; int nbuttons; Axis *axis; KeySym *button; } Joypad; typedef struct { Display *display; } Client; void usage(const char *); int joypad_load(Joypad *, const char *); int joypad_exec(Client *, Joypad *); int bind_axes(Joypad *, const char *); int bind_buttons(Joypad *, const char *); int gettok(const char *, char *, int, const char **); int sendkey(Client *, KeySym, int); void error(const char *, ...); int main(int argc, char **argv) { const char *progname; const char *devname; const char *axesstr; const char *buttonsstr; Joypad joypad; Client client; int opt; progname = argv[0]; devname = "/dev/input/js0"; axesstr = NULL; buttonsstr = NULL; while ((opt = getopt(argc, argv, "a:b:d:")) != -1) { switch (opt) { case 'a': axesstr = optarg; break; case 'b': buttonsstr = optarg; break; case 'd': devname = optarg; break; default: usage(progname); } } if ((client.display = XOpenDisplay(NULL)) == NULL) return EXIT_FAILURE; if (joypad_load(&joypad, devname) != 0) return EXIT_FAILURE; if (axesstr) if (bind_axes(&joypad, axesstr) != 0) return EXIT_FAILURE; if (buttonsstr) if (bind_buttons(&joypad, buttonsstr) != 0) return EXIT_FAILURE; while (joypad_exec(&client, &joypad) == 0) ; return EXIT_SUCCESS; } void usage(const char *progname) { printf("%s [-a axes] [-b buttons] [-d devname]\n", progname); exit(EXIT_FAILURE); } int joypad_load(Joypad *joy, const char *devname) { unsigned char v; size_t size; int i; if ((joy->fd = open(devname, O_RDONLY)) == -1) { error("open(`%s')", devname); return -1; } if (ioctl(joy->fd, JSIOCGNAME(sizeof(joy->name)), joy->name) < 0) { error("ioctl(name)"); close(joy->fd); return -1; } if (ioctl(joy->fd, JSIOCGAXES, &v) < 0) { error("ioctl(axes)"); close(joy->fd); return -1; } joy->naxes = v; if (ioctl(joy->fd, JSIOCGBUTTONS, &v) < 0) { error("ioctl(buttons)"); close(joy->fd); return -1; } joy->nbuttons = v; printf("NAME : %s\n", joy->name); printf("AXES : %d\n", joy->naxes); printf("BUTTONS : %d\n", joy->nbuttons); size = joy->naxes * sizeof(*joy->axis); if ((joy->axis = malloc(size)) == NULL) { error("malloc(axis: %zu)", size); close(joy->fd); return -1; } for (i = 0; i < joy->naxes; i++) { joy->axis[i].pos = NoSymbol; joy->axis[i].neg = NoSymbol; joy->axis[i].pos_on = 0; joy->axis[i].neg_on = 0; } size = joy->nbuttons * sizeof(*joy->button); if ((joy->button = malloc(size)) == NULL) { error("malloc(button: %zu)", size); close(joy->fd); free(joy->axis); return -1; } for (i = 0; i < joy->nbuttons; i++) joy->button[i] = NoSymbol; return 0; } int bind_axes(Joypad *joy, const char *s) { char token[80]; const char *brkp; int n; brkp = NULL; for (n = 0; gettok(s, token, sizeof(token), &brkp); n++) { if (n >= joy->naxes * 2) { error("Too many AXES %d > %d * 2.\n", n + 1, joy->naxes); return -1; } if (n & 1) joy->axis[n / 2].pos = XStringToKeysym(token); else joy->axis[n / 2].neg = XStringToKeysym(token); } if (n < joy->naxes * 2) { error("Too few AXES %d < %d * 2.\n", n, joy->naxes); return -1; } return 0; } int bind_buttons(Joypad *joy, const char *s) { char token[80]; const char *brkp; int n; brkp = NULL; for (n = 0; gettok(s, token, sizeof(token), &brkp); n++) { if (n >= joy->nbuttons) { error("Too many BUTTONS %d > %d.\n", n + 1, joy->nbuttons); return -1; } joy->button[n] = XStringToKeysym(token); } if (n < joy->nbuttons) { error("Too few BUTTONS %d < %d.\n", n, joy->nbuttons); return -1; } return 0; } int gettok(const char *s, char *buf, int len, const char **brkp) { const char *p; if (*brkp == NULL) p = s; else p = *brkp; if (*p == '\0') return 0; while (*p == ' ') p++; do { if (len <= 1) { error("Internal buffer too small.\n"); return 0; } *buf++ = *p++; len--; } while (*p != ' ' && *p != '\0'); *buf = '\0'; *brkp = p; return 1; } int joypad_exec(Client *client, Joypad *joy) { struct js_event e; KeySym key; Axis *axis; if (read(joy->fd, &e, sizeof(e)) != sizeof(e)) return -1; switch (e.type & ~JS_EVENT_INIT) { case JS_EVENT_BUTTON: if ((key = joy->button[e.number]) != NoSymbol) sendkey(client, key, e.value ? KeyPress : KeyRelease); break; case JS_EVENT_AXIS: axis = &joy->axis[e.number]; if (axis->neg_on && e.value >= 0) { sendkey(client, axis->neg, KeyRelease); axis->neg_on = 0; } if (axis->pos_on && e.value <= 0) { sendkey(client, axis->pos, KeyRelease); axis->pos_on = 0; } if (axis->neg != NoSymbol && e.value < 0) { sendkey(client, axis->neg, KeyPress); axis->neg_on = 1; } if (axis->pos != NoSymbol && e.value > 0) { sendkey(client, axis->pos, KeyPress); axis->pos_on = 1; } break; default: break; } return 0; } int sendkey(Client *client, KeySym key, int type) { Display *display = client->display; XKeyEvent event; Window window; int r; XGetInputFocus(display, &window, &r); event.type = type; event.serial = 0; /* undef */ event.send_event = 0; /* undef */ event.display = display; event.window = window; event.root = DefaultRootWindow(display); event.subwindow = None; event.time = CurrentTime; event.x = 1; /* undef */ event.y = 1; /* undef */ event.x_root = 1; /* undef */ event.y_root = 1; /* undef */ event.state = 0; event.keycode = XKeysymToKeycode(display, key); event.same_screen = True; /* undef */ XSendEvent(display, window, True, KeyPressMask, (XEvent *)&event); XFlush(display); return 0; } void error(const char *fmt, ...) { int sverror; va_list ap; sverror = errno; fprintf(stderr, "Error: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (strchr(fmt, '\n') == NULL) fprintf(stderr, " %s\n", strerror(sverror)); errno = sverror; }