Find the answer to your Linux question:
Results 1 to 9 of 9
I want to log it when a key being pressed.Here is the code: Code: #include <X11/Xlib.h> #include <assert.h> #include <unistd.h> #include <stdio.h> int main() { Display *display = XOpenDisplay(NULL); assert(display); ...
  1. #1
    Just Joined!
    Join Date
    May 2008
    Posts
    5

    Can not get the xevent with XNextEvent function?

    I want to log it when a key being pressed.Here is the code:
    Code:
    #include <X11/Xlib.h> 
    #include <assert.h>   
    #include <unistd.h>  
    #include <stdio.h>
     
    int main() {
    
    	Display *display = XOpenDisplay(NULL);
    	assert(display);
    
    	Screen *screen=XDefaultScreenOfDisplay(display);
    	int width=XWidthOfScreen(screen);
    	int height=XHeightOfScreen(screen);
    	printf("width:%d,height:%d\n", width, height);
    	
    	int f=1;
    	while (f) {
    		if (XPending(display)) {
    			int eq=XEventsQueued(display, QueuedAlready);
    			printf("events num in queue:%d\n", eq);
    			XEvent e;
    			XNextEvent(display, &e);
    			printf("event type:%d\n", e.type);
    			if (e.type == KeyPress) {
    				XKeyEvent y=e.xkey;
    				unsigned int keycode=y.keycode;
    				unsigned int state=y.state;
    				printf("keycode:%d,state:%d\n", keycode, state);
    				break;
    			}
    		}
    	}
    	return 0;
    }
    But I can not get any xevent,how to do the things correctly?

  2. #2
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    You can't receive events for any given window without indicating which events you wish to receive for that window. One way to do that is with XSelectInput().

    To make sure you get all the events of interest for any given window, be sure to specify which events you wish to receive for it before you map it.

    If you really mean the code you've posted to run as it is, it looks like you want to grab all KeyPress events, regardless of the window they're in. In that case, I imagine you can specify the root window in your XSelectInput(), but I've never done this. Since it doesn't make sense to map the root window, I imagine you can simply use XSelectInput() without mapping the root window, and you simply take your chances as to which KeyPress events have been missed before the XSelectInput() takes effect.

    Hope this helps.
    --
    Bill

    Old age and treachery will overcome youth and skill.

  3. #3
    Just Joined!
    Join Date
    May 2008
    Posts
    5

    Talking

    Quote Originally Posted by wje_lf View Post
    You can't receive events for any given window without indicating which events you wish to receive for that window. One way to do that is with XSelectInput().

    To make sure you get all the events of interest for any given window, be sure to specify which events you wish to receive for it before you map it.

    If you really mean the code you've posted to run as it is, it looks like you want to grab all KeyPress events, regardless of the window they're in. In that case, I imagine you can specify the root window in your XSelectInput(), but I've never done this. Since it doesn't make sense to map the root window, I imagine you can simply use XSelectInput() without mapping the root window, and you simply take your chances as to which KeyPress events have been missed before the XSelectInput() takes effect.

    Hope this helps.
    Thanks very much! I'm going to try it!

  4. #4
    Just Joined!
    Join Date
    May 2008
    Posts
    5
    I hava changed my code to this,but when the program is running,whaterver anykey I pressed,there is still nothing in output...
    Code:
    #include <X11/Xlib.h>
    #include <assert.h>
    #include <unistd.h>
    #include <stdio.h>
    int main() {
    	// Open the display
    
    	Display *display = XOpenDisplay(NULL);
    	assert(display);
    
    	Screen *screen=XDefaultScreenOfDisplay(display);
    	int width=XWidthOfScreen(screen);
    	int height=XHeightOfScreen(screen);
    	printf("width:%d,height:%d\n", width, height);
    	
    	Window window=XRootWindowOfScreen(screen);
    	
    	XWindowAttributes attributes;
    	XGetWindowAttributes(display,window,&attributes);
    	
    	printf("map_state:%d,width:%d,height:%d\n",attributes.map_state,attributes.width,attributes.height);
    	
    	XSelectInput(display,window,KeyPress);
    	
    	int f=1;
    	while (f) {
    		if (XPending(display)) {
    			int eq=XEventsQueued(display, QueuedAlready);
    			printf("events num in queue:%d\n", eq);
    			XEvent e;
    			XNextEvent(display, &e);
    			printf("event type:%d\n", e.type);
    			if (e.type == KeyPress) {
    				XKeyEvent y=e.xkey;
    				unsigned int keycode=y.keycode;
    				unsigned int state=y.state;
    				printf("keycode:%d,state:%d\n", keycode, state);
    				break;
    			}
    		}
    	}
    
    	return 0;
    }

  5. #5
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    I had previously said:
    I imagine you can specify the root window in your XSelectInput(), but I've never done this.
    Boy, was I ever wrong!

    But first, just for future reference, please know that your XSelectInput() call should look something like this:
    Code:
    XSelectInput(display,window,KeyPressMask);  /* good */
    not this:
    Code:
    XSelectInput(display,window,KeyPress);      /* bad */
    Now. The reason that waiting for events on the root window won't do what you want is twofold.

    First, not all events propagate from a given window to all its ancestors. This is controlled by the do_not_propagate_mask member of the window attributes structure.

    And I thought, fine, let's test this approach anyway by running the program (as corrected for KeyPressMask) with the cursor sitting on just the root window. It still didn't work. That leads us to the second reason:

    Second, your window manager may set the input focus to a particular window, or to no window at all if it wishes. It does this using XSetInputFocus(). If it sets the input focus to no window at all, then no window (not even the root window) will get KeyPress events.

    To find out which window has the input focus, you can use XGetInputFocus(). If you wish to be notified when that window no longer has focus, you can enable FocusOut events on that window.

    Even so, you won't be able to make this bulletproof. There is no guarantee that you can switch from one window to another before the user slips in a keystroke or two.
    --
    Bill

    Old age and treachery will overcome youth and skill.

  6. #6
    Just Joined!
    Join Date
    May 2008
    Posts
    5
    Thanks very much,where is a focus window indeed,and when I listen on that window,I got the key press event!
    Code:
    Window fw;
    	int state;
    	XGetInputFocus(display,&fw,&state);
    	
    	XGetWindowAttributes(display,fw,&attributes);
    	
    	printf("focus window---->map_state:%d,width:%d,height:%d\n",attributes.map_state,attributes.width,attributes.height);
    	
    	
    	XSelectInput(display,fw,KeyPressMask);

  7. #7
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    Now you have me curious! What happens when the mouse pointer is not inside any window (except the root window)?

    And which window manager are you running?
    --
    Bill

    Old age and treachery will overcome youth and skill.

  8. #8
    Just Joined!
    Join Date
    May 2008
    Posts
    5
    I use gnome,and I use the code below to log the key press event:
    Code:
    void addListener(Display* display, Window r) {
    	//get children list
    	unsigned int listnum;
    	Window parent;
    	Window root;
    	Window *wa;
    
    	XQueryTree(display, r, &root, &parent, &wa, &listnum);
    	if (wa==NULL) {
    		return;
    	}
    	int i=0;
    	printf("listnum:%d\n", listnum);
    	for (i=0; i<listnum; i++) {
    		Window w=wa[i];
    		//printf("alive here?\n");
    		XWindowAttributes tattributes;
    		XGetWindowAttributes(display, w, &tattributes);
    		printf("map_state:%d,width:%d,height:%d\n", tattributes.map_state,
    				tattributes.width, tattributes.height);
    		if (tattributes.map_state==2) {
    			XSelectInput(display, w, KeyPressMask);
    		}
    		if (tattributes.map_state==2) {
    
    			XGrabPointer(display,w,False,ButtonPressMask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
    		}
    		addListener(display, w);
    	}
    }
    It's working,but when I add the mouse button click event through xselectinput:
    Code:
    XSelectInput(display, w, KeyPressMask|ButtonPressMask);
    xlib throw a BadAccess exception.
    I found "Only one client at a time can select a ButtonPress event, which is associated with the event mask ButtonPressMask." in Xlib Programming Manual: XSelectInput

    so I change my code to:
    Code:
    XGrabPointer(display,w,False,ButtonPressMask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
    But I found that the buttonpressevent has been consumed by my code,the applications can not receive the event any more.
    How can I log all the mouse button click event happens in the display and dont affect the applications?

    Thanks in advance!

  9. #9
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    How can I log all the mouse button click event happens in the display and not affect the applications?
    The official answer is "You can't."

    If you are really determined to do this, however, I see two options.
    1. Use strace while running the X server. You will need to become familiar with the X Protocol. (See the O'Reilly book X Protocol Reference Manual.)
    2. Hack the source for X itself and make your copy non-standard.

    In either case, the yellow brick road you choose to follow will be a long, hard yellow brick road. I can see this requiring months of fulltime work to research, design, code, debug, and document. In the process, you will become the world's resident expert on the topic of non-intrusive grabbing of mouse events.

    I really, really hope you decide not to do this.
    --
    Bill

    Old age and treachery will overcome youth and skill.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...