Linux: Xautomation with fake mouse pointer

1.2k views Asked by At

I have created a fake mouse pointer using the xinput command as outlined here which produces a second pointer that hovers in the center of my screen.

I would now like to automate it using the xte command, but unfortunately xte only seems grab control of the hardware mouse that I wish to keep free.

The man page for xte does not have any flags to specify which pointer to take control of. I was wondering if anybody had any ideas?

NB: The second pointer is purely for me to able to work on the same computer whilst running the graphical pipeline


Edit: So by looking at the xte source I've found references to XQueryPointer

Bool XQueryPointer(display, w, root_return, child_return, root_x_return, root_y_return, 
                     win_x_return, win_y_return, mask_return)
      Display *display;
      Window w;
      Window *root_return, *child_return;
      int *root_x_return, *root_y_return;
      int *win_x_return, *win_y_return;
      unsigned int *mask_return;

//Arguments:
display         Specifies the connection to the X server.
w               Specifies the window.
root_return     Returns the root window that the pointer is in.
child_return    Returns the child window that the pointer is located in, if any.
root_x_return
root_y_return   Return the pointer coordinates relative to the root window's origin.
win_x_return
win_y_return    Return the pointer coordinates relative to the specified window.
mask_return     Returns the current state of the modifier keys and pointer buttons. 

from the Xlib class, which as you can see returns only the first mouse pointer and does not give option for another.


Edit2: Looking through the libx11-dev source I'm finding mentions of it at ./src/QuPntr.c and Xlibint.h, but the code is getting harder to read and I'm out of my depth here

2

There are 2 answers

0
Hans Müller On

Actually there isn't any mention of XQueryPointer inside the source code of xte.c (there are only a few inside xmousepos.c, which is code for a different tool). I checked a few older versions that existed before you asked the question.

The relevant functions are XIWarpPointer and XTestFakeDeviceButtonEvent. As seen here in the reduced source code:

#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XTest.h>
int main (int argc, char *argv[])
{
  int delta_x = 500, delta_y = 160;
  Display *display = XOpenDisplay(0);
  Window root = DefaultRootWindow(display);
  XIWarpPointer(display, 14, None, root, 0, 0, 0, 0, delta_x, delta_y);
  XDevice *device = NULL;
  device = XOpenDevice(display, 16);
  XTestFakeDeviceButtonEvent(display, device, 1, True, 0, 0, CurrentTime);
  XTestFakeDeviceButtonEvent(display, device, 1, False, 0, 0, CurrentTime);
  XCloseDisplay(display);
}

which does the same thing as xte -i 16 "mousemove 500 160" "mouseclick 1".

But what might bother you (at least it bothers me): Windows that got clicked gain focus, effectively unfocusing the window that you were working on.
Actually I asked a question that asks for an alternative to XTestFakeDeviceButtonEvent just recently (Sending a button press event for a second pointing device; I also provided some example code that actually performs mouse clicks without giving focus to a window, so it's possible but dunno how it's done with another pointing device).. An alternative might be to work with multiple X sessions like this user did it: Controlling multiple pointers with Xlib or xinput in ubuntu/linux. Sadly he hasn't shared any code. I have some hope with uinput (https://www.kernel.org/doc/html/v4.12/input/uinput.html) but haven't tried it yet.

0
Idl On

xinput makes use of the XI2 extension to allow for multiple pointers. This library (X11/extensions/XInput2.h) provides functions prefixed by "XI" which accept a device parameter (the same referenced by xinput --list), for instance XIQueryPointer, XIWarpPointer or XIGetClientPointer. Thus you can control your fake pointer programmatically if your automation tool doesn’t support XI2.

In a simpler way, it could suffice to xinput --reattach the hardware device (a slave device) to the new pointer (a master device).

Very late answer I know, but I came across this question via web search so I add what I know for reference.