Score:1

C programming: Detect mouse pointer movement

pt flag

I am working on a project in which I need to set a flag only when mouse pointer has not moved for a period of time (e.g: 30s): if the mouse was idle for 30s, set no_movement (no_movement=true;).

So far, I know the X window server is the backend for many desktop environment and I know there is a comprehensive documentation for it on x.org and tronche.com (I got it from there that there is an event for pointer called MotionNotify).

Using apt show xserver-xorg | grep Version I found out the Xserver version installed on my system is 1:7.7+22ubuntu1 (on Ubuntu 21.04)

What is the recommended way to get mouse pointer movement feedback?

Appreciate your time responding me.

HuHa avatar
es flag
Why do I smell some evil "are my home office workers working?" software here?
Shobeira avatar
pt flag
I'm trying to time mine indeed. I need to know how much I work on a project as we are facing the 5th lockdown and working from home still.
bd flag
This question is more likely to get good responses on [Stack Overflow](https://stackoverflow.com) meant for programming, or [Unix & Linux Stack Exchange](https://unix.stackexchange.com/)
Score:0
in flag

X11 is pretty well documented for 'Event masks'

https://tronche.com/gui/x/xlib/events/mask.html

Or there is always XQueryPointer)..

// Try this C program as the basis of what you want todo..

    #include <stdio.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

int main(int argc, char **argv)
{
    Display *display;
    Window root_window;

    /* Initialize (FIXME: no error checking). */
    display = XOpenDisplay(0);
    root_window = XRootWindow(display, 0);

    /* check XInput */
    int xi_opcode, event, error;
    if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
        fprintf(stderr, "Error: XInput extension is not supported!\n");
        return 1;
    }

    /* Check XInput 2.0 */
    int major = 2;
    int minor = 0;
    int retval = XIQueryVersion(display, &major, &minor);
    if (retval != Success) {
        fprintf(stderr, "Error: XInput 2.0 is not supported (ancient X11?)\n");
        return 1;
    }

    /*
     * Set mask to receive XI_RawMotion events. Because it's raw,
     * XWarpPointer() events are not included, you can use XI_Motion
     * instead.
     */
    unsigned char mask_bytes[(XI_LASTEVENT + 7) / 8] = {0};  /* must be zeroed! */
    XISetMask(mask_bytes, XI_RawMotion);

    /* Set mask to receive events from all master devices */
    XIEventMask evmasks[1];
    /* You can use XIAllDevices for XWarpPointer() */
    evmasks[0].deviceid = XIAllMasterDevices;
    evmasks[0].mask_len = sizeof(mask_bytes);
    evmasks[0].mask = mask_bytes;
    XISelectEvents(display, root_window, evmasks, 1);

    XEvent xevent;
    while (1) {
        XNextEvent(display, &xevent);

        if (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
            /* not an XInput event */
            continue;
        }
        XGetEventData(display, &xevent.xcookie);
        if (xevent.xcookie.evtype != XI_RawMotion) {
            /*
             * Not an XI_RawMotion event (you may want to detect
             * XI_Motion as well, see comments above).
             */
            XFreeEventData(display, &xevent.xcookie);
            continue;
        }
        XFreeEventData(display, &xevent.xcookie);

        Window root_return, child_return;
        int root_x_return, root_y_return;
        int win_x_return, win_y_return;
        unsigned int mask_return;
        /*
         * We need:
         *     child_return - the active window under the cursor
         *     win_{x,y}_return - pointer coordinate with respect to root window
         */
        int retval = XQueryPointer(display, root_window, &root_return, &child_return,
                                   &root_x_return, &root_y_return,
                                   &win_x_return, &win_y_return,
                                   &mask_return);
        if (!retval) {
            /* pointer is not in the same screen, ignore */
            continue;
        }

        /* We used root window as its reference, so both should be the same */
        assert(root_x_return == win_x_return);
        assert(root_y_return == win_y_return);

        printf("root: x %d y %d\n", root_x_return, root_y_return);

        if (child_return) {
            int local_x, local_y;
            XTranslateCoordinates(display, root_window, child_return,
                                  root_x_return, root_y_return,
                                  &local_x, &local_y, &child_return);
            printf("local: x %d y %d\n\n", local_x, local_y);
        }
    }

    XCloseDisplay(display);

    return 0;
}
Shobeira avatar
pt flag
Appreciate your reply. So, Am I on the right track? X window is a good approach? As I was lookinng at event masks, I found MotionNotify the most suitable mask as I need a boolean return for the problem. What I was thinking was having a relevent X structure, initialise it, and then evaluate it against the event mask. I need movement/no_movement..
in flag
No problem, I think if you just want to detect movement thats pretty easy... Just monitor the X\Y of the mouse position and if they change then you have movement.. The first step is getting the pointer events in the first place..
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.