[ecore-immodule] add ibus immodule. It support more than ibus-1.3.99 version.

SVN revision: 71927
This commit is contained in:
Jihoon Kim 2012-06-11 04:49:15 +00:00
parent 59b2545ded
commit 7d7697f102
6 changed files with 942 additions and 0 deletions

View File

@ -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"

View File

@ -9,3 +9,7 @@ endif
if BUILD_ECORE_IMF_SCIM
SUBDIRS += scim
endif
if BUILD_ECORE_IMF_IBUS
SUBDIRS += ibus
endif

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);