【问题标题】:X11/Xlib: virtual keyboard input and keyboard mapping synchronization issueX11/Xlib:虚拟键盘输入和键盘映射同步问题
【发布时间】:2019-08-09 03:06:57
【问题描述】:

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

  1. 保存当前键盘布局和锁定修饰符(XDisplayKeycodesXGetKeyboardMappingXkbGetState
  2. 解锁活动修饰符 (XkbLockModifiers)
  3. 通过 Xinput2 扩展禁用所有 X11 从键盘设备
  4. 将输入读入按键队列,直到遇到n 唯一符号,其中nXDisplayKeycodes 返回的可能键码数。
  5. 通过XChangeKeyboardMappingn 可用的KeyCodes 上映射这些n 唯一的X11 KeySyms
  6. 通过XTestFakeKeyEvent 为所有排队的 KeySyms 键入正确的 KeyCodes
  7. 清空队列并在 4 处继续。)直到没有可用输入
  8. 重新激活键盘并恢复初始修饰符和映射

基本上,这个系统比我目前见过的任何虚拟 X11 键输入工具都更好,性能也更高。

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

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

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

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

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

所以基本上我必须等到所有客户端(或至少具有输入焦点的客户端)都请求并收到我的最后一个 XChangeKeyboardMapping 映射,然后才能允许我执行下一个 XChangeKeyboardMapping

我可以在XChangeKeyboardMapping 之前使用延迟来修复 99.9% 的错误,并且延迟是通过一些丑陋的巫术(击键次数等)计算出来的,如果必须达到 100% 的准确度,那么延迟就很高了。

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

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

感谢任何提示!

【问题讨论】:

标签: c linux automation keyboard x11


【解决方案1】:

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

由于我还不能发表评论,所以我不得不给出一个建议作为答案:

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

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

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

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

【讨论】:

  • 好主意。不幸的是,剪贴板不是一种选择,至少在我所有的用例中都不是。但是,您提到的输入法在此应用程序中不起作用,我将检查是否支持其他输入法。但是,我的实际目标仍然是解决所描述的延迟问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-18
  • 2011-07-12
相关资源
最近更新 更多