forked from enlightenment/efl
[ecore-immodule] add ibus immodule. It support more than ibus-1.3.99 version.
SVN revision: 71927
This commit is contained in:
parent
59b2545ded
commit
7d7697f102
|
@ -179,6 +179,7 @@ want_ecore_evas_wayland_egl="no"
|
|||
# ecore_imf modules
|
||||
want_ecore_imf_xim="no"
|
||||
want_ecore_imf_scim="no"
|
||||
want_ecore_imf_ibus="no"
|
||||
|
||||
case "$host_os" in
|
||||
mingw32ce*)
|
||||
|
@ -243,6 +244,7 @@ case "$host_os" in
|
|||
want_ecore_evas_wayland_egl="yes"
|
||||
want_ecore_imf_xim="yes"
|
||||
want_ecore_imf_scim="yes"
|
||||
want_ecore_imf_ibus="yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -271,6 +273,7 @@ requirements_ecore_win32=""
|
|||
requirements_ecore_wince=""
|
||||
requirements_ecore_imf_xim=""
|
||||
requirements_ecore_imf_scim=""
|
||||
requirements_ecore_imf_ibus=""
|
||||
requirements_ecore_wayland=""
|
||||
|
||||
### Additional options to configure
|
||||
|
@ -1626,6 +1629,23 @@ fi
|
|||
ECORE_CHECK_MODULE([imf-scim], [${want_ecore_imf}], [Imf_SCIM], [${ecore_imf_scim_deps}],
|
||||
[requirements_ecore_imf_scim="ecore-imf >= 1.2.0 ecore-x >= 1.2.0 ecore-input >= 1.2.0 ${requirements_ecore_imf_scim}"])
|
||||
|
||||
# ecore_imf_ibus
|
||||
PKG_CHECK_MODULES([IBUS], [ibus-1.0 >= 1.3.99], [have_ibus="yes"], [have_ibus="no"])
|
||||
|
||||
AM_CONDITIONAL(BUILD_ECORE_IMF_IBUS, false)
|
||||
ecore_imf_ibus_deps="no"
|
||||
echo "have_ecore_x_xlib: ${have_ecore_x_xlib}"
|
||||
if test "x${have_ecore_imf}" = "xyes" \
|
||||
-a "x${have_glib}" = "xyes" \
|
||||
-a "x${have_ibus}" = "xyes" \
|
||||
-a "x${have_ecore_input}" = "xyes" ; then
|
||||
ecore_imf_ibus_deps="yes"
|
||||
AC_DEFINE(BUILD_ECORE_IMF_IBUS, 1, [Ecore Imf IBUS Support])
|
||||
fi
|
||||
|
||||
ECORE_CHECK_MODULE([imf-ibus], [${want_ecore_imf}], [Imf_IBUS], [${ecore_imf_ibus_deps}],
|
||||
[requirements_ecore_imf_ibus="ecore-imf >= 1.2.0 ecore-x >= 1.2.0 ecore-input >= 1.2.0 ${requirements_ecore_imf_ibus}"])
|
||||
|
||||
## Graphic systems
|
||||
|
||||
# ecore_x{cb}
|
||||
|
@ -1982,6 +2002,7 @@ AC_SUBST(requirements_ecore_win32)
|
|||
AC_SUBST(requirements_ecore_wince)
|
||||
AC_SUBST(requirements_ecore_imf_xim)
|
||||
AC_SUBST(requirements_ecore_imf_scim)
|
||||
AC_SUBST(requirements_ecore_imf_ibus)
|
||||
AC_SUBST(requirements_ecore_wayland)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
|
@ -2039,6 +2060,7 @@ src/modules/Makefile
|
|||
src/modules/immodules/Makefile
|
||||
src/modules/immodules/xim/Makefile
|
||||
src/modules/immodules/scim/Makefile
|
||||
src/modules/immodules/ibus/Makefile
|
||||
ecore.spec
|
||||
$po_makefile_in
|
||||
])
|
||||
|
@ -2104,6 +2126,7 @@ fi
|
|||
echo " Ecore_IMF....................: $have_ecore_imf"
|
||||
echo " XIM........................: $have_ecore_imf_xim"
|
||||
echo " SCIM.......................: $have_ecore_imf_scim"
|
||||
echo " IBUS.......................: $have_ecore_imf_ibus"
|
||||
echo " Ecore_IMF_Evas...............: $have_ecore_imf_evas"
|
||||
echo " Ecore_Input..................: $have_ecore_input"
|
||||
echo " Ecore_Input_Evas.............: $have_ecore_input_evas"
|
||||
|
|
|
@ -9,3 +9,7 @@ endif
|
|||
if BUILD_ECORE_IMF_SCIM
|
||||
SUBDIRS += scim
|
||||
endif
|
||||
|
||||
if BUILD_ECORE_IMF_IBUS
|
||||
SUBDIRS += ibus
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/src/lib/ecore \
|
||||
-I$(top_srcdir)/src/lib/ecore_input \
|
||||
-I$(top_srcdir)/src/lib/ecore_x \
|
||||
-I$(top_srcdir)/src/lib/ecore_imf \
|
||||
-I$(top_srcdir)/src/lib/ecore_evas \
|
||||
-I$(top_builddir)/src/lib/ecore \
|
||||
-I$(top_builddir)/src/lib/ecore_input \
|
||||
-I$(top_builddir)/src/lib/ecore_x \
|
||||
-I$(top_builddir)/src/lib/ecore_imf \
|
||||
-I$(top_builddir)/src/lib/ecore_evas \
|
||||
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
|
||||
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
|
||||
@IBUS_CFLAGS@ \
|
||||
@EVAS_CFLAGS@ \
|
||||
@EINA_CFLAGS@
|
||||
|
||||
pkgdir = $(libdir)/ecore/immodules
|
||||
|
||||
pkg_LTLIBRARIES = ibus.la
|
||||
ibus_la_SOURCES = \
|
||||
ibus_module.c \
|
||||
ibus_imcontext.c \
|
||||
ibus_imcontext.h
|
||||
|
||||
ibus_la_LIBADD = \
|
||||
$(top_builddir)/src/lib/ecore_imf/libecore_imf.la \
|
||||
$(top_builddir)/src/lib/ecore_x/libecore_x.la \
|
||||
@IBUS_LIBS@ \
|
||||
@EVAS_LIBS@ \
|
||||
@EINA_LIBS@
|
||||
ibus_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
|
||||
ibus_la_LIBTOOLFLAGS = --tag=disable-static
|
|
@ -0,0 +1,719 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <Ecore_X.h>
|
||||
#include <Ecore_Evas.h>
|
||||
|
||||
#include <ibus.h>
|
||||
#include "ibus_imcontext.h"
|
||||
|
||||
#if (ENABLE_DEBUG)
|
||||
#define IDEBUG(x, a...) fprintf (stderr, __FILE__ ",%d,%s: " x "\n", __LINE__, __func__, ##a)
|
||||
#else
|
||||
#define IDEBUG(x, a...) do {} while (0)
|
||||
#endif
|
||||
|
||||
struct _IBusIMContext {
|
||||
/* instance members */
|
||||
Ecore_IMF_Context *ctx;
|
||||
|
||||
/* enabled */
|
||||
Eina_Bool enable;
|
||||
IBusInputContext *ibuscontext;
|
||||
|
||||
/* preedit status */
|
||||
char *preedit_string;
|
||||
Eina_List *preedit_attrs;
|
||||
int preedit_cursor_pos;
|
||||
Eina_Bool preedit_visible;
|
||||
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int cursor_w;
|
||||
int cursor_h;
|
||||
|
||||
Eina_Bool has_focus;
|
||||
|
||||
Ecore_X_Window client_window;
|
||||
Evas *client_canvas;
|
||||
|
||||
int caps;
|
||||
};
|
||||
|
||||
static Ecore_IMF_Context *_focus_im_context = NULL;
|
||||
static IBusBus *_bus = NULL;
|
||||
|
||||
/* functions prototype */
|
||||
/* static methods*/
|
||||
static void _create_input_context (IBusIMContext *context);
|
||||
static void _set_cursor_location_internal
|
||||
(Ecore_IMF_Context *ctx);
|
||||
static void _bus_connected_cb (IBusBus *bus,
|
||||
IBusIMContext *context);
|
||||
|
||||
|
||||
static void
|
||||
_window_to_screen_geometry_get(Ecore_X_Window client_win, int *x, int *y)
|
||||
{
|
||||
Ecore_X_Window root_window, win;
|
||||
int win_x, win_y;
|
||||
int sum_x = 0, sum_y = 0;
|
||||
|
||||
root_window = ecore_x_window_root_get(client_win);
|
||||
win = client_win;
|
||||
|
||||
while (root_window != win)
|
||||
{
|
||||
ecore_x_window_geometry_get(win, &win_x, &win_y, NULL, NULL);
|
||||
sum_x += win_x;
|
||||
sum_y += win_y;
|
||||
win = ecore_x_window_parent_get(win);
|
||||
}
|
||||
|
||||
if (x)
|
||||
*x = sum_x;
|
||||
if (y)
|
||||
*y = sum_y;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_ecore_imf_modifier_to_ibus_modifier(unsigned int modifier)
|
||||
{
|
||||
unsigned int state = 0;
|
||||
|
||||
/**< "Control" is pressed */
|
||||
if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
|
||||
state |= IBUS_CONTROL_MASK;
|
||||
|
||||
/**< "Alt" is pressed */
|
||||
if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
|
||||
state |= IBUS_MOD1_MASK;
|
||||
|
||||
/**< "Shift" is pressed */
|
||||
if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
|
||||
state |= IBUS_SHIFT_MASK;
|
||||
|
||||
/**< "Win" (between "Ctrl" and "A */
|
||||
if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
|
||||
state |= IBUS_SUPER_MASK;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
IBusIMContext *
|
||||
ibus_im_context_new(void)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *context = calloc(1, sizeof(IBusIMContext));
|
||||
|
||||
/* init bus object */
|
||||
if (_bus == NULL)
|
||||
{
|
||||
char *display_name = NULL;
|
||||
|
||||
if ((display_name = getenv ("DISPLAY")))
|
||||
ibus_set_display (display_name);
|
||||
else
|
||||
ibus_set_display (":0.0");
|
||||
|
||||
_bus = ibus_bus_new();
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_add(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
ibusimcontext->client_window = 0;
|
||||
|
||||
// Init ibus status
|
||||
ibusimcontext->enable = EINA_FALSE;
|
||||
|
||||
// Init preedit status
|
||||
ibusimcontext->preedit_string = NULL;
|
||||
ibusimcontext->preedit_attrs = NULL;
|
||||
ibusimcontext->preedit_cursor_pos = 0;
|
||||
ibusimcontext->preedit_visible = EINA_FALSE;
|
||||
|
||||
// Init cursor area
|
||||
ibusimcontext->cursor_x = -1;
|
||||
ibusimcontext->cursor_y = -1;
|
||||
ibusimcontext->cursor_w = 0;
|
||||
ibusimcontext->cursor_h = 0;
|
||||
|
||||
ibusimcontext->ibuscontext = NULL;
|
||||
ibusimcontext->has_focus = EINA_FALSE;
|
||||
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
|
||||
ibusimcontext->ctx = ctx;
|
||||
|
||||
if (ibus_bus_is_connected(_bus))
|
||||
_create_input_context (ibusimcontext);
|
||||
|
||||
g_signal_connect(_bus, "connected", G_CALLBACK (_bus_connected_cb), ctx);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_del(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
g_signal_handlers_disconnect_by_func(_bus, G_CALLBACK(_bus_connected_cb), ctx);
|
||||
|
||||
if (ibusimcontext->ibuscontext)
|
||||
ibus_proxy_destroy((IBusProxy *)ibusimcontext->ibuscontext);
|
||||
|
||||
// release preedit
|
||||
if (ibusimcontext->preedit_string)
|
||||
free(ibusimcontext->preedit_string);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ibus_im_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
|
||||
{
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (type != ECORE_IMF_EVENT_KEY_UP && type != ECORE_IMF_EVENT_KEY_DOWN)
|
||||
return EINA_FALSE;
|
||||
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
if (G_LIKELY(ibusimcontext->ibuscontext && ibusimcontext->has_focus))
|
||||
{
|
||||
/* If context does not have focus, ibus will process key event in sync mode.
|
||||
* It is a workaround for increase search in treeview.
|
||||
*/
|
||||
Eina_Bool retval = EINA_FALSE;
|
||||
int keycode;
|
||||
int keysym;
|
||||
unsigned int state = 0;
|
||||
|
||||
if (type == ECORE_IMF_EVENT_KEY_UP)
|
||||
{
|
||||
Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
|
||||
if (ev->timestamp == 0)
|
||||
return EINA_FALSE;
|
||||
|
||||
keycode = ecore_x_keysym_keycode_get(ev->key);
|
||||
keysym = XStringToKeysym(ev->key);
|
||||
state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers) | IBUS_RELEASE_MASK;
|
||||
retval = ibus_input_context_process_key_event (ibusimcontext->ibuscontext,
|
||||
keysym,
|
||||
keycode - 8,
|
||||
state);
|
||||
}
|
||||
else if (type == ECORE_IMF_EVENT_KEY_DOWN)
|
||||
{
|
||||
Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
|
||||
if (ev->timestamp == 0)
|
||||
return EINA_FALSE;
|
||||
|
||||
keycode = ecore_x_keysym_keycode_get(ev->key);
|
||||
keysym = XStringToKeysym(ev->key);
|
||||
state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers);
|
||||
retval = ibus_input_context_process_key_event (ibusimcontext->ibuscontext,
|
||||
keysym,
|
||||
keycode - 8,
|
||||
state);
|
||||
}
|
||||
else
|
||||
retval = EINA_FALSE;
|
||||
|
||||
if (retval)
|
||||
return EINA_TRUE;
|
||||
else
|
||||
return EINA_FALSE;
|
||||
}
|
||||
else
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_focus_in(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->has_focus)
|
||||
return;
|
||||
|
||||
if (_focus_im_context != NULL)
|
||||
ecore_imf_context_focus_out(_focus_im_context);
|
||||
|
||||
ibusimcontext->has_focus = EINA_TRUE;
|
||||
if (ibusimcontext->ibuscontext)
|
||||
ibus_input_context_focus_in(ibusimcontext->ibuscontext);
|
||||
|
||||
if (_focus_im_context != ctx)
|
||||
_focus_im_context = ctx;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_focus_out(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->has_focus == EINA_FALSE)
|
||||
return;
|
||||
|
||||
if (_focus_im_context == ctx)
|
||||
_focus_im_context = NULL;
|
||||
|
||||
ibusimcontext->has_focus = EINA_FALSE;
|
||||
if (ibusimcontext->ibuscontext)
|
||||
ibus_input_context_focus_out(ibusimcontext->ibuscontext);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_reset(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->ibuscontext)
|
||||
ibus_input_context_reset(ibusimcontext->ibuscontext);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
|
||||
char **str,
|
||||
int *cursor_pos)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->preedit_visible)
|
||||
{
|
||||
if (str)
|
||||
*str = strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
|
||||
|
||||
if (cursor_pos)
|
||||
*cursor_pos = ibusimcontext->preedit_cursor_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str)
|
||||
*str = strdup("");
|
||||
|
||||
if (cursor_pos)
|
||||
*cursor_pos = 0;
|
||||
}
|
||||
IDEBUG("str=%s", *str);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
|
||||
char **str,
|
||||
Eina_List **attr __UNUSED__,
|
||||
int *cursor_pos)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->preedit_visible)
|
||||
{
|
||||
if (str)
|
||||
*str = strdup(ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
|
||||
|
||||
if (cursor_pos)
|
||||
*cursor_pos = ibusimcontext->preedit_cursor_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str)
|
||||
*str = strdup("");
|
||||
|
||||
if (cursor_pos)
|
||||
*cursor_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (window != NULL)
|
||||
ibusimcontext->client_window = (Ecore_X_Window)(Ecore_Window)window;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (canvas != NULL)
|
||||
ibusimcontext->client_canvas = canvas;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_cursor_location_internal(Ecore_IMF_Context *ctx)
|
||||
{
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
Ecore_Evas *ee;
|
||||
int canvas_x, canvas_y;
|
||||
|
||||
if (ibusimcontext->ibuscontext == NULL)
|
||||
return;
|
||||
|
||||
if (ibusimcontext->client_canvas)
|
||||
{
|
||||
ee = ecore_evas_ecore_evas_get(ibusimcontext->client_canvas);
|
||||
if (!ee) return;
|
||||
|
||||
ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ibusimcontext->client_window)
|
||||
_window_to_screen_geometry_get(ibusimcontext->client_window, &canvas_x, &canvas_y);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
ibus_input_context_set_cursor_location(ibusimcontext->ibuscontext,
|
||||
ibusimcontext->cursor_x + canvas_x,
|
||||
ibusimcontext->cursor_y + canvas_y,
|
||||
ibusimcontext->cursor_w,
|
||||
ibusimcontext->cursor_h);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int w, int h)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->cursor_x != x ||
|
||||
ibusimcontext->cursor_y != y ||
|
||||
ibusimcontext->cursor_w != w ||
|
||||
ibusimcontext->cursor_h != h)
|
||||
{
|
||||
ibusimcontext->cursor_x = x;
|
||||
ibusimcontext->cursor_y = y;
|
||||
ibusimcontext->cursor_w = w;
|
||||
ibusimcontext->cursor_h = h;
|
||||
|
||||
_set_cursor_location_internal(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ibus_im_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
|
||||
|
||||
if (ibusimcontext->ibuscontext)
|
||||
{
|
||||
if (use_preedit)
|
||||
ibusimcontext->caps |= IBUS_CAP_PREEDIT_TEXT;
|
||||
else
|
||||
ibusimcontext->caps &= ~IBUS_CAP_PREEDIT_TEXT;
|
||||
|
||||
ibus_input_context_set_capabilities(ibusimcontext->ibuscontext, ibusimcontext->caps);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_bus_connected_cb(IBusBus *bus __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
if (ibusimcontext)
|
||||
_create_input_context(ibusimcontext);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_commit_text_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusText *text,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext || !text) return;
|
||||
char *commit_str = text->text ? text->text : "";
|
||||
|
||||
if (ibusimcontext->ctx)
|
||||
{
|
||||
ecore_imf_context_commit_event_add(ibusimcontext->ctx, text->text);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit_str);
|
||||
}
|
||||
}
|
||||
|
||||
static XKeyEvent createXKeyEvent(Window win, Eina_Bool press, int keysym, int modifiers)
|
||||
{
|
||||
XKeyEvent event;
|
||||
Display *display = ecore_x_display_get();
|
||||
|
||||
event.display = display;
|
||||
event.window = win;
|
||||
event.root = ecore_x_window_root_get(win);
|
||||
event.subwindow = None;
|
||||
event.time = 0;
|
||||
event.x = 1;
|
||||
event.y = 1;
|
||||
event.x_root = 1;
|
||||
event.y_root = 1;
|
||||
event.same_screen = EINA_TRUE;
|
||||
event.state = modifiers;
|
||||
event.keycode = XKeysymToKeycode(display, keysym);
|
||||
if (press)
|
||||
event.type = KeyPress;
|
||||
else
|
||||
event.type = KeyRelease;
|
||||
event.send_event = EINA_FALSE;
|
||||
event.serial = 0;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_forward_key_event_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
guint keyval,
|
||||
guint state,
|
||||
IBusIMContext *ibusimcontext __UNUSED__)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
// Find the window which has the current keyboard focus.
|
||||
Window winFocus = 0;
|
||||
int revert = RevertToParent;
|
||||
|
||||
XGetInputFocus(ecore_x_display_get(), &winFocus, &revert);
|
||||
|
||||
XKeyEvent event;
|
||||
if (state & IBUS_RELEASE_MASK)
|
||||
{
|
||||
event = createXKeyEvent(winFocus, EINA_FALSE, keyval, state);
|
||||
XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
|
||||
}
|
||||
else
|
||||
{
|
||||
event = createXKeyEvent(winFocus, EINA_TRUE, keyval, state);
|
||||
XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_update_preedit_text_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusText *text,
|
||||
gint cursor_pos,
|
||||
gboolean visible,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext || !text) return;
|
||||
|
||||
const char *str;
|
||||
gboolean flag;
|
||||
|
||||
if (ibusimcontext->preedit_string)
|
||||
free (ibusimcontext->preedit_string);
|
||||
|
||||
str = text->text;
|
||||
|
||||
if (str)
|
||||
ibusimcontext->preedit_string = strdup(str);
|
||||
else
|
||||
ibusimcontext->preedit_string = strdup("");
|
||||
|
||||
ibusimcontext->preedit_cursor_pos = cursor_pos;
|
||||
|
||||
flag = ibusimcontext->preedit_visible != visible;
|
||||
ibusimcontext->preedit_visible = visible;
|
||||
|
||||
if (ibusimcontext->preedit_visible)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
ecore_imf_context_preedit_start_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
|
||||
}
|
||||
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
}
|
||||
|
||||
ecore_imf_context_preedit_end_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_show_preedit_text_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
|
||||
if (ibusimcontext->preedit_visible == EINA_TRUE)
|
||||
return;
|
||||
|
||||
ibusimcontext->preedit_visible = EINA_TRUE;
|
||||
|
||||
// call preedit start
|
||||
ecore_imf_context_preedit_start_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
|
||||
|
||||
// call preedit changed
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_hide_preedit_text_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
if (ibusimcontext->preedit_visible == EINA_FALSE)
|
||||
return;
|
||||
|
||||
ibusimcontext->preedit_visible = EINA_FALSE;
|
||||
|
||||
// call preedit changed
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
|
||||
// call preedit end
|
||||
ecore_imf_context_preedit_end_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_enabled_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
ibusimcontext->enable = EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_disabled_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
ibusimcontext->enable = EINA_FALSE;
|
||||
|
||||
/* clear preedit */
|
||||
ibusimcontext->preedit_visible = EINA_FALSE;
|
||||
ibusimcontext->preedit_cursor_pos = 0;
|
||||
free (ibusimcontext->preedit_string);
|
||||
ibusimcontext->preedit_string = NULL;
|
||||
|
||||
// call preedit changed
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
|
||||
// call preedit end
|
||||
ecore_imf_context_preedit_end_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_destroy_cb(IBusInputContext *ibuscontext __UNUSED__,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
ibusimcontext->ibuscontext = NULL;
|
||||
ibusimcontext->enable = EINA_FALSE;
|
||||
|
||||
/* clear preedit */
|
||||
ibusimcontext->preedit_visible = EINA_FALSE;
|
||||
ibusimcontext->preedit_cursor_pos = 0;
|
||||
free (ibusimcontext->preedit_string);
|
||||
ibusimcontext->preedit_string = NULL;
|
||||
|
||||
// call preedit changed
|
||||
ecore_imf_context_preedit_changed_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
||||
|
||||
// call preedit end
|
||||
ecore_imf_context_preedit_end_event_add(ibusimcontext->ctx);
|
||||
ecore_imf_context_event_callback_call(ibusimcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_create_input_context(IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG("%s", __FUNCTION__);
|
||||
if (!ibusimcontext) return;
|
||||
|
||||
ibusimcontext->ibuscontext = ibus_bus_create_input_context(_bus, "ecore");
|
||||
|
||||
g_return_if_fail(ibusimcontext->ibuscontext != NULL);
|
||||
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"commit-text",
|
||||
G_CALLBACK (_ibus_context_commit_text_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"forward-key-event",
|
||||
G_CALLBACK (_ibus_context_forward_key_event_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"update-preedit-text",
|
||||
G_CALLBACK (_ibus_context_update_preedit_text_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"show-preedit-text",
|
||||
G_CALLBACK (_ibus_context_show_preedit_text_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"hide-preedit-text",
|
||||
G_CALLBACK (_ibus_context_hide_preedit_text_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"enabled",
|
||||
G_CALLBACK (_ibus_context_enabled_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext,
|
||||
"disabled",
|
||||
G_CALLBACK (_ibus_context_disabled_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect(ibusimcontext->ibuscontext, "destroy",
|
||||
G_CALLBACK (_ibus_context_destroy_cb),
|
||||
ibusimcontext);
|
||||
|
||||
ibus_input_context_set_capabilities(ibusimcontext->ibuscontext, ibusimcontext->caps);
|
||||
|
||||
if (ibusimcontext->has_focus)
|
||||
ibus_input_context_focus_in(ibusimcontext->ibuscontext);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef __IBUS_IM_CONTEXT_H_
|
||||
#define __IBUS_IM_CONTEXT_H_
|
||||
|
||||
#include <Ecore_IMF.h>
|
||||
|
||||
typedef struct _IBusIMContext IBusIMContext;
|
||||
typedef struct _IBusIMContextClass IBusIMContextClass;
|
||||
typedef struct _IBusIMContextPrivate IBusIMContextPrivate;
|
||||
|
||||
EAPI void ibus_im_context_add (Ecore_IMF_Context *ctx);
|
||||
EAPI void ibus_im_context_del (Ecore_IMF_Context *ctx);
|
||||
EAPI void ibus_im_context_reset (Ecore_IMF_Context *context);
|
||||
EAPI void ibus_im_context_focus_in(Ecore_IMF_Context *context);
|
||||
EAPI void ibus_im_context_focus_out(Ecore_IMF_Context *context);
|
||||
EAPI void ibus_im_context_preedit_string_get
|
||||
(Ecore_IMF_Context *context,
|
||||
char **str,
|
||||
int *cursor_pos);
|
||||
EAPI void ibus_im_context_preedit_string_with_attributes_get
|
||||
(Ecore_IMF_Context *context,
|
||||
char **str,
|
||||
Eina_List **attr,
|
||||
int *cursor_pos);
|
||||
|
||||
EAPI void ibus_im_context_cursor_location_set(Ecore_IMF_Context *context,
|
||||
int x, int y, int w, int h);
|
||||
EAPI void ibus_im_context_use_preedit_set(Ecore_IMF_Context *context,
|
||||
Eina_Bool use_preedit);
|
||||
EAPI void
|
||||
ibus_im_context_client_window_set(Ecore_IMF_Context *context, void *window);
|
||||
EAPI void
|
||||
ibus_im_context_client_canvas_set(Ecore_IMF_Context *context, void *canvas);
|
||||
EAPI Eina_Bool
|
||||
ibus_im_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
|
||||
|
||||
IBusIMContext
|
||||
*ibus_im_context_new (void);
|
||||
void ibus_im_context_register_type
|
||||
(GTypeModule *type_module);
|
||||
void ibus_im_context_shutdown
|
||||
(void);
|
||||
|
||||
const gchar
|
||||
*ibus_im_context_get_ic (IBusIMContext *context);
|
||||
void ibus_im_context_set_ic (IBusIMContext *context,
|
||||
const gchar *ic);
|
||||
void ibus_im_context_enable (IBusIMContext *context);
|
||||
void ibus_im_context_disable (IBusIMContext *context);
|
||||
void ibus_im_context_commit_string
|
||||
(IBusIMContext *context,
|
||||
const gchar *string);
|
||||
void ibus_im_context_update_preedit
|
||||
(IBusIMContext *context,
|
||||
const gchar *string,
|
||||
Eina_List **attrs,
|
||||
gint cursor_pos,
|
||||
gboolean visible);
|
||||
void ibus_im_context_show_preedit
|
||||
(IBusIMContext *context);
|
||||
void ibus_im_context_hide_preedit
|
||||
(IBusIMContext *context);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#include <ibus.h>
|
||||
#include "ibus_imcontext.h"
|
||||
#include <Ecore_IMF.h>
|
||||
#include <Ecore.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define IBUS_LOCALDIR ""
|
||||
static const Ecore_IMF_Context_Info ibus_im_info = {
|
||||
"ibus",
|
||||
"IBus (Intelligent Input Bus)",
|
||||
"*",
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
static Ecore_IMF_Context_Class ibus_imf_class = {
|
||||
ibus_im_context_add, /* add */
|
||||
ibus_im_context_del, /* del */
|
||||
ibus_im_context_client_window_set, /* client_window_set */
|
||||
ibus_im_context_client_canvas_set, /* client_canvas_set */
|
||||
NULL, /* input_panel_show */
|
||||
NULL, /* input_panel_hide */
|
||||
ibus_im_context_preedit_string_get, /* get_preedit_string */
|
||||
ibus_im_context_focus_in, /* focus_in */
|
||||
ibus_im_context_focus_out, /* focus_out */
|
||||
ibus_im_context_reset, /* reset */
|
||||
NULL, /* cursor_position_set */
|
||||
ibus_im_context_use_preedit_set, /* use_preedit_set */
|
||||
NULL, /* input_mode_set */
|
||||
ibus_im_context_filter_event, /* filter_event */
|
||||
ibus_im_context_preedit_string_with_attributes_get, /* preedit_string_with_attribute_get */
|
||||
NULL, /* prediction_allow_set */
|
||||
NULL, /* autocapital_type_set */
|
||||
NULL, /* control panel show */
|
||||
NULL, /* control panel hide */
|
||||
NULL, /* input_panel_layout_set */
|
||||
NULL, /* ibus_im_context_input_panel_layout_get, */
|
||||
NULL, /* ibus_im_context_input_panel_language_set, */
|
||||
NULL, /* ibus_im_context_input_panel_language_get, */
|
||||
ibus_im_context_cursor_location_set, /* cursor_location_set */
|
||||
NULL, /* input_panel_imdata_set */
|
||||
NULL, /* input_panel_imdata_get */
|
||||
NULL, /* input_panel_return_key_type_set */
|
||||
NULL, /* input_panel_return_key_disabled_set */
|
||||
NULL /* input_panel_caps_lock_mode_set */
|
||||
};
|
||||
|
||||
static Ecore_IMF_Context *im_module_create (void);
|
||||
static Ecore_IMF_Context *im_module_exit (void);
|
||||
|
||||
static Eina_Bool
|
||||
im_module_init(void)
|
||||
{
|
||||
ecore_main_loop_glib_integrate();
|
||||
g_type_init();
|
||||
ecore_imf_module_register(&ibus_im_info, im_module_create, im_module_exit);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void im_module_shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
static Ecore_IMF_Context *
|
||||
im_module_exit(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Ecore_IMF_Context *
|
||||
im_module_create()
|
||||
{
|
||||
Ecore_IMF_Context *ctx = NULL;
|
||||
IBusIMContext *ctxd = NULL;
|
||||
|
||||
ctxd = ibus_im_context_new();
|
||||
if (!ctxd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = ecore_imf_context_new(&ibus_imf_class);
|
||||
if (!ctx)
|
||||
{
|
||||
free(ctxd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecore_imf_context_data_set(ctx, ctxd);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
EINA_MODULE_INIT(im_module_init);
|
||||
EINA_MODULE_SHUTDOWN(im_module_shutdown);
|
||||
|
Loading…
Reference in New Issue