From a2064e51c1ebc79ead33885c3474aa7b674a4723 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:43:18 +0100 Subject: [PATCH] Some changes to Unicode input processing - xrdp is not now built with XRDP_IBUS to allow other input methods to be more easily supported. - chansrv is only aked to start an input method if the client supports it. - chansrv sends a status report back to xrdp when asked to start and input method. - ./configure without --enable-ibus now works. --- common/xrdp_client_info.h | 11 +++++ libxrdp/xrdp_caps.c | 14 ++++++ sesman/chansrv/Makefile.am | 14 +++--- sesman/chansrv/chansrv.c | 45 ++++++++++++++++-- xrdp/Makefile.am | 7 +-- xrdp/xrdp_mm.c | 96 ++++++++++++++++++++++++-------------- xrdp/xrdp_wm.c | 24 +++++----- 7 files changed, 151 insertions(+), 60 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 0516f63c..aa76f098 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -74,6 +74,15 @@ enum client_resize_mode CRMODE_MULTI_SCREEN }; +/** + * Type describing Unicode input state + */ +enum unicode_input_state +{ + UIS_UNSUPPORTED = 0, ///< Client does not support Unicode + UIS_SUPPORTED, ///< Client supports Unicode, but it's not active + UIS_ACTIVE ///< Unicode input is active +}; /** * Information about the xrdp client * @@ -228,6 +237,8 @@ struct xrdp_client_info // Can we resize the desktop by using a Deactivation-Reactivation Sequence? enum client_resize_mode client_resize_mode; + + enum unicode_input_state unicode_input_support; }; enum xrdp_encoder_flags diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 7570968a..9ecf2486 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -422,6 +422,20 @@ xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, { self->client_info.use_fast_path &= ~2; } + + // We always advertise Unicode support, so if the client supports it too, + // we can use it + if ((inputFlags & INPUT_FLAG_UNICODE) != 0) + { + self->client_info.unicode_input_support = UIS_SUPPORTED; + LOG(LOG_LEVEL_INFO, "Client supports Unicode input"); + } + else + { + self->client_info.unicode_input_support = UIS_UNSUPPORTED; + LOG(LOG_LEVEL_INFO, "Client does not support Unicode input"); + } + return 0; } diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 7afc98c8..4b0154fa 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -38,11 +38,6 @@ if XRDP_RDPSNDAUDIN AM_CPPFLAGS += -DXRDP_RDPSNDAUDIN endif -if XRDP_IBUS -AM_CPPFLAGS += -DXRDP_IBUS $(IBUS_CFLAGS) $(GLIB2_CFLAGS) -CHANSRV_EXTRA_LIBS += $(IBUS_LIBS) $(GLIB2_LIBS) -endif - AM_CFLAGS = $(X_CFLAGS) sbin_PROGRAMS = \ @@ -78,11 +73,18 @@ xrdp_chansrv_SOURCES = \ sound.h \ xcommon.c \ xcommon.h \ - input_ibus.c \ input.h \ audin.c \ audin.h +if XRDP_IBUS +AM_CPPFLAGS += -DXRDP_IBUS $(IBUS_CFLAGS) $(GLIB2_CFLAGS) +CHANSRV_EXTRA_LIBS += $(IBUS_LIBS) $(GLIB2_LIBS) +xrdp_chansrv_SOURCES += \ + input_ibus.c +endif + + xrdp_chansrv_LDFLAGS = \ $(X_LIBS) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index a99e18f8..8f0a2c15 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -721,6 +721,26 @@ chansrv_drdynvc_open(const char *name, int flags, return error; } + +/*****************************************************************************/ +/* tell xrdp we can do Unicode input */ +static int +chansrv_advertise_unicode_input(int status) +{ + struct stream *s = trans_get_out_s(g_con_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 4); + out_uint32_le(s, 20); /* msg id */ + out_uint32_le(s, 8 + 4); + out_uint32_le(s, status); + s_mark_end(s); + return trans_write_copy(g_con_trans); +} + /*****************************************************************************/ /* close call from chansrv */ int @@ -861,7 +881,18 @@ process_message_unicode_data(struct stream *s) static int process_message_unicode_setup(struct stream *s) { - return xrdp_input_unicode_init(); + int rv = xrdp_input_unicode_init(); + if (rv == 0) + { + // Tell xrdp we can support Unicode input + rv = chansrv_advertise_unicode_input(0); + } + else + { + // Tell xrdp there's a problem starting the framework + chansrv_advertise_unicode_input(2); + } + return rv; } /*****************************************************************************/ @@ -924,17 +955,25 @@ process_message(void) case 19: /* drdynvc data */ rv = process_message_drdynvc_data(s); break; -#ifdef XRDP_IBUS case 21: /* unicode setup */ +#ifdef XRDP_IBUS rv = process_message_unicode_setup(s); +#else + // We don't support this. + rv = chansrv_advertise_unicode_input(1); +#endif break; case 23: /* unicode key event */ +#ifdef XRDP_IBUS rv = process_message_unicode_data(s); +#endif break; case 25: /* unicode shut down */ +#ifdef XRDP_IBUS rv = process_message_unicode_shutdown(s); - break; #endif + break; + default: LOG_DEVEL(LOG_LEVEL_ERROR, "process_message: unknown msg %d", id); break; diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index cf38cece..b771ff8c 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -15,8 +15,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/libipm \ -I$(top_srcdir)/libxrdp \ -I$(top_srcdir)/third_party \ - -I$(top_srcdir)/third_party/tomlc99 \ - $(IBUS_CFLAGS) + -I$(top_srcdir)/third_party/tomlc99 XRDP_EXTRA_LIBS = @@ -38,10 +37,6 @@ AM_CPPFLAGS += -I$(top_srcdir)/libpainter/include XRDP_EXTRA_LIBS += $(top_builddir)/libpainter/src/.libs/libpainter.a endif -if XRDP_IBUS -AM_CPPFLAGS += -DXRDP_IBUS -endif - sbin_PROGRAMS = \ xrdp diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index cd0e8eab..6910efbd 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -43,10 +43,8 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port); static void xrdp_mm_connect_sm(struct xrdp_mm *self); -#ifdef XRDP_IBUS static int xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans); -#endif /*****************************************************************************/ struct xrdp_mm * @@ -151,10 +149,8 @@ xrdp_mm_delete(struct xrdp_mm *self) return; } -#ifdef XRDP_IBUS /* shutdown input method */ xrdp_mm_send_unicode_shutdown(self, self->chan_trans); -#endif /* free any module stuff */ xrdp_mm_module_cleanup(self); @@ -667,7 +663,6 @@ xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s) return rv; } -#ifdef XRDP_IBUS /*****************************************************************************/ static int xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans) @@ -691,19 +686,28 @@ xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans) static int xrdp_mm_send_unicode_setup(struct xrdp_mm *self, struct trans *trans) { - struct stream *s = trans_get_out_s(self->chan_trans, 8192); - if (s == NULL) + int rv = 0; + + if (self->wm->client_info->unicode_input_support == UIS_SUPPORTED) { - return 1; + struct stream *s = trans_get_out_s(self->chan_trans, 8192); + if (s == NULL) + { + rv = 1; + } + else + { + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8); /* size */ + out_uint32_le(s, 21); /* msg id */ + out_uint32_le(s, 8); /* size */ + s_mark_end(s); + + rv = trans_write_copy(self->chan_trans); + } } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 21); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - - return trans_write_copy(self->chan_trans); + return rv; } /******************************************************************************/ @@ -725,7 +729,6 @@ int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, s_mark_end(s); return trans_write_copy(self->chan_trans); } -#endif /*****************************************************************************/ /* returns error @@ -2465,6 +2468,39 @@ xrdp_mm_trans_process_drdynvc_data(struct xrdp_mm *self, return 0; } +/*****************************************************************************/ +/* Acknowledgement from chansrv that Unicode input is supported + */ +static int +xrdp_mm_trans_process_unicode_ack(struct xrdp_mm *self, + struct stream *s) +{ + int status; + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, status); + switch (status) + { + case 0: + LOG(LOG_LEVEL_INFO, "Chansrv is handling Unicode input"); + self->wm->client_info->unicode_input_support = UIS_ACTIVE; + break; + + case 1: + LOG(LOG_LEVEL_INFO, "Chansrv does not support Unicode input"); + break; + + default: + LOG(LOG_LEVEL_INFO, + "Chansrv reported an error starting the Unicode input method"); + break; + } + + return 0; +} + /*****************************************************************************/ /* returns error process a message for the channel handler */ @@ -2517,6 +2553,9 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, case 18: rv = xrdp_mm_trans_process_drdynvc_data(self, s); break; + case 20: + rv = xrdp_mm_trans_process_unicode_ack(self, s); + default: LOG(LOG_LEVEL_ERROR, "xrdp_mm_chan_process_msg: unknown id %d", id); break; @@ -3034,30 +3073,19 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port) trans_delete(self->chan_trans); self->chan_trans = NULL; } + else if (xrdp_mm_send_unicode_setup(self, self->chan_trans) != 0) + { + LOG(LOG_LEVEL_ERROR, "xrdp_mm_chansrv_connect: error in " + "xrdp_mm_send_unicode_setup"); + trans_delete(self->chan_trans); + self->chan_trans = NULL; + } else { LOG(LOG_LEVEL_DEBUG, "xrdp_mm_chansrv_connect: chansrv " "connect successful"); } -#ifdef XRDP_IBUS - /* if client supports unicode input, initialize the input method */ - if (1) - { - LOG(LOG_LEVEL_INFO, "xrdp_mm_chansrv_connect: chansrv " - "client support unicode input, init the input method"); - - if (xrdp_mm_send_unicode_setup(self, self->chan_trans) != 0) - { - LOG(LOG_LEVEL_ERROR, "xrdp_mm_chansrv_connect: error in " - "xrdp_mm_send_unicode_setup"); - - /* disable unicode input */ - // self->wm->client_info->unicode_input = 0; - } - } -#endif - return 0; } diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index eebe0da4..9f6e7d18 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1722,6 +1722,7 @@ get_unicode_character(struct xrdp_wm *self, int device_flags, char16_t c16) static int xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) { + int index; char32_t c32 = get_unicode_character(self, device_flags, c16); if (c32 == 0) @@ -1729,8 +1730,19 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) return 0; } - int index; + // Send the character to chansrv if it's capable of doing something + // with it + if (self->mm->chan_trans != NULL && + self->client_info->unicode_input_support == UIS_ACTIVE && + self->mm->chan_trans->status == TRANS_STATUS_UP) + { + xrdp_mm_send_unicode_to_chansrv(self->mm, + !(device_flags & KBD_FLAG_UP), c32); + return 0; + } + // Fallback - see if we can find the character in the existing keymap, + // and if so, generate a normal key event. for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { if (c32 == self->keymap.keys_noshift[index].chr) @@ -1799,16 +1811,6 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) } } -#ifdef XRDP_IBUS - 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), c32); - return 0; - } -#endif - return 0; }