This commit is contained in:
2026-06-28 11:38:30 -05:00
parent 2611a273ca
commit f41bd8eba4
4 changed files with 328 additions and 0 deletions

182
pc/main.c Normal file
View File

@@ -0,0 +1,182 @@
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "../deps/nanocobs/cobs.h"
#include "../packet.h"
// 0 is little, 1 is big
#define srcend 0
#define tgtend 1
unsigned int w = 800;
unsigned int h = 600;
bool grabbed = false;
Display* dpy = NULL;
int screen;
Window root;
Window mousearea;
Window root_return, child_return;
int root_x, root_y, win_x, win_y;
unsigned int mask_return;
bool mb0, mb1;
unsigned int delay = 8333;
uint32_t scrapmem;
void* mbmap[] = {
&mb0,
&scrapmem,
&mb1,
&scrapmem,
&scrapmem, &scrapmem, &scrapmem, &scrapmem,
&scrapmem, &scrapmem, &scrapmem, &scrapmem,
&scrapmem, &scrapmem, &scrapmem, &scrapmem,
&scrapmem, &scrapmem, &scrapmem, &scrapmem,
&scrapmem, &scrapmem, &scrapmem, &scrapmem
};
void togglePtrLock() {
if (grabbed) {
XUngrabPointer(dpy, CurrentTime);
XStoreName(dpy, mousearea, "Mouse Area - Press F11 to lock");
} else {
int result =
XGrabPointer(dpy, mousearea, True,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
mousearea, None, CurrentTime
);
if (result != GrabSuccess) printf("couldn't reserve control of the mouse pointer\n");
XStoreName(dpy, mousearea, "Mouse Area - Press F11 to unlock");
}
grabbed = !grabbed;
}
uint32_t byteSwap32(uint32_t n) {
#if srcend != tgtend
n = (n&0xFFFF0000)>>16|(n&0x0000FFFF)<<16;
n = (n&0xFF00FF00)>>8|(n&0x00FF00FF)<<8;
#endif
return n;
}
uint16_t byteSwap16(uint16_t n) {
#if srcend != tgtend
return ((n>>8)|(n<<8));
#else
return n;
#endif
}
int main(int argc, char** argv) {
printf("Amipathy Client v1\n"
"by bonkmaykr/madarao\n"
);
if (argc < 2 || argc > 3) {
printf(
"\nusage: amipathy <file> [rate]\n\n"
"The file should be a path to a TTY or serial device.\n"
"For example: amipathy /dev/ttyUSB0\n"
"Rate is the number of times the mouse info is written per second.\n"
);
return 0;
}
if (argc > 2) delay = 1000000 / atoi(argv[2]);
FILE* com = fopen(argv[1], "r+b");
if (!com) {
printf("Can't open %s\n", argv[1]);
return 1;
}
dpy = XOpenDisplay(NULL);
screen = DefaultScreen(dpy);
root = DefaultRootWindow(dpy);
mousearea = XCreateSimpleWindow(
dpy, root,
0, 0, w, h, 0,
BlackPixel(dpy, screen),
BlackPixel(dpy, screen)
);
XStoreName(dpy, mousearea, "Mouse Area - Press F11 to unlock");
XMapWindow(dpy, mousearea);
togglePtrLock();
Atom wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, mousearea, &wm_delete, 1);
XSelectInput(dpy, mousearea,
ExposureMask |
KeyPressMask |
ButtonPressMask |
ButtonReleaseMask |
PointerMotionMask |
StructureNotifyMask
);
XEvent event;
bool first = true;
while (true) {
while (XPending(dpy)) {
XNextEvent(dpy, &event);
if (event.type == ClientMessage &&
(Atom)event.xclient.data.l[0] == wm_delete)
goto exit;
if (event.type == ButtonPress)
*(bool*)mbmap[event.xbutton.button-1] = true;
if (event.type == ButtonRelease)
*(bool*)mbmap[event.xbutton.button-1] = false;
}
if (XQueryPointer(dpy, mousearea,
&root_return, &child_return,
&root_x, &root_y,
&win_x, &win_y,
&mask_return)) {
if (!first) printf("\x1b[1F\x1b[2K");
printf("root=(%d, %d) win=(%d, %d) btn=(%d, %d)\n",
root_x, root_y, win_x, win_y, mb0, mb1);
struct packet p;
static const uint8_t delimit = 0x00;
p.magic = 0xFF;
p.x = byteSwap16((uint16_t)win_x);
p.y = byteSwap16((uint16_t)win_y);
p.mouse0 = mb0 ? 0xFF : 0x00;
p.mouse1 = mb1 ? 0xFF : 0x00;
p.sum = 0;
p.sum += p.magic;
p.sum += p.x;
p.sum += p.y;
p.sum += p.mouse0;
p.sum += p.mouse1;
uint8_t cobsbuf[sizeof(p)*2];
size_t cobslen = 0;
const cobs_ret_t cobsresult = cobs_encode(
&p, sizeof(p),
cobsbuf, sizeof(p)*2, &cobslen
);
if (cobsresult != COBS_RET_SUCCESS) {
printf("failed to encode packet!\n");
continue;
}
fwrite(&cobsbuf, cobslen, 1, com);
fwrite(&delimit, 1, 1, com);
fflush(com);
}
else abort();
usleep(delay);
first = false;
}
exit:
fclose(com);
XDestroyWindow(dpy, mousearea);
XCloseDisplay(dpy);
return 0;
}