简体   繁体   English

Linux x11 XGrabKeyboard()导致键盘被冻结

[英]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(),这是我的代码:

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. 我尝试了true或false或第3个参数,GrabModeAsync和GrabModeSync用于第4和第5个参数,但它不起作用。

After calling XGrabKeyboard(), the keyboard is frozen and mouse click doesn't response. 调用XGrabKeyboard()后,键盘被冻结,鼠标单击不响应。

Any ideas? 有任何想法吗?

XGrabKeyboard() (if successful - be sure to check the return value), redirects all key events to your client. XGrabKeyboard()(如果成功 - 请务必检查返回值),将所有关键事件重定向到您的客户端。

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. 因此,如果while(true)内的“...”没有正确处理这些键事件,或者没有ungrab(XUngrabKeyboard)或释放同步事件(XAllowEvents,仅适用于GrabModeSync),那么键盘似乎会锁定起来。

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. boolean参数是owner_events,它指示是否始终向提供给XGrabKeyboard的窗口报告键事件,或者将它们报告给它们通常在没有抓取的情况下进入的窗口。 Typically you want False (report to the grab window). 通常,您需要False(报告到抓取窗口)。

For typical uses of XGrabKeyboard (I don't know your use-case) the parameters you would want are: 对于XGrabKeyboard的典型用法(我不知道你的用例),你想要的参数是:

  • 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 owner_events = False将所有事件发送到该窗口
  • pointer_mode=Async to not screw with the pointer pointer_mode =不同于指针的Async
  • keyboard_mode=Async to just redirect all key events and avoid need for AllowEvents keyboard_mode = Async只是重定向所有键事件,避免需要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 time =事件触发抓取的时间戳,理想情况下,或者通过更改属性并从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. 我无法帮助XGrabKeyboard功能 - 我之前没有使用它,也不知道它是如何工作的 - 但我可以建议另一种获取键盘事件的方法。

When creating my window using XCreateWindow, the last argument is a XSetWindowAttributes object. 使用XCreateWindow创建窗口时,最后一个参数是XSetWindowAttributes对象。 This object has a member event_mask, which you can use to choose which events your window will receive. 此对象具有成员event_mask,您可以使用该成员选择窗口将接收的事件。

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. 这意味着如果在创建窗口时将此对象传递给XCreateWindow,则会收到键盘按键和鼠标按键单击的事件。

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. 另外另一个注意事项是你可以使用XPending(pDisplay)检查是否还有等待处理的事件 - 所以它可以在你的while(true)行中替换为true

Edit: Also your freezing issue could be that you dont return false anywhere in your while loop? 编辑:你的冻结问题也可能是你在while循环中的任何地方都没有返回false? 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. 尝试用上面提到的xpending替换true,它可以解决问题,或者只是在处理事件后返回false,但这只会处理每帧一个事件,而不是像XPending那样处理所有当前挂起的事件,我假设这就是你想要做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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