From 7bea1f9d56bf477ec75e58adeea25f2b1376105d Mon Sep 17 00:00:00 2001 From: sefler Date: Tue, 16 Apr 2024 16:21:49 +0800 Subject: [PATCH] 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 a6ba833a..9633c500 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 9916ba00..817f9aae 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 00000000..1062d886 --- /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 00000000..1f10df1c --- /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 845091ba..58641617 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 77af4665..50535439 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 c49209a5..ff20e3c0 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 0a1f6f3f..619e5f88 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; }