diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 124ff4aa..c49209a5 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2115,8 +2115,9 @@ xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, return 1; } out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 4 + 4 + 4); + out_uint32_le(s, 24); /* size */ out_uint32_le(s, 21); /* msg id */ + out_uint32_le(s, 16); /* size */ out_uint32_le(s, key_down); out_uint32_le(s, unicode); s_mark_end(s); diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index c2195a9c..b1202a46 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -547,6 +547,9 @@ struct xrdp_wm int caps_lock; int scroll_lock; int num_lock; + /* Unicode input */ + int last_high_surrogate_key_up; + int last_high_surrogate_key_down; /* client info */ struct xrdp_client_info *client_info; /* session log */ diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 7c64c662..0a1f6f3f 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -28,6 +28,7 @@ #include "ms-rdpbcgr.h" #include "log.h" #include "string_calls.h" +#include "unicode_defines.h" /*****************************************************************************/ static void @@ -1675,17 +1676,65 @@ xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags) } /*****************************************************************************/ -static int -xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) +/** + * Takes a stream of UTF-16 characters and maps then to Unicode characters + */ +static char32_t +get_unicode_character(struct xrdp_wm *self, int device_flags, char16_t c16) { + char32_t c32 = 0; + int *high_ptr; + + if (device_flags & KBD_FLAG_UP) + { + high_ptr = &self->last_high_surrogate_key_up; + } + else + { + high_ptr = &self->last_high_surrogate_key_down; + } + + if (IS_HIGH_SURROGATE(c16)) + { + // Record high surrogate for next time + *high_ptr = c16; + } + else if (IS_LOW_SURROGATE(c16)) + { + // If last character was a high surrogate, we can use it + if (*high_ptr != 0) + { + c32 = C32_FROM_SURROGATE_PAIR(c16, *high_ptr); + *high_ptr = 0; + } + } + else + { + // Character maps straight across + c32 = c16; + *high_ptr = 0; + } + + return c32; +} + +/*****************************************************************************/ +static int +xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char16_t c16) +{ + char32_t c32 = get_unicode_character(self, device_flags, c16); + + if (c32 == 0) + { + return 0; + } #ifdef XRDP_IBUS // Test code for ibus Unicode forwarding if (self->mm->chan_trans != NULL && self->mm->chan_trans->status == TRANS_STATUS_UP) { xrdp_mm_send_unicode_to_chansrv(self->mm, - (device_flags & KBD_FLAG_UP) == 0, - unicode); + !(device_flags & KBD_FLAG_UP), c32); return 0; } #endif @@ -1694,7 +1743,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (unicode == self->keymap.keys_noshift[index].chr) + if (c32 == self->keymap.keys_noshift[index].chr) { xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE); return 0; @@ -1703,7 +1752,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (unicode == self->keymap.keys_shift[index].chr) + if (c32 == self->keymap.keys_shift[index].chr) { if (device_flags & KBD_FLAG_UP) { @@ -1721,7 +1770,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (unicode == self->keymap.keys_altgr[index].chr) + if (c32 == self->keymap.keys_altgr[index].chr) { if (device_flags & KBD_FLAG_UP) { @@ -1741,7 +1790,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (unicode == self->keymap.keys_shiftaltgr[index].chr) + if (c32 == self->keymap.keys_shiftaltgr[index].chr) { if (device_flags & KBD_FLAG_UP) {