Merge pull request #3058 from seflerZ/unicode_contr

Add ibus unicode input support
This commit is contained in:
matt335672
2024-05-20 12:27:52 +01:00
committed by GitHub
15 changed files with 646 additions and 16 deletions
+2 -2
View File
@@ -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:
+7 -7
View File
@@ -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:
+11
View File
@@ -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
+16
View File
@@ -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"
+21
View File
@@ -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 \
+9
View File
@@ -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)
+99
View File
@@ -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;
+34
View File
@@ -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
+248
View File
@@ -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
View File
@@ -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 =
+3
View File
@@ -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
View File
@@ -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 "
+3
View File
@@ -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
View File
@@ -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;
}