对于一个自动化测试应用程序,我必须模拟大量的Unicode键盘输入到一个旧的X11应用程序中(我没有任何源代码访问权限)。
我的程序通过stdin从一个UCS-2 LE编码的输入流中获取输入,基本操作如下:
1. 保存当前键盘布局并锁定修饰符(`XDisplayKeycodes`,`XGetKeyboardMapping`,`XkbGetState`)。 2. 解锁活动修饰符(`XkbLockModifiers`)。 3. 通过Xinput2扩展禁用所有X11从设备。 4. 将输入读入按键队列,直到遇到n个唯一的符号,其中n是由`XDisplayKeycodes`返回的可能按键数。 5. 通过`XChangeKeyboardMapping`将这些n个唯一的X11 KeySyms映射到n个可用的KeyCodes上。 6. 通过`XTestFakeKeyEvent`键入所有排队的KeySyms的正确KeyCodes。 7. 清除队列并在4处继续,直到没有输入可用。 8. 激活键盘并恢复初始修饰符和映射。
基本上,这个系统比我目前看到的任何虚拟X11键盘输入工具都要好得多,性能也更好。
然而,目前我只能使用丑陋的延迟来解决一个问题:
与任何其他X11应用程序一样,目标应用程序从X服务器接收到一个MappingNotify(request==Keyboard)事件,表示我的应用程序成功更改了键盘映射表。 X11客户端的通常响应是调用`XRefreshKeyboardMapping`以更新Xlib对新键盘布局的知识。
现在,如果客户端在处理其X11事件队列时有一些延迟,那么`XRefreshKeyboardMapping`调用可能会返回一个太新的映射,这个映射已经超前了若干代。 例如,当目标应用程序刚刚处理第二个MappingNotify事件时,我的输入生成器已经完成了第四个XChangeKeyboardMapping。 实际上,它应该得到地图的第二代,但此时X服务器不再提供该代。
不幸的是,在键盘MappingNotify事件中没有任何地图ID或版本,因此`XRefreshKeyboardMapping`无法引用特定地图......而且X服务器似乎也没有保留历史记录。
结果是X11应用程序的KeyCode到KeySym转换使用无效布局并生成错误的KeySyms。
因此,基本上我必须等待所有客户端(或至少具有输入焦点的客户端)请求并接收我的最后一个XChangeKeyboardMapping映射,然后才能执行下一个XChangeKeyboardMapping。
我可以通过在
所以我的问题是,是否有任何编程方式可以通知或检查X11客户端是否已完成
如果没有,是否有一种通过xlib获取另一个X11客户端当前映射的方法(以检查映射是否当前)?
谢谢任何提示!
1. 保存当前键盘布局并锁定修饰符(`XDisplayKeycodes`,`XGetKeyboardMapping`,`XkbGetState`)。 2. 解锁活动修饰符(`XkbLockModifiers`)。 3. 通过Xinput2扩展禁用所有X11从设备。 4. 将输入读入按键队列,直到遇到n个唯一的符号,其中n是由`XDisplayKeycodes`返回的可能按键数。 5. 通过`XChangeKeyboardMapping`将这些n个唯一的X11 KeySyms映射到n个可用的KeyCodes上。 6. 通过`XTestFakeKeyEvent`键入所有排队的KeySyms的正确KeyCodes。 7. 清除队列并在4处继续,直到没有输入可用。 8. 激活键盘并恢复初始修饰符和映射。
基本上,这个系统比我目前看到的任何虚拟X11键盘输入工具都要好得多,性能也更好。
然而,目前我只能使用丑陋的延迟来解决一个问题:
与任何其他X11应用程序一样,目标应用程序从X服务器接收到一个MappingNotify(request==Keyboard)事件,表示我的应用程序成功更改了键盘映射表。 X11客户端的通常响应是调用`XRefreshKeyboardMapping`以更新Xlib对新键盘布局的知识。
现在,如果客户端在处理其X11事件队列时有一些延迟,那么`XRefreshKeyboardMapping`调用可能会返回一个太新的映射,这个映射已经超前了若干代。 例如,当目标应用程序刚刚处理第二个MappingNotify事件时,我的输入生成器已经完成了第四个XChangeKeyboardMapping。 实际上,它应该得到地图的第二代,但此时X服务器不再提供该代。
不幸的是,在键盘MappingNotify事件中没有任何地图ID或版本,因此`XRefreshKeyboardMapping`无法引用特定地图......而且X服务器似乎也没有保留历史记录。
结果是X11应用程序的KeyCode到KeySym转换使用无效布局并生成错误的KeySyms。
因此,基本上我必须等待所有客户端(或至少具有输入焦点的客户端)请求并接收我的最后一个XChangeKeyboardMapping映射,然后才能执行下一个XChangeKeyboardMapping。
我可以通过在
XChangeKeyboardMapping
之前使用延迟来修复99.9%的错误,这个延迟是通过一些丑陋的巫术(按键数等)计算出来的,如果需要达到100%的准确性,那么这个延迟就太高了。所以我的问题是,是否有任何编程方式可以通知或检查X11客户端是否已完成
XRefreshKeyboardMapping
或其映射是否与服务器映射同步?如果没有,是否有一种通过xlib获取另一个X11客户端当前映射的方法(以检查映射是否当前)?
谢谢任何提示!