2

我正在使用“XGrabPointer”来获取活动窗口中发生的鼠标点击事件。但我的要求是全局检测点击,即在 X11 桌面上的任何应用程序中。XGrabPointer 会阻止活动窗口,因此我无法移动到其他应用程序并检测鼠标单击事件。

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

int main(int argc, char **argv)
{
  Display *display;
  XEvent xevent;
  Window window;
  int grb;
  int scr;

  if( (display = XOpenDisplay(NULL)) == NULL )
    return -1;

  unsigned int t_new=0,t_prev=0,t_diff=0;
  scr = DefaultScreen(display);
  window = RootWindow(display, scr);

  while(1) {
    XGrabPointer(display,
                 window,
                 True,
                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
                 GrabModeAsync,
                 GrabModeAsync,
                 None,
                 None,
                 CurrentTime);

    XAllowEvents(display,AsyncPointer, CurrentTime);
    XNextEvent(display, &xevent);

    switch (xevent.type) {
      case MotionNotify:{
        printf("motion event\n");
        break;
      }
      case ButtonPress:{
        switch (xevent.xbutton.button) {
          case 1:
            printf("Left Click\n");
            t_prev=t_new;
            printf("Click Occured      : [%d, %d]\n",
                   xevent.xbutton.x_root,
                   xevent.xbutton.y_root);
            break;
          case 2:
            printf("Grabed\n");
            printf("Middle Click\n");
            break;
          case 3:
            printf("Right Click\n");
            break;
          case 4:
            printf("Grabed\n");
            printf("Scroll UP\n");
            break;
          case 5:
            printf("Scroll Down\n");
            break;
        }
        break;
      }
    }
  }
  XUngrabPointer(display,CurrentTime);
  return 0;
}
4

1 回答 1

1

也找不到有关如何在后台收听鼠标事件的答案。用鼠标抓取是不可能的,而且您将无法点击程序之外的任何地方。

所以解决方案是读取 linux 的/dev/input/mice设备以获取原始鼠标输入(我们想要按钮单击),当发生低级事件时,我们查询 X 服务器以获取鼠标位置(不能以这种方式从 X 查询鼠标按键)。

Display *display;
Window root_window;
XEvent event;

display = XOpenDisplay(0);
root_window = DefaultRootWindow(display);

int fd, bytes;
unsigned char data[3];

const char *pDevice = "/dev/input/mice";

// Open Mouse
fd = open(pDevice, O_RDWR);
if (fd == -1) {
    printf("ERROR Opening %s\n", pDevice);
    return -1;
}

int left, middle, right;
while (1) {
    // Read Mouse
    bytes = read(fd, data, sizeof(data));

    if (bytes > 0) {
        left = data[0] & 0x1;
        right = data[0] & 0x2;
        middle = data[0] & 0x4;

        XQueryPointer(
                display,
                root_window,
                &event.xbutton.root,
                &event.xbutton.subwindow,
                &event.xbutton.x_root,
                &event.xbutton.y_root,
                &event.xbutton.x,
                &event.xbutton.y,
                &event.xbutton.state
            );

        printf("x=%d, y=%d, left=%d, middle=%d, right=%d\n", event.xmotion.x, event.xmotion.y, left, middle, right);
    }
}

样本输出

x=470, y=969, left=1, middle=0, right=0
x=470, y=969, left=0, middle=0, right=0
x=467, y=969, left=0, middle=4, right=0
x=463, y=969, left=0, middle=0, right=0
x=444, y=971, left=0, middle=0, right=2
x=441, y=971, left=0, middle=0, right=0
于 2021-05-21T05:48:04.397 回答