Skip to content

Instantly share code, notes, and snippets.

@DataKinds
Last active June 20, 2016 05:10
Show Gist options
  • Save DataKinds/d3c5fe6bd5737c2b80c2bb4360208496 to your computer and use it in GitHub Desktop.
Save DataKinds/d3c5fe6bd5737c2b80c2bb4360208496 to your computer and use it in GitHub Desktop.
controls kbd+mouse with a controller
#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;
}
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