【问题标题】:X11 XGrabPointer, how do I clear all the events before I release the mouse?X11 XGrabPointer,如何在释放鼠标之前清除所有事件?
【发布时间】:2018-06-16 21:32:58
【问题描述】:

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

这是我到现在为止的代码:

#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。 无论我尝试什么功能,我在抓住鼠标时所做的所有鼠标事件都是在我关闭显示器后发生的。

有人可以帮忙吗?

【问题讨论】:

    标签: linux x11 xlib xgrabpointer


    【解决方案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);
    ...
    

    以上信息将是您研究的良好起点。

    【讨论】:

    • 我正在尝试在整个屏幕上捕获事件。当我将您的代码更改为使用 root 而不是窗口时,它不起作用。你能帮忙吗?
    • 像这样在无限循环中查询指针是使用 100% CPU 并将您的机器变成烤箱的好方法。如果你想在不阻塞的情况下跟踪指针事件,最好的方法是 Xinput 扩展和原始事件。
    • 我认为没有理由仅仅因为小错误而降低响应分数。这是不尊重他人的。如果你有正确的答案 - 让我们看看。
    • 如果上下文菜单打开(通常在右击后) XGrabPointer() 返回 AlreadyGrabbed 我不知道如何恢复抓住鼠标的可能性。能给我点建议吗?
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 2017-02-02
      • 1970-01-01
      • 2019-11-30
      • 1970-01-01
      相关资源
      最近更新 更多