X11 / Xlib:虚拟键盘输入和键盘映射同步问题

问题描述 投票:1回答:1

对于自动测试应用程序,我必须模拟大量的unicode键盘输入到旧的X11应用程序(我没有任何源访问)。我的程序通过stdin从UCS-2 LE编码的输入流中获取输入,基本操作如下:

  1. 保存当前键盘布局和锁定修饰符(qazxsw poi,qazxsw poi,qazxsw poi)
  2. 解锁活动修饰符(XDisplayKeycodes
  3. 通过Xinput2扩展禁用所有X11从键盘设备
  4. 将输入读入按键队列,直到遇到XGetKeyboardMapping唯一符号,其中XkbGetStateXkbLockModifiers返回的可能密钥代码的数量。
  5. 通过nn可用KeyCodes上映射这些XDisplayKeycodes独特的X11 KeySyms
  6. 通过n为所有入队的KeySyms键入正确的KeyCodes
  7. 清除队列并继续执行4.)直到没有输入可用
  8. 重新激活键盘并恢复初始修改器和映射

基本上这个系统比我到目前为止看到的任何虚拟X11键输入工具工作得更好,性能更好。

但是,我目前只能使用丑陋的延迟解决问题:

与任何其他X11应用程序一样,目标应用程序在我的应用程序成功更改键盘映射表后从X服务器接收XChangeKeyboardMapping(request == Keyboard)事件。 X11客户端通常的响应是调用n来更新Xlib对新键盘布局的了解。

现在,如果客户端处理其X11事件队列有一些延迟,那么XTestFakeKeyEvent调用可能会返回一个过去的映射,这个映射在未来已经过了几代。例如。当目标应用程序刚刚在其XEvent队列处理程序中处理第二个MappingNotify事件时,我的输入生成器已经完成了第四个XRefreshKeyboardMapping。实际上它应该得到第二代地图,当时不再在X服务器上可用。

不幸的是,在键盘XRefreshKeyboardMapping事件中没有地图ID或任何类型的版本,因此XChangeKeyboardMapping可以引用特定的地图......并且X服务器似乎也没有保留历史记录。

结果是X11应用程序的MappingNotifyMappingNotify转换以无效布局运行并生成错误的KeySyms。

所以基本上我必须等到所有客户(或者至少是具有输入焦点的客户)请求并接收我的最后一张XRefreshKeyboardMapping地图,然后才允许我做下一个KeyCode

我可以在KeySym之前使用延迟来修复99.9%的错误,并且该延迟是通过一些丑陋的巫术(击键量等)来计算的,并且如果必须达到100%的准确度则是高的。

所以我的问题是,是否有任何方式以编程方式通知或检查X11客户端是否已完成XChangeKeyboardMapping或其地图是否与服务器地图同步?

如果没有,有没有办法通过xlib获取另一个X11客户端的当前映射(以检查映射是否是当前的)?

谢谢你的任何提示!

c linux automation keyboard x11
1个回答
1
投票

我过去在Windows上做过类似的事情。我很幸运能够使用XChangeKeyboardMapping函数,该函数接受KEYEVENTF_UNICODE标志的KEYBDINPUT结构。不幸的是,X11不支持直接击键合成Unicode字符。

由于我无法评论,我不得不给出一个建议作为答案:

您是否考虑使用剪贴板将“unicode输入”传输到此X11应用程序的输入字段?

如果该应用程序使用支持此功能的工具包,您也可以考虑使用直接Unicode输入:

例如。基于GTK +的程序(包括所有GNOME应用程序)支持Unicode输入。 按住XChangeKeyboardMapping + XRefreshKeyboardMapping并键入SendInput,然后输入Unicode十六进制数字,再次释放CtrlShift

我想使用Xtest扩展来合成这些序列应该很容易。

© www.soinside.com 2019 - 2024. All rights reserved.