3

I am using "XGrabPointer" to get the mouse click events when ever they occured in the active window.But my requirement is to detect the clicks globally i.e in any application on the X11 desktop. XGrabPointer blocks the active window so i can not move to other applications and detect the mouse click events.

Here are the codes:

#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;
}
emcconville
24.6k4 gold badges52 silver badges66 bronze badges
asked Apr 24, 2013 at 6:54
9
  • The following code returns the mouse events on the terminal but it also LOCKS the entire terminal so i can not move to other application.And also the clicks are not effective i.e if i click on the X buton,then it reports about the click event but it does nt do any thing. Codes have been added in the above. Commented Apr 24, 2013 at 11:01
  • There is no good way (or perhaps just no way) to do this. Why do you need these events? Commented Apr 24, 2013 at 11:38
  • I am doing a small project where i need to identify the mouse click events any where on the linux desktop along with the respective co-ordinates. But since i am using XGrabPointer so i can not move out of the terminal and click on other applications. Commented Apr 24, 2013 at 11:53
  • 1
    while(1){ XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,&rootX,&rootY,&winX,&winY,&mask); while(read(fd, &ie, sizeof(struct input_event))) { if (ie.type == EV_KEY) { if (ie.code == 272 ) { XGrabPointer(dpy,DefaultRootWindow(dpy),False,PointerMotionMask|ButtonPressMask|ButtonReleaseMask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime); printf("grabbed\n"); XAllowEvents(dpy,SyncPointer, CurrentTime); XNextEvent(dpy,&xevent); if(xevent.type==ButtonPress){printf("button pressed"); Commented Apr 27, 2013 at 8:55
  • 1
    The abpve code works alittle i.e the pointer is grabbed but no events are reported.Checked that because of the "XNextEvent" it is not proceding further and evets are not reported i.e it could not enter in to the section "if(xevent.type==ButtonPress){printf("button pressed");" Commented Apr 27, 2013 at 8:59

1 Answer 1

1

Couldn't find an answer on how to listen to mouse events in the background as well. It's impossible to do it with mouse grabbing and you won't be able to click anywhere outside of your program.

So the solution is to read linux's /dev/input/mice device for the raw mouse input (we want button clicks) and when a low-level event occur we query X server for mouse position (can't query mouse key presses from X this way).

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

Sample output

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
answered May 21, 2021 at 5:48
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.