繁体   English   中英

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

[英]X11/Xlib: virtual keyboard input and keyboard mapping synchronization issue

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

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

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

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

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

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

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

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

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

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

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

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

感谢您的任何提示!

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

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

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

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

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

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

暂无
暂无

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

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