/* * Ivypointer * * Copyright (C) 2007 * DGAC / DSNA / DTI / R&D * * Main and only file * * Authors: Benjamin Tissoires * * Please refer to file version.h for the * copyright notice regarding this software */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #if X_DISPLAY_MISSING # error X11 is required to build xtest #else # include # include # include # define XK_MISCELLANY # define XK_XKB_KEYS # include # if HAVE_X11_EXTENSIONS_XTEST_H # include //# else //# error The XTest extension is required to build xtest # endif # if HAVE_X11_EXTENSIONS_XINERAMA_H // Xinerama.h may lack extern "C" for inclusion by C++ extern "C" { # include } # endif # if HAVE_XKB_EXTENSION # include # endif #endif #include #include #include #include "getopt.h" #define REGEXP_CHANGE_GEOMETRY_INPUT "^geometry_event device_id=(.*) x0=(.*) y0=(.*) x1=(.*) y1=(.*)" #define REGEXP_MOVE "^TelepointerMotion Id=(.*) X=(.*) Y=(.*)" #define REGEXP_DRAG "^TelepointerDrag Id=(.*) X=(.*) Y=(.*)" #define REGEXP_REL_MOVE "^TelepointerRelativeMotion Id=(.*) X=(.*) Y=(.*)" #define REGEXP_BUTTON "^TelepointerButton Id=(.*) Button=(.*) status=(.*)" #define REGEXP_POINTER "^pointer_event device_id=(.*) x=(.*) y=(.*) presure=(.*) tilt_x=(.*) tilt_y=(.*) wheel=(.*) predicted_x=(.*) predicted_y=(.*) type=(.*) serial_number=(.*) time=(.*)" #define REGEXP_PAD "^pad_event device_id=(.*) button=(.*) status=(.*) time=(.*)" #define REGEXP_SLIDER "^slider_event device_id=(.*) value=(.*) side=(.*) time=(.*)" #define WIDTH_WACOM 1600.0 #define HEIGHT_WACOM 1200.0 Display* display = NULL; int width,height; float coords_input[4] = {0.0,0.0,100.0,100.0}; int width_input,height_input; int dragged = 0; Display* openDisplay(const char* displayName) { // get the DISPLAY if (displayName == NULL) { displayName = getenv("DISPLAY"); if (displayName == NULL) { displayName = ":0.0"; } } // open the display printf("XOpenDisplay(\"%s\")\n", displayName); display = XOpenDisplay(displayName); if (display == NULL) { printf("EE : can't open display \"%s\"\n", displayName); return NULL; // throw XScreenUnavailable(60.0); } // verify the availability of the XTest extension int majorOpcode, firstEvent, firstError; #if HAVE_X11_EXTENSIONS_XTEST_H if (!XQueryExtension(display, XTestExtensionName, &majorOpcode, &firstEvent, &firstError)) { printf("XTEST extension not available"); XCloseDisplay(display); return NULL; } #endif #if HAVE_XKB_EXTENSION { m_xkb = false; int major = XkbMajorVersion, minor = XkbMinorVersion; if (XkbLibraryVersion(&major, &minor)) { int opcode, firstError; if (XkbQueryExtension(display, &opcode, &m_xkbEventBase, &firstError, &major, &minor)) { m_xkb = true; XkbSelectEvents(display, XkbUseCoreKbd, XkbMapNotifyMask, XkbMapNotifyMask); XkbSelectEventDetails(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbGroupStateMask, XkbGroupStateMask); } } } #endif return display; } // -------------------------------------------------------------------------- // tools // -------------------------------------------------------------------------- void print_coords_input(void){ printf("coords of input : %.0f,%.0f %.0f,%.0f\n", coords_input[0], coords_input[1], coords_input[2], coords_input[3]); } int valid(float x, float y) { if (xcoords_input[2]) { // printf("x > x1\n"); return 0; } if (ycoords_input[3]){ // printf("y < y1\n"); return 0; } return 1; } // -------------------------------------------------------------------------- // X11 functions // -------------------------------------------------------------------------- void fakeMouseButton(const unsigned int xButton, Bool press) { #if HAVE_X11_EXTENSIONS_XTEST_H if (xButton != 0) { XTestFakeButtonEvent(display, xButton, press ? True : False, 0); XFlush(display); } #endif } void fakeMouseMove(int x, int y) { XWarpPointer(display, None, RootWindow(display, 0), 0, 0, 0, 0, x, y); XFlush(display); } void fakeMouseRelativeMove(int dx, int dy) { XWarpPointer(display, None, None, 0, 0, 0, 0, dx, dy); XFlush(display); } // -------------------------------------------------------------------------- // Geometry callback // -------------------------------------------------------------------------- void CallbackGeometry(IvyClientPtr app, void *user_data, int argc, char *argv[]) { // char *id = argv[0]; float x0 = atof(argv[1]); float y0 = atof(argv[2]); float x1 = atof(argv[3]); float y1 = atof(argv[4]); if (x1 > x0 && y1 > y0 ){ coords_input[0] = x0; coords_input[1] = y0; coords_input[2] = x1; coords_input[3] = y1; width_input = coords_input[2]-coords_input[0]; height_input = coords_input[3]-coords_input[1]; print_coords_input(); } else { printf("bad coords received : %.0f,%.0f %.0f,%.0f\n",x0,y0,x1,y1); } } // -------------------------------------------------------------------------- // Telepointer callbacks // -------------------------------------------------------------------------- void CallbackMove (IvyClientPtr app, void *user_data, int argc, char *argv[]) { // printf ("%s sent (size : %d)",IvyGetApplicationName(app),argc); // for (i = 0; i < argc; i++) // printf(" '%s'",argv[i]); if (dragged){ fakeMouseButton(1,0); dragged = 0; } // char *id = argv[0]; float x = atof(argv[1]); float y = atof(argv[2]); // printf("x = %f,y = %f; ",x,y); x = x*width/100.0; y = y*height/100.0; // printf("x = %f,y = %f\n",x,y); if (valid(x,y)) fakeMouseMove((int)x,(int)y); // IvyUnbindMsg(*ptr); } void CallbackDrag (IvyClientPtr app, void *user_data, int argc, char *argv[]) { if (!dragged){ fakeMouseButton(1,1); dragged = 1; } // char *id = argv[0]; float x = atof(argv[1]); float y = atof(argv[2]); x *= width/100.0; y *= height/100.0; // printf("x = %f,y = %f\n",x,y); if (valid(x,y)) fakeMouseMove((int)x,(int)y); } void CallbackRelMove (IvyClientPtr app, void *user_data, int argc, char *argv[]) { // char *id = argv[0]; float x = atof(argv[1]); float y = atof(argv[2]); x *= width/100.0; y *= height/100.0; fakeMouseRelativeMove((int)x,(int)y); } void CallbackButton (IvyClientPtr app, void *user_data, int argc, char *argv[]) { // char *id = argv[0]; int b = atoi(argv[1]); int press = atoi(argv[2]); // if (!b) // return fakeMouseButton(b,press); } // -------------------------------------------------------------------------- // Wacom callbacks // -------------------------------------------------------------------------- void CallbackPointer (IvyClientPtr app, void *user_data, int argc, char *argv[]) { // char *id = argv[0]; float x = atof(argv[1]); float y = atof(argv[2]); int presure = atoi(argv[3]); if (dragged && presure==0){ fakeMouseButton(1,0); dragged = 0; } if (!dragged && presure>0){ fakeMouseButton(1,1); dragged = 1; } // printf("x = %f,y = %f; ",x,y); if (valid(x,y)){ x = (x-coords_input[0])*width/width_input; y = (y-coords_input[1])*height/height_input; // printf("x = %f,y = %f\n",x,y); fakeMouseMove((int)x,(int)y); // } else { // printf("bad event\n"); } } void CallbackPad (IvyClientPtr app, void *user_data, int argc, char *argv[]) { // char *id = argv[0]; int b = atoi(argv[1]); int press = atoi(argv[2]); // if (!b) // return fakeMouseButton(b,press); } void CallbackSlider (IvyClientPtr app, void *user_data, int argc, char *argv[]) { //TODO // char *id = argv[0]; // int b = atoi(argv[1]); // int press = atoi(argv[2]); // if (!b) // return // fakeMouseButton(b,press); } // -------------------------------------------------------------------------- // Main // -------------------------------------------------------------------------- int main(int argc, char *argv[]) { const char* bus = 0; char busbuf [1024] = ""; const char* helpmsg = "[options] [regexps]\n\t-b bus\t\tdefines the Ivy bus to which to connect to, defaults to 127:2010\n" "\t-w\t\tuse data from xinput_wacom instead of ModeManager\n" "\t-c x0,y0,x1,y1\tspecify the coords of the window used (only used with wacom)\n" "\t-v\t\tprints the ivy relase number\n\n" ; int wacom = 0; int user_coords = 0; int coords[4] = {0,0,0,0}; int c; int i = 0; int j = 0; int coupures[4] = {0,0,0,0}; int last = 0; while ((c = getopt(argc, argv, "vb:wc:")) != EOF) switch (c) { case 'b': strcpy (busbuf, optarg); bus = busbuf; break; case 'v': printf("ivy c library version %d.%d\n",IVYMAJOR_VERSION,IVYMINOR_VERSION); break; case 'w': wacom = 1; break; case 'c': while(optarg[i]){ if (optarg[i] == ','){ coupures[j] = i; j++; } i++; } if (j != 3) { printf("usage: %s %s",argv[0],helpmsg); exit(1); } else { coupures[j] = i; } j = 0; last = 0; for (i=0; i< 4; i++){ int length = coupures[i]-last; char buf [1024] = ""; int k; for (k = 0; k < length; k++) { buf[k] = optarg[last+k]; } coords[i] = atoi(buf); last = coupures[i]+1; } user_coords = 1; break; default: printf("usage: %s %s",argv[0],helpmsg); exit(1); } Display* d = openDisplay(NULL); if (!d){ return 1; } if (wacom) { if (user_coords){ int i; for (i=0;i<4;i++) { coords_input[i] = coords[i]; } } else { coords_input[2] = WIDTH_WACOM; coords_input[3] = HEIGHT_WACOM; } print_coords_input(); width_input = coords_input[2]-coords_input[0]; height_input = coords_input[3]-coords_input[1]; } width = DisplayWidth(d, DefaultScreen(d)); height = DisplayHeight(d, DefaultScreen(d)); printf("screen : %dx%d\n",width,height); MsgRcvPtr ptrMove,ptrRelMove,ptrButton; IvyInit("IvyPointer","IvyPointer Ready",NULL,NULL,NULL,NULL); if (!wacom) { // telepointer callbacks ptrMove=IvyBindMsg(CallbackMove,&ptrMove,REGEXP_MOVE); printf("bound to %s\n",REGEXP_MOVE); ptrMove=IvyBindMsg(CallbackDrag,&ptrMove,REGEXP_DRAG); printf("bound to %s\n",REGEXP_DRAG); ptrMove=IvyBindMsg(CallbackRelMove,&ptrRelMove,REGEXP_REL_MOVE); printf("bound to %s\n",REGEXP_REL_MOVE); ptrMove=IvyBindMsg(CallbackButton,&ptrButton,REGEXP_BUTTON); printf("bound to %s\n",REGEXP_BUTTON); } else { //wacom callbacks ptrMove=IvyBindMsg(CallbackGeometry,&ptrMove,REGEXP_CHANGE_GEOMETRY_INPUT); printf("bound to %s\n",REGEXP_CHANGE_GEOMETRY_INPUT); ptrMove=IvyBindMsg(CallbackPointer,&ptrMove,REGEXP_POINTER); printf("bound to %s\n",REGEXP_POINTER); // ptrMove=IvyBindMsg(CallbackSlider,&ptrMove,REGEXP_SLIDER); // printf("bound to %s\n",REGEXP_SLIDER); ptrMove=IvyBindMsg(CallbackPad,&ptrButton,REGEXP_PAD); printf("bound to %s\n",REGEXP_PAD); } IvyStart(bus); #if (IVYMAJOR_VERSION == 3) && (IVYMINOR_VERSION < 9) IvyMainLoop(NULL, NULL); #else IvyMainLoop(); #endif return 0; }