Merge pull request #3058 from seflerZ/unicode_contr
Add ibus unicode input support
This commit is contained in:
+2
-2
@@ -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:
|
||||
|
||||
@@ -129,14 +129,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"
|
||||
steps:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,17 @@ 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])])
|
||||
|
||||
# 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)] )
|
||||
|
||||
# checking for TurboJPEG
|
||||
@@ -646,6 +661,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"
|
||||
|
||||
@@ -422,6 +422,27 @@ 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 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -73,9 +73,18 @@ xrdp_chansrv_SOURCES = \
|
||||
sound.h \
|
||||
xcommon.c \
|
||||
xcommon.h \
|
||||
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)
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#ifdef XRDP_IBUS
|
||||
#include "input.h"
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
@@ -717,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
|
||||
@@ -823,6 +847,62 @@ chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef XRDP_IBUS
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
process_message_unicode_data(struct stream *s)
|
||||
{
|
||||
int rv = 0;
|
||||
int key_down;
|
||||
char32_t unicode;
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
process_message_unicode_shutdown(struct stream *s)
|
||||
{
|
||||
return xrdp_input_unicode_destroy();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int
|
||||
@@ -875,6 +955,25 @@ process_message(void)
|
||||
case 19: /* drdynvc data */
|
||||
rv = process_message_drdynvc_data(s);
|
||||
break;
|
||||
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);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_message: unknown msg %d", id);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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(char32_t unicode);
|
||||
|
||||
int
|
||||
xrdp_input_unicode_init(void);
|
||||
|
||||
int
|
||||
xrdp_input_unicode_destroy(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* 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 <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <ibus.h>
|
||||
#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 *last_input_name;
|
||||
static int id = 0;
|
||||
|
||||
static int
|
||||
xrdp_input_enable(void)
|
||||
{
|
||||
IBusEngineDesc *desc;
|
||||
const gchar *name;
|
||||
|
||||
if (last_input_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 */
|
||||
last_input_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", last_input_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xrdp_input_send_unicode(char32_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;
|
||||
}
|
||||
|
||||
static void
|
||||
xrdp_input_ibus_engine_enable(IBusEngine *engine)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_enable: IM enabled");
|
||||
g_engine = engine;
|
||||
}
|
||||
|
||||
static void
|
||||
xrdp_input_ibus_engine_disable(IBusEngine *engine)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled");
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
engine_process_key_event_cb(IBusEngine *engine,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state)
|
||||
{
|
||||
/* Pass the keyboard event to system */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static THREAD_RV THREAD_CC
|
||||
xrdp_input_main_loop(void *in_val)
|
||||
{
|
||||
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 */
|
||||
"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",
|
||||
"default", /* icon */
|
||||
"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_destroy(void)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory");
|
||||
if (last_input_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);
|
||||
|
||||
last_input_name = NULL;
|
||||
bus = NULL;
|
||||
g_engine = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xrdp_input_unicode_init(void)
|
||||
{
|
||||
if (bus)
|
||||
{
|
||||
/* Already initialized, just re-enable it */
|
||||
xrdp_input_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
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);
|
||||
|
||||
if (!ibus_bus_get_global_engine(bus))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to get origin global engine");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-2
@@ -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 \
|
||||
$(IMLIB2_CFLAGS)
|
||||
-I$(top_srcdir)/third_party/tomlc99
|
||||
|
||||
XRDP_EXTRA_LIBS =
|
||||
|
||||
|
||||
@@ -483,6 +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,
|
||||
char32_t unicode);
|
||||
struct xrdp_mm *
|
||||
xrdp_mm_create(struct xrdp_wm *owner);
|
||||
void
|
||||
|
||||
+122
@@ -43,6 +43,9 @@ 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 *
|
||||
xrdp_mm_create(struct xrdp_wm *owner)
|
||||
@@ -146,6 +149,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 +663,73 @@ 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)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (self->wm->client_info->unicode_input_support == UIS_SUPPORTED)
|
||||
{
|
||||
struct stream *s = trans_get_out_s(self->chan_trans, 8192);
|
||||
if (s == NULL)
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 8 + 8); /* size */
|
||||
out_uint32_le(s, 21); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
|
||||
rv = trans_write_copy(self->chan_trans);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error
|
||||
process rail create window order */
|
||||
@@ -2395,6 +2468,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 */
|
||||
@@ -2447,6 +2559,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);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_mm_chan_process_msg: unknown id %d", id);
|
||||
break;
|
||||
@@ -2964,6 +3079,13 @@ 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 "
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+68
-5
@@ -28,6 +28,7 @@
|
||||
#include "ms-rdpbcgr.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "unicode_defines.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
@@ -1674,15 +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, char32_t c16)
|
||||
{
|
||||
int index;
|
||||
char32_t c32 = get_unicode_character(self, device_flags, c16);
|
||||
|
||||
if (c32 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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 (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;
|
||||
@@ -1691,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_shift[index].chr)
|
||||
if (c32 == self->keymap.keys_shift[index].chr)
|
||||
{
|
||||
if (device_flags & KBD_FLAG_UP)
|
||||
{
|
||||
@@ -1709,7 +1761,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)
|
||||
{
|
||||
@@ -1729,7 +1781,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)
|
||||
{
|
||||
@@ -1748,6 +1800,17 @@ xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode)
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user