Sending a button press event for a second pointing device

北慕城南 提交于 2020-02-06 09:50:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!