问题
So I want to make left mouse clicks using another pointing device (that can be created with e.g. xinput create-master mouse) but those clicks shouldn't give focus to windows.
This is what I got so far: (Compile this code with gcc -lX11 -lXtst -lXext -o test test.c and move your mouse over e.g. text that is inside of a text editor like Kate)
#include <X11/Xlib.h>
// Simulate mouse click
void click (Display *display, int button)
{
// Create and setting up the event
XEvent event;
event.xbutton.button = button;
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;
XSendEvent (display, PointerWindow, True, ButtonPressMask, &event);
// Release
event.type = ButtonRelease;
XSendEvent (display, PointerWindow, True, ButtonReleaseMask, &event);
}
int main (int argc, char *argv[])
{
Display *display = XOpenDisplay(0);
click (display, Button1);
XCloseDisplay(display);
}
If you run the compiled binary you should notice that a mouse click was performed but the window that got the mouse click did not gain focus and you could just press up to re-run the binary again.
The problem is that I can't specify a pointer with this code. I stumpled across xte which works with another pointer but sadly gives focus.. It uses the XTestFakeDeviceButtonEvent of XTest; I reduced the code to this:
#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);
}
It should be possible somehow with XInput2 cause it has MPX support. I tried it with some functions like DeviceButtonPress but only found examples that handle events that devices created:
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <stdio.h>
#include <X11/extensions/XTest.h>
int main (int argc, char* * argv) {
Display * dpy;
dpy = XOpenDisplay(NULL);
XDevice *pointer1;
XDevice *pointer2;
XEvent ev;
int type_bpress;
XEventClass cls[1];
pointer1 = XOpenDevice(dpy, 12); /* get the ID from ListInputDevices */
/* register for events */
DeviceButtonPress(pointer1, type_bpress, cls[0]);
XSelectExtensionEvent(dpy, RootWindow(dpy, DefaultScreen(dpy)), cls, 2);
while(1) {
XNextEvent(dpy, &ev);
printf("Event type %d received\n", ev.type);
if (ev.type == type_bpress)
{
XDeviceButtonEvent* bev = (XDeviceButtonEvent*)&ev;
printf("Press received by device %d\n", bev->deviceid);
}
}
XCloseDisplay(dpy);
return 0;
}
来源:https://stackoverflow.com/questions/59597037/sending-a-button-press-event-for-a-second-pointing-device