X11 XGrabPointer,如何在发布鼠标之前清除所有事件?

时间:2018-01-07 20:30:31

标签: linux x11 xlib xgrabpointer

我能够抓住鼠标,但我的问题是抓取鼠标时发生的鼠标事件只是排队,并且在我释放鼠标后发生。

这是我迄今为止的代码:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    XEvent e;

    Display* dispaly = XOpenDisplay(NULL);
    Window window = XDefaultRootWindow(dispaly);

    unsigned int count = 0;
    XGrabPointer(dispaly, window, true, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None, CurrentTime);

    while(count < 500000) {
        if (XPending(dispaly))
            XNextEvent(dispaly, &e);

        count++;
        printf("%d\n", count);
    }


    XFlush(dispaly);

    XCloseDisplay(dispaly);

    scanf("%d", &count);

    printf("end\n");

    return 0;
}

正如您所看到的,我尝试以多种方式使用所有事件,例如使用XPending和XNextEvent,使用XFlush,以及使用XSync。 无论我尝试了什么功能,我抓住鼠标时所做的所有鼠标事件都是在我关闭显示器后发生的。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

创建窗口:

#include <stdio.h>
#include <unistd.h>

#include <X11/X.h>
#include <X11/Xlib.h>

int main()
{
  Display* disp     = XOpenDisplay(NULL);
  Window   root     = XDefaultRootWindow(disp);
  int      scr      = XDefaultScreen(disp);
  GC       context  = XDefaultGC(disp, scr);
  ulong fg          = BlackPixel(disp, scr);  // fg color
  ulong bg          = WhitePixel(disp, scr);  // bg color
  int depth         = 1;
  Window win        = XCreateSimpleWindow(disp, root, 0, 0, 50, 50, depth, fg, bg);

  long events = 
    ExposureMask |
    ButtonPressMask | 
    ButtonReleaseMask | 
    PointerMotionMask;

  XSelectInput(disp, win, events);
  XMapWindow(disp, win);
  XFlush(disp);

  unsigned int masks = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
  XGrabPointer(
    disp, win, true, masks, GrabModeSync, GrabModeAsync, None, None, CurrentTime
  );

抓住指针事件:

  XEvent event;

  do { 
    XNextEvent(disp, &event);
    switch (event.type) {
      case ButtonPress    :
        printf("pressed  %i\n", event.xbutton.button);
        break;
      case ButtonRelease  :
        printf("released %i\n", event.xbutton.button);
        break;
      case MotionNotify   :
        printf("move x %i y %i\n", event.xmotion.x, event.xmotion.y);
        break;
      default : break;
    }
    usleep(1000);    

  } while (true);

  XCloseDisplay(disp);
  return 0;
}

或者,如果您需要捕获 root 窗口中的所有事件,则可以使用XQueryPointer代替XNextEvent

...
Window root_ret;
Window child_ret;
int x_rel, y_rel;
int x_win, y_win;
unsigned int mask;

do {

  XQueryPointer(
    disp, root,
    &root_ret, &child_ret,
    &x_rel, &y_rel, &x_win, &y_win,
    &mask);
  printf("%d %d\n", x_rel, y_rel);
  usleep(1000);
) while (true);
...

以上信息将是您研究的一个良好开端。

答案 1 :(得分:1)

如果你注销这两行代码,你也可以获得鼠标事件。

unsigned int masks = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
XGrabPointer(disp, win, 1, masks, GrabModeSync, GrabModeAsync, None, None, CurrentTime);