簡體   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