Sending X11 click event doesn't work with some

2019-05-01 01:11发布

The following snippet of code works most of the time, except in certain windows. For instance, under the latest Ubuntu it does not work for selecting folders in the file explorer. It seems to work just about everywhere else, but this gap is significant. I suspect it has to do with how I am using XQueryPointer, but I've tried nearly every example I can find. If I use the computer's mouse instead, it work's fine. FYI: I've already tried the answers to these questions: Sending Programmatic events Capuring Mouse Input but they don't work any different...

Here's the code:

#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

void SendClick(int button, int down) {
    Display *display = XOpenDisplay(NULL);
    XEvent event;

    if(display == NULL)
    {
        return;
    }

    memset(&event, 0, sizeof(event));

    event.xbutton.button = button;
    event.xbutton.same_screen = True;
    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);
    }

    event.type = down ? ButtonPress : ButtonRelease;

    XSendEvent(display, PointerWindow, True, down ? ButtonPressMask : ButtonReleaseMask, &event); 

    XFlush(display);

    XCloseDisplay(display);
}

标签: c x11
2条回答
我命由我不由天
2楼-- · 2019-05-01 01:47

Thanks to ninjalj's comment above for putting me on the right track. I don't like the idea of relying on an extension to do this and the extra dependency it creates, but it is a pretty standard extension too. Works perfect...

For those running into the same issue as me, the following code block replaces the code I was using before and works well:

#include <X11/extensions/XTest.h>

void SendClick(int button, Bool down) {
    Display *display = XOpenDisplay(NULL);
    XTestFakeButtonEvent(display, button, down, CurrentTime);
    XFlush(display);
    XCloseDisplay(display);
}

Much shorter!

For Ubuntu, don't forget to install the libxtst-dev package. Be sure to add -lXtst to your LDFLAGS.

查看更多
虎瘦雄心在
3楼-- · 2019-05-01 02:03

This link is also useful:

X11 Fake Mouse Events Generation using XTest Extension http://bharathisubramanian.wordpress.com/2010/04/01/x11-fake-mouse-events-generation-using-xtest/

Here is a link explaining how to use the XTest Extension for the generation of fake keyboard events:

X11 Fake Key Event Generation using XTest Extension http://bharathisubramanian.wordpress.com/2010/03/14/x11-fake-key-event-generation-using-xtest-ext/

查看更多
登录 后发表回答