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;
}
-
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.user2314247– user23142472013年04月24日 11:01:51 +00:00Commented 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?n. m. could be an AI– n. m. could be an AI2013年04月24日 11:38:54 +00:00Commented 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.user2314247– user23142472013年04月24日 11:53:46 +00:00Commented Apr 24, 2013 at 11:53
-
1while(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");user2314247– user23142472013年04月27日 08:55:59 +00:00Commented Apr 27, 2013 at 8:55
-
1The 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");"user2314247– user23142472013年04月27日 08:59:59 +00:00Commented Apr 27, 2013 at 8:59
1 Answer 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