2

我正在编写一个需要听用户键盘敲击的程序。

我使用函数 XGrabKeyboard() 这是我的代码:

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

但它会导致键盘和光标被冻结。

我查看了手册页,它只说:“第三个参数指定一个布尔值,指示是否要像往常一样报告键盘事件。”

我尝试了 true 或 false 或第三个参数,GrabModeAsync 和 GrabModeSync 都用于第四个和第五个参数,但它不起作用。

调用 XGrabKeyboard() 后,键盘被冻结,鼠标点击无响应。

有任何想法吗?

4

2 回答 2

3

XGrabKeyboard() (如果成功 - 请务必检查返回值),将所有关键事件重定向到您的客户端。

因此,如果您在 while(true) 中的“...”没有正确处理这些键事件,或者从未取消抓取 (XUngrabKeyboard) 或释放同步事件 (XAllowEvents,仅适用于 GrabModeSync),那么键盘将出现锁定向上。

布尔参数是 owner_events,它指示是始终将关键事件报告给提供给 XGrabKeyboard 的窗口,还是将它们报告给他们通常在没有抓取的情况下会去的窗口。通常你想要 False(报告到抓取窗口)。

对于 XGrabKeyboard 的典型用途(我不知道您的用例),您需要的参数是:

  • 抓取窗口 = 应用中与抓取原因相关的某个窗口
  • owner_events=False 将所有事件发送到该窗口
  • pointer_mode=Async 不拧指针
  • keyboard_mode=Async 仅重定向所有键事件并避免需要 AllowEvents
  • 时间=触发抓取的事件的时间戳,理想情况下,或者是通过更改属性并从 PropertyNotify 抓取时间戳而生成的时间戳

但是,这取决于。要给出任何明确的答案,您可能需要发布一个可编译的程序,我认为该错误可能在代码的“...”部分。尝试将您的应用程序缩小到可能由其他人运行的单文件测试用例。或者更多地解释你为什么要抓住,以及你想在大局中完成什么。

于 2012-09-03T13:05:21.830 回答
1

我对 XGrabKeyboard 功能无能为力——我以前没有使用过它,也不知道它是如何工作的——但我可以建议另一种获取键盘事件的方法。

使用 XCreateWindow 创建窗口时,最后一个参数是 XSetWindowAttributes 对象。此对象有一个成员 event_mask,您可以使用它来选择您的窗口将接收哪些事件。

我这样设置我的:

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

这意味着如果您在创建窗口时将此对象传递给 XCreateWindow,您将收到键盘按键和鼠标按钮单击的事件。

您还可以使用另一个注释XPending(pDisplay)来检查是否仍有事件等待处理 - 因此它可以true在您的while(true)行中替换。

编辑:您的冻结问题也可能是您在 while 循环中的任何地方都没有返回 false ?它可能会陷入无限循环,除非您刚刚为帖子删除了该位。尝试按照我上面的建议将 true 替换为 xpending ,它可能会解决问题,或者在处理事件后仅返回 false ,但这只会处理每帧一个事件,而不是像 XPending 那样处理所有当前待处理的事件,我假设这就是你想要做的。

于 2012-09-02T18:57:59.920 回答