summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjihoon <jihoon@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>2012-06-11 04:49:15 +0000
committerjihoon <jihoon@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>2012-06-11 04:49:15 +0000
commit6102c801a0d647e4b9e19eea8352941f3357aaa7 (patch)
treeb76fd8b61fbe57dd2a776b20cbbbf9a29ee1406e
parent3f793bc789065e106f3a9b40defd402159eac2ff (diff)
downloadecore-6102c801a0d647e4b9e19eea8352941f3357aaa7.tar.gz
ecore-6102c801a0d647e4b9e19eea8352941f3357aaa7.tar.bz2
ecore-6102c801a0d647e4b9e19eea8352941f3357aaa7.zip
[ecore-immodule] add ibus immodule. It support more than ibus-1.3.99 version.
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@71927 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33
-rw-r--r--configure.ac23
-rw-r--r--src/modules/immodules/Makefile.am4
-rw-r--r--src/modules/immodules/ibus/Makefile.am36
-rw-r--r--src/modules/immodules/ibus/ibus_imcontext.c719
-rw-r--r--src/modules/immodules/ibus/ibus_imcontext.h63
-rw-r--r--src/modules/immodules/ibus/ibus_module.c97
6 files changed, 942 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 10877b12..cb87607f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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"
diff --git a/src/modules/immodules/Makefile.am b/src/modules/immodules/Makefile.am
index 2f121ae3..22b64967 100644
--- a/src/modules/immodules/Makefile.am
+++ b/src/modules/immodules/Makefile.am
@@ -9,3 +9,7 @@ endif
if BUILD_ECORE_IMF_SCIM
SUBDIRS += scim
endif
+
+if BUILD_ECORE_IMF_IBUS
+SUBDIRS += ibus
+endif
diff --git a/src/modules/immodules/ibus/Makefile.am b/src/modules/immodules/ibus/Makefile.am
new file mode 100644
index 00000000..a59b5e85
--- /dev/null
+++ b/src/modules/immodules/ibus/Makefile.am
@@ -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
diff --git a/src/modules/immodules/ibus/ibus_imcontext.c b/src/modules/immodules/ibus/ibus_imcontext.c
new file mode 100644
index 00000000..92513f51
--- /dev/null
+++ b/src/modules/immodules/ibus/ibus_imcontext.c
@@ -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);
+}
diff --git a/src/modules/immodules/ibus/ibus_imcontext.h b/src/modules/immodules/ibus/ibus_imcontext.h
new file mode 100644
index 00000000..415eeca9
--- /dev/null
+++ b/src/modules/immodules/ibus/ibus_imcontext.h
@@ -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
+
diff --git a/src/modules/immodules/ibus/ibus_module.c b/src/modules/immodules/ibus/ibus_module.c
new file mode 100644
index 00000000..89c2ebed
--- /dev/null
+++ b/src/modules/immodules/ibus/ibus_module.c
@@ -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);
+