【问题标题】:getting mouseclick coordinates with Xlib使用 Xlib 获取鼠标点击坐标
【发布时间】:2013-04-20 15:45:45
【问题描述】:

我想知道如何使用 Xlib 在屏幕上的任何位置获取鼠标点击的 x 和 y 坐标。我发现这篇文章获取当前指针位置

How can I get the current mouse (pointer) position co-ordinates in X,

但我不知道如何修改它,以便在单击鼠标时获取 x y 坐标。 我试过写这段代码,但它什么也没做。

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

int main (){
int x=-1,y=-1;
XEvent event;
int button;
Display *display = XOpenDisplay(NULL);
if (display == NULL) {
    fprintf(stderr, "Cannot connect to X server!\n");
    exit (EXIT_FAILURE);
}
Window root= XDefaultRootWindow(display);
XSelectInput(display, root, ButtonReleaseMask) ;
while(1){
XNextEvent(display,&event);
switch(event.type){
    case ButtonRelease:
        switch(event.xbutton.button){
            case Button1:
                x=event.xbutton.x;
                y=event.xbutton.y;
                button=Button1;
                break;

            case Button3:
                x=event.xbutton.x;
                y=event.xbutton.y;
                button=Button3;
                break;
            default:
                break;

        }
        break;
    default:
        break;
}
if(x>=0 && y>=0)break;
}
if(button==Button1)printf("leftclick at %d %d \n",x,y);
else printf("rightclick at %d %d \n",x,y);
XCloseDisplay(display);
return 0;
}

事件可能被发送到其他窗口,这就是它不起作用的原因。另一个问题是,当我将 ButtonPressMask 添加到 XSelectInput 函数时,出现以下错误:

X Error of failed request:  BadAccess (attempt to access private resource denied)
Major opcode of failed request:  2 (X_ChangeWindowAttributes)
Serial number of failed request:  7
Current serial number in output stream:  7

如果在 C 中有更简单的方法可以做到这一点,我很高兴听到它。

【问题讨论】:

    标签: c x11 xlib


    【解决方案1】:

    我知道这是几年后的事情,所以这对其他人来说是有用的。首先,使用另一个库不符合我对更简单的定义。我自己正在使用 xlib 和 C 做一些自己需要的东西,我想看看我可以使代码变得多么简单。

    基本上你只需要四行代码就可以在现有程序的 xlib 中执行此操作,剩下的就是你想要如何处理它,printf/sprintf、grab_pixel_color(Display *display, XColor *color) 等。

    /** gcc position.c -o position -lX11 **/
    #include <X11/Xlib.h>
    #include <stdio.h>
    
    int main (int argc, char **argv) {
        Window root_window; //<--one
        int root_x, root_y; //<--two
        unsigned int mask; //<--three
    
        Display *display = XOpenDisplay(NULL);
    
        /*
        Bool XQueryPointer(display, w, root_return, child_return, root_x_return, root_y_return,
                             win_x_return, win_y_return, mask_return)
              Display *display;
              Window w;
              Window *root_return, *child_return;
              int *root_x_return, *root_y_return;
              int *win_x_return, *win_y_return;
              unsigned int *mask_return;
        */
    
        XQueryPointer(display, DefaultRootWindow(display), &root_window, &root_window, &root_x, &root_y, &root_x, &root_y, &mask); //<--four
    
        printf("Mouse coordinates (X: %d, Y: %d)\n", root_x, root_y);
    
        XCloseDisplay(display);
        return 0;
    }
    

    我希望这对其他人有用。

    【讨论】:

    • 没有额外的库,直截了当:优秀答案(无论 OP 对事件的请求如何)。请不要从这个答案中删除任何内容。
    【解决方案2】:

    您可能需要抓住指针。

    我不知道您是否只想按下按钮释放。我已将其更改为印刷机,但您可以同时使用:

    XSelectInput(display, root, ButtonPressMask|ButtonReleaseMask) ;
    

    并重新添加 ButtonRelease 案例。

    #include <stdio.h>
    #include <stdlib.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    
    int main (){
        int x=-1,y=-1;
        XEvent event;
        int button;
        Display *display = XOpenDisplay(NULL);
        if (display == NULL) {
        fprintf(stderr, "Cannot connect to X server!\n");
        exit (EXIT_FAILURE);
        }
        Window root= XDefaultRootWindow(display);
        XGrabPointer(display, root, False, ButtonPressMask, GrabModeAsync,
             GrabModeAsync, None, None, CurrentTime);
    
        XSelectInput(display, root, ButtonPressMask) ;
        while(1){
        XNextEvent(display,&event);
        switch(event.type){
        case ButtonPress:
            switch(event.xbutton.button){
            case Button1:
            x=event.xbutton.x;
            y=event.xbutton.y;
            button=Button1;
            break;
    
            case Button3:
            x=event.xbutton.x;
            y=event.xbutton.y;
            button=Button3;
            break;
            default:
            break;
    
            }
            break;
        default:
            break;
        }
        if(x>=0 && y>=0)break;
        }
        if(button==Button1)printf("leftclick at %d %d \n",x,y);
        else printf("rightclick at %d %d \n",x,y);
        XCloseDisplay(display);
        return 0;
    }
    

    【讨论】:

    • 谢谢,代码对我来说工作正常,但我必须更改为 ButtonRelease 否则我会收到与上述相同的错误。你不知道为什么?
    • 这两个事件都对我有用。你用的是哪个窗口管理器?我正在使用 KDE 窗口管理器。
    • 我做了一些研究,您的问题似乎是其他一些进程已经从根窗口捕获按钮按下事件,我可以通过运行您的程序的 2 个实例来重现该问题(第二个给出这个错误)。
    【解决方案3】:

    如果在 C 中有更简单的方法可以做到这一点,我很高兴听到它。

    完美!然后使用一些人已经为你制作的libxdo library

    int x, y, scrn;
    
    xdo_t *hndl = xdo_new(NULL);
    xdo_mouselocation(hndl, &x, &y, &scrn);
    xdo_free(hndl);
    
    printf("Mouse coordinates: x = %4d, y = %4d\n", x, y);
    

    【讨论】:

    • 谢谢。该库肯定比 xlib 本身更易于使用,并且非常适合我的项目。但是我没有看到任何在单击鼠标时返回坐标的函数,因为您的示例只是在调用时返回坐标。
    猜你喜欢
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    相关资源
    最近更新 更多