Created
April 13, 2019 13:11
-
-
Save bathtime/faa2fc830391e2323107fdf171756509 to your computer and use it in GitHub Desktop.
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
/* | |
Key/Touch/Secondary Button Stimulator | |
Compile with: | |
gcc -Wall -O2 mouse.c -o mouse -lX11 -lXtst -lXext | |
SendKey function courtesy of: | |
https://bharathisubramanian.wordpress.com/2010/03/14/x11-fake-key-event-generation-using-xtest-ext/ | |
*/ | |
#include<fcntl.h> | |
#include<unistd.h> | |
#include<stdio.h> | |
#include<linux/input.h> | |
#include<X11/extensions/XTest.h> | |
#include<stdlib.h> | |
int fast_abs(int num) | |
{ | |
if(num < 0) | |
num *= -1; | |
return num; | |
} | |
void fast_memcpy(char *str, const char *str2, int length) | |
{ | |
for(;--length > -1; ) | |
str[length] = str2[length]; | |
} | |
void fast_memcpyS(char *str, const char *str2, int start, int length) | |
{ | |
for(; --length > -1; ) | |
str[length + start] = str2[length]; | |
} | |
int fast_memcmp(char *str, const char *str2, int length) | |
{ | |
length--; | |
do{ | |
}while(str[length] == str2[length] && --length > -1); | |
return ++length; | |
} | |
/*static void SendKey(Display * disp, KeySym keysym, KeySym modsym) | |
{ | |
KeyCode keycode = 0, modcode = 0; | |
keycode = XKeysymToKeycode (disp, keysym); | |
if (keycode == 0) return; | |
XTestGrabControl (disp, True); | |
if (modsym != 0) { | |
modcode = XKeysymToKeycode(disp, modsym); | |
XTestFakeKeyEvent (disp, modcode, True, 0); | |
} | |
XTestFakeKeyEvent (disp, keycode, True, 0); | |
XTestFakeKeyEvent (disp, keycode, False, 0); | |
if (modsym != 0) | |
XTestFakeKeyEvent (disp, modcode, False, 0); | |
XSync (disp, False); | |
XTestGrabControl (disp, False); | |
}*/ | |
char *get_device() | |
{ | |
char data[120]; | |
int ret; | |
FILE * const file = fopen( "/proc/bus/input/devices", "r"); | |
do | |
ret=fscanf(file, "%*2s %s %*[^\n]\n", data); | |
while(fast_memcmp(data, "Name=\"FT5406", 12) != 0 && ret != EOF); | |
fscanf(file, "%*[^\n]\n%*[^\n]\n%*[^\n]\n%*2s %*15s %6s", data); | |
char *result = (char*)malloc(20); | |
fast_memcpyS(result, "/dev/input/", 0, 11); | |
fast_memcpyS(result, data, 11, 6); | |
return result; | |
} | |
void right(Display *dpy, XEvent event) | |
{ | |
XQueryPointer(dpy, RootWindow (dpy, 0), &event.xbutton.root, | |
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state); | |
usleep(5000); | |
XTestFakeButtonEvent(dpy, 3, True, CurrentTime); | |
usleep(5000); | |
XTestFakeButtonEvent(dpy, 3, False, CurrentTime); | |
usleep(5000); | |
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root, | |
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state); | |
} | |
void middle(Display *dpy, XEvent event) | |
{ | |
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root, | |
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state); | |
usleep(5000); | |
XTestFakeButtonEvent (dpy, 2, True, CurrentTime); | |
usleep(5000); | |
XTestFakeButtonEvent (dpy, 2, False, CurrentTime); | |
usleep(5000); | |
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root, | |
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state); | |
} | |
int main() { | |
Display *dpy = XOpenDisplay(NULL); | |
XEvent event; | |
//Window rootw = XDefaultRootWindow(dpy); | |
short fd; | |
struct input_event ie; | |
Window root, child; | |
int rootX, rootY, winX, winY; | |
unsigned int mask; | |
XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &rootX, &rootY, &winX, &winY, &mask); | |
char *eventFile = get_device(); | |
//printf("Using device: %s\n", eventFile); | |
if((fd = open(eventFile, O_RDONLY)) == -1) { | |
perror("opening device"); | |
return 1; | |
} | |
time_t time_start_sec = ie.time.tv_sec; | |
time_t time_stop_sec = ie.time.tv_sec; | |
time_t time_start_usec = ie.time.tv_usec; | |
time_t time_stop_usec = ie.time.tv_usec; | |
time_t time_stop_usec_adj = ie.time.tv_usec; | |
time_t time_real = ie.time.tv_sec; | |
float time_elapsed_adj; | |
#define time_to_click .3 | |
#define time_to_hold .9 | |
#define time_max_flick 1 | |
#define xyClickThreshold 10 | |
int Ycaptured = 0; | |
int Xcaptured = 0; | |
// X = 0 - 799 | |
// Y = 0 - 479 | |
int Y = 0; | |
int X = 0; | |
int lastX = 0; | |
int lastY = 0; | |
int moved = 0; | |
#define bottomMinYEnter 450 | |
#define bottomYRangeThreshold 15 | |
#define bottomXRangeLower 245 | |
#define bottomXRangeUpper 550 | |
#define topMinYEnter 30 | |
#define topYRangeThreshold 15 | |
#define topXRangeLower 300 | |
#define topXRangeUpper 750 | |
#define leftMinXEnter 30 | |
#define leftXRangeThreshold 15 | |
#define leftYRangeLower 80 | |
#define leftYRangeUpper 400 | |
#define rightMinXEnter 785 | |
#define rightXRangeThreshold 30 | |
#define rightYRangeLower 50 | |
#define rightYRangeUpper 430 | |
//printf("Ready for mouse events...\n"); | |
int maskOn = 0; | |
int masked = 0; | |
while(1){ | |
// Grab mouse events: | |
read(fd, &ie, sizeof(struct input_event)); | |
//printf("ie.type: %i ie.code: %i ie.value: %i moved: %i\n", ie.type, ie.code, ie.value, moved); | |
if (ie.type == 3) | |
{ | |
if (ie.code == 1) | |
lastY = ie.value; | |
else if (ie.code == 0) | |
lastX = ie.value; | |
else if (!Ycaptured && ie.code == 54) { | |
Ycaptured = 1; | |
Y = ie.value; | |
}else if (!Xcaptured && ie.code == 53) { | |
Xcaptured = 1; | |
X = ie.value; | |
} | |
if (maskOn && ((Ycaptured && Y > bottomMinYEnter) || (Ycaptured && Y < topMinYEnter) || (Xcaptured && X < leftMinXEnter) || (Xcaptured && X > rightMinXEnter)) && !masked) | |
{ | |
if ((Y > bottomMinYEnter || Y < topMinYEnter || X < leftMinXEnter || X > rightMinXEnter) && !masked){ | |
masked = 1; | |
puts("\nMASKED!!!"); | |
XGrabPointer(dpy, XDefaultRootWindow(dpy), False, PointerMotionMask|ButtonMotionMask|PointerMotionHintMask|ButtonReleaseMask|ButtonPressMask, GrabModeSync, GrabModeAsync, None, None, CurrentTime); | |
} | |
} | |
if (!moved) | |
{ | |
time_start_sec = ie.time.tv_sec; | |
time_start_usec = ie.time.tv_usec; | |
//puts("Entered!"); | |
} | |
++moved; | |
} | |
if (ie.type == 1 && ie.code == 330 && ie.value == 0) | |
{ | |
// Timer from mouse events is used | |
time_real = ie.time.tv_sec; | |
time_stop_sec = time_real - time_start_sec ; | |
time_stop_usec = ie.time.tv_usec; | |
if (time_stop_usec < time_start_usec){ | |
time_stop_usec_adj = time_stop_usec + (1000000 - time_start_usec); | |
if (time_real - time_start_sec > 0 ) | |
time_stop_sec = time_stop_sec - 1; | |
}else | |
time_stop_usec_adj = time_stop_usec - time_start_usec; | |
time_elapsed_adj = time_stop_sec + ((float)time_stop_usec_adj / 1000000); | |
//printf("time: %f\n", time_elapsed_adj); | |
Ycaptured = 0; | |
Xcaptured = 0; | |
if(time_elapsed_adj < time_max_flick) | |
{ | |
if (Y > bottomMinYEnter && (Y - lastY) > bottomYRangeThreshold && fast_abs(X - lastX) < fast_abs(Y - lastY) && fast_abs(lastX - X) < fast_abs(lastY - Y) && X > bottomXRangeLower && X < bottomXRangeUpper) | |
{ | |
system("/home/pi/scripts/kbd.sh&"); | |
//SendKey (dpy, 32, 65513); // XK_Spaec, XK_Alt_L | |
printf("Bottom enter!\n"); | |
}else if (Y < topMinYEnter && (lastY - Y) > topYRangeThreshold && fast_abs(X - lastX) < fast_abs(Y - lastY) && fast_abs(lastX - X) < fast_abs(lastY - Y) && X > topXRangeLower && X < topXRangeUpper ) | |
{ | |
system("xsetroot -name 'fsignal:3'"); | |
//SendKey (dpy, 98, 65513); // XK_b, XK_Alt_L | |
//printf("Top enter!\n"); | |
}else if (X < leftMinXEnter && (lastX - X) > leftXRangeThreshold && fast_abs(Y - lastY) < fast_abs(X - lastX) && fast_abs(lastY - Y) < fast_abs(lastX - X) && Y > leftYRangeLower && Y < leftYRangeUpper) | |
{ | |
system("xsetroot -name 'fsignal:4'"); | |
//SendKey (dpy, 107, 65513); // XK_k, XK_Alt_L | |
//printf("Left enter!\n"); | |
}else if (X > rightMinXEnter && (X - lastX) > rightXRangeThreshold && fast_abs(Y - lastY) < fast_abs(X - lastX) && fast_abs(lastY - Y) < fast_abs(lastX - X) && Y > rightYRangeLower && Y < rightYRangeUpper) | |
{ | |
system("xsetroot -name 'fsignal:5'"); | |
//SendKey (dpy, 120, 65513); // XK_x, XK_Alt_L | |
//printf("Right enter!\n"); | |
} | |
} | |
printf("Thres x: %i y: %i\n", fast_abs(lastX - X), fast_abs(Y - lastY)); | |
if (time_elapsed_adj > time_to_click && fast_abs(Y - lastY) < xyClickThreshold && fast_abs(lastX - X) < xyClickThreshold) | |
{ | |
printf("time: %f\n", time_elapsed_adj); | |
if(time_elapsed_adj > time_to_hold) | |
{ | |
puts("Middle click down!"); | |
middle(dpy, event); | |
//clickMiddle(dpy, event); | |
puts("Middle click up!"); | |
}else{ | |
puts("Right click down!"); | |
right(dpy, event); | |
//clickRight(dpy, event); | |
puts("Right click up!"); | |
} | |
} | |
if(maskOn && masked) | |
{ | |
XFlush(dpy); | |
XSync(dpy, 0); | |
while(XPending(dpy)) | |
{ | |
puts("Pending event!"); | |
XNextEvent(dpy, &event); | |
} | |
/* XQueryPointer(dpy, XDefaultRootWindow(dpy), | |
&event.xbutton.root, &event.xbutton.window, | |
&event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, | |
&event.xbutton.state); | |
usleep(1000); | |
XAllowEvents(dpy, SyncPointer, CurrentTime); | |
usleep(1000);*/ | |
XQueryPointer(dpy, XDefaultRootWindow(dpy), | |
&event.xbutton.root, &event.xbutton.window, | |
&event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, | |
&event.xbutton.state); | |
usleep(1000); | |
XUngrabPointer(dpy, CurrentTime); | |
usleep(1000); | |
XQueryPointer(dpy, XDefaultRootWindow(dpy), | |
&event.xbutton.root, &event.xbutton.window, | |
&event.xbutton.x_root, &event.xbutton.y_root, | |
&event.xbutton.x, &event.xbutton.y, | |
&event.xbutton.state); | |
} | |
//} | |
puts("reset moved"); | |
masked = 0; | |
// Reset moved: | |
moved = 0; | |
} | |
} | |
XCloseDisplay (dpy); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, could you please include a license indication in the header comment such that your code can be used, modified and redistributed? If you wish the highest freedom as possible, I would suggest MIT or BSD. I you want to force others to keep your code free, use the GPL or LGPL.