Thread: Stimulating Mouse Clicks: only works on certain windows

  1. #1
    Registered User
    Join Date
    Feb 2019
    Posts
    12

    Stimulating Mouse Clicks: only works on certain windows

    First post!

    The code below is made and run on my Raspberry Pi 3b+. It is made for use on a touchscreen, and it detects when the user is holding the left mouse button down (or pressing the touch screen) and then clicks the right button. When the button is held down a little longer (1.5 vs .5 secs), then the right mouse button is held down by a mouse button down call, causing the button to be held to allow for right-click dragging.

    The detection part of the code works perfectly; one can see by the printout in terminal. The issue is getting the program's click to work consistently. The click only seems to work on certain windows. Likely I have not included code to check properly which window I am in. On some apps the click will click behind the app and on the desktop (root window) instead. On other apps the click won't click anything. Holding is the same.

    The program works excellent when I use a system call to xdotool to do the clicking and holding (this alternative will be in the code), but I'd like to get away from that sort of dependency. The Raspberry Pi forum seems to have a demand for this type of thing, and it would be great if I could give them something to build on.


    Code:
    // Compile with:
    // g++ -Wall mouse.cpp -o mouse -lX11
    
    
    #include <fcntl.h>
    #include <iostream>
    #include <linux/input.h>
    #include <string.h> 
    #include <unistd.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    
    
    #define MOUSEFILE "/dev/input/event0"
    
    
    
    
    void click(Display *display, int button)
    {
        // Create and setting up the event
        XEvent event;
        memset (&event, 0, sizeof (event));
        event.xbutton.button = button;
        event.xbutton.same_screen = True;
        event.xbutton.subwindow = DefaultRootWindow (display);
    
    
        while (event.xbutton.subwindow)
        {
             event.xbutton.window = event.xbutton.subwindow;
             XQueryPointer (display, event.xbutton.window,
                 &event.xbutton.root, &event.xbutton.subwindow,
                 &event.xbutton.x_root, &event.xbutton.y_root,
                 &event.xbutton.x, &event.xbutton.y,
                 &event.xbutton.state);
        }
    
    
        // Press
        event.type = ButtonPress;
        if (XSendEvent (display, PointerWindow, True, ButtonPressMask, &event) == 0)
        fprintf (stderr, "Error to send the event!\n");
        XFlush (display);
        usleep (1);
    
    
        // Release
        event.type = ButtonRelease;
        if (XSendEvent (display, PointerWindow, True, ButtonReleaseMask, &event) == 0)
        fprintf (stderr, "Error to send the event!\n");
        XFlush (display);
        usleep (1);
    }
    
    
    
    
    void clickDown (Display *display, int button)
    {
        // Create and setting up the event
        XEvent event;
        memset (&event, 0, sizeof (event));
        event.xbutton.button = button;
        event.xbutton.same_screen = True;
        event.xbutton.subwindow = DefaultRootWindow (display);
    
    
        while (event.xbutton.subwindow)
        {
                event.xbutton.window = event.xbutton.subwindow;
                XQueryPointer (display, event.xbutton.window,
                 &event.xbutton.root, &event.xbutton.subwindow,
                 &event.xbutton.x_root, &event.xbutton.y_root,
                 &event.xbutton.x, &event.xbutton.y,
                 &event.xbutton.state);
        }
    
    
        // Press
        event.type = ButtonPress;
        if (XSendEvent (display, PointerWindow, True, ButtonPressMask, &event) == 0)
        fprintf (stderr, "Error to send the event!\n");
        XFlush (display);
        usleep (1);
    }
    
    
    
    
    void clickUp (Display *display, int button)
    {
        // Create and setting up the event
        XEvent event;
        memset (&event, 0, sizeof (event));
        event.xbutton.button = button;
        event.xbutton.same_screen = True;
        event.xbutton.subwindow = DefaultRootWindow (display);
    
    
        while (event.xbutton.subwindow)
        {
            event.xbutton.window = event.xbutton.subwindow;
            XQueryPointer (display, event.xbutton.window,
                 &event.xbutton.root, &event.xbutton.subwindow,
                 &event.xbutton.x_root, &event.xbutton.y_root,
                 &event.xbutton.x, &event.xbutton.y,
                 &event.xbutton.state);
        }
    
    
        // Release
        event.type = ButtonRelease;
        if (XSendEvent (display, PointerWindow, True, ButtonReleaseMask, &event) == 0)
        fprintf (stderr, "Error to send the event!\n");
        XFlush (display);
        usleep (1);
    }
    
    
    
    
    int main()
    {
    
    
        Display *display = XOpenDisplay(0);
        int fd;
        struct input_event ie;
        Display *dpy;
        Window root, child;
        int rootX, rootY, winX, winY;
        unsigned int mask;
        dpy = XOpenDisplay(NULL);
        XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,&rootX,&rootY,&winX,&winY,&mask);
    
    
        if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
            perror("opening device");
            exit(EXIT_FAILURE);
        }
    
    
        bool hold = false;
        bool scrolling = false;    // Canel if user is scrolling with wheel
        auto time_start_sec = ie.time.tv_sec;
        auto time_stop_sec = ie.time.tv_sec;
        auto time_start_usec = ie.time.tv_usec;
        auto time_stop_usec = ie.time.tv_usec;
        auto time_stop_usec_adj = ie.time.tv_usec;
        auto time_real = ie.time.tv_usec;
        float time_elapsed_adj;
        float time_to_click = .5;    // How long to hold the button down?
        float time_to_hold = 1.5;    // Hold down longer for holding click
        short startX;
        short stopX;
        short startY;
        short stopY;
        short range = 10;    // How much can mouse move whilst clicking?
    
    
    
    
        std::cout << "Ready for mouse events..." << std::endl;
    
    
        while(true){
    
    
            // Grab mouse events:
            read(fd, &ie, sizeof(struct input_event));
    
    
            if (ie.type == 2) {
                if (ie.code == 8 ){
                    std::cout << "Other button pressed!" << std::endl;
                    scrolling=true;
                }
    
    
                if (ie.code == 0) { rootX += ie.value;  
                }else if (ie.code == 1) { rootY += ie.value; }
                } else if (ie.type == 1) {
                    if (ie.code == 272 ) { 
     
                        if (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;
                                    //std::cout << "OVER" << std::endl;
                    }
                            }else
                                time_stop_usec_adj = time_stop_usec - time_start_usec;
                            time_elapsed_adj = float(time_stop_sec) + (float(time_stop_usec_adj) / 1000000); 
    
    
                            stopX = rootX;
                            stopY = rootY;
    
    
                            std::cout << "Released @ X: " << stopX << " Y: " << stopY << " Time held: " << time_elapsed_adj << " seconds." << std::endl;        
    
    
    
    
                            if (time_elapsed_adj >= time_to_click){
    
    
                                if (stopX <= (startX + range) && stopX >= (startX - range) && stopY <= (startY + range) && stopY >= (startY - range) && scrolling == false){
    
    
                                    std::cout << "Clicked!" << std::endl;
     
                                    if(time_elapsed_adj >= time_to_hold){
                                        std::cout << "Activating Hold!" << std::endl;
                                        hold = true;
                                        clickDown(XOpenDisplay(NULL),Button3);
    
    
                                        // Alternative (works)
                                        //system("xdotool mousedown 3");
                                    }else{
                                        std::cout << "Activating Click!" << std::endl;
                                        //click(XOpenDisplay(NULL),Button3);
    
    
                                        // Alternative (works)
                                        //system("xdotool click 3");
                                    }
    
    
    
    
                                }
                            }
    
    
                        }
    
    
                        // Mouse button is 'clicked' (initial press):
                        if (ie.value == 1)  {
                            scrolling = false;
                            startX = rootX;
                            startY = rootY; 
                            time_start_sec = ie.time.tv_sec;
                            time_start_usec = ie.time.tv_usec;
                            std::cout << "\nPressed  @ X: " << startX << " Y: "<< startY << std::endl;
    
    
                            // Clicking cancels the hold:
                if (hold){
                                std::cout << "Mouse up!" << std::endl;
                                clickUp(XOpenDisplay(NULL),Button3);
    
    
                                // Alternative (works)
                                //system("xdotool mouseup --clearmodifiers 3");
                            }
                    hold = false;
                        }
                   } 
            }
        
        }
    
    
        XCloseDisplay(display);
        return 0;
    
    
    }
    I am only concerned with the click stimulation itself, not the other part of the code, so you need not lose hair over understanding the timer system and click detection; that code works as far as I can tell.

    The code has been tested with a mouse (not touchscreen).

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,485
    A couple of thoughts.

    Capture the X11 protocol&#39;s traffic - Unix & Linux Stack Exchange
    Compare your code with what xdotool does in the same circumstance.

    > clickDown(XOpenDisplay(NULL),Button3);
    You mention that the click ends up in weird places.
    Perhaps try to find out what the current window focus is, and aim the click there.
    Rather than just sending it to the root display.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    12
    Sorry for the late response. I am a little burnt out after plugging away for 6 hours trying to make a C++ curl library not cause memory leaks... but I wanted to respond to say that I am still here and appreciate your reply.

    Quote Originally Posted by Salem View Post
    A couple of thoughts.

    Capture the X11 protocol&#39;s traffic - Unix & Linux Stack Exchange
    Compare your code with what xdotool does in the same circumstance.
    This is a really good idea. I'll be sure to check it out, though I'm wondering how much I'll understand of it.

    > clickDown(XOpenDisplay(NULL),Button3);
    You mention that the click ends up in weird places.
    Perhaps try to find out what the current window focus is, and aim the click there.
    Rather than just sending it to the root display.
    Working with X on C++ is new to me. I should have mentioned that much of the code is not mine. In fact, all of the code you speak of in that function isn't mine at all but a copy.

    If you or anyone else knows of a tutorial that could explain this C++ library in an fairly easy to understand manner, then that would be great. I'll be checking that code tomorrow when my mind is more fresh.

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    12
    I read in a post that the library I was using to make clicks was not completely made for what I was using it for. People were saying to use the XTest library.

    I did such, and, as it seems for now, the code is working without the need of xdotool or system command.

    For those interested:

    mouse.cpp
    Code:
    /*        Secondary Button Mouse stimulator
     Compile with:
     g++ -Wall -Ofast mouse.cpp -o mouse -lX11 -lXtst -lXext
    */
    
    
    #include <fcntl.h>
    #include <iostream>
    #include <linux/input.h>
    #include <string.h> 
    #include <unistd.h>
    #include <X11/extensions/XTest.h>
    
    
    #define MOUSEFILE "/dev/input/event0"
    
    
    int main()
    {
    
    
        Display *dpy = NULL;
        XEvent event;
        dpy = XOpenDisplay(NULL);
    
    
        int 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);
    
    
    
    
        if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
            perror("opening device");
            exit(EXIT_FAILURE);
        }
    
    
        bool scrolling = false;  // Cancel if user is scrolling with wheel
        bool hold = false;
        auto time_start_sec      = ie.time.tv_sec;
        auto time_stop_sec       = ie.time.tv_sec;
        auto time_start_usec     = ie.time.tv_usec;
        auto time_stop_usec      = ie.time.tv_usec;
        auto time_stop_usec_adj  = ie.time.tv_usec;
        auto time_real           = ie.time.tv_usec;
        float time_elapsed_adj;
        float time_to_click      = 0.4; // How long to hold the button down?
        float time_to_hold       = 1.2; // Time pressed for holding click
        short startX =  0;       // Mouse location (cancel click if moved)
        short stopX  =  0;
        short startY =  0;
        short stopY  =  0;
        short range =  10;       // How much can mouse move whilst clicking?
    
    
    
    
        std::cout << "Ready for mouse events..." << std::endl;
    
    
        while(true){
    
    
            // Grab mouse events:
            read(fd, &ie, sizeof(struct input_event));
    
    
            if (ie.type == 2) {
                if (ie.code == 8 ){
                    std::cout << "Other button pressed!" << std::endl;
                    scrolling=true;
                }
    
    
                if (ie.code == 0) { rootX += ie.value;
                }else if (ie.code == 1) { rootY += ie.value; }
                } else if (ie.type == 1) {
                    if (ie.code == 272 ) {
     
                    if (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 = float(time_stop_sec) + (float(time_stop_usec_adj) / 1000000);
                    stopX = rootX;
                    stopY = rootY;
    
    
                    std::cout << "Released @ X: " << stopX << " Y: " << stopY << " Time held: " << time_elapsed_adj << " seconds." << std::endl;	
    
    
    
    
                    if (time_elapsed_adj >= time_to_click){
    
    
                        if (stopX <= (startX + range) && stopX >= (startX - range) && stopY <= (startY + range) && stopY >= (startY - range) && scrolling == false)
                        {
    
    
                            std::cout << "Clicked!" << std::endl;
     
                            if(time_elapsed_adj >= time_to_hold)
                            {
    
    
                                std::cout << "Activating Hold!" << std::endl;
                                
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                                usleep(1000);
    
    
                                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);
    
    
                                hold = true;
    
    
                            }else{
    
    
                                std::cout << "Activating Click!" << std::endl;
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                                usleep(1000);
    
    
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 3, False, CurrentTime);
                                usleep(1000);
    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);
    
    
                            }
                        }
                    }
                }
    
    
                // Mouse button is 'clicked' (initial press):
                if (ie.value == 1)  {
    
    
                    scrolling = false;
                    startX = rootX;
                    startY = rootY; 
                    time_start_sec  = ie.time.tv_sec;
                    time_start_usec = ie.time.tv_usec;
                    std::cout << "\nPressed  @ X: " << startX << " Y: "<< startY << std::endl;
    
    
                    // Left-clicking cancels the hold:
                    if (hold){
                        std::cout << "Cancelling hold!" << std::endl;
    
    
                        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(1000);
    
    
                        XTestFakeButtonEvent (dpy, 3, False,  CurrentTime);
    
    
                        usleep(1000);
    
    
                        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);
                    }
    
    
                    hold = false;
                }
            } 
        }
    	
    }
    
    
        XCloseDisplay (dpy);
    
    
        return 0;
    
    
    }
    Code on github:
    Secondary Mouse Button Stimulator * GitHub
    Oh, and I had a chance to look at that code Salem. For now, it's a trifle over my head.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    12
    Updated code is below for anyone interested. I got everything working great using the xtest library!

    This code works on my Raspberry Pi 3b+ and will likely work on other Linux-based systems. It is meant to be used with a touch-screen and will not work with a mouse. It is hard-coded, so you'll have some serious adjustments to make. I just wanted to make sure lurkers knew my solution and were not left in the dust in their search.

    mouse.cpp
    Code:
    /*
    
    
     Secondary Button Mouse stimulator
    
    
     g++ -Wall -Ofast mouse.cpp -o mouse -lX11 -lXtst -lXext
    
    
    */
    
    
    #include<fcntl.h>
    #include<iostream>
    #include<linux/input.h>
    #include<string> 
    #include<unistd.h>
    #include<X11/extensions/XTest.h>
    #include<string>
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<array>
    #include<fstream>
    #include<iostream>
    #include <limits>
    
    
    std::string get_device() 
    {
    
    
        static const std::string tokenToFind[] = {"Name=\"FT5406", "H:"};    
        std::string token, s;
        std::ifstream file("/proc/bus/input/devices");
        unsigned int i = 0;
    
    
        while(file >> token)
            if(token == tokenToFind[i])
            {
                    if(++i == 2)
                    {
                        // grab one token after 'H:'
                        file >> s >> s;
                        file.close();
                        return "/dev/input/" + s; 
                    }
            }
    
    
        return "...";
    }
    
    
    void clickRight(Display *dpy, XEvent &event)
    {
    
    
    std::cout << "Right button clicked!" << std::endl;
    
    
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                                usleep(1000);
    
    
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 3, False, CurrentTime);
                                usleep(1000);
    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 clickMiddle(Display *dpy, XEvent &event)
    {
        std::cout << "Middle button clicked!" << std::endl;
    
    
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 2, True,  CurrentTime);
                                usleep(1000);
    
    
                                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(1000);
    
    
                                XTestFakeButtonEvent (dpy, 2, False, CurrentTime);
                                usleep(1000);
    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 = NULL;
        XEvent event;
        dpy = XOpenDisplay(NULL);
    
    
        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);
    
    
        const std::string result = get_device(); 
        std::cout << "Using file:" << result << std::endl;
    
    
        const char* eventFile = result.c_str();
    
    
        if((fd = open(eventFile, O_RDONLY)) == -1) {
            perror("opening device");
            return 1; 
        }
    
    
        auto time_start_sec     = ie.time.tv_sec;
        auto time_stop_sec      = ie.time.tv_sec;
        auto time_start_usec    = ie.time.tv_usec;
        auto time_stop_usec     = ie.time.tv_usec;
        auto time_stop_usec_adj = ie.time.tv_usec;
        auto time_real          = ie.time.tv_usec;
        float time_elapsed_adj;
    
    
        #define time_to_click .3
        #define time_to_hold 1.2
    
    
        bool Ycaptured     = false;
        bool Xcaptured     = false;
    
    
        //  X = 0 - 799
        //  Y = 0 - 479
        
        short Y     = 0;
        short X     = 0;
        short lastX = 0;
        short lastY = 0;
    
    
        #define bottomMinYEnter 450
        #define bottomYRangeThreshold 15
        #define bottomXRangeLower 245
        #define bottomXRangeUpper 550 
        #define topMinYEnter 30
        #define topYRangeThreshold 15
        #define topXRangeLower 300 
        #define topXRangeUpper 800
        #define leftMinXEnter 30
        #define leftXRangeThreshold 15
        #define leftYRangeLower 80
        #define leftYRangeUpper 400
        #define rightMinXEnter 770
        #define rightXRangeThreshold 15
        #define rightYRangeLower 50
        #define rightYRangeUpper 430
    
    
    
    
        std::cout << "Ready for mouse events..." << std::endl;
    
    
        while(true){
    
    
            // Grab mouse events:
            read(fd, &ie, sizeof(struct input_event));
    
    
            if (ie.type == 3 && ie.code == 54 )
                lastY = ie.value;
    
    
            if (ie.type == 3 && ie.code == 53 )
                lastX = ie.value;
    
    
            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 = float(time_stop_sec) + (float(time_stop_usec_adj) / 1000000);
    
    
                Ycaptured = false;
                Xcaptured = false;
    
    
                if (Y > bottomMinYEnter && (Y - lastY) > bottomYRangeThreshold && abs(X - lastX) < abs(Y - lastY) && abs(lastX - X) < abs(lastY - Y) && X > bottomXRangeLower && X < bottomXRangeUpper)
                {
    
    
                    system("xdotool key alt+space");
                    std::cout << "BOTTOM ENTRY!!!" << std::endl;
    
    
                }else if (Y < topMinYEnter && (lastY - Y) > topYRangeThreshold && abs(X - lastX) < abs(Y - lastY) && abs(lastX - X) < abs(lastY - Y) && X > topXRangeLower && X < topXRangeUpper )
                {
    
    
                    //system("killall svkbd-en");
                    system("xdotool key alt+b");
                    std::cout << "TOP ENTRY!!!" << std::endl;
    
    
                }else if (X < leftMinXEnter && (lastX - X) > leftXRangeThreshold && abs(Y - lastY) < abs(X - lastX) && abs(lastY - Y) < abs(lastX - X) && Y > leftYRangeLower && Y < leftYRangeUpper)
                {
    
    
                    system("xdotool key alt+k");
                    std::cout << "LEFT ENTRY!!!" << std::endl;
    
    
                }else if (X > rightMinXEnter && (X - lastX) > rightXRangeThreshold && abs(Y - lastY) < abs(X - lastX) && abs(lastY - Y) < abs(lastX - X) && Y > rightYRangeLower && Y < rightYRangeUpper)
                { 
    
    
                    system("xdotool key alt+x");
                    std::cout << "RIGHT ENTRY!!!" << std::endl;
    
    
                }
    
    
                if (time_elapsed_adj >= time_to_click)
                {
                    if(time_elapsed_adj >= time_to_hold)
                        clickMiddle(dpy, event);
                    else
                        clickRight(dpy, event);
                }
        }
    
    
    
    
        if (!Ycaptured && ie.type == 3 && ie.code == 1 ) {
            Ycaptured = true;
            Y = ie.value;
        }
    
    
        if (!Xcaptured && ie.type == 3 && ie.code == 0 ) {
            Xcaptured = true;
            X = ie.value;
        }
    
    
    
    
        // Mouse button is 'clicked' (initial press):
        if (ie.type == 0 && ie.code == 0 && ie.value == 0){ 
            time_start_sec  = ie.time.tv_sec;
            time_start_usec = ie.time.tv_usec;
        }
    
    
    }
        
        XCloseDisplay (dpy);
    
    
        return 0;
    
    
    }
    People looking to use it must make sure to enter their device or it won't work. It can be entered on this line:

    Code:
    static const std::string tokenToFind[] = {"Name=\"FT5406", "H:"};
    Replace with your device where it says 'FT5406'.

  6. #6
    Informer -Adrian's Avatar
    Join Date
    Jan 2013
    Posts
    811
    Nice work, and thanks for sharing.

    (It was cases like this where the like button was a perfect, unobtrusive instrument)

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    12
    You're welcome.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to add mouse simulation clicks
    By whatnext in forum C Programming
    Replies: 6
    Last Post: 09-30-2011, 01:18 PM
  2. Monitor Mouse Clicks
    By mmarab in forum Windows Programming
    Replies: 10
    Last Post: 09-04-2007, 04:52 AM
  3. mouse clicks
    By chris1985 in forum C Programming
    Replies: 1
    Last Post: 01-14-2005, 04:19 PM
  4. Mouse Clicks
    By Unregistered in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 11-07-2001, 09:12 AM

Tags for this Thread