我正在尝试通过 x11 为 ubuntu 编写简单的鼠标点击器。
首先,我编写了单击过程的第一个变体(基于 XSendEvent):
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void mouseClick(int button)
{
Display *display = XOpenDisplay(NULL);
XEvent event;
if(display == NULL)
{
std::cout << "clicking error 0" << std::endl;
exit(EXIT_FAILURE);
}
memset(&event, 0x00, sizeof(event));
event.type = ButtonPress;
event.xbutton.button = button;
event.xbutton.same_screen = True;
XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
event.xbutton.subwindow = event.xbutton.window;
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);
}
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0)
std::cout << "clicking error 1" << std::endl;
XFlush(display);
event.type = ButtonRelease;
event.xbutton.state = 0x100;
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0)
std::cout << "clicking error 2" << std::endl;
XFlush(display);
XCloseDisplay(display);
}
这段代码在除 chrome 之外的每个应用程序上都可以正常工作(mozilla 也可以正常工作)。
所以我写了第二个变体(基于XTestFakeButtonEvent):
#include <X11/extensions/XTest.h>
void SendClick(int button, Bool down)
{
Display *display = XOpenDisplay(NULL);
XTestFakeButtonEvent(display, button, down, CurrentTime);
XFlush(display);
XCloseDisplay(display);
}
这段代码在每个地方都可以正常工作,包括 chrome。
这些函数的调用非常简单
// XSendEvent variant
mouseClick(1);
// XTestFakeButtonEvent variant
SendClick(1, true); // press lmb
SendClick(1, false); // release lmb
1:帮助我理解我在第一个变体中做错了什么(或者chrome可能出了什么问题)。
1.1:我认为当我使用 XOpenDisplay(NULL); 打开显示时,我正在尝试发送不是所需窗口的事件。 chrome 与 x11 服务器有不同的连接系统吗?
2:在应用程序中使用第二种变体是个好主意吗?它很短并且可以很好地与我拥有的每个应用程序一起使用)
附:要编译此代码,您需要添加 -lX11 -lXtst 库