[Spice-devel] [PATCH win32/vd_agent] Handling keyboard description message

Pavel Grunt pgrunt at redhat.com
Wed Nov 5 02:44:53 PST 2014


The agent tries to find the appropriate keyboard layout
and loads it into the language bar when the message is received.

RFE: https://bugs.freedesktop.org/show_bug.cgi?id=85332
---
depends on: http://lists.freedesktop.org/archives/spice-devel/2014-November/017821.html
---
 vdagent/vdagent.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index aa44383..e299d97 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -93,6 +93,7 @@ private:
     void handle_clipboard_release();
     bool handle_display_config(VDAgentDisplayConfig* display_config, uint32_t port);
     bool handle_max_clipboard(VDAgentMaxClipboard *msg, uint32_t size);
+    void handle_keyboard_description(char *msg, uint32_t size);
     void handle_chunk(VDIChunk* chunk);
     void on_clipboard_grab();
     void on_clipboard_request(UINT format);
@@ -104,6 +105,7 @@ private:
     static DWORD WINAPI event_thread_proc(LPVOID param);
     static VOID CALLBACK read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped);
     static VOID CALLBACK write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped);
+    static BOOL CALLBACK setup_keyboard_layout(LPTSTR lpLocaleString);
     void dispatch_message(VDAgentMessage* msg, uint32_t port);
     uint32_t get_clipboard_format(uint32_t type);
     uint32_t get_clipboard_type(uint32_t format);
@@ -161,6 +163,7 @@ private:
     mutex_t _message_mutex;
     std::queue<int> _control_queue;
     std::queue<VDIChunk*> _message_queue;
+    WCHAR* _keyboard_locale;
 
     bool _logon_desktop;
     bool _display_setting_initialized;
@@ -898,6 +901,20 @@ bool VDAgent::handle_max_clipboard(VDAgentMaxClipboard *msg, uint32_t size)
     return true;
 }
 
+void VDAgent::handle_keyboard_description(char *msg, uint32_t size)
+{
+    int req_size;
+
+    if ((req_size = MultiByteToWideChar(CP_UTF8, 0, msg, size, NULL, 0)) == 0)
+        return;
+
+    _keyboard_locale = new WCHAR[req_size];
+
+    if (MultiByteToWideChar(CP_UTF8, 0, msg, size, _keyboard_locale, req_size))
+        EnumSystemLocales(setup_keyboard_layout, LCID_INSTALLED);
+    delete [] _keyboard_locale;
+}
+
 #define MIN(a, b) ((a) > (b) ? (b) : (a))
 
 bool VDAgent::write_clipboard(VDAgentMessage* msg, uint32_t size)
@@ -1294,6 +1311,9 @@ void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port)
     case VD_AGENT_MAX_CLIPBOARD:
         res = handle_max_clipboard((VDAgentMaxClipboard*)msg->data, msg->size);
         break;
+    case VD_AGENT_KEYBOARD_DESCRIPTION:
+        handle_keyboard_description((char *) msg->data, msg->size);
+        break;
     default:
         vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
     }
@@ -1381,6 +1401,31 @@ void VDAgent::handle_chunk(VDIChunk* chunk)
     }
 }
 
+BOOL VDAgent::setup_keyboard_layout(LPTSTR lpLocaleString)
+{
+    WCHAR country_name[KL_NAMELENGTH], *fnd;
+    LCID lcid;
+    int len;
+    VDAgent *a = _singleton;
+
+    if (lpLocaleString == NULL)
+        return FALSE;
+
+    lcid = _tcstol(lpLocaleString, NULL, 16);
+    GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, country_name, KL_NAMELENGTH);
+    CharLowerW(country_name);
+
+    len = wcslen(country_name);
+    fnd = wcsstr(a->_keyboard_locale, country_name);
+    if (fnd != NULL &&
+        (fnd == a->_keyboard_locale || !IsCharAlphaW(*CharPrevW(a->_keyboard_locale, fnd))) &&
+        !IsCharAlphaW(*(fnd+len))) {
+        LoadKeyboardLayout(lpLocaleString, 0);
+    }
+
+    return TRUE;
+}
+
 void VDAgent::cleanup_in_msg()
 {
     _in_msg_pos = 0;
-- 
1.9.3



More information about the Spice-devel mailing list