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: 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/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 dcb754e22a..a5c92f8eaa 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/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 \ 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 7f81a9a3d0..dd59227300 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/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 +} diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 99548ac1f0..1060877552 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 0d2170811f..c9d6085b2d 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -42,10 +42,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 * @@ -150,10 +148,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); @@ -666,7 +662,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) @@ -690,19 +685,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; } /******************************************************************************/ @@ -724,7 +728,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 @@ -2464,6 +2467,45 @@ 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; + + 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; +} + /*****************************************************************************/ /* returns error process a message for the channel handler */ @@ -2516,6 +2558,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; @@ -3033,30 +3078,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 69f62f4b71..6b18d6fe93 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,8 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) return 0; } - int index; - + // 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) @@ -1799,15 +1800,16 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t c16) } } -#ifdef XRDP_IBUS + // 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; } -#endif return 0; }