Last active
June 20, 2016 05:10
-
-
Save DataKinds/d3c5fe6bd5737c2b80c2bb4360208496 to your computer and use it in GitHub Desktop.
controls kbd+mouse with a controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <linux/input.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <X11/X.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
#include <X11/extensions/XTest.h> | |
#include <stdbool.h> | |
#include <pthread.h> | |
int fd; | |
struct input_event e; | |
//set up my storage | |
struct joystick_storage { | |
//left stick X and Y | |
int lSX; | |
int lSY; | |
//right stick X and Y | |
int rSX; | |
int rSY; | |
//buttons A, B, X, Y | |
int a; | |
int aChanged; | |
int b; | |
int bChanged; | |
int x; | |
int xChanged; | |
int y; | |
int yChanged; | |
}; | |
struct joystick_storage controller; | |
void getMousePos(Display* dpy, Window root, int* xOut, int* yOut) { | |
int winXOut, winYOut; | |
unsigned int maskOut; | |
Window rootOut, childOut; | |
XQueryPointer(dpy, root, &rootOut, &childOut, xOut, yOut, &winXOut, &winYOut, &maskOut); | |
} | |
void moveMouseAbs(Display* dpy, Window root, int x, int y) { | |
XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y); | |
} | |
void moveMouseRel(Display* dpy, Window root, int dx, int dy) { | |
int x; | |
int y; | |
getMousePos(dpy, root, &x, &y); | |
moveMouseAbs(dpy, root, x + dx, y + dy); | |
} | |
int populateEvent(struct input_event *ev, int fD) { | |
memset(ev, 0, sizeof(*ev)); | |
return read(fD, ev, sizeof(*ev)); | |
} | |
void *updateEvent() { | |
for (;;) { | |
populateEvent(&e, fd); | |
switch (e.type) { | |
case EV_ABS: | |
switch (e.code) { | |
case ABS_X: | |
controller.lSX = e.value; | |
break; | |
case ABS_Y: | |
controller.lSY = e.value; | |
break; | |
case ABS_RX: | |
controller.rSX = e.value; | |
break; | |
case ABS_RY: | |
controller.rSY = e.value; | |
break; | |
} | |
break; | |
case EV_KEY: | |
switch (e.code) { | |
case BTN_A: | |
if (e.value != controller.a) | |
controller.aChanged = 1; | |
controller.a = e.value; | |
if (controller.a > 1) | |
controller.a = 1; | |
break; | |
case BTN_B: | |
if (e.value != controller.b) | |
controller.bChanged = 1; | |
controller.b = e.value; | |
if (controller.b > 1) | |
controller.b = 1; | |
break; | |
case BTN_X: | |
if (e.value != controller.x) | |
controller.xChanged = 1; | |
controller.x = e.value; | |
if (controller.x > 1) | |
controller.x = 1; | |
break; | |
case BTN_Y: | |
if (e.value != controller.y) | |
controller.yChanged = 1; | |
controller.y = e.value; | |
if (controller.y > 1) | |
controller.y = 1; | |
break; | |
} | |
} | |
} | |
} | |
int main() { | |
//set up udev boilerplate (output from controller) | |
fd = open("/dev/input/event16", O_RDONLY | O_NONBLOCK); | |
//set up x11 boilerplate (input to computer) | |
Display *dpy; | |
Window root; | |
dpy = XOpenDisplay(0); | |
root = XRootWindow(dpy, 0); | |
XSelectInput(dpy, root, KeyReleaseMask); | |
memset(&controller, 0, sizeof(controller)); | |
//threading boilerplate | |
pthread_t controllerUpdate; | |
pthread_create(&controllerUpdate, NULL, updateEvent, NULL); | |
//main loop | |
for (;;) { | |
//move the mouse | |
moveMouseRel(dpy, root, | |
(int)((long double)controller.lSX / 5000.0), (int)((long double)controller.lSY / 5000.0)); | |
//press mouse buttons | |
if (controller.aChanged) { | |
switch (controller.a){ | |
case 1: | |
XTestFakeButtonEvent(dpy, 1, true, 0); | |
break; | |
case 0: | |
XTestFakeButtonEvent(dpy, 1, false, 0); | |
break; | |
} | |
controller.aChanged = 0; | |
} | |
if (controller.bChanged) { | |
switch (controller.b){ | |
case 1: | |
XTestFakeButtonEvent(dpy, 3, true, 0); | |
break; | |
case 0: | |
XTestFakeButtonEvent(dpy, 3, false, 0); | |
break; | |
} | |
controller.bChanged = 0; | |
} | |
if (controller.yChanged) { | |
switch (controller.y){ | |
case 1: | |
XTestFakeButtonEvent(dpy, 2, true, 0); | |
break; | |
case 0: | |
XTestFakeButtonEvent(dpy, 2, false, 0); | |
break; | |
} | |
controller.yChanged = 0; | |
} | |
XFlush(dpy); | |
usleep(10000); | |
} | |
//end | |
close(fd); | |
exit(0); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: | |
gcc -lX11 -lpthread -lXtst -std=gnu11 main.c |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment