From 20b90c1098cb3809c9faa68b035668e1ee1f339d Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 25 Mar 2024 10:35:58 +0000 Subject: [PATCH 01/21] Initial support for ibus input from chansrv --- configure.ac | 12 ++++++++++++ sesman/chansrv/Makefile.am | 5 +++++ sesman/chansrv/chansrv.c | 30 ++++++++++++++++++++++++++++++ xrdp/Makefile.am | 4 ++++ xrdp/xrdp.h | 4 ++++ xrdp/xrdp_mm.c | 20 ++++++++++++++++++++ xrdp/xrdp_wm.c | 12 ++++++++++++ 7 files changed, 87 insertions(+) diff --git a/configure.ac b/configure.ac index 11b2b85e68..a6ba833a7a 100644 --- a/configure.ac +++ b/configure.ac @@ -164,6 +164,10 @@ AC_ARG_ENABLE(mp3lame, AS_HELP_STRING([--enable-mp3lame], [Build lame mp3(audio codec) (default: no)]), [], [enable_mp3lame=no]) AM_CONDITIONAL(XRDP_MP3LAME, [test x$enable_mp3lame = xyes]) +AC_ARG_ENABLE(ibus, AS_HELP_STRING([--enable-ibus], + [Allow unicode input via IBus) (default: no)]), + [], [enable_ibus=no]) +AM_CONDITIONAL(XRDP_IBUS, [test x$enable_ibus = xyes]) AC_ARG_ENABLE(pixman, AS_HELP_STRING([--enable-pixman], [Use pixman library (default: no)]), [], [enable_pixman=no]) @@ -472,6 +476,13 @@ then [AC_MSG_ERROR([please install libmp3lame-dev or lamemp3-devel])]) fi +# checking for ibus includes +if test "x$enable_ibus" = "xyes" +then + PKG_CHECK_MODULES([IBUS], [ibus-1.0 >= 1.5], [], + [AC_MSG_ERROR([please install libibus-1.0-dev or ibus-devel])]) +fi + AS_IF( [test "x$enable_pixman" = "xyes"] , [PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.1.0)] ) # checking for TurboJPEG @@ -646,6 +657,7 @@ echo " fuse $enable_fuse" echo " ipv6 $enable_ipv6" echo " ipv6only $enable_ipv6only" echo " vsock $enable_vsock" +echo " ibus $enable_ibus" echo " auth mechanism $auth_mech" echo " rdpsndaudin $enable_rdpsndaudin" echo " utmp support $enable_utmp" diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 959cdb52fb..9916ba0022 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -38,6 +38,11 @@ if XRDP_RDPSNDAUDIN AM_CPPFLAGS += -DXRDP_RDPSNDAUDIN endif +if XRDP_IBUS +AM_CPPFLAGS += -DXRDP_IBUS $(IBUS_CFLAGS) +CHANSRV_EXTRA_LIBS += $(IBUS_LIBS) +endif + AM_CFLAGS = $(X_CFLAGS) sbin_PROGRAMS = \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index d3a32165b2..f97de07cde 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -823,6 +823,31 @@ chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes) return 0; } +/*****************************************************************************/ +#ifdef XRDP_IBUS +static int +process_message_unicode_key_press(struct stream *s) +{ + int rv = 0; + int key_down; + char32_t unicode_char; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_unicode_keypress:"); + if (!s_check_rem(s, 8)) + { + rv = 1; + } + else + { + in_uint32_le(s, key_down); + in_uint32_le(s, unicode_char); + LOG(LOG_LEVEL_INFO, "Unicode char 0x%08x received down=%d", + unicode_char, key_down); + } + return rv; +} +#endif // XRDP_IBUS + /*****************************************************************************/ /* returns error */ static int @@ -875,6 +900,11 @@ process_message(void) case 19: /* drdynvc data */ rv = process_message_drdynvc_data(s); break; +#ifdef XRDP_IBUS + case 21: /* Unicode key press */ + rv = process_message_unicode_key_press(s); + break; +#endif default: LOG_DEVEL(LOG_LEVEL_ERROR, "process_message: unknown msg %d", id); break; diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 69658a2b48..845091ba8a 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -38,6 +38,10 @@ 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.h b/xrdp/xrdp.h index b2a8ae9717..77af46651b 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -483,6 +483,10 @@ xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress, int left, int top, int right, int bottom); int xrdp_mm_up_and_running(struct xrdp_mm *self); +int +xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, + int key_down, + char32_t unicode); struct xrdp_mm * xrdp_mm_create(struct xrdp_wm *owner); void diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 034d63a9b7..124ff4aa7b 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2103,6 +2103,26 @@ xrdp_mm_up_and_running(struct xrdp_mm *self) return 0; } +/******************************************************************************/ +int +xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, + int key_down, + char32_t unicode) +{ + struct stream *s = trans_get_out_s(self->chan_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 4 + 4 + 4); + out_uint32_le(s, 21); /* msg id */ + out_uint32_le(s, key_down); + out_uint32_le(s, unicode); + s_mark_end(s); + return trans_write_copy(self->chan_trans); +} + /*****************************************************************************/ /* open response from client going to channel server */ static int diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index e77fdabd1c..7c64c662a9 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1678,6 +1678,18 @@ 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) { +#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); + return 0; + } +#endif + int index; for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) From 6da58825fe02de2d527768f31257979cfa8c1f97 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:16:09 +0000 Subject: [PATCH 02/21] Fix packet format and support Unicode 32 Fixes a packet in the format send between xrdp and chansrv. UTF-16 surrogate pairs sent from the client are remapped to full unicode characters. --- xrdp/xrdp_mm.c | 3 ++- xrdp/xrdp_types.h | 3 +++ xrdp/xrdp_wm.c | 63 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 124ff4aa7b..c49209a5e7 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 c2195a9cf5..b1202a4694 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 7c64c662a9..0a1f6f3f6b 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 @@ -1674,18 +1675,66 @@ xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags) return 0; } +/*****************************************************************************/ +/** + * 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, char32_t unicode) +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) { From 7bea1f9d56bf477ec75e58adeea25f2b1376105d Mon Sep 17 00:00:00 2001 From: sefler Date: Tue, 16 Apr 2024 16:21:49 +0800 Subject: [PATCH 03/21] compile suscceed --- configure.ac | 4 + sesman/chansrv/Makefile.am | 8 +- sesman/chansrv/input.h | 35 +++++ sesman/chansrv/input_ibus.c | 258 ++++++++++++++++++++++++++++++++++++ xrdp/Makefile.am | 6 +- xrdp/xrdp.h | 2 +- xrdp/xrdp_mm.c | 63 ++++++++- xrdp/xrdp_wm.c | 77 ++--------- 8 files changed, 383 insertions(+), 70 deletions(-) create mode 100644 sesman/chansrv/input.h create mode 100644 sesman/chansrv/input_ibus.c diff --git a/configure.ac b/configure.ac index a6ba833a7a..9633c500c9 100644 --- a/configure.ac +++ b/configure.ac @@ -481,6 +481,10 @@ if test "x$enable_ibus" = "xyes" then PKG_CHECK_MODULES([IBUS], [ibus-1.0 >= 1.5], [], [AC_MSG_ERROR([please install libibus-1.0-dev or ibus-devel])]) + + # ibus uses dbus which depends on glib + PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.56], [], + [AC_MSG_ERROR([please install libglib2.0-dev or glib2.0-devel])]) fi AS_IF( [test "x$enable_pixman" = "xyes"] , [PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.1.0)] ) diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 9916ba0022..817f9aaeb4 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -10,7 +10,9 @@ AM_CPPFLAGS = \ -DXRDP_PID_PATH=\"${localstatedir}/run\" \ -DXRDP_SOCKET_ROOT_PATH=\"${socketdir}\" \ -I$(top_srcdir)/sesman/libsesman \ - -I$(top_srcdir)/common + -I$(top_srcdir)/common \ + $(IBUS_CFLAGS) \ + $(GLIB2_CFLAGS) CHANSRV_EXTRA_LIBS = @@ -78,6 +80,8 @@ xrdp_chansrv_SOURCES = \ sound.h \ xcommon.c \ xcommon.h \ + input_ibus.c \ + input.h \ audin.c \ audin.h @@ -89,4 +93,6 @@ xrdp_chansrv_LDADD = \ $(top_builddir)/sesman/libsesman/libsesman.la \ $(top_builddir)/libipm/libipm.la \ $(X_PRE_LIBS) -lXfixes -lXrandr -lX11 $(X_EXTRA_LIBS) \ + $(GLIB2_LIBS) \ + $(IBUS_LIBS) \ $(CHANSRV_EXTRA_LIBS) diff --git a/sesman/chansrv/input.h b/sesman/chansrv/input.h new file mode 100644 index 0000000000..1062d88695 --- /dev/null +++ b/sesman/chansrv/input.h @@ -0,0 +1,35 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#if !defined(INPUT_H) +#define INPUT_H + +#include "arch.h" +#include "parse.h" + +int +xrdp_input_send_unicode(uint32_t unicode); + +int +xrdp_input_unicode_init(); + +int +xrdp_input_unicode_destory(); + +#endif \ No newline at end of file diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c new file mode 100644 index 0000000000..1f10df1c7e --- /dev/null +++ b/sesman/chansrv/input_ibus.c @@ -0,0 +1,258 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2013 + * Copyright (C) Laxmikant Rashinkar 2009-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include "input.h" +#include "thread_calls.h" + +static IBusBus *bus; +static IBusEngine *g_engine; +// This is the engine name enabled before unicode engine enabled +static const gchar *ori_name; +static int id = 0; + +int +xrdp_input_enable() +{ + IBusEngineDesc *desc; + const gchar *name; + + if (ori_name) + { + // already enabled + return 0; + } + + if (!bus) + { + LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: input method switched failed, ibus not connected"); + return 1; + } + + desc = ibus_bus_get_global_engine(bus); + name = ibus_engine_desc_get_name (desc); + if (!g_ascii_strcasecmp(name, "XrdpIme")) + { + return 0; + } + + // remember user's input method, will switch back when disconnect + ori_name = name; + + if (!ibus_bus_set_global_engine(bus, "XrdpIme")) + { + LOG(LOG_LEVEL_ERROR, "xrdp_input_enable: input method enable failed"); + return 1; + } + + LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: input method switched sucessfully, old input name: %s", ori_name); + + return 0; +} + +int +xrdp_input_send_unicode(uint32_t unicode) +{ + LOG(LOG_LEVEL_DEBUG, "xrdp_input_send_unicode: received unicode input %i", unicode); + + if (xrdp_input_enable()) + { + return 1; + } + + gunichar chr = unicode; + ibus_engine_commit_text(g_engine, ibus_text_new_from_unichar(chr)); + + return 0; +} + +void +xrdp_input_ibus_engine_enable(IBusEngine *engine) +{ + LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_enable: IM enabled"); + g_engine = engine; +} + +void +xrdp_input_ibus_engine_disable(IBusEngine *engine) +{ + LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); +} + +void +xrdp_input_ibus_disconnect(IBusEngine *engine) +{ + LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); + g_object_unref(g_engine); + g_object_unref(bus); +} + +gboolean engine_process_key_event_cb(IBusEngine *engine, + guint keyval, + guint keycode, + guint state) +{ + // Pass the keyboard event to system + return FALSE; +} + +IBusEngine * +xrdp_input_ibus_create_engine(IBusFactory *factory, + gchar *engine_name, + gpointer user_data) +{ + IBusEngine *engine; + gchar *path = g_strdup_printf("/org/freedesktop/IBus/Engine/%i", 1); + engine = ibus_engine_new(engine_name, + path, + ibus_bus_get_connection(bus)); + + LOG(LOG_LEVEL_DEBUG, "xrdp_input_ibus_create_engine: Creating IM Engine with name:%s and id:%d\n", engine_name, ++id); + + g_signal_connect(engine, "process-key-event", G_CALLBACK(engine_process_key_event_cb), NULL); + g_signal_connect(engine, "enable", G_CALLBACK(xrdp_input_ibus_engine_enable), NULL); + g_signal_connect(engine, "disable", G_CALLBACK(xrdp_input_ibus_engine_disable), NULL); + + return engine; +} + +/*****************************************************************************/ +THREAD_RV THREAD_CC +xrdp_input_main_loop() +{ + IBusFactory *factory; + IBusComponent *component; + IBusEngineDesc *desc; + THREAD_RV rv = 0; + + LOG(LOG_LEVEL_DEBUG, "xrdp_input_main_loop: Entering ibus loop"); + + g_signal_connect(bus, "disconnected", G_CALLBACK(xrdp_input_ibus_disconnect), NULL); + + factory = ibus_factory_new(ibus_bus_get_connection(bus)); + g_object_ref_sink(factory); + g_signal_connect(factory, "create-engine", G_CALLBACK(xrdp_input_ibus_create_engine), NULL); + g_signal_connect(factory, "enable", G_CALLBACK(xrdp_input_ibus_engine_enable), NULL); + g_signal_connect(factory, "disable", G_CALLBACK(xrdp_input_ibus_engine_disable), NULL); + + ibus_factory_add_engine(factory, "XrdpIme", IBUS_TYPE_ENGINE); + + component = ibus_component_new("org.freedesktop.IBus.XrdpIme", // name + "Xrdp input method", // description + "1.1", // version + "MIT", // license + "seflerZ", // author + "fake_page", // homepage + "/exec/fake_path", // cmd + "xrdpime"); // text domain + + desc = ibus_engine_desc_new("XrdpIme", + "unicode input method for xrdp", + "unicode input method for xrdp", + "unicode", + "MIT", + "seflerZ", + "fake_icon.png", + "default"); // layout + + ibus_component_add_engine(component, desc); + ibus_bus_register_component(bus, component); + + ibus_main(); + + g_object_unref(desc); + g_object_unref(component); + g_object_unref(factory); + + return rv; +} + +int +xrdp_input_unicode_destory() +{ + LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory"); + if (ori_name) + { + LOG(LOG_LEVEL_INFO, "xrdp_input_unicode_destory: ibus engine rolling back to origin: %s", ori_name); + ibus_bus_set_global_engine(bus, ori_name); + } + + g_object_unref(g_engine); + g_object_unref(bus); + + ori_name = NULL; + bus = NULL; + g_engine = NULL; + + return 0; +} + +int +xrdp_input_unicode_init() +{ + int retry = 10; + + if (bus) + { + // Already initialized, just re-enable it + xrdp_input_enable(); + return 0; + } + + LOG(LOG_LEVEL_DEBUG, "xrdp_ibus_init: Initializing the iBus engine"); + ibus_init(); + bus = ibus_bus_new(); + g_object_ref_sink(bus); + + if (!ibus_bus_is_connected(bus)) + { + LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: Connect to iBus failed"); + return 1; + } + + LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: iBus connected"); + + tc_thread_create(xrdp_input_main_loop, NULL); + + // session may not be ready, repeat until input method enabled + while (retry--) + { + if (ibus_bus_get_global_engine(bus)) + { + break; + } + + sleep(1); + } + + if (retry == 0) + { + LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to connect to ibus"); + return 1; + } + + return 1; +} \ No newline at end of file diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 845091ba8a..586416173a 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -16,7 +16,9 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/libxrdp \ -I$(top_srcdir)/third_party \ -I$(top_srcdir)/third_party/tomlc99 \ - $(IMLIB2_CFLAGS) + $(IMLIB2_CFLAGS) \ + $(GLIB2_CFLAGS) \ + $(IBUS_CFLAGS) XRDP_EXTRA_LIBS = @@ -76,6 +78,8 @@ xrdp_LDADD = \ $(top_builddir)/libxrdp/libxrdp.la \ $(top_builddir)/third_party/tomlc99/libtoml.la \ $(IMLIB2_LIBS) \ + $(GLIB2_LIBS) \ + $(IBUS_LIBS) \ $(XRDP_EXTRA_LIBS) xrdpsysconfdir=$(sysconfdir)/xrdp diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 77af46651b..50535439be 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -486,7 +486,7 @@ xrdp_mm_up_and_running(struct xrdp_mm *self); int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, int key_down, - char32_t unicode); + uint32_t unicode); struct xrdp_mm * xrdp_mm_create(struct xrdp_wm *owner); void diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index c49209a5e7..ff20e3c0dd 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -42,6 +42,8 @@ static int xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port); static void xrdp_mm_connect_sm(struct xrdp_mm *self); +static int +xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans); /*****************************************************************************/ struct xrdp_mm * @@ -146,6 +148,9 @@ xrdp_mm_delete(struct xrdp_mm *self) return; } + /* shutdown input method */ + xrdp_mm_send_unicode_shutdown(self, self->chan_trans); + /* free any module stuff */ xrdp_mm_module_cleanup(self); @@ -657,6 +662,45 @@ xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s) return rv; } + +/*****************************************************************************/ +static int +xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans) +{ + struct stream *s = trans_get_out_s(self->chan_trans, 8192); + if (s == NULL) + { + return 1; + } + + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8); /* size */ + out_uint32_le(s, 25); /* msg id */ + out_uint32_le(s, 8); /* size */ + s_mark_end(s); + + return trans_write_copy(self->chan_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) + { + return 1; + } + + 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); +} + /*****************************************************************************/ /* returns error process rail create window order */ @@ -2107,7 +2151,7 @@ xrdp_mm_up_and_running(struct xrdp_mm *self) int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, int key_down, - char32_t unicode) + uint32_t unicode) { struct stream *s = trans_get_out_s(self->chan_trans, 8192); if (s == NULL) @@ -2991,6 +3035,23 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port) "connect successful"); } + + /* 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; + } + } + return 0; } diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 0a1f6f3f6b..619e5f88d5 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1675,75 +1675,15 @@ xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags) return 0; } -/*****************************************************************************/ -/** - * 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) +xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, int unicode) { - 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), c32); - return 0; - } -#endif - int index; - + for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (c32 == self->keymap.keys_noshift[index].chr) + if (unicode == self->keymap.keys_noshift[index].chr) { xrdp_wm_key(self, device_flags, index - XR_MIN_KEY_CODE); return 0; @@ -1752,7 +1692,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char16_t c16) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (c32 == self->keymap.keys_shift[index].chr) + if (unicode == self->keymap.keys_shift[index].chr) { if (device_flags & KBD_FLAG_UP) { @@ -1770,7 +1710,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char16_t c16) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (c32 == self->keymap.keys_altgr[index].chr) + if (unicode == self->keymap.keys_altgr[index].chr) { if (device_flags & KBD_FLAG_UP) { @@ -1790,7 +1730,7 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char16_t c16) for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { - if (c32 == self->keymap.keys_shiftaltgr[index].chr) + if (unicode == self->keymap.keys_shiftaltgr[index].chr) { if (device_flags & KBD_FLAG_UP) { @@ -1809,6 +1749,11 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char16_t c16) } } +#ifdef XRDP_IBUS + // Forward unicode to chansrv to input method like iBus + xrdp_mm_send_unicode_to_chansrv(self->mm, !(device_flags & KBD_FLAG_UP), unicode); +#endif + return 0; } From 97138d5bad0fb1a22727b5738ecde96db924dc33 Mon Sep 17 00:00:00 2001 From: seflerZ Date: Tue, 16 Apr 2024 21:59:09 +0800 Subject: [PATCH 04/21] add missing code --- sesman/chansrv/chansrv.c | 43 ++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index f97de07cde..8a4692ef9c 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -40,6 +40,7 @@ #include "chansrv_config.h" #include "xrdp_sockets.h" #include "audin.h" +#include "input.h" #include "ms-rdpbcgr.h" @@ -823,14 +824,14 @@ chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes) return 0; } -/*****************************************************************************/ #ifdef XRDP_IBUS +/*****************************************************************************/ static int -process_message_unicode_key_press(struct stream *s) +process_message_unicode_data(struct stream *s) { int rv = 0; int key_down; - char32_t unicode_char; + uint32_t unicode; LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_unicode_keypress:"); if (!s_check_rem(s, 8)) @@ -840,12 +841,32 @@ process_message_unicode_key_press(struct stream *s) else { in_uint32_le(s, key_down); - in_uint32_le(s, unicode_char); - LOG(LOG_LEVEL_INFO, "Unicode char 0x%08x received down=%d", - unicode_char, key_down); + in_uint32_le(s, unicode); + + LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_unicode_keypress: received unicode %i", unicode); + + if (key_down) + { + xrdp_input_send_unicode(unicode); + } } + return rv; } + +/*****************************************************************************/ +static int +process_message_unicode_setup(struct stream *s) +{ + return xrdp_input_unicode_init(); +} + +/*****************************************************************************/ +static int +process_message_unicode_shutdown(struct stream *s) +{ + return xrdp_input_unicode_destory(); +} #endif // XRDP_IBUS /*****************************************************************************/ @@ -901,8 +922,14 @@ process_message(void) rv = process_message_drdynvc_data(s); break; #ifdef XRDP_IBUS - case 21: /* Unicode key press */ - rv = process_message_unicode_key_press(s); + case 21: /* unicode setup */ + rv = process_message_unicode_setup(s); + break; + case 23: /* unicode key event */ + rv = process_message_unicode_data(s); + break; + case 25: /* unicode shut down */ + rv = process_message_unicode_shutdown(s); break; #endif default: From a8c075e84eab3ffdc486caefd90cad4f156c99e7 Mon Sep 17 00:00:00 2001 From: seflerZ Date: Tue, 16 Apr 2024 23:19:06 +0800 Subject: [PATCH 05/21] refine makefile --- sesman/chansrv/Makefile.am | 10 +++------- xrdp/Makefile.am | 4 ---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 817f9aaeb4..7afc98c85e 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -10,9 +10,7 @@ AM_CPPFLAGS = \ -DXRDP_PID_PATH=\"${localstatedir}/run\" \ -DXRDP_SOCKET_ROOT_PATH=\"${socketdir}\" \ -I$(top_srcdir)/sesman/libsesman \ - -I$(top_srcdir)/common \ - $(IBUS_CFLAGS) \ - $(GLIB2_CFLAGS) + -I$(top_srcdir)/common CHANSRV_EXTRA_LIBS = @@ -41,8 +39,8 @@ AM_CPPFLAGS += -DXRDP_RDPSNDAUDIN endif if XRDP_IBUS -AM_CPPFLAGS += -DXRDP_IBUS $(IBUS_CFLAGS) -CHANSRV_EXTRA_LIBS += $(IBUS_LIBS) +AM_CPPFLAGS += -DXRDP_IBUS $(IBUS_CFLAGS) $(GLIB2_CFLAGS) +CHANSRV_EXTRA_LIBS += $(IBUS_LIBS) $(GLIB2_LIBS) endif AM_CFLAGS = $(X_CFLAGS) @@ -93,6 +91,4 @@ xrdp_chansrv_LDADD = \ $(top_builddir)/sesman/libsesman/libsesman.la \ $(top_builddir)/libipm/libipm.la \ $(X_PRE_LIBS) -lXfixes -lXrandr -lX11 $(X_EXTRA_LIBS) \ - $(GLIB2_LIBS) \ - $(IBUS_LIBS) \ $(CHANSRV_EXTRA_LIBS) diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 586416173a..cf38cece0d 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -16,8 +16,6 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/libxrdp \ -I$(top_srcdir)/third_party \ -I$(top_srcdir)/third_party/tomlc99 \ - $(IMLIB2_CFLAGS) \ - $(GLIB2_CFLAGS) \ $(IBUS_CFLAGS) XRDP_EXTRA_LIBS = @@ -78,8 +76,6 @@ xrdp_LDADD = \ $(top_builddir)/libxrdp/libxrdp.la \ $(top_builddir)/third_party/tomlc99/libtoml.la \ $(IMLIB2_LIBS) \ - $(GLIB2_LIBS) \ - $(IBUS_LIBS) \ $(XRDP_EXTRA_LIBS) xrdpsysconfdir=$(sysconfdir)/xrdp From bea72150fb690cc9cd1fb5cd38a15993a1690fcb Mon Sep 17 00:00:00 2001 From: seflerZ Date: Tue, 16 Apr 2024 23:19:40 +0800 Subject: [PATCH 06/21] change parameter types --- sesman/chansrv/input_ibus.c | 2 +- xrdp/xrdp.h | 7 +++---- xrdp/xrdp_mm.c | 7 +++---- xrdp/xrdp_wm.c | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index 1f10df1c7e..003cd58a30 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -222,7 +222,7 @@ xrdp_input_unicode_init() return 0; } - LOG(LOG_LEVEL_DEBUG, "xrdp_ibus_init: Initializing the iBus engine"); + LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: Initializing the iBus engine"); ibus_init(); bus = ibus_bus_new(); g_object_ref_sink(bus); diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 50535439be..91a262179c 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -483,10 +483,9 @@ xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress, int left, int top, int right, int bottom); int xrdp_mm_up_and_running(struct xrdp_mm *self); -int -xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, - int key_down, - uint32_t unicode); +int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, + int key_down, + char32_t unicode); struct xrdp_mm * xrdp_mm_create(struct xrdp_wm *owner); void diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index ff20e3c0dd..28a6e04179 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2148,10 +2148,9 @@ xrdp_mm_up_and_running(struct xrdp_mm *self) } /******************************************************************************/ -int -xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, - int key_down, - uint32_t unicode) +int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, + int key_down, + char32_t unicode) { struct stream *s = trans_get_out_s(self->chan_trans, 8192); if (s == NULL) diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 619e5f88d5..642e3fb63e 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1677,7 +1677,7 @@ 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, int unicode) +xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) { int index; From d4e2e0a093116e03489d8cc8cc84a04101293f8e Mon Sep 17 00:00:00 2001 From: seflerZ Date: Wed, 17 Apr 2024 12:02:20 +0800 Subject: [PATCH 07/21] It works now --- sesman/chansrv/input_ibus.c | 2 ++ xrdp/xrdp_mm.c | 7 ++-- xrdp/xrdp_wm.c | 71 ++++++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index 003cd58a30..b2b4deba67 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -222,6 +222,8 @@ xrdp_input_unicode_init() return 0; } + sleep(5); + LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: Initializing the iBus engine"); ibus_init(); bus = ibus_bus_new(); diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 28a6e04179..dd1916b60d 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2159,7 +2159,7 @@ int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 24); /* size */ - out_uint32_le(s, 21); /* msg id */ + out_uint32_le(s, 23); /* msg id */ out_uint32_le(s, 16); /* size */ out_uint32_le(s, key_down); out_uint32_le(s, unicode); @@ -3034,17 +3034,16 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port) "connect successful"); } - /* 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"); + "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"); + "xrdp_mm_send_unicode_setup"); /* disable unicode input */ // self->wm->client_info->unicode_input = 0; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 642e3fb63e..5954fbca00 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1675,15 +1675,65 @@ xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags) return 0; } +/*****************************************************************************/ +/** + * 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, char32_t unicode) +xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) { + char32_t c32 = get_unicode_character(self, device_flags, c16); + + if (c32 == 0) + { + return 0; + } + int index; - + 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; @@ -1692,7 +1742,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) { @@ -1710,7 +1760,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) { @@ -1730,7 +1780,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) { @@ -1750,8 +1800,13 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode) } #ifdef XRDP_IBUS - // Forward unicode to chansrv to input method like iBus - xrdp_mm_send_unicode_to_chansrv(self->mm, !(device_flags & KBD_FLAG_UP), unicode); + 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; From 3b1cc551e40ee9bdd079e6b40c885dd69e6f3e05 Mon Sep 17 00:00:00 2001 From: seflerZ Date: Wed, 17 Apr 2024 13:56:52 +0800 Subject: [PATCH 08/21] format code --- sesman/chansrv/chansrv.c | 5 ++- sesman/chansrv/input_ibus.c | 76 ++++++++++++++++--------------------- xrdp/xrdp_mm.c | 64 +++++++++++++++++-------------- xrdp/xrdp_wm.c | 2 +- 4 files changed, 73 insertions(+), 74 deletions(-) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 8a4692ef9c..dc973d67f6 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -21,6 +21,10 @@ #include #endif +#ifdef XRDP_IBUS +#include "input.h" +#endif + #include "arch.h" #include "os_calls.h" #include "string_calls.h" @@ -40,7 +44,6 @@ #include "chansrv_config.h" #include "xrdp_sockets.h" #include "audin.h" -#include "input.h" #include "ms-rdpbcgr.h" diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index b2b4deba67..5de3b81f78 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -30,7 +30,7 @@ static IBusBus *bus; static IBusEngine *g_engine; -// This is the engine name enabled before unicode engine enabled +/* This is the engine name enabled before unicode engine enabled */ static const gchar *ori_name; static int id = 0; @@ -42,10 +42,10 @@ xrdp_input_enable() if (ori_name) { - // already enabled + /* already enabled */ return 0; } - + if (!bus) { LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: input method switched failed, ibus not connected"); @@ -58,8 +58,8 @@ xrdp_input_enable() { return 0; } - - // remember user's input method, will switch back when disconnect + + /* remember user's input method, will switch back when disconnect */ ori_name = name; if (!ibus_bus_set_global_engine(bus, "XrdpIme")) @@ -69,7 +69,7 @@ xrdp_input_enable() } LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: input method switched sucessfully, old input name: %s", ori_name); - + return 0; } @@ -89,20 +89,20 @@ xrdp_input_send_unicode(uint32_t unicode) return 0; } -void +void xrdp_input_ibus_engine_enable(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_enable: IM enabled"); g_engine = engine; } -void +void xrdp_input_ibus_engine_disable(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); } -void +void xrdp_input_ibus_disconnect(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); @@ -115,14 +115,14 @@ gboolean engine_process_key_event_cb(IBusEngine *engine, guint keycode, guint state) { - // Pass the keyboard event to system + /* Pass the keyboard event to system */ return FALSE; } IBusEngine * xrdp_input_ibus_create_engine(IBusFactory *factory, - gchar *engine_name, - gpointer user_data) + gchar *engine_name, + gpointer user_data) { IBusEngine *engine; gchar *path = g_strdup_printf("/org/freedesktop/IBus/Engine/%i", 1); @@ -160,23 +160,23 @@ xrdp_input_main_loop() ibus_factory_add_engine(factory, "XrdpIme", IBUS_TYPE_ENGINE); - component = ibus_component_new("org.freedesktop.IBus.XrdpIme", // name - "Xrdp input method", // description - "1.1", // version - "MIT", // license - "seflerZ", // author - "fake_page", // homepage - "/exec/fake_path", // cmd - "xrdpime"); // text domain + component = ibus_component_new("org.freedesktop.IBus.XrdpIme", /* name */ + "Xrdp input method", /* description */ + "1.1", /* version */ + "MIT", /* license */ + "seflerZ", /* author */ + "default", /* homepage */ + "default", /* cmd */ + "xrdpime"); /* text domain */ desc = ibus_engine_desc_new("XrdpIme", - "unicode input method for xrdp", - "unicode input method for xrdp", - "unicode", - "MIT", - "seflerZ", - "fake_icon.png", - "default"); // layout + "unicode input method for xrdp", + "unicode input method for xrdp", + "unicode", + "MIT", + "seflerZ", + "default", /* icon */ + "default"); /* layout */ ibus_component_add_engine(component, desc); ibus_bus_register_component(bus, component); @@ -213,16 +213,15 @@ xrdp_input_unicode_destory() int xrdp_input_unicode_init() { - int retry = 10; - if (bus) { - // Already initialized, just re-enable it + /* Already initialized, just re-enable it */ xrdp_input_enable(); return 0; } - sleep(5); + /* Wait becasue ibus daemon may not be ready in first login. Do we have a flag to avoid busy waiting? */ + sleep(3); LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: Initializing the iBus engine"); ibus_init(); @@ -239,20 +238,9 @@ xrdp_input_unicode_init() tc_thread_create(xrdp_input_main_loop, NULL); - // session may not be ready, repeat until input method enabled - while (retry--) - { - if (ibus_bus_get_global_engine(bus)) - { - break; - } - - sleep(1); - } - - if (retry == 0) + if (!ibus_bus_get_global_engine(bus)) { - LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to connect to ibus"); + LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to get origin global engine"); return 1; } diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index dd1916b60d..cd0e8eab8c 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -42,8 +42,11 @@ static int 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 * @@ -148,8 +151,10 @@ 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); @@ -662,7 +667,7 @@ 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) @@ -673,12 +678,12 @@ xrdp_mm_send_unicode_shutdown(struct xrdp_mm *self, struct trans *trans) return 1; } - out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 25); /* msg id */ - out_uint32_le(s, 8); /* size */ + out_uint32_le(s, 25); /* msg id */ + out_uint32_le(s, 8); /* size */ s_mark_end(s); - + return trans_write_copy(self->chan_trans); } @@ -697,10 +702,31 @@ xrdp_mm_send_unicode_setup(struct xrdp_mm *self, struct trans *trans) out_uint32_le(s, 21); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - + return trans_write_copy(self->chan_trans); } +/******************************************************************************/ +int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, + int key_down, + char32_t unicode) +{ + struct stream *s = trans_get_out_s(self->chan_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 24); /* size */ + out_uint32_le(s, 23); /* msg id */ + out_uint32_le(s, 16); /* size */ + out_uint32_le(s, key_down); + out_uint32_le(s, unicode); + s_mark_end(s); + return trans_write_copy(self->chan_trans); +} +#endif + /*****************************************************************************/ /* returns error process rail create window order */ @@ -2147,26 +2173,6 @@ xrdp_mm_up_and_running(struct xrdp_mm *self) return 0; } -/******************************************************************************/ -int xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self, - int key_down, - char32_t unicode) -{ - struct stream *s = trans_get_out_s(self->chan_trans, 8192); - if (s == NULL) - { - return 1; - } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 24); /* size */ - out_uint32_le(s, 23); /* msg id */ - out_uint32_le(s, 16); /* size */ - out_uint32_le(s, key_down); - out_uint32_le(s, unicode); - s_mark_end(s); - return trans_write_copy(self->chan_trans); -} - /*****************************************************************************/ /* open response from client going to channel server */ static int @@ -3034,21 +3040,23 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port) "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"); + "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"); + "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 5954fbca00..eebe0da433 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1801,7 +1801,7 @@ 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) + self->mm->chan_trans->status == TRANS_STATUS_UP) { xrdp_mm_send_unicode_to_chansrv(self->mm, !(device_flags & KBD_FLAG_UP), c32); From bcd690f0377c5b5afef97c0487f7923be42b12fd Mon Sep 17 00:00:00 2001 From: seflerZ Date: Wed, 17 Apr 2024 18:44:51 +0800 Subject: [PATCH 09/21] code refactored --- sesman/chansrv/chansrv.c | 4 ++-- sesman/chansrv/input_ibus.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index dc973d67f6..a99e18f8eb 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -834,7 +834,7 @@ process_message_unicode_data(struct stream *s) { int rv = 0; int key_down; - uint32_t unicode; + char32_t unicode; LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_unicode_keypress:"); if (!s_check_rem(s, 8)) @@ -870,7 +870,7 @@ process_message_unicode_shutdown(struct stream *s) { return xrdp_input_unicode_destory(); } -#endif // XRDP_IBUS +#endif /*****************************************************************************/ /* returns error */ diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index 5de3b81f78..cffe0667c2 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -31,7 +31,7 @@ static IBusBus *bus; static IBusEngine *g_engine; /* This is the engine name enabled before unicode engine enabled */ -static const gchar *ori_name; +static const gchar *last_input_name; static int id = 0; int @@ -40,7 +40,7 @@ xrdp_input_enable() IBusEngineDesc *desc; const gchar *name; - if (ori_name) + if (last_input_name) { /* already enabled */ return 0; @@ -60,7 +60,7 @@ xrdp_input_enable() } /* remember user's input method, will switch back when disconnect */ - ori_name = name; + last_input_name = name; if (!ibus_bus_set_global_engine(bus, "XrdpIme")) { @@ -68,13 +68,13 @@ xrdp_input_enable() return 1; } - LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: input method switched sucessfully, old input name: %s", ori_name); + LOG(LOG_LEVEL_INFO, "xrdp_ibus_init: input method switched sucessfully, old input name: %s", last_input_name); return 0; } int -xrdp_input_send_unicode(uint32_t unicode) +xrdp_input_send_unicode(char32_t unicode) { LOG(LOG_LEVEL_DEBUG, "xrdp_input_send_unicode: received unicode input %i", unicode); @@ -194,16 +194,16 @@ int xrdp_input_unicode_destory() { LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory"); - if (ori_name) + if (last_input_name) { - LOG(LOG_LEVEL_INFO, "xrdp_input_unicode_destory: ibus engine rolling back to origin: %s", ori_name); - ibus_bus_set_global_engine(bus, ori_name); + LOG(LOG_LEVEL_INFO, "xrdp_input_unicode_destory: ibus engine rolling back to origin: %s", last_input_name); + ibus_bus_set_global_engine(bus, last_input_name); } g_object_unref(g_engine); g_object_unref(bus); - ori_name = NULL; + last_input_name = NULL; bus = NULL; g_engine = NULL; From 8c98ed4a5885d6ce69687ec7465f7dcb2d05c97c Mon Sep 17 00:00:00 2001 From: seflerZ Date: Wed, 17 Apr 2024 22:16:28 +0800 Subject: [PATCH 10/21] add conditional compilation annotations --- sesman/chansrv/input.h | 3 +++ sesman/chansrv/input_ibus.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sesman/chansrv/input.h b/sesman/chansrv/input.h index 1062d88695..dd18502a30 100644 --- a/sesman/chansrv/input.h +++ b/sesman/chansrv/input.h @@ -16,6 +16,7 @@ * limitations under the License. * */ +#ifdef XRDP_IBUS #if !defined(INPUT_H) #define INPUT_H @@ -32,4 +33,6 @@ xrdp_input_unicode_init(); int xrdp_input_unicode_destory(); +#endif + #endif \ No newline at end of file diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index cffe0667c2..44dc4a7064 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -17,6 +17,8 @@ * limitations under the License. */ +#ifdef XRDP_IBUS + #if defined(HAVE_CONFIG_H) #include #endif @@ -245,4 +247,6 @@ xrdp_input_unicode_init() } return 1; -} \ No newline at end of file +} + +#endif \ No newline at end of file From b623766503c79a4226d28f900d5b51513658ea46 Mon Sep 17 00:00:00 2001 From: seflerZ Date: Sat, 20 Apr 2024 13:37:08 +0800 Subject: [PATCH 11/21] remote uncessary conditional compilation --- sesman/chansrv/input.h | 4 ---- sesman/chansrv/input_ibus.c | 7 +------ 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/sesman/chansrv/input.h b/sesman/chansrv/input.h index dd18502a30..1bfcaed094 100644 --- a/sesman/chansrv/input.h +++ b/sesman/chansrv/input.h @@ -16,8 +16,6 @@ * limitations under the License. * */ -#ifdef XRDP_IBUS - #if !defined(INPUT_H) #define INPUT_H @@ -33,6 +31,4 @@ xrdp_input_unicode_init(); int xrdp_input_unicode_destory(); -#endif - #endif \ No newline at end of file diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index 44dc4a7064..f531e162d2 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -16,9 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifdef XRDP_IBUS - #if defined(HAVE_CONFIG_H) #include #endif @@ -247,6 +244,4 @@ xrdp_input_unicode_init() } return 1; -} - -#endif \ No newline at end of file +} \ No newline at end of file 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 12/21] 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 0516f63c01..aa76f09867 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 7570968a0b..9ecf2486f1 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 7afc98c85e..4b0154fac1 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 a99e18f8eb..8f0a2c1500 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 cf38cece0d..b771ff8c4b 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 cd0e8eab8c..6910efbd05 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); - 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); + } + } - 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 eebe0da433..9f6e7d1892 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; } From 430e980c9c9e0840fabe62f7f700c828c94e4822 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:43:02 +0100 Subject: [PATCH 13/21] Add --enable-ibus to github CI --- .github/workflows/build.yml | 14 +++++++------- .../install_xrdp_build_dependencies_with_apt.sh | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd83c838ed..ee9422abf6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,14 +111,14 @@ jobs: CONF_FLAGS_amd64_min: "--disable-ipv6 --disable-jpeg --disable-fuse --disable-mp3lame --disable-fdkaac --disable-opus --disable-rfxcodec --disable-painter --disable-pixman --disable-utmp" - CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame - --enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter - --enable-pixman --enable-utmp + CONF_FLAGS_amd64_max: "--enable-ibus --enable-ipv6 --enable-jpeg --enable-fuse + --enable-mp3lame --enable-fdkaac --enable-opus --enable-rfxcodec + --enable-painter --enable-pixman --enable-utmp --with-imlib2 --with-freetype2 --enable-tests" - CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-mp3lame - --enable-opus --enable-rfxcodec --enable-painter - --disable-pixman --with-imlib2 --with-freetype2 - --host=i686-linux --enable-tests" + CONF_FLAGS_i386_max: "--enable-ibus --enable-ipv6 --enable-jpeg + --enable-mp3lame --enable-opus --enable-rfxcodec + --enable-painter --disable-pixman --with-imlib2 + --with-freetype2 --host=i686-linux --enable-tests" PKG_CONFIG_PATH_i386: "/usr/lib/i386-linux-gnu/pkgconfig" CFLAGS_i386: "-m32" diff --git a/scripts/install_xrdp_build_dependencies_with_apt.sh b/scripts/install_xrdp_build_dependencies_with_apt.sh index dec91a65f4..ff1a081a80 100755 --- a/scripts/install_xrdp_build_dependencies_with_apt.sh +++ b/scripts/install_xrdp_build_dependencies_with_apt.sh @@ -93,6 +93,7 @@ in libjpeg-dev \ libmp3lame-dev \ libfdk-aac-dev \ + libibus-1.0-dev \ libimlib2-dev \ libopus-dev \ libpixman-1-dev" @@ -118,6 +119,7 @@ in $LIBFREETYPE_DEV:i386 \ libgl1-mesa-dev:i386 \ libglu1-mesa-dev:i386 \ + libibus-1.0-dev:i386 \ libjpeg-dev:i386 \ libimlib2-dev:i386 \ libmp3lame-dev:i386 \ From 7ae69a663e07f882354f9c274555b5a96612089a Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:19:25 +0100 Subject: [PATCH 14/21] Add --enable-ibus to FreeBSD CI --- .cirrus.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index f650248a8c..624d50f256 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,11 +6,11 @@ FreeBSD_task: freebsd_instance: image_family: freebsd-13-2 prepare_script: - - pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check imlib2 freetype2 cmocka + - pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check imlib2 freetype2 cmocka ibus - git submodule update --init --recursive configure_script: - ./bootstrap - - env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse --with-imlib2 --with-freetype2 + - env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ibus --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse --with-imlib2 --with-freetype2 build_script: - make -j $(sysctl -n hw.ncpu || echo 4) check_script: From 1e78b420224c83e399c6f47c35c765a0f6fdbb69 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:19:50 +0100 Subject: [PATCH 15/21] Fix CI errors using C++ compiler --- sesman/chansrv/input.h | 4 ++-- sesman/chansrv/input_ibus.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sesman/chansrv/input.h b/sesman/chansrv/input.h index 1bfcaed094..a49a91a5d0 100644 --- a/sesman/chansrv/input.h +++ b/sesman/chansrv/input.h @@ -23,7 +23,7 @@ #include "parse.h" int -xrdp_input_send_unicode(uint32_t unicode); +xrdp_input_send_unicode(char32_t unicode); int xrdp_input_unicode_init(); @@ -31,4 +31,4 @@ xrdp_input_unicode_init(); int xrdp_input_unicode_destory(); -#endif \ No newline at end of file +#endif diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index f531e162d2..0f700f3d93 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -140,7 +140,7 @@ xrdp_input_ibus_create_engine(IBusFactory *factory, /*****************************************************************************/ THREAD_RV THREAD_CC -xrdp_input_main_loop() +xrdp_input_main_loop(void *in_val) { IBusFactory *factory; IBusComponent *component; @@ -244,4 +244,4 @@ xrdp_input_unicode_init() } return 1; -} \ No newline at end of file +} From 48644258e0cc663acc9f9e61279871205466d458 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:23:09 +0100 Subject: [PATCH 16/21] Addressed review comments --- xrdp/xrdp_mm.c | 8 +++++++- xrdp/xrdp_wm.c | 26 +++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 6910efbd05..ef1198d25c 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2492,10 +2492,16 @@ xrdp_mm_trans_process_unicode_ack(struct xrdp_mm *self, LOG(LOG_LEVEL_INFO, "Chansrv does not support Unicode input"); break; - default: + case 2: LOG(LOG_LEVEL_INFO, "Chansrv reported an error starting the Unicode input method"); break; + + default: + LOG(LOG_LEVEL_INFO, + "Chansrv reported an unknown status %d" + " starting the Unicode input method", status); + break; } return 0; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 9f6e7d1892..d6e2145e7b 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1730,19 +1730,8 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) return 0; } - // 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. + // See if we can find the character in the existing keymap, + // and if so, generate normal key event(s) for it for (index = XR_MIN_KEY_CODE; index < XR_MAX_KEY_CODE; index++) { if (c32 == self->keymap.keys_noshift[index].chr) @@ -1811,6 +1800,17 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) } } + // 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; + } + return 0; } From c42a09709e2051deb1311ec28a6a19d97e407bdc Mon Sep 17 00:00:00 2001 From: seflerZ Date: Wed, 1 May 2024 18:09:54 +0800 Subject: [PATCH 17/21] fix a bug in returning the init result. --- sesman/chansrv/input_ibus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index 0f700f3d93..d4cb1a4d12 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -243,5 +243,5 @@ xrdp_input_unicode_init() return 1; } - return 1; + return 0; } From 4599ac7bf6c136d820b046db5cc9b76905247d0e Mon Sep 17 00:00:00 2001 From: sefler Date: Sat, 4 May 2024 13:24:20 +0800 Subject: [PATCH 18/21] apply patch generated by matt --- sesman/chansrv/chansrv.c | 2 +- sesman/chansrv/input.h | 4 ++-- sesman/chansrv/input_ibus.c | 27 ++++++++++++++------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 8f0a2c1500..2cd8cf0ae7 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -899,7 +899,7 @@ process_message_unicode_setup(struct stream *s) static int process_message_unicode_shutdown(struct stream *s) { - return xrdp_input_unicode_destory(); + return xrdp_input_unicode_destroy(); } #endif diff --git a/sesman/chansrv/input.h b/sesman/chansrv/input.h index a49a91a5d0..37cefb06b2 100644 --- a/sesman/chansrv/input.h +++ b/sesman/chansrv/input.h @@ -26,9 +26,9 @@ int xrdp_input_send_unicode(char32_t unicode); int -xrdp_input_unicode_init(); +xrdp_input_unicode_init(void); int -xrdp_input_unicode_destory(); +xrdp_input_unicode_destroy(void); #endif diff --git a/sesman/chansrv/input_ibus.c b/sesman/chansrv/input_ibus.c index d4cb1a4d12..c247efed51 100644 --- a/sesman/chansrv/input_ibus.c +++ b/sesman/chansrv/input_ibus.c @@ -33,8 +33,8 @@ static IBusEngine *g_engine; static const gchar *last_input_name; static int id = 0; -int -xrdp_input_enable() +static int +xrdp_input_enable(void) { IBusEngineDesc *desc; const gchar *name; @@ -88,20 +88,20 @@ xrdp_input_send_unicode(char32_t unicode) return 0; } -void +static void xrdp_input_ibus_engine_enable(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_enable: IM enabled"); g_engine = engine; } -void +static void xrdp_input_ibus_engine_disable(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); } -void +static void xrdp_input_ibus_disconnect(IBusEngine *engine) { LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled"); @@ -109,16 +109,17 @@ xrdp_input_ibus_disconnect(IBusEngine *engine) g_object_unref(bus); } -gboolean engine_process_key_event_cb(IBusEngine *engine, - guint keyval, - guint keycode, - guint state) +static gboolean +engine_process_key_event_cb(IBusEngine *engine, + guint keyval, + guint keycode, + guint state) { /* Pass the keyboard event to system */ return FALSE; } -IBusEngine * +static IBusEngine * xrdp_input_ibus_create_engine(IBusFactory *factory, gchar *engine_name, gpointer user_data) @@ -139,7 +140,7 @@ xrdp_input_ibus_create_engine(IBusFactory *factory, } /*****************************************************************************/ -THREAD_RV THREAD_CC +static THREAD_RV THREAD_CC xrdp_input_main_loop(void *in_val) { IBusFactory *factory; @@ -190,7 +191,7 @@ xrdp_input_main_loop(void *in_val) } int -xrdp_input_unicode_destory() +xrdp_input_unicode_destroy(void) { LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory"); if (last_input_name) @@ -210,7 +211,7 @@ xrdp_input_unicode_destory() } int -xrdp_input_unicode_init() +xrdp_input_unicode_init(void) { if (bus) { From c53662e3c169700b729bbe3ce56c8afa10b32df6 Mon Sep 17 00:00:00 2001 From: seflerZ Date: Thu, 9 May 2024 11:25:08 +0800 Subject: [PATCH 19/21] apply xrdp_caps.c patach written by mattt --- libxrdp/xrdp_caps.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 9ecf2486f1..8837102907 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -424,16 +424,23 @@ xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, } // We always advertise Unicode support, so if the client supports it too, - // we can use it - if ((inputFlags & INPUT_FLAG_UNICODE) != 0) + // we can use it. + // + // If Unicode support is already active, the CAPSTYPE_INPUT + // PDU has been received as part of a Deactivation-Reactivation sequence. + // In this case, ignore the flag. + if (self->client_info.unicode_input_support != UIS_ACTIVE) { - 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"); + 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; From d512b0dbc096779add47f82e22a7ae4e22bbd1b2 Mon Sep 17 00:00:00 2001 From: sefler Date: Tue, 14 May 2024 23:58:57 +0800 Subject: [PATCH 20/21] add missing "break" statement --- xrdp/xrdp_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index ef1198d25c..ac24623126 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2561,7 +2561,7 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, break; case 20: rv = xrdp_mm_trans_process_unicode_ack(self, s); - + break; default: LOG(LOG_LEVEL_ERROR, "xrdp_mm_chan_process_msg: unknown id %d", id); break; From cad94531da6b21635ebd7ea0958c279c36397c9d Mon Sep 17 00:00:00 2001 From: sefler Date: Wed, 15 May 2024 00:05:17 +0800 Subject: [PATCH 21/21] fix tab --- xrdp/xrdp_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index ac24623126..156b465752 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2561,7 +2561,7 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, break; case 20: rv = xrdp_mm_trans_process_unicode_ack(self, s); - break; + break; default: LOG(LOG_LEVEL_ERROR, "xrdp_mm_chan_process_msg: unknown id %d", id); break;