diff --git a/driver-uinput/Makefile b/driver-uinput/Makefile index 9370e34..e91f28d 100644 --- a/driver-uinput/Makefile +++ b/driver-uinput/Makefile @@ -1,2 +1,2 @@ - -networktablet : networktablet.c protocol.h +export CC=c99 +networktablet : networktablet.c protocol.h -lX11 -lXrandr diff --git a/driver-uinput/networktablet.c b/driver-uinput/networktablet.c index e7cde9c..9d4f3d6 100644 --- a/driver-uinput/networktablet.c +++ b/driver-uinput/networktablet.c @@ -10,8 +10,11 @@ #include #include #include +#include +#include #include "protocol.h" - +#include +#include #define die(str, args...) { \ perror(str); \ exit(EXIT_FAILURE); \ @@ -19,7 +22,12 @@ int udp_socket; - +// parse args +int screenId = -1; +int width = -1; +int height = -1; +int xOffset = 0; +int yOffset = 0; void init_device(int fd) { @@ -93,9 +101,83 @@ void quit(int signal) { close(udp_socket); } +gfx_host_monitor* getMonitors() { + unsigned size = sizeof(gfx_host_monitor); + Display *display = XOpenDisplay(0); + Window root = RootWindow(display, 0); -int main(void) + XRRScreenResources* screenResources = XRRGetScreenResources(display, root); + RROutput primary = XRRGetOutputPrimary(display, root); + + int screenCount = 0; + gfx_host_monitor* monitors = malloc(size); + for (int i = 0; i < screenResources->ncrtc; i++) { + XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screenResources, screenResources->crtcs[i]); + + for (int j = 0; j < crtcInfo->noutput; j++) { + XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screenResources, crtcInfo->outputs[j]); + + if (outputInfo->connection != RR_Connected) { + XRRFreeOutputInfo(outputInfo); + continue; + } + + size += sizeof(gfx_host_monitor); + gfx_host_monitor* rallac = realloc(monitors, size); + if (rallac) { + monitors = rallac; + if (screenCount > 0) { + monitors[i].x = crtcInfo->x + monitors[i - 1].x; + monitors[i].y = crtcInfo->y + monitors[i - 1].x; + } else { + monitors[i].x = crtcInfo->x; + monitors[i].y = crtcInfo->y; + } + monitors[i].width = crtcInfo->width; + monitors[i].height = crtcInfo->height; + monitors[i].mm_width = outputInfo->mm_width; + monitors[i].mm_height = outputInfo->mm_height; + } else { + // + } + + XRRFreeOutputInfo(outputInfo); + screenCount++; + } + XRRFreeCrtcInfo(crtcInfo); + } + + XRRFreeScreenResources(screenResources); + for (unsigned i = 0; i < screenCount; i++) { + printf("Monitor %d: w:%d h:%d x:%d y:%d\n", i, monitors[i].width, monitors[i].height, monitors[i].x, monitors[i].y); + } + + return monitors; +} + +int main(int argc, char *argv[]) { + Display *display = XOpenDisplay(NULL); + Window root = RootWindow(display, 0); + int totalWidth = width = XDisplayWidth(display, 0); + int totalHeight = height = XDisplayHeight(display, 0); + + printf("totalWidth %d\n", totalWidth); + + int opt; + while ((opt = getopt(argc, argv, "s:w:h:x:y:")) != -1) { + switch (opt) { + case 's': screenId = atoi(optarg); break; + case 'w': width = atoi(optarg); break; + case 'h': height = atoi(optarg); break; + case 'x': xOffset = atoi(optarg); break; + case 'y': yOffset = atoi(optarg); break; + default: + fprintf(stderr, "Usage: %s [-s=SCREEN_NO -w=WIDTH -h=HEIGHT -x=X_OFFSET -y=Y-OFFSET]\n", argv[0]); + exit(EXIT_FAILURE); + } + } + int device; struct event_packet ev_pkt; @@ -111,6 +193,18 @@ int main(void) signal(SIGINT, quit); signal(SIGTERM, quit); + gfx_host_monitor* monitors = getMonitors(); + + if (screenId != -1) { + if (width == -1) + width = monitors[screenId].width; + if (height == -1) + height = monitors[screenId].height; + xOffset = monitors[screenId].x + xOffset; + yOffset = monitors[screenId].y + yOffset; + } + + //print_screen_information(); while (recv(udp_socket, &ev_pkt, sizeof(ev_pkt), 0) >= 9) { // every packet has at least 9 bytes printf("."); fflush(0); @@ -130,9 +224,16 @@ int main(void) ev_pkt.pressure = ntohs(ev_pkt.pressure); printf("x: %hi, y: %hi, pressure: %hi\n", ev_pkt.x, ev_pkt.y, ev_pkt.pressure); + ev_pkt.x = ev_pkt.x * (float) totalWidth / SHRT_MAX; + ev_pkt.x = ev_pkt.x * (float) width / totalWidth; + ev_pkt.x = (short) ((float) SHRT_MAX / totalWidth * (xOffset + ev_pkt.x)); + ev_pkt.y = ev_pkt.y * (float) totalHeight / SHRT_MAX; + ev_pkt.y = ev_pkt.y * (float) height / totalHeight; + ev_pkt.y = (short) ((float) SHRT_MAX / totalHeight * (yOffset + ev_pkt.y)); send_event(device, EV_ABS, ABS_X, ev_pkt.x); send_event(device, EV_ABS, ABS_Y, ev_pkt.y); - send_event(device, EV_ABS, ABS_PRESSURE, ev_pkt.pressure); + + //send_event(device, EV_ABS, ABS_PRESSURE, ev_pkt.pressure); switch (ev_pkt.type) { case EVENT_TYPE_MOTION: diff --git a/driver-uinput/protocol.h b/driver-uinput/protocol.h index fc9191f..3222fff 100644 --- a/driver-uinput/protocol.h +++ b/driver-uinput/protocol.h @@ -10,6 +10,16 @@ #define EVENT_TYPE_MOTION 0 #define EVENT_TYPE_BUTTON 1 +typedef struct +{ + int x; + int y; + unsigned width; + unsigned height; + unsigned long mm_height; + unsigned long mm_width; +} gfx_host_monitor; + struct event_packet { char signature[9];