getting mouseclick coordinates with Xlib

2020-02-12 18:17发布

I would like to know how to get the x and y coordinates of a mouseclick with Xlib anywhere on the screen. I've found this post which gets the current pointer position

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

but I don't know how to modify it so it gets the x y coordinates when the mouse is clicked. I've tried to write this code but it does nothing.

#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;
}

The events are probably send to other windows and that is the reason it's not working. Another problem is that when I add ButtonPressMask to the XSelectInput function I get the following error:

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

If there is simpler way to do this in C, I am happy to hear it.

标签: c x11 xlib
3条回答
叛逆
2楼-- · 2020-02-12 18:47

You'll probably need to grab the pointer.

I don't know if you want just want button presses of releases. I've changed it to presses, but you can pick up both with:

XSelectInput(display, root, ButtonPressMask|ButtonReleaseMask) ;

and add the ButtonRelease case back in.

#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;
}
查看更多
一纸荒年 Trace。
3楼-- · 2020-02-12 19:08

I know this is a couple years out so this is informational for others coming along. First, using yet another library does not fit my definition of easier. I was working on something that needed this myself using xlib and C only and I wanted to see how simple I could make the code.

Essentially you only need four lines of code to do this in xlib in an existing program the rest is all in how you want to deal with it, printf/sprintf, grab_pixel_color(Display *display, XColor *color) etc.

/** 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;
}

I hope this is useful to someone else.

查看更多
beautiful°
4楼-- · 2020-02-12 19:13

If there is simpler way to do this in C, I am happy to hear it.

Perfect! Then use the libxdo library that some folks have already made for you.

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);
查看更多
登录 后发表回答