6

I want to write a simple Xlib program changing the mouse behavior (to give an example, invert vertical movement). I have a problem with capturing the events.

I would like the code to

  • capture changes in the controllers position (I move mouse upward, MotionEvent)
  • calculate new cursor position (new_x -= difference_x)
  • set new cursor position ( move pointer down, XWarpPointer, prevent event generation here)

The code below should capture a motion event every time the mouse is moved, but it generates the event only when the pointer moves from one window to another... How to capture all the movement events?

#include "X11/Xlib.h"
#include "stdio.h"

int main(int argc, char *argv[])
{
    Display *display;
    Window root_window;
    XEvent event;

    display = XOpenDisplay(0);
    root_window = XRootWindow(display, 0);
    XSelectInput(display, root_window, PointerMotionMask );

    while(1) {
        XNextEvent( display, &event );
        switch( event.type ) {
            case MotionNotify:
                printf("x %d y %d\n", event.xmotion.x, event.xmotion.y );
                break;
        }
    }

    return 0;
}

Related:

X11: How do I REALLY grab the mouse pointer?

Community
  • 1
  • 1
Jakub M.
  • 32,471
  • 48
  • 110
  • 179

2 Answers2

7

When your program receives mouse events, it receives a copy of the events; copies are also sent to other programs that are listening for those events (see XSelectInput(3)). You cannot override this without using XGrabPointer(3) to take exclusive ownership of the mouse, which will prevent other programs from receiving any mouse events. In short, you can't actually do what you are trying to do.

Note also that if a client has specified PointerMotion in its do-not-propagate mask for one of its windows, you will not receive any pointer motion events within its window (again, unless you do a grab).

geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • Thanks. In the perfect case I would like to grab the mouse events "before" they are processed by the X input layer (but messing with mouse drivers would be too low probably). Do you know if it's possible? – Jakub M. Apr 25 '12 at 09:41
  • 1
    X11 doesn't generally provide for this level of control; if you can't do it with the XInput API, you would indeed need to do it at the level of a driver or at least a server plugin. X11 isn't very flexible in this regard. – geekosaur Apr 25 '12 at 18:57
3

If you want to change the behavior of the mouse when it is being moved, I suggest you to play with the input properties instead of trying to do the processing in your program.

  • xinput --list
  • xinput --list-props 'USB Optical Mouse'
  • xinput --set-prop 'USB Optical Mouse' 'Evdev Axis Inversion' 1 0
  • xinput --set-prop 'USB Optical Mouse' 'Evdev Axes Swap' 1
  • There's also the 'Coordinate Transformation Matrix' property but for some reason it's not working for me right now.

You don't need to call the xinput program yourself: you can use Xlib calls (look at xinput's source code).

pzanoni
  • 2,979
  • 2
  • 18
  • 18