简体   繁体   中英

Linux x11 XGrabKeyboard() cause keyboard to be frozen

I am writing a program which need to listen the user keyboard stroks.

I use function XGrabKeyboard() and this is my code:

XGrabKeyboard(pDisplay, DefaultRootWindow(pDisplay), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while (true)
{
  XNextEvent(pDisplay, &event);
  switch (event.type)
  {
  ...
  }
}

But it causes the keyboard and cursor to be frozen.

I looked up the man page, it only says: "The third parameter specifies a Boolean value that indicates whether the keyboard events are to be reported as usual."

I tried both true or false or the 3rd param, both GrabModeAsync and GrabModeSync for the 4th and 5th param, but it doesn't work.

After calling XGrabKeyboard(), the keyboard is frozen and mouse click doesn't response.

Any ideas?

XGrabKeyboard() (if successful - be sure to check the return value), redirects all key events to your client.

So if your "..." inside the while(true) does not properly handle those key events, or does not ever ungrab (XUngrabKeyboard) or release sync events (XAllowEvents, only applies to GrabModeSync), then the keyboard would appear to lock up.

The boolean parameter is owner_events which indicates whether to report key events always to the window provided to XGrabKeyboard, or report them to the window they normally would have gone to without the grab. Typically you want False (report to the grab window).

For typical uses of XGrabKeyboard (I don't know your use-case) the parameters you would want are:

  • grab window = some window in your app that relates to the reason for the grab
  • owner_events=False to send all events to that window
  • pointer_mode=Async to not screw with the pointer
  • keyboard_mode=Async to just redirect all key events and avoid need for AllowEvents
  • time=the timestamp from the event triggering the grab, ideally, or one generated by changing a property and grabbing the timestamp off the PropertyNotify

But, it depends. To give any definitive answer you'd probably need to post a compilable program, I think the bug is likely in the "..." part of your code. Try narrowing your app down to a single-file test case that can be run by others perhaps. Or explain more why you are grabbing and what you're trying to accomplish in the big picture.

I cant help with the XGrabKeyboard function - I havent used it before and dont know how it works - but I can suggest another way of getting the keyboard events.

When creating my window using XCreateWindow, the last argument is a XSetWindowAttributes object. This object has a member event_mask, which you can use to choose which events your window will receive.

I set mine like this:

XSetWindowAttributes setWindAttrs
setWindAttrs.event_mask = ExposureMask           
                        | KeyPressMask  
                        | KeyReleaseMask    
                        | ButtonPressMask 
                        | ButtonReleaseMask;

That will mean you receive events for keyboard key presses and mouse button clicks if you pass this object to XCreateWindow on window creation.

Also another note you can use XPending(pDisplay) to check if there are still events waiting to be handled - so it could replace true in your while(true) line.

Edit: Also your freezing issue could be that you dont return false anywhere in your while loop? It may be stuck in an infinite loop, unless you just removed that bit for the post. Try replacing true with xpending as I suggested above and it may fix the issue, or just returning false after handling the event, but this would only handle one event per frame rather than handling all the currently pending events like XPending would do, and I assume that is what you want to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM