Move both the source tree and the install directory.
SVN revision: 82474
# Ibus
if BUILD_ECORE_IMF_IBUS
-ecoreimfibuspkgdir = $(libdir)/ecore/immodules
-ecoreimfibuspkg_LTLIBRARIES = modules/ecore/immodules/ibus/ibus.la
-modules_ecore_immodules_ibus_ibus_la_SOURCES = \
-modules/ecore/immodules/ibus/ibus_module.c \
-modules/ecore/immodules/ibus/ibus_imcontext.c \
-modules/ecore/immodules/ibus/ibus_imcontext.h
-modules_ecore_immodules_ibus_ibus_la_CPPFLAGS = \
+ecoreimfibuspkgdir = $(libdir)/ecore_imf
+ecoreimfibuspkg_LTLIBRARIES = modules/ecore_imf/ibus/ibus.la
+modules_ecore_imf_ibus_ibus_la_SOURCES = \
+modules/ecore_imf/ibus/ibus_module.c \
+modules/ecore_imf/ibus/ibus_imcontext.c \
+modules/ecore_imf/ibus/ibus_imcontext.h
+modules_ecore_imf_ibus_ibus_la_CPPFLAGS = \
-I$(top_srcdir)/src/lib/eina \
-I$(top_builddir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eo \
@ECORE_IMF_CFLAGS@ \
@EFL_COV_CFLAGS@ \
@IBUS_CFLAGS@
-modules_ecore_immodules_ibus_ibus_la_LIBADD = \
+modules_ecore_imf_ibus_ibus_la_LIBADD = \
lib/ecore_evas/libecore_evas.la \
lib/ecore_imf/libecore_imf.la \
lib/ecore_x/libecore_x.la \
lib/eina/libeina.la \
@IBUS_LIBS@ \
@EFL_COV_LIBS@
-modules_ecore_immodules_ibus_ibus_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
-modules_ecore_immodules_ibus_ibus_la_LIBTOOLFLAGS = --tag=disable-static
+modules_ecore_imf_ibus_ibus_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_imf_ibus_ibus_la_LIBTOOLFLAGS = --tag=disable-static
endif
# Scim
if BUILD_ECORE_IMF_SCIM
-ecoreimfscimpkgdir = $(libdir)/ecore/immodules
-ecoreimfscimpkg_LTLIBRARIES = modules/ecore/immodules/scim/scim.la
-modules_ecore_immodules_scim_scim_la_SOURCES = \
-modules/ecore/immodules/scim/scim_module.cpp \
-modules/ecore/immodules/scim/scim_imcontext.cpp \
-modules/ecore/immodules/scim/scim_imcontext.h
-modules_ecore_immodules_scim_scim_la_CPPFLAGS = \
+ecoreimfscimpkgdir = $(libdir)/ecore_imf
+ecoreimfscimpkg_LTLIBRARIES = modules/ecore_imf/scim/scim.la
+modules_ecore_imf_scim_scim_la_SOURCES = \
+modules/ecore_imf/scim/scim_module.cpp \
+modules/ecore_imf/scim/scim_imcontext.cpp \
+modules/ecore_imf/scim/scim_imcontext.h
+modules_ecore_imf_scim_scim_la_CPPFLAGS = \
-I$(top_srcdir)/src/lib/eina \
-I$(top_builddir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eo \
@ECORE_IMF_CFLAGS@ \
@EFL_COV_CFLAGS@ \
@SCIM_CFLAGS@
-modules_ecore_immodules_scim_scim_la_LIBADD = \
+modules_ecore_imf_scim_scim_la_LIBADD = \
lib/ecore_evas/libecore_evas.la \
lib/ecore_imf/libecore_imf.la \
lib/ecore_x/libecore_x.la \
lib/eina/libeina.la \
@SCIM_LIBS@ \
@EFL_COV_LIBS@
-modules_ecore_immodules_scim_scim_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
-modules_ecore_immodules_scim_scim_la_LIBTOOLFLAGS = --tag=disable-static
+modules_ecore_imf_scim_scim_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_imf_scim_scim_la_LIBTOOLFLAGS = --tag=disable-static
endif
# Xim
if BUILD_ECORE_IMF_XIM
-ecoreimfximpkgdir = $(libdir)/ecore/immodules
-ecoreimfximpkg_LTLIBRARIES = modules/ecore/immodules/xim/xim.la
-modules_ecore_immodules_xim_xim_la_SOURCES = \
-modules/ecore/immodules/xim/ecore_imf_xim.c
-modules_ecore_immodules_xim_xim_la_CPPFLAGS = \
+ecoreimfximpkgdir = $(libdir)/ecore_imf
+ecoreimfximpkg_LTLIBRARIES = modules/ecore_imf/xim/xim.la
+modules_ecore_imf_xim_xim_la_SOURCES = \
+modules/ecore_imf/xim/ecore_imf_xim.c
+modules_ecore_imf_xim_xim_la_CPPFLAGS = \
-I$(top_srcdir)/src/lib/eina \
-I$(top_builddir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eo \
-I$(top_srcdir)/src/lib/ecore_imf \
@ECORE_IMF_CFLAGS@ \
@EFL_COV_CFLAGS@
-modules_ecore_immodules_xim_xim_la_LIBADD = \
+modules_ecore_imf_xim_xim_la_LIBADD = \
lib/ecore_imf/libecore_imf.la \
lib/ecore_x/libecore_x.la \
lib/ecore/libecore.la \
lib/eo/libeo.la \
lib/eina/libeina.la \
@EFL_COV_LIBS@
-modules_ecore_immodules_xim_xim_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
-modules_ecore_immodules_xim_xim_la_LIBTOOLFLAGS = --tag=disable-static
+modules_ecore_imf_xim_xim_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_imf_xim_xim_la_LIBTOOLFLAGS = --tag=disable-static
endif
if (getenv("EFL_RUN_IN_TREE"))
{
struct stat st;
- snprintf(buf, sizeof(buf), "%s/src/modules/ecore/immodules",
+ snprintf(buf, sizeof(buf), "%s/src/modules/ecore_imf",
PACKAGE_BUILD_DIR);
if (stat(buf, &st) == 0)
{
for (itr = built_modules; *itr != NULL; itr++)
{
snprintf(buf, sizeof(buf),
- "%s/src/modules/ecore/immodules/%s/.libs",
+ "%s/src/modules/ecore_imf/%s/.libs",
PACKAGE_BUILD_DIR, *itr);
module_list = eina_module_list_get(module_list, buf,
EINA_FALSE, NULL, NULL);
}
}
- snprintf(buf, sizeof(buf), "%s/ecore/immodules", eina_prefix_lib_get(pfx));
+ snprintf(buf, sizeof(buf), "%s/ecore_imf", eina_prefix_lib_get(pfx));
module_list = eina_module_list_get(NULL, buf, 0, NULL, NULL);
- homedir = eina_module_environment_path_get("HOME", "/.ecore/immodules");
+ homedir = eina_module_environment_path_get("HOME", "/.ecore_imf");
if (homedir)
{
module_list = eina_module_list_get(module_list, homedir, 0, NULL, NULL);
+++ /dev/null
-#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"
-
-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;
-};
-
-typedef struct _KeyEvent KeyEvent;
-
-struct _KeyEvent
-{
- int keysym;
- int state;
-};
-
-static Eina_Bool _use_sync_mode = EINA_FALSE;
-
-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 XKeyEvent createXKeyEvent (Window win, Eina_Bool press, int keysym, int modifiers);
-
-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 "Alt") */
- if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
- state |= IBUS_SUPER_MASK;
-
- /**< "AltGr" is pressed */
- if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
- state |= IBUS_MOD5_MASK;
-
- return state;
-}
-
-static void
-key_event_put(int keysym, int state)
-{
- // 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, keysym, state);
- XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
- }
- else
- {
- event = createXKeyEvent(winFocus, EINA_TRUE, keysym, state);
- XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
- }
-}
-
-static KeyEvent *
-key_event_copy(int keysym, int state)
-{
- KeyEvent *kev = calloc(1, sizeof(KeyEvent));
- kev->keysym = keysym;
- kev->state = state;
-
- return kev;
-}
-
-IBusIMContext *
-ibus_im_context_new(void)
-{
- EINA_LOG_DBG("%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;
-}
-
-static void
-_process_key_event_done(GObject *object,
- GAsyncResult *res,
- gpointer user_data)
-{
- IBusInputContext *context = (IBusInputContext *)object;
- KeyEvent *event = (KeyEvent *)user_data;
-
- GError *error = NULL;
- Eina_Bool retval = ibus_input_context_process_key_event_async_finish(context,
- res,
- &error);
-
- if (error != NULL)
- {
- g_warning("Process Key Event failed: %s.", error->message);
- g_error_free(error);
- }
-
- if (retval == EINA_FALSE)
- {
- key_event_put(event->keysym, event->state);
- }
- free(event);
-}
-
-EAPI void
-ibus_im_context_add(Ecore_IMF_Context *ctx)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
-
- char *s = NULL;
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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;
-
- s = getenv("IBUS_ENABLE_SYNC_MODE");
- if (s)
- _use_sync_mode = !!atoi(s);
-
- 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)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
-
- IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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);
- if (_focus_im_context == ctx)
- _focus_im_context = NULL;
-}
-
-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);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ibusimcontext, EINA_FALSE);
-
- if (type != ECORE_IMF_EVENT_KEY_UP && type != ECORE_IMF_EVENT_KEY_DOWN)
- return EINA_FALSE;
-
- EINA_LOG_DBG("%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;
-
- if (_use_sync_mode)
- {
- retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
- keysym,
- keycode - 8,
- state);
- }
- else
- {
- ibus_input_context_process_key_event_async(ibusimcontext->ibuscontext,
- keysym,
- keycode - 8,
- state,
- -1,
- NULL,
- _process_key_event_done,
- key_event_copy(keysym, state));
- retval = EINA_TRUE;
- }
- }
- 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);
- if (_use_sync_mode)
- {
- retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
- keysym,
- keycode - 8,
- state);
- }
- else
- {
- ibus_input_context_process_key_event_async(ibusimcontext->ibuscontext,
- keysym,
- keycode - 8,
- state,
- -1,
- NULL,
- _process_key_event_done,
- key_event_copy(keysym, state));
- retval = EINA_TRUE;
- }
- }
- 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)
-{
- EINA_LOG_DBG("ctx : %p", ctx);
-
- IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- EINA_LOG_DBG("ctx : %p", ctx);
-
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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;
- }
- EINA_LOG_DBG("str : %s, cursor_pos : %d", *str, *cursor_pos);
-}
-
-EAPI void
-ibus_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
- char **str,
- Eina_List **attr EINA_UNUSED,
- int *cursor_pos)
-{
- IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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;
- }
- EINA_LOG_DBG("str : %s, cursor_pos : %d", *str, *cursor_pos);
-}
-
-EAPI void
-ibus_im_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
-{
- EINA_LOG_DBG("canvas : %p", window);
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- EINA_LOG_DBG("canvas : %p", canvas);
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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;
-
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- EINA_LOG_DBG("x : %d, y : %d, w, %d, h :%d", x, y, w, h);
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- EINA_LOG_DBG("preedit : %d", use_preedit);
- IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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 EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("ibus is connected");
-
- if (ibusimcontext)
- _create_input_context(ibusimcontext);
-}
-
-static void
-_ibus_context_commit_text_cb(IBusInputContext *ibuscontext EINA_UNUSED,
- IBusText *text,
- IBusIMContext *ibusimcontext)
-{
- if (!ibusimcontext || !text) return;
- char *commit_str = text->text ? text->text : "";
-
- EINA_LOG_DBG("commit string : %s", commit_str);
-
- 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 EINA_UNUSED,
- guint keyval,
- guint state,
- IBusIMContext *ibusimcontext EINA_UNUSED)
-{
- EINA_LOG_DBG("keyval : %d, state : %d", keyval, state);
-
- key_event_put(keyval, state);
-}
-
-static void
-_ibus_context_update_preedit_text_cb(IBusInputContext *ibuscontext EINA_UNUSED,
- IBusText *text,
- gint cursor_pos,
- gboolean visible,
- IBusIMContext *ibusimcontext)
-{
- 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;
-
- EINA_LOG_DBG("string : %s, cursor : %d", ibusimcontext->preedit_string, ibusimcontext->preedit_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 EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("preedit visible : %d", ibusimcontext->preedit_visible);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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 EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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 EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- ibusimcontext->enable = EINA_TRUE;
-}
-
-static void
-_ibus_context_disabled_cb(IBusInputContext *ibuscontext EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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 EINA_UNUSED,
- IBusIMContext *ibusimcontext)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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)
-{
- EINA_LOG_DBG("%s", __FUNCTION__);
- EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
-
- 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);
-}
+++ /dev/null
-#ifndef __IBUS_IM_CONTEXT_H_
-#define __IBUS_IM_CONTEXT_H_
-
-#include <Ecore_IMF.h>
-
-typedef struct _IBusIMContext IBusIMContext;
-
-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);
-#endif
+++ /dev/null
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include <Ecore.h>
-#include <Ecore_IMF.h>
-
-#include <ibus.h>
-#include "ibus_imcontext.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 */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-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();
- ibus_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(void)
-{
- 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);
-
+++ /dev/null
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define Uses_SCIM_DEBUG
-#define Uses_SCIM_BACKEND
-#define Uses_SCIM_IMENGINE_MODULE
-#define Uses_SCIM_HOTKEY
-#define Uses_SCIM_PANEL_CLIENT
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <Ecore_Evas.h>
-#include <Ecore_X.h>
-#include <Ecore.h>
-#include <Evas.h>
-
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-#include <X11/Xutil.h>
-
-#include <scim.h>
-#include "scim_imcontext.h"
-
-using namespace scim;
-
-struct _EcoreIMFContextISFImpl
-{
- EcoreIMFContextISF *parent;
- IMEngineInstancePointer si;
- Ecore_X_Window client_window;
- Evas *client_canvas;
- Ecore_IMF_Input_Mode input_mode;
- WideString preedit_string;
- AttributeList preedit_attrlist;
- Ecore_IMF_Autocapital_Type autocapital_type;
- int preedit_caret;
- int cursor_x;
- int cursor_y;
- int cursor_pos;
- bool use_preedit;
- bool is_on;
- bool shared_si;
- bool preedit_started;
- bool preedit_updating;
- bool need_commit_preedit;
- bool uppercase;
- bool prediction_allow;
-
- EcoreIMFContextISFImpl *next;
-};
-
-/* Input Context handling functions. */
-static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
-static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
-static void delete_all_ic_impl (void);
-
-static EcoreIMFContextISF *find_ic (int id);
-
-
-/* private functions */
-static void panel_slot_reload_config (int context);
-static void panel_slot_exit (int context);
-static void panel_slot_update_lookup_table_page_size(int context,
- int page_size);
-static void panel_slot_lookup_table_page_up (int context);
-static void panel_slot_lookup_table_page_down (int context);
-static void panel_slot_trigger_property (int context,
- const String &property);
-static void panel_slot_process_helper_event (int context,
- const String &target_uuid,
- const String &helper_uuid,
- const Transaction &trans);
-static void panel_slot_move_preedit_caret (int context,
- int caret_pos);
-static void panel_slot_select_candidate (int context,
- int cand_index);
-static void panel_slot_process_key_event (int context,
- const KeyEvent &key);
-static void panel_slot_commit_string (int context,
- const WideString &wstr);
-static void panel_slot_forward_key_event (int context,
- const KeyEvent &key);
-static void panel_slot_request_help (int context);
-static void panel_slot_request_factory_menu (int context);
-static void panel_slot_change_factory (int context,
- const String &uuid);
-
-static void panel_req_focus_in (EcoreIMFContextISF *ic);
-static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
-static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
-static void panel_req_show_help (EcoreIMFContextISF *ic);
-static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
-
-/* Panel iochannel handler*/
-static bool panel_initialize (void);
-static void panel_finalize (void);
-static Eina_Bool panel_iochannel_handler (void *data,
- Ecore_Fd_Handler *fd_handler);
-
-/* utility functions */
-static bool filter_hotkeys (EcoreIMFContextISF *ic,
- const KeyEvent &key);
-static void turn_on_ic (EcoreIMFContextISF *ic);
-static void turn_off_ic (EcoreIMFContextISF *ic);
-static void set_ic_capabilities (EcoreIMFContextISF *ic);
-
-static void initialize (void);
-static void finalize (void);
-
-static void open_next_factory (EcoreIMFContextISF *ic);
-static void open_previous_factory (EcoreIMFContextISF *ic);
-static void open_specific_factory (EcoreIMFContextISF *ic,
- const String &uuid);
-static void initialize_modifier_bits (Display *display);
-static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
-static XKeyEvent createKeyEvent (Display *display, Window &win,
- Window &winRoot, bool press,
- int keysym, int modifiers);
-static void _x_send_key_event (const KeyEvent &key);
-
-static void attach_instance (const IMEngineInstancePointer &si);
-
-/* slot functions */
-static void slot_show_preedit_string (IMEngineInstanceBase *si);
-static void slot_show_aux_string (IMEngineInstanceBase *si);
-static void slot_show_lookup_table (IMEngineInstanceBase *si);
-
-static void slot_hide_preedit_string (IMEngineInstanceBase *si);
-static void slot_hide_aux_string (IMEngineInstanceBase *si);
-static void slot_hide_lookup_table (IMEngineInstanceBase *si);
-
-static void slot_update_preedit_caret (IMEngineInstanceBase *si,
- int caret);
-static void slot_update_preedit_string (IMEngineInstanceBase *si,
- const WideString &str,
- const AttributeList &attrs);
-static void slot_update_aux_string (IMEngineInstanceBase *si,
- const WideString &str,
- const AttributeList &attrs);
-static void slot_commit_string (IMEngineInstanceBase *si,
- const WideString &str);
-static void slot_forward_key_event (IMEngineInstanceBase *si,
- const KeyEvent &key);
-static void slot_update_lookup_table (IMEngineInstanceBase *si,
- const LookupTable &table);
-
-static void slot_register_properties (IMEngineInstanceBase *si,
- const PropertyList &properties);
-static void slot_update_property (IMEngineInstanceBase *si,
- const Property &property);
-static void slot_beep (IMEngineInstanceBase *si);
-static void slot_start_helper (IMEngineInstanceBase *si,
- const String &helper_uuid);
-static void slot_stop_helper (IMEngineInstanceBase *si,
- const String &helper_uuid);
-static void slot_send_helper_event (IMEngineInstanceBase *si,
- const String &helper_uuid,
- const Transaction &trans);
-static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
- WideString &text,
- int &cursor,
- int maxlen_before,
- int maxlen_after);
-static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
- int offset,
- int len);
-
-static void reload_config_callback (const ConfigPointer &config);
-
-static void fallback_commit_string_cb (IMEngineInstanceBase *si,
- const WideString &str);
-
-static void caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force);
-
-/* Local variables declaration */
-static String _language;
-static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
-static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
-static EcoreIMFContextISF *_ic_list = 0;
-
-static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
-static int _valid_key_mask = SCIM_KEY_AllMasks;
-
-static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
-static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
-
-static IMEngineInstancePointer _default_instance;
-
-static ConfigModule *_config_module = 0;
-static ConfigPointer _config;
-static BackEndPointer _backend;
-
-static EcoreIMFContextISF *_focused_ic = 0;
-
-static bool _scim_initialized = false;
-
-static int _instance_count = 0;
-static int _context_count = 0;
-
-static IMEngineFactoryPointer _fallback_factory;
-static IMEngineInstancePointer _fallback_instance;
-static PanelClient _panel_client;
-
-static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
-static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
-
-static Ecore_X_Window _client_window = 0;
-
-static bool _on_the_spot = true;
-static bool _shared_input_method = false;
-
-static Eina_Bool autocap_allow = EINA_FALSE;
-
-static Display *__current_display = 0;
-static int __current_alt_mask = Mod1Mask;
-static int __current_meta_mask = 0;
-static int __current_super_mask = 0;
-static int __current_hyper_mask = 0;
-static int __current_numlock_mask = Mod2Mask;
-
-// A hack to shutdown the immodule cleanly even if im_module_exit() is not called when exiting.
-class FinalizeHandler
-{
-public:
- FinalizeHandler()
- {
- SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler()\n";
- }
- ~FinalizeHandler()
- {
- SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler()\n";
- isf_imf_context_shutdown();
- }
-};
-
-static FinalizeHandler _finalize_handler;
-
-static unsigned int
-utf8_offset_to_index(const char *str, int offset)
-{
- int index = 0;
- int i;
- for (i = 0; i < offset; i++)
- {
- eina_unicode_utf8_get_next(str, &index);
- }
-
- return index;
-}
-
-static unsigned int
-get_time(void)
-{
- unsigned int tint;
- struct timeval tv;
- struct timezone tz; /* is not used since ages */
- gettimeofday(&tv, &tz);
- tint = tv.tv_sec * 1000;
- tint = tint / 1000 * 1000;
- tint = tint + tv.tv_usec / 1000;
- return tint;
-}
-
-/* Function Implementations */
-static EcoreIMFContextISFImpl *
-new_ic_impl(EcoreIMFContextISF *parent)
-{
- EcoreIMFContextISFImpl *impl = NULL;
-
- if (_free_ic_impl_list != NULL)
- {
- impl = _free_ic_impl_list;
- _free_ic_impl_list = _free_ic_impl_list->next;
- }
- else
- {
- impl = new EcoreIMFContextISFImpl;
- if (impl == NULL)
- return NULL;
- }
-
- impl->uppercase = false;
- impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
- impl->next = _used_ic_impl_list;
- _used_ic_impl_list = impl;
-
- impl->parent = parent;
-
- return impl;
-}
-
-static void
-delete_ic_impl(EcoreIMFContextISFImpl *impl)
-{
- EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
-
- for (; rec != 0; last = rec, rec = rec->next)
- {
- if (rec == impl)
- {
- if (last != 0)
- last->next = rec->next;
- else
- _used_ic_impl_list = rec->next;
-
- rec->next = _free_ic_impl_list;
- _free_ic_impl_list = rec;
-
- rec->parent = 0;
- rec->si.reset();
- rec->client_window = 0;
- rec->preedit_string = WideString();
- rec->preedit_attrlist.clear();
-
- return;
- }
- }
-}
-
-static void
-delete_all_ic_impl(void)
-{
- EcoreIMFContextISFImpl *it = _used_ic_impl_list;
-
- while (it != 0)
- {
- _used_ic_impl_list = it->next;
- delete it;
- it = _used_ic_impl_list;
- }
-
- it = _free_ic_impl_list;
- while (it != 0)
- {
- _free_ic_impl_list = it->next;
- delete it;
- it = _free_ic_impl_list;
- }
-}
-
-static EcoreIMFContextISF *
-find_ic(int id)
-{
- EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
-
- while (rec != 0)
- {
- if (rec->parent && rec->parent->id == id)
- return rec->parent;
- rec = rec->next;
- }
-
- return 0;
-}
-
-static Eina_Bool
-analyze_surrounding_text(Ecore_IMF_Context *ctx)
-{
- char *plain_str = NULL;
- char *markup_str = NULL;
- const char *puncs[] = {". ", "! ", "? "};
- Eina_Bool ret = EINA_FALSE;
- int cursor_pos = 0;
- int i = 0;
- Eina_Unicode *tail = NULL;
- Eina_Unicode *ustr = NULL;
- const int punc_num = sizeof(puncs) / sizeof(puncs[0]);
- Eina_Unicode *uni_puncs[punc_num];
- EcoreIMFContextISF *context_scim;
-
- if (!ctx) return EINA_FALSE;
- context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
- if (!context_scim || !context_scim->impl) return EINA_FALSE;
-
- switch (context_scim->impl->autocapital_type)
- {
- case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
- return EINA_FALSE;
- case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
- return EINA_TRUE;
- default:
- break;
- }
-
- for (i = 0; i < punc_num; i++)
- uni_puncs[i] = eina_unicode_utf8_to_unicode(puncs[i], NULL);
-
- ecore_imf_context_surrounding_get(ctx, &markup_str, &cursor_pos);
- if (!markup_str) goto done;
-
- if (cursor_pos == 0)
- {
- ret = EINA_TRUE;
- goto done;
- }
-
- // Convert into plain string
- plain_str = evas_textblock_text_markup_to_utf8(NULL, markup_str);
- if (!plain_str) goto done;
-
- // Convert string from UTF-8 to unicode
- ustr = eina_unicode_utf8_to_unicode(plain_str, NULL);
- if (!ustr) goto done;
-
- if (cursor_pos >= 1)
- {
- if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
- {
- if (ustr[cursor_pos-1] == ' ')
- {
- ret = EINA_TRUE;
- goto done;
- }
- }
-
- // Check paragraph separator <PS> and carriage return <br>
- if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n'))
- {
- ret = EINA_TRUE;
- goto done;
- }
- }
-
- // check punctuation
- if (cursor_pos >= 2)
- {
- tail = eina_unicode_strndup(ustr+cursor_pos-2, 2);
-
- if (tail)
- {
- for (i = 0; i < punc_num; i++)
- {
- if (!eina_unicode_strcmp(tail, uni_puncs[i]))
- {
- ret = EINA_TRUE;
- break;
- }
- }
- free(tail);
- tail = NULL;
- }
- }
-
-done:
- if (ustr) free(ustr);
- if (markup_str) free(markup_str);
- if (plain_str) free(plain_str);
-
- for (i = 0; i < punc_num; i++)
- if (uni_puncs[i]) free(uni_puncs[i]);
-
- return ret;
-}
-
-static void
-caps_mode_check(Ecore_IMF_Context *ctx, Eina_Bool force)
-{
- Eina_Bool uppercase;
- EcoreIMFContextISF *context_scim;
-
- if (!ctx) return;
- context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (autocap_allow == EINA_FALSE)
- return;
-
- // Check autocapital type
- if (!context_scim || !context_scim->impl)
- return;
-
- if (analyze_surrounding_text(ctx))
- uppercase = EINA_TRUE;
- else
- uppercase = EINA_FALSE;
-
- if (force)
- context_scim->impl->uppercase = uppercase;
- else
- if (context_scim->impl->uppercase != uppercase)
- context_scim->impl->uppercase = uppercase;
-}
-
-static void
-feed_key_event(Evas *evas, const char *str, Eina_Bool fake)
-{
- char key_string[128] = {0};
- unsigned int timestamp = 0;
-
- if (!fake)
- timestamp = get_time();
-
- if (strncmp(str, "KeyRelease+", 11) == 0)
- {
- strncpy(key_string, str + 11, strlen(str)-11);
- evas_event_feed_key_up(evas, key_string, key_string, NULL, NULL, timestamp, NULL);
- SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_up()...\n";
- }
- else
- {
- strncpy(key_string, str, strlen(str));
- evas_event_feed_key_down(evas, key_string, key_string, NULL, NULL, timestamp, NULL);
- SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_down()...\n";
- }
-}
-
-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;
-}
-
-/* Public functions */
-/**
- * isf_imf_context_new
- *
- * This function will be called by Ecore IMF.
- * Create a instance of type EcoreIMFContextISF.
- *
- * Return value: A pointer to the newly created EcoreIMFContextISF instance
- */
-EAPI EcoreIMFContextISF *
-isf_imf_context_new(void)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
- char *env;
-
- EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
- if (context_scim == NULL)
- {
- std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
- return NULL;
- }
-
- context_scim->id = _context_count++;
-
- if (!_scim_initialized)
- {
- initialize();
- _scim_initialized = true;
- }
-
- env = getenv("ECORE_IMF_AUTOCAPITAL_ALLOW");
- if (env)
- autocap_allow = !!atoi(env);
-
- return context_scim;
-}
-
-/**
- * isf_imf_context_shutdown
- *
- * It will be called when the scim im module is unloaded by ecore. It will do some
- * cleanup job.
- */
-EAPI void
-isf_imf_context_shutdown(void)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (_scim_initialized)
- {
- _scim_initialized = false;
- finalize();
- }
-}
-
-EAPI void
-isf_imf_context_add(Ecore_IMF_Context *ctx)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
-
- if (!context_scim) return;
-
- context_scim->impl = NULL;
-
- if (_backend.null())
- return;
-
- IMEngineInstancePointer si;
-
- // Use the default instance if "shared input method" mode is enabled.
- if (_shared_input_method && !_default_instance.null())
- {
- si = _default_instance;
- SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
- }
-
- // Not in "shared input method" mode, or no default instance, create an instance.
- if (si.null())
- {
- IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
- if (factory.null()) return;
- si = factory->create_instance("UTF-8", _instance_count++);
- if (si.null()) return;
- attach_instance(si);
- SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
- }
-
- // If "shared input method" mode is enabled, and there is no default instance,
- // then store this instance as default one.
- if (_shared_input_method && _default_instance.null())
- {
- SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
- _default_instance = si;
- }
-
- context_scim->ctx = ctx;
- context_scim->impl = new_ic_impl(context_scim);
- if (context_scim->impl == NULL)
- {
- std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
- return;
- }
-
- context_scim->impl->si = si;
- context_scim->impl->client_window = 0;
- context_scim->impl->client_canvas = NULL;
- context_scim->impl->preedit_caret = 0;
- context_scim->impl->cursor_x = 0;
- context_scim->impl->cursor_y = 0;
- context_scim->impl->cursor_pos = -1;
- context_scim->impl->is_on = false;
- context_scim->impl->shared_si = _shared_input_method;
- context_scim->impl->use_preedit = _on_the_spot;
- context_scim->impl->preedit_started = false;
- context_scim->impl->preedit_updating = false;
- context_scim->impl->need_commit_preedit = false;
-
- if (!_ic_list)
- context_scim->next = NULL;
- else
- context_scim->next = _ic_list;
- _ic_list = context_scim;
-
- if (_shared_input_method)
- context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
-
- _panel_client.prepare(context_scim->id);
- _panel_client.register_input_context(context_scim->id, si->get_factory_uuid());
- set_ic_capabilities(context_scim);
- _panel_client.send();
-
- SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
-}
-
-EAPI void
-isf_imf_context_del(Ecore_IMF_Context *ctx)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (!_ic_list) return;
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
-
- if (context_scim)
- {
- if (context_scim->id != _ic_list->id)
- {
- EcoreIMFContextISF * pre = _ic_list;
- EcoreIMFContextISF * cur = _ic_list->next;
- while (cur != NULL)
- {
- if (cur->id == context_scim->id)
- {
- pre->next = cur->next;
- break;
- }
- pre = cur;
- cur = cur->next;
- }
- }
- else
- _ic_list = _ic_list->next;
- }
-
- if (context_scim && context_scim->impl)
- {
- _panel_client.prepare(context_scim->id);
-
- if (context_scim == _focused_ic)
- context_scim->impl->si->focus_out();
-
- // Delete the instance.
- EcoreIMFContextISF *old_focused = _focused_ic;
- _focused_ic = context_scim;
- context_scim->impl->si.reset();
- _focused_ic = old_focused;
-
- if (context_scim == _focused_ic)
- {
- _panel_client.turn_off(context_scim->id);
- _panel_client.focus_out(context_scim->id);
- }
-
- _panel_client.remove_input_context(context_scim->id);
- _panel_client.send();
-
- if (context_scim->impl->client_window)
- isf_imf_context_client_window_set(ctx, NULL);
-
- if (context_scim->impl)
- {
- delete_ic_impl(context_scim->impl);
- context_scim->impl = 0;
- }
- }
-
- if (context_scim == _focused_ic)
- _focused_ic = 0;
-
- if (context_scim)
- {
- delete context_scim;
- context_scim = 0;
- }
-}
-
-/**
- * isf_imf_context_client_canvas_set
- * @ctx: a #Ecore_IMF_Context
- * @canvas: the client canvas
- *
- * This function will be called by Ecore IMF.
- *
- * Set the client canvas for the Input Method Context; this is the canvas
- * in which the input appears.
- *
- * The canvas type can be determined by using the context canvas type.
- * Actually only canvas with type "evas" (Evas *) is supported. This canvas
- * may be used in order to correctly position status windows, and may also
- * be used for purposes internal to the Input Method Context.
- */
-EAPI void
-isf_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas)
- context_scim->impl->client_canvas = (Evas*)canvas;
-}
-
-/**
- * isf_imf_context_client_window_set
- * @ctx: a #Ecore_IMF_Context
- * @window: the client window
- *
- * This function will be called by Ecore IMF.
- *
- * Set the client window for the Input Method Context; this is the Ecore_X_Window
- * when using X11, Ecore_Win32_Window when using Win32, etc.
- *
- * This window is used in order to correctly position status windows,
- * and may also be used for purposes internal to the Input Method Context.
- */
-EAPI void
-isf_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window))
- {
- context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
-
- if ((context_scim->impl->client_window != 0) &&
- (context_scim->impl->client_window != _client_window))
- _client_window = context_scim->impl->client_window;
- }
-}
-
-/**
- * isf_imf_context_reset
- * @ctx: a #Ecore_IMF_Context
- *
- * This function will be called by Ecore IMF.
- *
- * Notify the Input Method Context that a change such as a change in cursor
- * position has been made. This will typically cause the Input Method Context
- * to clear the preedit state.
- */
-EAPI void
-isf_imf_context_reset(Ecore_IMF_Context *ctx)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim == _focused_ic)
- {
- WideString wstr = context_scim->impl->preedit_string;
-
- _panel_client.prepare(context_scim->id);
- context_scim->impl->si->reset();
- _panel_client.send();
-
- if (context_scim->impl->need_commit_preedit)
- {
- if (wstr.length())
- {
- ecore_imf_context_commit_event_add(context_scim->ctx, utf8_wcstombs(wstr).c_str());
- ecore_imf_context_event_callback_call(context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
- }
- _panel_client.prepare(context_scim->id);
- _panel_client.send();
- }
- }
-}
-
-/**
- * isf_imf_context_focus_in
- * @ctx: a #Ecore_IMF_Context
- *
- * This function will be called by Ecore IMF.
- *
- * Notify the Input Method Context that the widget to which its correspond has gained focus.
- */
-EAPI void
-isf_imf_context_focus_in(Ecore_IMF_Context *ctx)
-{
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (!context_scim)
- return;
-
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
-
- if (_focused_ic)
- {
- if (_focused_ic == context_scim)
- {
- SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
- return;
- }
- SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
- if (_focused_ic->ctx)
- isf_imf_context_focus_out(_focused_ic->ctx);
- }
-
- bool need_cap = false;
- bool need_reset = false;
- bool need_reg = false;
-
- if (context_scim && context_scim->impl)
- {
- _focused_ic = context_scim;
- _panel_client.prepare(context_scim->id);
-
- // Handle the "Shared Input Method" mode.
- if (_shared_input_method)
- {
- SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
- IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
- if (!factory.null())
- {
- if (_default_instance.null() || _default_instance->get_factory_uuid() != factory->get_uuid())
- {
- _default_instance = factory->create_instance("UTF-8", _default_instance.null() ? _instance_count++ : _default_instance->get_id());
- attach_instance(_default_instance);
- SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id() << " " << _default_instance->get_factory_uuid() << "\n";
- }
-
- context_scim->impl->shared_si = true;
- context_scim->impl->si = _default_instance;
-
- context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
- context_scim->impl->preedit_string.clear();
- context_scim->impl->preedit_attrlist.clear();
- context_scim->impl->preedit_caret = 0;
- context_scim->impl->preedit_started = false;
- need_cap = true;
- need_reset = true;
- need_reg = true;
- }
- }
- else if (context_scim->impl->shared_si)
- {
- SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
- IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
- if (!factory.null())
- {
- context_scim->impl->si = factory->create_instance("UTF-8", _instance_count++);
- context_scim->impl->preedit_string.clear();
- context_scim->impl->preedit_attrlist.clear();
- context_scim->impl->preedit_caret = 0;
- context_scim->impl->preedit_started = false;
- attach_instance(context_scim->impl->si);
- need_cap = true;
- need_reg = true;
- context_scim->impl->shared_si = false;
- SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id() << " " << context_scim->impl->si->get_factory_uuid() << "\n";
- }
- }
-
- context_scim->impl->si->set_frontend_data(static_cast <void*>(context_scim));
-
- if (need_reg) _panel_client.register_input_context(context_scim->id, context_scim->impl->si->get_factory_uuid());
- if (need_cap) set_ic_capabilities(context_scim);
- if (need_reset) context_scim->impl->si->reset();
-
- panel_req_focus_in(context_scim);
- panel_req_update_spot_location(context_scim);
- panel_req_update_factory_info(context_scim);
-
- if (context_scim->impl->is_on)
- {
- _panel_client.turn_on(context_scim->id);
- _panel_client.hide_preedit_string(context_scim->id);
- _panel_client.hide_aux_string(context_scim->id);
- _panel_client.hide_lookup_table(context_scim->id);
- context_scim->impl->si->focus_in();
- }
- else
- {
- _panel_client.turn_off(context_scim->id);
- }
-
- _panel_client.send();
- }
-
- if (ecore_imf_context_input_panel_enabled_get(ctx))
- ecore_imf_context_input_panel_show(ctx);
-}
-
-/**
- * isf_imf_context_focus_out
- * @ctx: a #Ecore_IMF_Context
- *
- * This function will be called by Ecore IMF.
- *
- * Notify the Input Method Context that the widget to which its correspond has lost focus.
- */
-EAPI void
-isf_imf_context_focus_out(Ecore_IMF_Context *ctx)
-{
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (!context_scim) return;
-
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
-
- if (context_scim && context_scim->impl && context_scim == _focused_ic)
- {
- WideString wstr = context_scim->impl->preedit_string;
-
- if (context_scim->impl->need_commit_preedit)
- {
- if (wstr.length())
- {
- ecore_imf_context_commit_event_add(context_scim->ctx, utf8_wcstombs(wstr).c_str());
- ecore_imf_context_event_callback_call(context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
- }
- _panel_client.prepare(context_scim->id);
- _panel_client.send();
- }
-
- _panel_client.prepare(context_scim->id);
- context_scim->impl->si->focus_out();
- context_scim->impl->si->reset();
- _panel_client.turn_off(context_scim->id);
- _panel_client.focus_out(context_scim->id);
- _panel_client.send();
- _focused_ic = 0;
- }
-
- if (ecore_imf_context_input_panel_enabled_get(ctx))
- ecore_imf_context_input_panel_hide(ctx);
-}
-
-/**
- * isf_imf_context_cursor_location_set
- * @ctx: a #Ecore_IMF_Context
- * @x: x position of New cursor.
- * @y: y position of New cursor.
- * @w: the width of New cursor.
- * @h: the height of New cursor.
- *
- * This function will be called by Ecore IMF.
- *
- * Notify the Input Method Context that a change in the cursor location has been made.
- */
-EAPI void
-isf_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
- Ecore_Evas *ee;
- int canvas_x, canvas_y;
- int new_cursor_x, new_cursor_y;
-
- if (cw == 0 && ch == 0)
- return;
-
- if (context_scim && context_scim->impl && context_scim == _focused_ic)
- {
- if (context_scim->impl->client_canvas)
- {
- ee = ecore_evas_ecore_evas_get(context_scim->impl->client_canvas);
- if (!ee) return;
-
- ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
- }
- else
- {
- if (context_scim->impl->client_window)
- window_to_screen_geometry_get(context_scim->impl->client_window, &canvas_x, &canvas_y);
- else
- return;
- }
-
- new_cursor_x = canvas_x + cx;
- new_cursor_y = canvas_y + cy + ch;
-
- // Don't update spot location while updating preedit string.
- if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
- return;
-
- if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y)
- {
- context_scim->impl->cursor_x = new_cursor_x;
- context_scim->impl->cursor_y = new_cursor_y;
- _panel_client.prepare(context_scim->id);
- panel_req_update_spot_location(context_scim);
- _panel_client.send();
- SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
- }
- }
-}
-
-/**
- * isf_imf_context_use_preedit_set
- * @ctx: a #Ecore_IMF_Context
- * @use_preedit: Whether the IM context should use the preedit string.
- *
- * This function will be called by Ecore IMF.
- *
- * Set whether the IM context should use the preedit string to display feedback.
- * If is 0 (default is 1), then the IM context may use some other method to
- * display feedback, such as displaying it in a child of the root window.
- */
-EAPI void
-isf_imf_context_use_preedit_set(Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit ? "true" : "false") << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
-
- if (!_on_the_spot) return;
-
- if (context_scim && context_scim->impl)
- {
- bool old = context_scim->impl->use_preedit;
- context_scim->impl->use_preedit = use_preedit;
- if (context_scim == _focused_ic)
- {
- _panel_client.prepare(context_scim->id);
-
- if (old != use_preedit)
- set_ic_capabilities(context_scim);
-
- if (context_scim->impl->preedit_string.length())
- slot_show_preedit_string(context_scim->impl->si);
-
- _panel_client.send();
- }
- }
-}
-
-EAPI void
-isf_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->is_on)
- {
- String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
-
- if (str)
- {
- if (mbs.length())
- *str = strdup(mbs.c_str());
- else
- *str = strdup("");
- }
-
- if (cursor_pos)
- {
- *cursor_pos = context_scim->impl->preedit_caret;
- }
-
- if (attrs)
- {
- if (mbs.length())
- {
- int start_index, end_index;
- int wlen = context_scim->impl->preedit_string.length();
-
- Ecore_IMF_Preedit_Attr *attr = NULL;
- AttributeList::const_iterator i;
- bool *attrs_flag = new bool [mbs.length()];
- memset(attrs_flag, 0, mbs.length() *sizeof(bool));
-
- for (i = context_scim->impl->preedit_attrlist.begin();
- i != context_scim->impl->preedit_attrlist.end(); ++i)
- {
- start_index = i->get_start();
- end_index = i->get_end();
-
- if (end_index <= wlen && start_index < end_index && i->get_type() != SCIM_ATTR_DECORATE_NONE)
- {
- start_index = utf8_offset_to_index(mbs.c_str(), i->get_start());
- end_index = utf8_offset_to_index(mbs.c_str(), i->get_end());
-
- if (i->get_type() == SCIM_ATTR_DECORATE)
- {
- attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
- if (attr == NULL)
- continue;
- attr->start_index = start_index;
- attr->end_index = end_index;
-
- if (i->get_value() == SCIM_ATTR_DECORATE_UNDERLINE)
- {
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
- *attrs = eina_list_append(*attrs, (void *)attr);
- }
- else if (i->get_value() == SCIM_ATTR_DECORATE_REVERSE)
- {
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
- *attrs = eina_list_append(*attrs, (void *)attr);
- }
- else if (i->get_value() == SCIM_ATTR_DECORATE_HIGHLIGHT)
- {
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
- *attrs = eina_list_append(*attrs, (void *)attr);
- }
- else
- {
- free(attr);
- }
-
- switch(i->get_value())
- {
- case SCIM_ATTR_DECORATE_UNDERLINE:
- case SCIM_ATTR_DECORATE_REVERSE:
- case SCIM_ATTR_DECORATE_HIGHLIGHT:
- // Record which character has attribute.
- for (int pos = start_index; pos < end_index; ++pos)
- attrs_flag [pos] = 1;
- break;
- default:
- break;
- }
- }
- else if (i->get_type() == SCIM_ATTR_FOREGROUND)
- {
- SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
- }
- else if (i->get_type() == SCIM_ATTR_BACKGROUND)
- {
- SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
- }
- }
- }
-
- // Add underline for all characters which don't have attribute.
- for (unsigned int pos = 0; pos < mbs.length(); ++pos)
- {
- if (!attrs_flag [pos])
- {
- int begin_pos = pos;
-
- while (pos < mbs.length() && !attrs_flag[pos])
- ++pos;
-
- // use REVERSE style as default
- attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
- if (attr == NULL)
- continue;
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
- attr->start_index = begin_pos;
- attr->end_index = pos;
- *attrs = eina_list_append(*attrs, (void *)attr);
- }
- }
-
- delete [] attrs_flag;
- }
- }
- }
- else
- {
- if (str)
- *str = strdup("");
-
- if (cursor_pos)
- *cursor_pos = 0;
-
- if (attrs)
- *attrs = NULL;
- }
-}
-
-/**
- * isf_imf_context_preedit_string_get
- * @ctx: a #Ecore_IMF_Context
- * @str: the preedit string
- * @cursor_pos: the cursor position
- *
- * This function will be called by Ecore IMF.
- *
- * To get the preedit string of the input method.
- */
-EAPI void
-isf_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->is_on)
- {
- String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
-
- if (str)
- {
- if (mbs.length())
- *str = strdup(mbs.c_str());
- else
- *str = strdup("");
- }
-
- if (cursor_pos)
- *cursor_pos = context_scim->impl->preedit_caret;
- }
- else
- {
- if (str)
- *str = strdup("");
-
- if (cursor_pos)
- *cursor_pos = 0;
- }
-}
-
-/**
- * isf_imf_context_cursor_position_set
- * @ctx: a #Ecore_IMF_Context
- * @cursor_pos: New cursor position in characters.
- *
- * This function will be called by Ecore IMF.
- *
- * Notify the Input Method Context that a change in the cursor position has been made.
- */
-EAPI void
-isf_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim == _focused_ic)
- {
- // Don't update spot location while updating preedit string.
- if (context_scim->impl->preedit_updating)
- return;
-
- if (context_scim->impl->cursor_pos != cursor_pos)
- {
- context_scim->impl->cursor_pos = cursor_pos;
- caps_mode_check(ctx, EINA_FALSE);
- }
- }
-}
-
-/**
- * isf_imf_context_input_mode_set
- * @ctx: a #Ecore_IMF_Context
- * @input_mode: the input mode
- *
- * This function will be called by Ecore IMF.
- *
- * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
- * is in Ecore_IMF.h.
- */
-EAPI void
-isf_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
- if (context_scim && context_scim->impl)
- context_scim->impl->input_mode = input_mode;
-}
-
-/**
- * isf_imf_context_prediction_allow_set
- * @ctx: a #Ecore_IMF_Context
- * @use_prediction: Whether the IM context should use the prediction.
- *
- * This function will be called by Ecore IMF.
- *
- * Set whether the IM context should use the prediction.
- */
-EAPI void
-isf_imf_context_prediction_allow_set(Ecore_IMF_Context* ctx, Eina_Bool prediction)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction ? "true" : "false") << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction)
- context_scim->impl->prediction_allow = prediction;
-}
-
-EAPI void
-isf_imf_context_autocapital_type_set(Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
-
- EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
-
- if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type)
- context_scim->impl->autocapital_type = autocapital_type;
-}
-
-/**
- * isf_imf_context_filter_event
- * @ctx: a #Ecore_IMF_Context
- * @type: The type of event defined by Ecore_IMF_Event_Type.
- * @event: The event itself.
- * Return value: %TRUE if the input method handled the key event.
- *
- * This function will be called by Ecore IMF.
- *
- * Allow an Ecore Input Context to internally handle an event. If this function
- * returns 1, then no further processing should be done for this event. Input
- * methods must be able to accept all types of events (simply returning 0 if
- * the event was not handled), but there is no obligation of any events to be
- * submitted to this function.
- */
-EAPI Eina_Bool
-isf_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
- Eina_Bool ret = EINA_FALSE;
-
- if (ic == NULL || ic->impl == NULL)
- return ret;
-
- KeyEvent key;
-
- if (type == ECORE_IMF_EVENT_KEY_DOWN)
- {
- Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
- scim_string_to_key(key, ev->key);
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
- if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
- if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
- }
- else if (type == ECORE_IMF_EVENT_KEY_UP)
- {
- Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
- scim_string_to_key(key, ev->key);
- key.mask = SCIM_KEY_ReleaseMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
- if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
- if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
- if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
- }
- else
- {
- return ret;
- }
-
- key.mask &= _valid_key_mask;
-
- _panel_client.prepare(ic->id);
-
- ret = EINA_TRUE;
- if (!filter_hotkeys(ic, key))
- {
- if (!_focused_ic || !_focused_ic->impl->is_on ||
- !_focused_ic->impl->si->process_key_event(key))
- ret = EINA_FALSE;
- }
-
- _panel_client.send();
-
- return ret;
-}
-
-EAPI void
-isf_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
- if (ic == NULL || ic->impl == NULL)
- return;
-
- ecore_x_e_virtual_keyboard_state_set
- (ic->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
-}
-
-EAPI void
-isf_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
- if (ic == NULL || ic->impl == NULL)
- return;
-
- ecore_x_e_virtual_keyboard_state_set
- (ic->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
-}
-
-/* Panel Slot functions */
-static void
-panel_slot_reload_config(int context EINA_UNUSED)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
- _config->reload();
-}
-
-static void
-panel_slot_exit(int /* context */)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- finalize();
-}
-
-static void
-panel_slot_update_lookup_table_page_size(int context, int page_size)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->update_lookup_table_page_size(page_size);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_lookup_table_page_up(int context)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->lookup_table_page_up();
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_lookup_table_page_down(int context)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->lookup_table_page_down();
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_trigger_property(int context, const String &property)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->trigger_property(property);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_process_helper_event(int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
- << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic ? ic->impl : 0) << " ic-uuid="
- << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid() : "" ) << "\n";
- if (ic && ic->impl && ic->impl->si->get_factory_uuid() == target_uuid)
- {
- _panel_client.prepare(ic->id);
- SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
- ic->impl->si->process_helper_event(helper_uuid, trans);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_move_preedit_caret(int context, int caret_pos)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->move_preedit_caret(caret_pos);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_select_candidate(int context, int cand_index)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- ic->impl->si->select_candidate(cand_index);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_process_key_event(int context, const KeyEvent &key)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
-
- if (key.is_key_press())
- ecore_x_test_fake_key_press(key.get_key_string().c_str());
-}
-
-static void
-panel_slot_commit_string(int context, const WideString &wstr)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs(wstr) << " ic=" << ic << "\n";
-
- if (ic && ic->impl)
- {
- if (_focused_ic != ic)
- return;
-
- ecore_imf_context_commit_event_add(ic->ctx, utf8_wcstombs(wstr).c_str());
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
- }
-}
-
-static void
-panel_slot_forward_key_event(int context, const KeyEvent &key)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
-
- if (ic && ic->impl && ic->impl->client_canvas)
- feed_key_event(ic->impl->client_canvas, key.get_key_string().c_str(), EINA_TRUE);
-}
-
-static void
-panel_slot_request_help(int context)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
-
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- panel_req_show_help(ic);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_request_factory_menu(int context)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
-
- if (ic && ic->impl)
- {
- _panel_client.prepare(ic->id);
- panel_req_show_factory_menu(ic);
- _panel_client.send();
- }
-}
-
-static void
-panel_slot_change_factory(int context, const String &uuid)
-{
- EcoreIMFContextISF *ic = find_ic(context);
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
-
- if (ic && ic->impl)
- {
- ic->impl->si->reset();
- _panel_client.prepare(ic->id);
- open_specific_factory(ic, uuid);
- _panel_client.send();
- }
-}
-
-/* Panel Requestion functions. */
-static void
-panel_req_show_help(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- String help;
-
- help = String("Smart Common Input Method platform ") +
- //String(SCIM_VERSION) +
- String("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n");
-
- if (ic && ic->impl)
- {
- IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
- if (sf)
- {
- help += utf8_wcstombs(sf->get_name());
- help += String(":\n\n");
-
- help += utf8_wcstombs(sf->get_help());
- help += String("\n\n");
-
- help += utf8_wcstombs(sf->get_credits());
- }
- _panel_client.show_help(ic->id, help);
- }
-}
-
-static void
-panel_req_show_factory_menu(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- std::vector<IMEngineFactoryPointer> factories;
- std::vector <PanelFactoryInfo> menu;
-
- _backend->get_factories_for_encoding(factories, "UTF-8");
-
- for (size_t i = 0; i < factories.size(); ++ i)
- {
- menu.push_back(PanelFactoryInfo(
- factories [i]->get_uuid(),
- utf8_wcstombs(factories [i]->get_name()),
- factories [i]->get_language(),
- factories [i]->get_icon_file()));
- }
-
- if (menu.size())
- _panel_client.show_factory_menu(ic->id, menu);
-}
-
-static void
-panel_req_update_factory_info(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (ic && ic->impl && ic == _focused_ic)
- {
- PanelFactoryInfo info;
- if (ic->impl->is_on)
- {
- IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
- if (sf)
- info = PanelFactoryInfo(sf->get_uuid(), utf8_wcstombs(sf->get_name()), sf->get_language(), sf->get_icon_file());
- }
- else
- {
- info = PanelFactoryInfo(String(""), String("English/Keyboard"), String("C"), "");
- }
- _panel_client.update_factory_info(ic->id, info);
- }
-}
-
-static void
-panel_req_focus_in(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- _panel_client.focus_in(ic->id, ic->impl->si->get_factory_uuid());
-}
-
-static void
-panel_req_update_spot_location(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- _panel_client.update_spot_location(ic->id, ic->impl->cursor_x, ic->impl->cursor_y);
-}
-
-static bool
-filter_hotkeys(EcoreIMFContextISF *ic, const KeyEvent &key)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- bool ret = false;
-
- _frontend_hotkey_matcher.push_key_event(key);
- _imengine_hotkey_matcher.push_key_event(key);
-
- FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result();
-
- if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER)
- {
- if (!ic->impl->is_on)
- turn_on_ic(ic);
- else
- turn_off_ic(ic);
- ret = true;
- }
- else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON)
- {
- if (!ic->impl->is_on)
- turn_on_ic(ic);
- ret = true;
- }
- else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF)
- {
- if (ic->impl->is_on)
- turn_off_ic(ic);
- ret = true;
- }
- else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY)
- {
- open_next_factory(ic);
- ret = true;
- }
- else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY)
- {
- open_previous_factory(ic);
- ret = true;
- }
- else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU)
- {
- panel_req_show_factory_menu(ic);
- ret = true;
- }
- else if (_imengine_hotkey_matcher.is_matched())
- {
- String sfid = _imengine_hotkey_matcher.get_match_result();
- open_specific_factory(ic, sfid);
- ret = true;
- }
- return ret;
-}
-
-static bool
-panel_initialize(void)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- String display_name;
- {
- const char *p = getenv("DISPLAY");
- if (p) display_name = String(p);
- }
-
- if (_panel_client.open_connection(_config->get_name(), display_name) >= 0)
- {
- int fd = _panel_client.get_connection_number();
-
- _panel_iochannel_read_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
-
- SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
-
- return true;
- }
- std::cerr << "panel_initialize() failed!!!\n";
- return false;
-}
-
-static void
-panel_finalize(void)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- _panel_client.close_connection();
-
- if (_panel_iochannel_read_handler)
- {
- ecore_main_fd_handler_del(_panel_iochannel_read_handler);
- _panel_iochannel_read_handler = 0;
- }
-
- if (_panel_iochannel_err_handler)
- {
- ecore_main_fd_handler_del(_panel_iochannel_err_handler);
- _panel_iochannel_err_handler = 0;
- }
-}
-
-static Eina_Bool
-panel_iochannel_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (fd_handler == _panel_iochannel_read_handler)
- {
- if (!_panel_client.filter_event())
- {
- panel_finalize();
- panel_initialize();
- return ECORE_CALLBACK_CANCEL;
- }
- }
- else if (fd_handler == _panel_iochannel_err_handler)
- {
- panel_finalize();
- panel_initialize();
- return ECORE_CALLBACK_CANCEL;
- }
- return ECORE_CALLBACK_RENEW;
-}
-
-static void
-turn_on_ic(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (ic && ic->impl && !ic->impl->is_on)
- {
- ic->impl->is_on = true;
-
- if (ic == _focused_ic)
- {
- panel_req_focus_in(ic);
- panel_req_update_spot_location(ic);
- panel_req_update_factory_info(ic);
- _panel_client.turn_on(ic->id);
- _panel_client.hide_preedit_string(ic->id);
- _panel_client.hide_aux_string(ic->id);
- _panel_client.hide_lookup_table(ic->id);
- ic->impl->si->focus_in();
- }
-
- //Record the IC on/off status
- if (_shared_input_method)
- _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
-
- if (ic->impl->use_preedit && ic->impl->preedit_string.length())
- {
- ecore_imf_context_preedit_start_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- ic->impl->preedit_started = true;
- }
- }
-}
-
-static void
-turn_off_ic(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (ic && ic->impl && ic->impl->is_on)
- {
- ic->impl->is_on = false;
-
- if (ic == _focused_ic)
- {
- ic->impl->si->focus_out();
-
- panel_req_update_factory_info(ic);
- _panel_client.turn_off(ic->id);
- }
-
- //Record the IC on/off status
- if (_shared_input_method)
- _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
-
- if (ic->impl->use_preedit && ic->impl->preedit_string.length())
- {
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- ecore_imf_context_preedit_end_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
- ic->impl->preedit_started = false;
- }
- }
-}
-
-static void
-set_ic_capabilities(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (ic && ic->impl)
- {
- unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
-
- if (!_on_the_spot || !ic->impl->use_preedit)
- cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
-
- ic->impl->si->update_client_capabilities(cap);
- }
-}
-
-static bool
-check_socket_frontend(void)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- SocketAddress address;
- SocketClient client;
-
- uint32 magic;
-
- address.set_address(scim_get_default_socket_frontend_address());
-
- if (!client.connect(address))
- return false;
-
- if (!scim_socket_open_connection(magic,
- String("ConnectionTester"),
- String("SocketFrontEnd"),
- client,
- 1000))
- return false;
-
- return true;
-}
-
-void
-initialize(void)
-{
- std::vector<String> config_list;
- std::vector<String> engine_list;
- std::vector<String> load_engine_list;
-
- std::vector<String>::iterator it;
-
- bool manual = false;
-
- bool socket = true;
-
- String config_module_name = "simple";
-
- printf("Initializing Ecore SCIM IMModule...\n");
-
- SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore SCIM IMModule...\n";
-
- // Get system language.
- _language = scim_get_locale_language(scim_get_current_locale());
-
- if (socket)
- {
- // If no Socket FrontEnd is running, then launch one.
- // And set manual to false.
- bool check_result = check_socket_frontend();
- if (!check_result)
- {
- std::cerr << "Launching a SCIM daemon with Socket FrontEnd...\n";
- //get modules list
- scim_get_imengine_module_list(engine_list);
-
- for (it = engine_list.begin(); it != engine_list.end(); it++)
- {
- if (*it != "socket")
- load_engine_list.push_back(*it);
- }
-
- const char *new_argv [] = { "--no-stay", 0 };
- scim_launch(true,
- config_module_name,
- (load_engine_list.size() ? scim_combine_string_list(load_engine_list, ',') : "none"),
- "socket",
- (char **)new_argv);
- manual = false;
- }
-
- // If there is one Socket FrontEnd running and it's not manual mode,
- // then just use this Socket Frontend.
- if (!manual)
- {
- for (int i = 0; i < 200; ++i)
- {
- if (check_result)
- {
- config_module_name = "socket";
- load_engine_list.clear();
- load_engine_list.push_back("socket");
- break;
- }
- scim_usleep(50000);
- check_result = check_socket_frontend();
- }
- }
- }
-
- if (config_module_name != "dummy")
- {
- //load config module
- SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
- _config_module = new ConfigModule(config_module_name);
-
- //create config instance
- if (_config_module != NULL && _config_module->valid())
- _config = _config_module->create_config();
- }
-
- if (_config.null())
- {
- SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
-
- if (_config_module) delete _config_module;
- _config_module = NULL;
-
- _config = new DummyConfig();
- config_module_name = "dummy";
- }
-
- reload_config_callback(_config);
- _config->signal_connect_reload(slot(reload_config_callback));
-
- // create backend
- _backend = new CommonBackEnd(_config, load_engine_list.size() ? load_engine_list : engine_list);
-
- if (_backend.null())
- std::cerr << "Cannot create BackEnd Object!\n";
- else
- _fallback_factory = _backend->get_factory(SCIM_COMPOSE_KEY_FACTORY_UUID);
-
- if (_fallback_factory.null())
- _fallback_factory = new DummyIMEngineFactory();
-
- _fallback_instance = _fallback_factory->create_instance(String("UTF-8"), 0);
- _fallback_instance->signal_connect_commit_string(slot(fallback_commit_string_cb));
-
- // Attach Panel Client signal.
- _panel_client.signal_connect_reload_config (slot(panel_slot_reload_config));
- _panel_client.signal_connect_exit (slot(panel_slot_exit));
- _panel_client.signal_connect_update_lookup_table_page_size(slot(panel_slot_update_lookup_table_page_size));
- _panel_client.signal_connect_lookup_table_page_up (slot(panel_slot_lookup_table_page_up));
- _panel_client.signal_connect_lookup_table_page_down (slot(panel_slot_lookup_table_page_down));
- _panel_client.signal_connect_trigger_property (slot(panel_slot_trigger_property));
- _panel_client.signal_connect_process_helper_event (slot(panel_slot_process_helper_event));
- _panel_client.signal_connect_move_preedit_caret (slot(panel_slot_move_preedit_caret));
- _panel_client.signal_connect_select_candidate (slot(panel_slot_select_candidate));
- _panel_client.signal_connect_process_key_event (slot(panel_slot_process_key_event));
- _panel_client.signal_connect_commit_string (slot(panel_slot_commit_string));
- _panel_client.signal_connect_forward_key_event (slot(panel_slot_forward_key_event));
- _panel_client.signal_connect_request_help (slot(panel_slot_request_help));
- _panel_client.signal_connect_request_factory_menu (slot(panel_slot_request_factory_menu));
- _panel_client.signal_connect_change_factory (slot(panel_slot_change_factory));
-
- if (!panel_initialize())
- std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
-}
-
-static void
-finalize(void)
-{
- SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
-
- // Reset this first so that the shared instance could be released correctly afterwards.
- _default_instance.reset();
-
- SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
- while (_used_ic_impl_list)
- {
- // In case in "shared input method" mode,
- // all contexts share only one instance,
- // so we need point the reference pointer correctly before finalizing.
- _used_ic_impl_list->si->set_frontend_data(static_cast <void*>(_used_ic_impl_list->parent));
- isf_imf_context_del(_used_ic_impl_list->parent->ctx);
- }
-
- delete_all_ic_impl();
-
- _fallback_instance.reset();
- _fallback_factory.reset();
-
- SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
- _backend.reset();
-
- SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
- _config.reset();
-
- if (_config_module)
- {
- SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
- delete _config_module;
- _config_module = 0;
- }
-
- _focused_ic = NULL;
- _ic_list = NULL;
-
- _scim_initialized = false;
-
- panel_finalize();
-}
-
-static void
-open_next_factory(EcoreIMFContextISF *ic)
-{
- SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
- IMEngineFactoryPointer sf = _backend->get_next_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
-
- if (!sf.null())
- {
- turn_off_ic(ic);
- ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
- ic->impl->si->set_frontend_data(static_cast <void*>(ic));
- ic->impl->preedit_string = WideString();
- ic->impl->preedit_caret = 0;
- attach_instance(ic->impl->si);
- _backend->set_default_factory(_language, sf->get_uuid());
- _panel_client.register_input_context(ic->id, sf->get_uuid());
- set_ic_capabilities(ic);
- turn_on_ic(ic);
-
- if (_shared_input_method)
- {
- _default_instance = ic->impl->si;
- ic->impl->shared_si = true;
- }
- }
-}
-
-static void
-open_previous_factory(EcoreIMFContextISF *ic)
-{
- if (ic == NULL)
- return;
-
- SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
- IMEngineFactoryPointer sf = _backend->get_previous_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
-
- if (!sf.null())
- {
- turn_off_ic(ic);
- ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
- ic->impl->si->set_frontend_data(static_cast <void*>(ic));
- ic->impl->preedit_string = WideString();
- ic->impl->preedit_caret = 0;
- attach_instance(ic->impl->si);
- _backend->set_default_factory(_language, sf->get_uuid());
- _panel_client.register_input_context(ic->id, sf->get_uuid());
- set_ic_capabilities(ic);
- turn_on_ic(ic);
-
- if (_shared_input_method)
- {
- _default_instance = ic->impl->si;
- ic->impl->shared_si = true;
- }
- }
-}
-
-static void
-open_specific_factory(EcoreIMFContextISF *ic,
- const String &uuid)
-{
- if (ic == NULL)
- return;
-
- SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
-
- // The same input method is selected, just turn on the IC.
- if (ic->impl->si->get_factory_uuid() == uuid)
- {
- turn_on_ic(ic);
- return;
- }
-
- IMEngineFactoryPointer sf = _backend->get_factory(uuid);
-
- if (uuid.length() && !sf.null())
- {
- turn_off_ic(ic);
- ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
- ic->impl->si->set_frontend_data(static_cast <void*>(ic));
- ic->impl->preedit_string = WideString();
- ic->impl->preedit_caret = 0;
- attach_instance(ic->impl->si);
- _backend->set_default_factory(_language, sf->get_uuid());
- _panel_client.register_input_context(ic->id, sf->get_uuid());
- set_ic_capabilities(ic);
- turn_on_ic(ic);
-
- if (_shared_input_method)
- {
- _default_instance = ic->impl->si;
- ic->impl->shared_si = true;
- }
- }
- else
- {
- // turn_off_ic comment out panel_req_update_factory_info()
- turn_off_ic(ic);
- if (ic && ic->impl->is_on)
- {
- ic->impl->is_on = false;
-
- if (ic == _focused_ic)
- {
- ic->impl->si->focus_out();
-
- panel_req_update_factory_info(ic);
- _panel_client.turn_off(ic->id);
- }
-
- //Record the IC on/off status
- if (_shared_input_method)
- _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
-
- if (ic->impl->use_preedit && ic->impl->preedit_string.length())
- {
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- ecore_imf_context_preedit_end_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
- ic->impl->preedit_started = false;
- }
- }
- }
-}
-
-static void initialize_modifier_bits(Display *display)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (__current_display == display)
- return;
-
- __current_display = display;
-
- if (display == 0)
- {
- __current_alt_mask = Mod1Mask;
- __current_meta_mask = ShiftMask | Mod1Mask;
- __current_super_mask = 0;
- __current_hyper_mask = 0;
- __current_numlock_mask = Mod2Mask;
- return;
- }
-
- XModifierKeymap *mods = NULL;
-
- ::KeyCode ctrl_l = XKeysymToKeycode(display, XK_Control_L);
- ::KeyCode ctrl_r = XKeysymToKeycode(display, XK_Control_R);
- ::KeyCode meta_l = XKeysymToKeycode(display, XK_Meta_L);
- ::KeyCode meta_r = XKeysymToKeycode(display, XK_Meta_R);
- ::KeyCode alt_l = XKeysymToKeycode(display, XK_Alt_L);
- ::KeyCode alt_r = XKeysymToKeycode(display, XK_Alt_R);
- ::KeyCode super_l = XKeysymToKeycode(display, XK_Super_L);
- ::KeyCode super_r = XKeysymToKeycode(display, XK_Super_R);
- ::KeyCode hyper_l = XKeysymToKeycode(display, XK_Hyper_L);
- ::KeyCode hyper_r = XKeysymToKeycode(display, XK_Hyper_R);
- ::KeyCode numlock = XKeysymToKeycode(display, XK_Num_Lock);
-
- int i, j;
-
- mods = XGetModifierMapping(display);
- if (mods == NULL)
- return;
-
- __current_alt_mask = 0;
- __current_meta_mask = 0;
- __current_super_mask = 0;
- __current_hyper_mask = 0;
- __current_numlock_mask = 0;
-
- /* We skip the first three sets for Shift, Lock, and Control. The
- remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
- for (i = 3; i < 8; i++)
- {
- for (j = 0; j < mods->max_keypermod; j++)
- {
- ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
- if (! code) continue;
- if (code == alt_l || code == alt_r)
- __current_alt_mask |= (1 << i);
- else if (code == meta_l || code == meta_r)
- __current_meta_mask |= (1 << i);
- else if (code == super_l || code == super_r)
- __current_super_mask |= (1 << i);
- else if (code == hyper_l || code == hyper_r)
- __current_hyper_mask |= (1 << i);
- else if (code == numlock)
- __current_numlock_mask |= (1 << i);
- }
- }
-
- /* Check whether there is a combine keys mapped to Meta */
- if (__current_meta_mask == 0)
- {
- char buf [32];
- XKeyEvent xkey;
- KeySym keysym_l, keysym_r;
-
- xkey.type = KeyPress;
- xkey.display = display;
- xkey.serial = 0L;
- xkey.send_event = False;
- xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
- xkey.time = 0;
- xkey.same_screen = False;
- xkey.subwindow = None;
- xkey.window = None;
- xkey.root = DefaultRootWindow(display);
- xkey.state = ShiftMask;
-
- xkey.keycode = meta_l;
- XLookupString(&xkey, buf, 32, &keysym_l, 0);
- xkey.keycode = meta_r;
- XLookupString(&xkey, buf, 32, &keysym_r, 0);
-
- if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
- __current_meta_mask = ShiftMask + __current_alt_mask;
- else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
- __current_meta_mask = ShiftMask + ControlMask;
- }
-
- XFreeModifiermap(mods);
-}
-
-static unsigned int scim_x11_keymask_scim_to_x11(Display *display, uint16 scimkeymask)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- unsigned int state = 0;
-
- initialize_modifier_bits(display);
-
- if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
- if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
- if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
- if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
- if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
- if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
- if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
- if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
-
- return state;
-}
-
-static XKeyEvent createKeyEvent(Display *display, Window &win,
- Window &winRoot, bool press,
- int keysym, int modifiers)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- XKeyEvent event;
-
- event.display = display;
- event.window = win;
- event.root = winRoot;
- event.subwindow = None;
- event.time = CurrentTime;
- 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 _x_send_key_event(const KeyEvent &key)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- // Obtain the X11 display.
- Display *display = (Display *)ecore_x_display_get();
- if (display == NULL)
- {
- std::cerr << "ecore_x_display_get() failed\n";
- return;
- }
-
- // Get the root window for the current display.
- Window winRoot = 0;
-
- // Find the window which has the current keyboard focus.
- Window winFocus = 0;
- int revert = RevertToParent;
-
- XGetInputFocus(display, &winFocus, &revert);
-
- unsigned int modifier = scim_x11_keymask_scim_to_x11(display, key.mask);
- XKeyEvent event;
- if (key.is_key_press())
- {
- event = createKeyEvent(display, winFocus, winRoot, true, key.code, modifier);
- XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
- }
- else
- {
- event = createKeyEvent(display, winFocus, winRoot, false, key.code, modifier);
- XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
- }
-}
-
-static void
-attach_instance(const IMEngineInstancePointer &si)
-{
- si->signal_connect_show_preedit_string(
- slot(slot_show_preedit_string));
- si->signal_connect_show_aux_string(
- slot(slot_show_aux_string));
- si->signal_connect_show_lookup_table(
- slot(slot_show_lookup_table));
-
- si->signal_connect_hide_preedit_string(
- slot(slot_hide_preedit_string));
- si->signal_connect_hide_aux_string(
- slot(slot_hide_aux_string));
- si->signal_connect_hide_lookup_table(
- slot(slot_hide_lookup_table));
-
- si->signal_connect_update_preedit_caret(
- slot(slot_update_preedit_caret));
- si->signal_connect_update_preedit_string(
- slot(slot_update_preedit_string));
- si->signal_connect_update_aux_string(
- slot(slot_update_aux_string));
- si->signal_connect_update_lookup_table(
- slot(slot_update_lookup_table));
-
- si->signal_connect_commit_string(
- slot(slot_commit_string));
-
- si->signal_connect_forward_key_event(
- slot(slot_forward_key_event));
-
- si->signal_connect_register_properties(
- slot(slot_register_properties));
-
- si->signal_connect_update_property(
- slot(slot_update_property));
-
- si->signal_connect_beep(
- slot(slot_beep));
-
- si->signal_connect_start_helper(
- slot(slot_start_helper));
-
- si->signal_connect_stop_helper(
- slot(slot_stop_helper));
-
- si->signal_connect_send_helper_event(
- slot(slot_send_helper_event));
-
- si->signal_connect_get_surrounding_text(
- slot(slot_get_surrounding_text));
-
- si->signal_connect_delete_surrounding_text(
- slot(slot_delete_surrounding_text));
-}
-
-// Implementation of slot functions
-static void
-slot_show_preedit_string(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- {
- if (ic->impl->use_preedit)
- {
- if (!ic->impl->preedit_started)
- {
- ecore_imf_context_preedit_start_event_add(_focused_ic->ctx);
- ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
- ic->impl->preedit_started = true;
- }
- }
- else
- _panel_client.show_preedit_string(ic->id);
- }
-}
-
-static void
-slot_show_aux_string(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.show_aux_string(ic->id);
-}
-
-static void
-slot_show_lookup_table(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.show_lookup_table(ic->id);
-}
-
-static void
-slot_hide_preedit_string(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- {
- bool emit = false;
- if (ic->impl->preedit_string.length())
- {
- ic->impl->preedit_string = WideString();
- ic->impl->preedit_caret = 0;
- ic->impl->preedit_attrlist.clear();
- emit = true;
- }
- if (ic->impl->use_preedit)
- {
- if (emit)
- {
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
- if (ic->impl->preedit_started)
- {
- ecore_imf_context_preedit_end_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
- ic->impl->preedit_started = false;
- }
- }
- else
- _panel_client.hide_preedit_string(ic->id);
- }
-}
-
-static void
-slot_hide_aux_string(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.hide_aux_string(ic->id);
-}
-
-static void
-slot_hide_lookup_table(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.hide_lookup_table(ic->id);
-}
-
-static void
-slot_update_preedit_caret(IMEngineInstanceBase *si, int caret)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret)
- {
- ic->impl->preedit_caret = caret;
- if (ic->impl->use_preedit)
- {
- if (!ic->impl->preedit_started)
- {
- ecore_imf_context_preedit_start_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
- ic->impl->preedit_started = true;
- }
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
- else
- _panel_client.update_preedit_caret(ic->id, caret);
- }
-}
-
-static void
-slot_update_preedit_string(IMEngineInstanceBase *si,
- const WideString & str,
- const AttributeList & attrs)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length()))
- {
- ic->impl->preedit_string = str;
- ic->impl->preedit_attrlist = attrs;
- if (ic->impl->use_preedit)
- {
- if (!ic->impl->preedit_started)
- {
- ecore_imf_context_preedit_start_event_add(_focused_ic->ctx);
- ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
- ic->impl->preedit_started = true;
- }
- ic->impl->preedit_caret = str.length();
- ic->impl->preedit_updating = true;
- ecore_imf_context_preedit_changed_event_add(ic->ctx);
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- ic->impl->preedit_updating = false;
- }
- else
- {
- _panel_client.update_preedit_string(ic->id, str, attrs);
- }
- }
-}
-
-static void
-slot_update_aux_string(IMEngineInstanceBase *si,
- const WideString & str,
- const AttributeList & attrs)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.update_aux_string(ic->id, str, attrs);
-}
-
-static void
-slot_commit_string(IMEngineInstanceBase *si,
- const WideString & str)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->ctx)
- {
- ecore_imf_context_commit_event_add(ic->ctx, utf8_wcstombs(str).c_str());
- ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());
- }
-}
-
-static void
-slot_forward_key_event(IMEngineInstanceBase *si,
- const KeyEvent & key)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && _focused_ic == ic)
- {
- if (!_fallback_instance->process_key_event(key))
- _x_send_key_event(key);
- }
-}
-
-static void
-slot_update_lookup_table(IMEngineInstanceBase *si,
- const LookupTable & table)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.update_lookup_table(ic->id, table);
-}
-
-static void
-slot_register_properties(IMEngineInstanceBase *si,
- const PropertyList & properties)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.register_properties(ic->id, properties);
-}
-
-static void
-slot_update_property(IMEngineInstanceBase *si,
- const Property & property)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- _panel_client.update_property(ic->id, property);
-}
-
-static void
-slot_beep(IMEngineInstanceBase *si)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- ecore_x_bell(0);
-}
-
-static void
-slot_start_helper(IMEngineInstanceBase *si,
- const String &helper_uuid)
-{
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
- << (ic ? ic->id : -1) << " ic=" << ic
- << " ic-uuid=" << ((ic ) ? ic->impl->si->get_factory_uuid() : "") << "...\n";
-
- if (ic && ic->impl)
- _panel_client.start_helper(ic->id, helper_uuid);
-}
-
-static void
-slot_stop_helper(IMEngineInstanceBase *si,
- const String &helper_uuid)
-{
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic ? ic->id : -1) << " ic=" << ic << "...\n";
-
- if (ic && ic->impl)
- _panel_client.stop_helper(ic->id, helper_uuid);
-}
-
-static void
-slot_send_helper_event(IMEngineInstanceBase *si,
- const String &helper_uuid,
- const Transaction &trans)
-{
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
- << (ic ? ic->id : -1) << " ic=" << ic
- << " ic-uuid=" << ((ic) ? ic->impl->si->get_factory_uuid() : "") << "...\n";
-
- if (ic && ic->impl)
- _panel_client.send_helper_event(ic->id, helper_uuid, trans);
-}
-
-static bool
-slot_get_surrounding_text(IMEngineInstanceBase *si,
- WideString &text,
- int &cursor,
- int maxlen_before,
- int maxlen_after)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- {
- char *surrounding = NULL;
- int cursor_index;
- if (ecore_imf_context_surrounding_get(_focused_ic->ctx, &surrounding, &cursor_index))
- {
- SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
- SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
- WideString before(utf8_mbstowcs(String(surrounding, surrounding + cursor_index)));
- WideString after(utf8_mbstowcs(String(surrounding + cursor_index)));
- if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length())
- before = WideString(before.begin() + (before.length() - maxlen_before), before.end());
- else if (maxlen_before == 0) before = WideString();
- if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length())
- after = WideString(after.begin(), after.begin() + maxlen_after);
- else if (maxlen_after == 0) after = WideString();
- text = before + after;
- cursor = before.length();
- return true;
- }
- }
- return false;
-}
-
-static bool
-slot_delete_surrounding_text(IMEngineInstanceBase *si,
- int offset,
- int len)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
-
- if (ic && ic->impl && _focused_ic == ic)
- {
- Ecore_IMF_Event_Delete_Surrounding ev;
- ev.ctx = _focused_ic->ctx;
- ev.n_chars = len;
- ev.offset = offset;
- ecore_imf_context_delete_surrounding_event_add(_focused_ic->ctx, offset, len);
- ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
- return true;
- }
- return false;
-}
-
-static void
-reload_config_callback(const ConfigPointer &config)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- _frontend_hotkey_matcher.load_hotkeys(config);
- _imengine_hotkey_matcher.load_hotkeys(config);
-
- KeyEvent key;
-
- scim_string_to_key(key,
- config->read(String(SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
- String("Shift+Control+Alt+Lock")));
-
- _valid_key_mask = (key.mask > 0)?(key.mask):0xFFFF;
- _valid_key_mask |= SCIM_KEY_ReleaseMask;
- // Special treatment for two backslash keys on jp106 keyboard.
- _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
-
- _on_the_spot = config->read(String(SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
- _shared_input_method = config->read(String(SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
-
- // Get keyboard layout setting
- // Flush the global config first, in order to load the new configs from disk.
- scim_global_config_flush();
-
- _keyboard_layout = scim_get_default_keyboard_layout();
-}
-
-static void
-fallback_commit_string_cb(IMEngineInstanceBase *si EINA_UNUSED,
- const WideString &str)
-{
- SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
-
- if (_focused_ic && _focused_ic->impl)
- {
- ecore_imf_context_commit_event_add(_focused_ic->ctx, utf8_wcstombs(str).c_str());
- ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());
- }
-}
-
+++ /dev/null
-#ifndef __ISF_IMF_CONTEXT_H
-#define __ISF_IMF_CONTEXT_H
-
-#include <Ecore_IMF.h>
-
-typedef struct _EcoreIMFContextISF EcoreIMFContextISF;
-typedef struct _EcoreIMFContextISFImpl EcoreIMFContextISFImpl;
-
-struct _EcoreIMFContextISF {
- Ecore_IMF_Context *ctx;
-
- EcoreIMFContextISFImpl *impl;
-
- int id; /* Input Context id*/
- struct _EcoreIMFContextISF *next;
-};
-
-void isf_imf_context_add (Ecore_IMF_Context *ctx);
-void isf_imf_context_del (Ecore_IMF_Context *ctx);
-void isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window);
-void isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *window);
-void isf_imf_context_focus_in (Ecore_IMF_Context *ctx);
-void isf_imf_context_focus_out (Ecore_IMF_Context *ctx);
-void isf_imf_context_reset (Ecore_IMF_Context *ctx);
-void isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos);
-void isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int x, int y, int w, int h);
-void isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
-void isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos);
-void isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos);
-void isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit);
-Eina_Bool isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
-void isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction);
-void isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type);
-void isf_imf_context_input_panel_layout_set (Ecore_IMF_Context* ctx, Ecore_IMF_Input_Panel_Layout layout);
-void isf_imf_context_input_panel_show(Ecore_IMF_Context *ctx);
-void isf_imf_context_input_panel_hide(Ecore_IMF_Context *ctx);
-
-EcoreIMFContextISF* isf_imf_context_new (void);
-void isf_imf_context_shutdown (void);
-
-#endif /* __ISF_IMF_CONTEXT_H */
-
+++ /dev/null
-#include <stdio.h>
-#include "scim_imcontext.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
- static const Ecore_IMF_Context_Info isf_imf_info = {
- "scim", /* ID */
- "SCIM immodule for Ecore", /* Description */
- "*", /* Default locales */
- NULL, /* Canvas type */
- 0 /* Canvas required */
- };
-
- static Ecore_IMF_Context_Class isf_imf_class = {
- isf_imf_context_add, /* add */
- isf_imf_context_del, /* del */
- isf_imf_context_client_window_set, /* client_window_set */
- isf_imf_context_client_canvas_set, /* client_canvas_set */
- isf_imf_context_input_panel_show, /* input_panel_show, - show */
- isf_imf_context_input_panel_hide, /* input_panel_hide, - hide */
- isf_imf_context_preedit_string_get, /* get_preedit_string */
- isf_imf_context_focus_in, /* focus_in */
- isf_imf_context_focus_out, /* focus_out */
- isf_imf_context_reset, /* reset */
- isf_imf_context_cursor_position_set, /* cursor_position_set */
- isf_imf_context_use_preedit_set, /* use_preedit_set */
- isf_imf_context_input_mode_set, /* input_mode_set */
- isf_imf_context_filter_event, /* filter_event */
- isf_imf_context_preedit_string_with_attributes_get, /* preedit_string_with_attribute_get */
- isf_imf_context_prediction_allow_set, /* prediction_allow_set */
- isf_imf_context_autocapital_type_set, /* autocapital_type_set */
- NULL, /* control panel show */
- NULL, /* control panel hide */
- NULL, /* input_panel_layout_set */
- NULL, /* isf_imf_context_input_panel_layout_get, */
- NULL, /* isf_imf_context_input_panel_language_set, */
- NULL, /* isf_imf_context_input_panel_language_get, */
- isf_imf_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 */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- };
-
- static Ecore_IMF_Context *imf_module_create (void);
- static Ecore_IMF_Context *imf_module_exit (void);
-
- static Eina_Bool imf_module_init (void)
- {
- ecore_imf_module_register (&isf_imf_info, imf_module_create, imf_module_exit);
- return EINA_TRUE;
- }
-
- static void imf_module_shutdown (void)
- {
- isf_imf_context_shutdown ();
- }
-
- static Ecore_IMF_Context *imf_module_create (void)
- {
- Ecore_IMF_Context *ctx = NULL;
- EcoreIMFContextISF *ctxd = NULL;
-
- ctxd = isf_imf_context_new ();
- if (!ctxd)
- {
- printf ("isf_imf_context_new () failed!!!\n");
- return NULL;
- }
-
- ctx = ecore_imf_context_new (&isf_imf_class);
- if (!ctx)
- {
- delete ctxd;
- return NULL;
- }
-
- ecore_imf_context_data_set (ctx, ctxd);
-
- return ctx;
- }
-
- static Ecore_IMF_Context *imf_module_exit (void)
- {
- return NULL;
- }
-
- EINA_MODULE_INIT(imf_module_init);
- EINA_MODULE_SHUTDOWN(imf_module_shutdown);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
+++ /dev/null
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <Eina.h>
-#include <Ecore.h>
-#include <Ecore_Input.h>
-#include <Ecore_IMF.h>
-#include <Ecore_X.h>
-#include <X11/Xlib.h>
-#include <X11/Xlocale.h>
-#include <X11/Xutil.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <langinfo.h>
-#include <assert.h>
-
-static int _ecore_imf_xim_log_dom = -1;
-
-#ifdef CRITICAL
-#undef CRITICAL
-#endif
-#define CRITICAL(...) EINA_LOG_DOM_CRIT(_ecore_imf_xim_log_dom, __VA_ARGS__)
-
-#ifdef ERR
-#undef ERR
-#endif
-#define ERR(...) EINA_LOG_DOM_ERR(_ecore_imf_xim_log_dom, __VA_ARGS__)
-
-#ifdef WRN
-#undef WRN
-#endif
-#define WRN(...) EINA_LOG_DOM_WARN(_ecore_imf_xim_log_dom, __VA_ARGS__)
-
-#ifdef DBG
-#undef DBG
-#endif
-#define DBG(...) EINA_LOG_DOM_DBG(_ecore_imf_xim_log_dom, __VA_ARGS__)
-
-
-static Eina_List *open_ims = NULL;
-
-#define FEEDBACK_MASK (XIMReverse | XIMUnderline | XIMHighlight)
-
-typedef struct _XIM_Im_Info XIM_Im_Info;
-
-typedef struct _Ecore_IMF_Context_Data Ecore_IMF_Context_Data;
-
-struct _XIM_Im_Info
-{
- Ecore_X_Window win;
- Ecore_IMF_Context_Data *user;
- char *locale;
- XIM im;
- Eina_List *ics;
- Eina_Bool reconnecting;
- XIMStyles *xim_styles;
- Eina_Bool supports_string_conversion : 1;
- Eina_Bool supports_cursor : 1;
-};
-
-struct _Ecore_IMF_Context_Data
-{
- Ecore_X_Window win;
- long mask;
- XIC ic; /* Input context for composed characters */
- char *locale;
- XIM_Im_Info *im_info;
- int preedit_length;
- int preedit_cursor;
- Eina_Unicode *preedit_chars;
- Eina_Bool use_preedit;
- Eina_Bool finalizing;
- Eina_Bool has_focus;
- Eina_Bool in_toplevel;
- XIMFeedback *feedbacks;
-
- XIMCallback destroy_cb;
-
- XIMCallback preedit_start_cb;
- XIMCallback preedit_done_cb;
- XIMCallback preedit_draw_cb;
- XIMCallback preedit_caret_cb;
-};
-
-/* prototype */
-static Ecore_IMF_Context_Data *_ecore_imf_xim_context_data_new(void);
-static void _ecore_imf_xim_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data);
-
-static void _ecore_imf_xim_feedback_attr_add(Eina_List **attrs,
- const char *str,
- XIMFeedback feedback,
- int start_pos,
- int end_pos);
-
-static void _ecore_imf_xim_ic_reinitialize(Ecore_IMF_Context *ctx);
-static void _ecore_imf_xim_ic_client_window_set(Ecore_IMF_Context *ctx,
- Ecore_X_Window window);
-static int _ecore_imf_xim_preedit_start_call(XIC xic,
- XPointer client_data,
- XPointer call_data);
-static void _ecore_imf_xim_preedit_done_call(XIC xic,
- XPointer client_data,
- XPointer call_data);
-static void _ecore_imf_xim_preedit_draw_call(XIC xic,
- XPointer client_data,
- XIMPreeditDrawCallbackStruct *call_data);
-static void _ecore_imf_xim_preedit_caret_call(XIC xic,
- XPointer client_data,
- XIMPreeditCaretCallbackStruct *call_data);
-
-static int _ecore_imf_xim_text_to_utf8(Ecore_IMF_Context *ctx,
- XIMText *xim_text,
- char **text);
-
-static XVaNestedList _ecore_imf_xim_preedit_callback_set(Ecore_IMF_Context *ctx);
-static XIC _ecore_imf_xim_ic_get(Ecore_IMF_Context *ctx);
-static XIM_Im_Info *_ecore_imf_xim_im_get(Ecore_X_Window window,
- char *locale);
-static void _ecore_imf_xim_info_im_init(XIM_Im_Info *info);
-static void _ecore_imf_xim_info_im_shutdown(Ecore_X_Display *display,
- int is_error,
- XIM_Im_Info *info);
-static void _ecore_imf_xim_instantiate_cb(Display *display,
- XPointer client_data,
- XPointer call_data);
-static void _ecore_imf_xim_destroy_cb(XIM xim,
- XPointer client_data,
- XPointer call_data);
-static void _ecore_imf_xim_im_setup(XIM_Im_Info *info);
-
-static unsigned int
-_ecore_imf_xim_utf8_offset_to_index(const char *str, int offset)
-{
- int idx = 0;
- int i;
- for (i = 0; i < offset; i++)
- {
- eina_unicode_utf8_get_next(str, &idx);
- }
-
- return idx;
-}
-
-static void
-_ecore_imf_context_xim_add(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = _ecore_imf_xim_context_data_new();
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- imf_context_data->use_preedit = EINA_TRUE;
- imf_context_data->finalizing = EINA_FALSE;
- imf_context_data->has_focus = EINA_FALSE;
- imf_context_data->in_toplevel = EINA_FALSE;
-
- ecore_imf_context_data_set(ctx, imf_context_data);
-}
-
-static void
-_ecore_imf_context_xim_del(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- imf_context_data->finalizing = EINA_TRUE;
- if (imf_context_data->im_info && !imf_context_data->im_info->ics->next)
- {
- if (imf_context_data->im_info->reconnecting == EINA_TRUE)
- {
- Ecore_X_Display *dsp;
- dsp = ecore_x_display_get();
- XUnregisterIMInstantiateCallback(dsp,
- NULL, NULL, NULL,
- _ecore_imf_xim_instantiate_cb,
- (XPointer)imf_context_data->im_info);
- }
- else if (imf_context_data->im_info->im)
- {
- XIMCallback im_destroy_callback;
- im_destroy_callback.client_data = NULL;
- im_destroy_callback.callback = NULL;
- XSetIMValues(imf_context_data->im_info->im,
- XNDestroyCallback, &im_destroy_callback,
- NULL);
- }
- }
-
- _ecore_imf_xim_ic_client_window_set(ctx, 0);
-
- _ecore_imf_xim_context_data_destroy(imf_context_data);
-}
-
-static void
-_ecore_imf_context_xim_client_window_set(Ecore_IMF_Context *ctx,
- void *window)
-{
- DBG("ctx=%p, window=%p", ctx, window);
- _ecore_imf_xim_ic_client_window_set(ctx, (Ecore_X_Window)((unsigned long)window));
-}
-
-static void
-_ecore_imf_context_xim_preedit_string_get(Ecore_IMF_Context *ctx,
- char **str,
- int *cursor_pos)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- char *utf8;
- int len;
-
- DBG("ctx=%p, imf_context_data=%p, str=%p, cursor_pos=%p",
- ctx, imf_context_data, str, cursor_pos);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- if (imf_context_data->preedit_chars)
- {
- utf8 = eina_unicode_unicode_to_utf8(imf_context_data->preedit_chars,
- &len);
- if (str)
- *str = utf8;
- else
- free(utf8);
- }
- else
- {
- if (str)
- *str = NULL;
- if (cursor_pos)
- *cursor_pos = 0;
- }
-
- if (cursor_pos)
- *cursor_pos = imf_context_data->preedit_cursor;
-}
-
-static void
-_ecore_imf_context_xim_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
- char **str,
- Eina_List **attrs,
- int *cursor_pos)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
-
- DBG("ctx=%p, imf_context_data=%p, str=%p, attrs=%p, cursor_pos=%p",
- ctx, imf_context_data, str, attrs, cursor_pos);
-
- _ecore_imf_context_xim_preedit_string_get(ctx, str, cursor_pos);
-
- if (!attrs) return;
- if (!imf_context_data || !imf_context_data->feedbacks) return;
-
- int i = 0;
- XIMFeedback last_feedback = 0;
- int start = -1;
-
- for (i = 0; i < imf_context_data->preedit_length; i++)
- {
- XIMFeedback new_feedback = imf_context_data->feedbacks[i] & FEEDBACK_MASK;
-
- if (new_feedback != last_feedback)
- {
- if (start >= 0)
- _ecore_imf_xim_feedback_attr_add(attrs, *str, last_feedback, start, i);
-
- last_feedback = new_feedback;
- start = i;
- }
- }
-
- if (start >= 0)
- _ecore_imf_xim_feedback_attr_add(attrs, *str, last_feedback, start, i);
-}
-
-static void
-_ecore_imf_context_xim_focus_in(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIC ic;
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- ic = imf_context_data->ic;
- imf_context_data->has_focus = EINA_TRUE;
-
- if (ecore_imf_context_input_panel_enabled_get(ctx))
- ecore_imf_context_input_panel_show(ctx);
-
- if (ic)
- {
- char *str;
-
-#ifdef X_HAVE_UTF8_STRING
- if ((str = Xutf8ResetIC(ic)))
-#else
- if ((str = XmbResetIC(ic)))
-#endif
- XFree(str);
-
- XSetICFocus(ic);
- }
-}
-
-static void
-_ecore_imf_context_xim_focus_out(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIC ic;
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- if (imf_context_data->has_focus == EINA_TRUE)
- {
- imf_context_data->has_focus = EINA_FALSE;
- ic = imf_context_data->ic;
- if (ic)
- XUnsetICFocus(ic);
-
- if (ecore_imf_context_input_panel_enabled_get(ctx))
- ecore_imf_context_input_panel_hide(ctx);
- }
-}
-
-static void
-_ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIC ic;
- char *result;
- /* restore conversion state after resetting ic later */
- XIMPreeditState preedit_state = XIMPreeditUnKnown;
- XVaNestedList preedit_attr;
- Eina_Bool have_preedit_state = EINA_FALSE;
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- ic = imf_context_data->ic;
- if (!ic)
- return;
-
- if (imf_context_data->preedit_length == 0)
- return;
-
- preedit_attr = XVaCreateNestedList(0,
- XNPreeditState, &preedit_state,
- NULL);
- if (!XGetICValues(ic,
- XNPreeditAttributes, preedit_attr,
- NULL))
- have_preedit_state = EINA_TRUE;
-
- XFree(preedit_attr);
-
- result = XmbResetIC(ic);
-
- preedit_attr = XVaCreateNestedList(0,
- XNPreeditState, preedit_state,
- NULL);
- if (have_preedit_state)
- XSetICValues(ic,
- XNPreeditAttributes, preedit_attr,
- NULL);
-
- XFree(preedit_attr);
-
- if (imf_context_data->feedbacks)
- {
- free(imf_context_data->feedbacks);
- imf_context_data->feedbacks = NULL;
- }
-
- if (imf_context_data->preedit_length)
- {
- imf_context_data->preedit_length = 0;
- free(imf_context_data->preedit_chars);
- imf_context_data->preedit_chars = NULL;
-
- ecore_imf_context_preedit_changed_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
-
- if (result)
- {
- char *result_utf8 = strdup(result);
- if (result_utf8)
- {
- ecore_imf_context_commit_event_add(ctx, result_utf8);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, result_utf8);
- free(result_utf8);
- }
- }
-
- XFree(result);
-}
-
-static void
-_ecore_imf_context_xim_use_preedit_set(Ecore_IMF_Context *ctx,
- Eina_Bool use_preedit)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
-
- DBG("ctx=%p, imf_context_data=%p, use_preedit=%hhu", ctx, imf_context_data, use_preedit);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- use_preedit = use_preedit != EINA_FALSE;
-
- if (imf_context_data->use_preedit != use_preedit)
- {
- imf_context_data->use_preedit = use_preedit;
- _ecore_imf_xim_ic_reinitialize(ctx);
- }
-}
-
-static void
-_ecore_imf_xim_feedback_attr_add(Eina_List **attrs,
- const char *str,
- XIMFeedback feedback,
- int start_pos,
- int end_pos)
-{
- Ecore_IMF_Preedit_Attr *attr;
- unsigned int start_index = _ecore_imf_xim_utf8_offset_to_index(str, start_pos);
- unsigned int end_index = _ecore_imf_xim_utf8_offset_to_index(str, end_pos);
-
- if (feedback & FEEDBACK_MASK)
- {
- attr = calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
- attr->start_index = start_index;
- attr->end_index = end_index;
- *attrs = eina_list_append(*attrs, attr);
- }
- else
- return;
-
- if (feedback & XIMUnderline)
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
-
- if (feedback & XIMReverse)
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
-
- if (feedback & XIMHighlight)
- attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
-}
-
-static void
-_ecore_imf_context_xim_cursor_location_set(Ecore_IMF_Context *ctx,
- int x, int y, int w, int h)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIC ic;
- XVaNestedList preedit_attr;
- XPoint spot;
-
- DBG("ctx=%p, imf_context_data=%p, location=(%d, %d, %d, %d)",
- ctx, imf_context_data, x, y, w, h);
-
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
- ic = imf_context_data->ic;
- if (!ic)
- return;
-
- spot.x = x;
- spot.y = y + h;
-
- preedit_attr = XVaCreateNestedList(0,
- XNSpotLocation, &spot,
- NULL);
- XSetICValues(ic,
- XNPreeditAttributes, preedit_attr,
- NULL);
-
- XFree(preedit_attr);
-}
-
-static void
-_ecore_imf_context_xim_input_panel_show(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- ecore_x_e_virtual_keyboard_state_set
- (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
-}
-
-static void
-_ecore_imf_context_xim_input_panel_hide(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- ecore_x_e_virtual_keyboard_state_set
- (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
-}
-
-static unsigned int
-_ecore_x_event_reverse_modifiers(unsigned int state)
-{
- unsigned int modifiers = 0;
-
- /**< "Control" is pressed */
- if (state & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
- modifiers |= ECORE_X_MODIFIER_CTRL;
-
- /**< "Alt" is pressed */
- if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
- modifiers |= ECORE_X_MODIFIER_ALT;
-
- /**< "Shift" is pressed */
- if (state & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
- modifiers |= ECORE_X_MODIFIER_SHIFT;
-
- /**< "Win" (between "Ctrl" and "Alt") is pressed */
- if (state & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
- modifiers |= ECORE_X_MODIFIER_WIN;
-
- /**< "AltGr" is pressed */
- if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
- modifiers |= ECORE_X_MODIFIER_ALTGR;
-
- return modifiers;
-}
-
-static unsigned int
-_ecore_x_event_reverse_locks(unsigned int state)
-{
- unsigned int locks = 0;
-
- /**< "Num" lock is active */
- if (state & ECORE_IMF_KEYBOARD_LOCK_NUM)
- locks |= ECORE_X_LOCK_NUM;
-
- if (state & ECORE_IMF_KEYBOARD_LOCK_CAPS)
- locks |= ECORE_X_LOCK_CAPS;
-
- if (state & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
- locks |= ECORE_X_LOCK_SCROLL;
-
- return locks;
-}
-
-static KeyCode
-_ecore_imf_xim_keycode_get(Ecore_X_Display *dsp,
- const char *keyname)
-{
- KeyCode keycode;
-
- //DBG("keyname=%s keysym=%lu", keyname, XStringToKeysym(keyname));
- if (strcmp(keyname, "Keycode-0") == 0)
- keycode = 0;
- else
- keycode = XKeysymToKeycode(dsp, XStringToKeysym(keyname));
-
- return keycode;
-}
-
-static Eina_Bool
-_ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx,
- Ecore_IMF_Event_Type type,
- Ecore_IMF_Event *event)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIC ic;
- Ecore_X_Display *dsp;
- Ecore_X_Window win;
-
- int val;
- char compose_buffer[256];
- KeySym sym;
- char *compose = NULL;
- char *tmp = NULL;
- Eina_Bool result = EINA_FALSE;
-
- DBG("ctx=%p, imf_context_data=%p, type=%d, event=%p",
- ctx, imf_context_data, type, event);
- EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, EINA_FALSE);
- ic = imf_context_data->ic;
- if (!ic)
- ic = _ecore_imf_xim_ic_get(ctx);
-
- if (type == ECORE_IMF_EVENT_KEY_DOWN)
- {
- XKeyPressedEvent xev;
- Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
- DBG("ECORE_IMF_EVENT_KEY_DOWN");
-
- dsp = ecore_x_display_get();
- win = imf_context_data->win;
-
- xev.type = KeyPress;
- xev.serial = 0; /* hope it doesn't matter */
- xev.send_event = 0;
- xev.display = dsp;
- xev.window = win;
- xev.root = ecore_x_window_root_get(win);
- xev.subwindow = win;
- xev.time = ev->timestamp;
- xev.x = xev.x_root = 0;
- xev.y = xev.y_root = 0;
- xev.state = 0;
- xev.state |= _ecore_x_event_reverse_modifiers(ev->modifiers);
- xev.state |= _ecore_x_event_reverse_locks(ev->locks);
- xev.keycode = _ecore_imf_xim_keycode_get(dsp, ev->keyname);
- xev.same_screen = True;
-
- if (ic)
- {
- Status mbstatus;
-#ifdef X_HAVE_UTF8_STRING
- val = Xutf8LookupString(ic,
- &xev,
- compose_buffer,
- sizeof(compose_buffer) - 1,
- &sym,
- &mbstatus);
-#else /* ifdef X_HAVE_UTF8_STRING */
- val = XmbLookupString(ic,
- &xev,
- compose_buffer,
- sizeof(compose_buffer) - 1,
- &sym,
- &mbstatus);
-#endif /* ifdef X_HAVE_UTF8_STRING */
- if (mbstatus == XBufferOverflow)
- {
- tmp = malloc(sizeof (char) * (val + 1));
- if (!tmp)
- return EINA_FALSE;
-
- compose = tmp;
-
-#ifdef X_HAVE_UTF8_STRING
- val = Xutf8LookupString(ic,
- &xev,
- tmp,
- val,
- &sym,
- &mbstatus);
-#else /* ifdef X_HAVE_UTF8_STRING */
- val = XmbLookupString(ic,
- &xev,
- tmp,
- val,
- &sym,
- &mbstatus);
-#endif /* ifdef X_HAVE_UTF8_STRING */
- if (val > 0)
- {
- tmp[val] = '\0';
-#ifndef X_HAVE_UTF8_STRING
- compose = eina_str_convert(nl_langinfo(CODESET),
- "UTF-8", tmp);
- free(tmp);
- tmp = compose;
-#endif /* ifndef X_HAVE_UTF8_STRING */
- }
- else
- compose = NULL;
- }
- else if (val > 0)
- {
- compose_buffer[val] = '\0';
-#ifdef X_HAVE_UTF8_STRING
- compose = strdup(compose_buffer);
-#else /* ifdef X_HAVE_UTF8_STRING */
- compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8",
- compose_buffer);
-#endif /* ifdef X_HAVE_UTF8_STRING */
- }
- }
- else
- {
- compose = strdup(ev->compose);
- }
-
- if (compose)
- {
- Eina_Unicode *unicode;
- int len;
- unicode = eina_unicode_utf8_to_unicode(compose, &len);
- if (!unicode) abort();
- if (unicode[0] >= 0x20 && unicode[0] != 0x7f)
- {
- ecore_imf_context_commit_event_add(ctx, compose);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, compose);
- result = EINA_TRUE;
- }
- free(compose);
- free(unicode);
- }
- }
-
- return result;
-}
-
-static const Ecore_IMF_Context_Info xim_info = {
- .id = "xim",
- .description = "X input method",
- .default_locales = "ko:ja:th:zh",
- .canvas_type = "evas",
- .canvas_required = 1,
-};
-
-static Ecore_IMF_Context_Class xim_class = {
- .add = _ecore_imf_context_xim_add,
- .del = _ecore_imf_context_xim_del,
- .client_window_set = _ecore_imf_context_xim_client_window_set,
- .client_canvas_set = NULL,
- .show = _ecore_imf_context_xim_input_panel_show,
- .hide = _ecore_imf_context_xim_input_panel_hide,
- .preedit_string_get = _ecore_imf_context_xim_preedit_string_get,
- .focus_in = _ecore_imf_context_xim_focus_in,
- .focus_out = _ecore_imf_context_xim_focus_out,
- .reset = _ecore_imf_context_xim_reset,
- .cursor_position_set = NULL,
- .use_preedit_set = _ecore_imf_context_xim_use_preedit_set,
- .input_mode_set = NULL,
- .filter_event = _ecore_imf_context_xim_filter_event,
- .preedit_string_with_attributes_get = _ecore_imf_context_xim_preedit_string_with_attributes_get,
- .prediction_allow_set = NULL,
- .autocapital_type_set = NULL,
- .control_panel_show = NULL,
- .control_panel_hide = NULL,
- .input_panel_layout_set = NULL,
- .input_panel_layout_get = NULL,
- .input_panel_language_set = NULL,
- .input_panel_language_get = NULL,
- .cursor_location_set = _ecore_imf_context_xim_cursor_location_set,
- .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 = NULL
-};
-
-static Ecore_IMF_Context *
-xim_imf_module_create(void)
-{
- Ecore_IMF_Context *ctx = ecore_imf_context_new(&xim_class);
- DBG("ctx=%p", ctx);
- return ctx;
-}
-
-static Ecore_IMF_Context *
-xim_imf_module_exit(void)
-{
- DBG(" ");
- return NULL;
-}
-
-static Eina_Bool
-_ecore_imf_xim_init(void)
-{
- eina_init();
-
- _ecore_imf_xim_log_dom = eina_log_domain_register("ecore_imf_xim", NULL);
- if (_ecore_imf_xim_log_dom < 0)
- {
- EINA_LOG_ERR("Could not register log domain: ecore_imf_xim");
- return EINA_FALSE;
- }
-
- DBG(" ");
-
- ecore_x_init(NULL);
- ecore_imf_module_register(&xim_info,
- xim_imf_module_create,
- xim_imf_module_exit);
-
- return EINA_TRUE;
-}
-
-static void
-_ecore_imf_xim_shutdown(void)
-{
- while (open_ims)
- {
- XIM_Im_Info *info = open_ims->data;
- Ecore_X_Display *display = ecore_x_display_get();
-
- _ecore_imf_xim_info_im_shutdown(display, EINA_FALSE, info);
- }
-
- ecore_x_shutdown();
-
- if (_ecore_imf_xim_log_dom > 0)
- {
- eina_log_domain_unregister(_ecore_imf_xim_log_dom);
- _ecore_imf_xim_log_dom = -1;
- }
-
- eina_shutdown();
-}
-
-EINA_MODULE_INIT(_ecore_imf_xim_init);
-EINA_MODULE_SHUTDOWN(_ecore_imf_xim_shutdown);
-
-/*
- * internal functions
- */
-static Ecore_IMF_Context_Data *
-_ecore_imf_xim_context_data_new(void)
-{
- Ecore_IMF_Context_Data *imf_context_data = NULL;
- char *locale;
-
- locale = setlocale(LC_CTYPE, "");
- if (!locale) return NULL;
-
- if (!XSupportsLocale()) return NULL;
-
- imf_context_data = calloc(1, sizeof(Ecore_IMF_Context_Data));
- EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, NULL);
-
- imf_context_data->locale = strdup(locale);
- if (!imf_context_data->locale) goto error;
-
- return imf_context_data;
-error:
- _ecore_imf_xim_context_data_destroy(imf_context_data);
- return NULL;
-}
-
-static void
-_ecore_imf_xim_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data)
-{
- if (!imf_context_data)
- return;
-
- if (imf_context_data->ic)
- XDestroyIC(imf_context_data->ic);
-
- free(imf_context_data->preedit_chars);
-
- if (imf_context_data->feedbacks)
- {
- free(imf_context_data->feedbacks);
- imf_context_data->feedbacks = NULL;
- }
-
- free(imf_context_data->locale);
- free(imf_context_data);
-}
-
-static int
-_ecore_imf_xim_preedit_start_call(XIC xic EINA_UNUSED,
- XPointer client_data,
- XPointer call_data EINA_UNUSED)
-{
- Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, -1);
-
- if (imf_context_data->finalizing == EINA_FALSE)
- {
- ecore_imf_context_preedit_start_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
- }
- return -1;
-}
-
-static void
-_ecore_imf_xim_preedit_done_call(XIC xic EINA_UNUSED,
- XPointer client_data,
- XPointer call_data EINA_UNUSED)
-{
- Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- if (imf_context_data->preedit_length)
- {
- imf_context_data->preedit_length = 0;
- free(imf_context_data->preedit_chars);
- imf_context_data->preedit_chars = NULL;
- ecore_imf_context_preedit_changed_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
-
- if (imf_context_data->finalizing == EINA_FALSE)
- {
- ecore_imf_context_preedit_end_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
- }
-}
-
-/* FIXME */
-static int
-_ecore_imf_xim_text_to_utf8(Ecore_IMF_Context *ctx EINA_UNUSED,
- XIMText *xim_text,
- char **text)
-{
- int text_length = 0;
- char *result = NULL;
-
- if (xim_text && xim_text->string.multi_byte)
- {
- if (xim_text->encoding_is_wchar)
- {
- WRN("Wide character return from Xlib not currently supported");
- *text = NULL;
- return 0;
- }
-
- /* XXX Convert to UTF-8 */
- result = strdup(xim_text->string.multi_byte);
- if (result)
- {
- text_length = eina_unicode_utf8_get_len(result);
- if (text_length != xim_text->length)
- {
- WRN("Size mismatch when converting text from input method: supplied length = %d, result length = %d",
- xim_text->length, text_length);
- }
- }
- else
- {
- WRN("Error converting text from IM to UCS-4");
- *text = NULL;
- return 0;
- }
-
- *text = result;
- return text_length;
- }
- else
- {
- *text = NULL;
- return 0;
- }
-}
-
-static void
-_ecore_imf_xim_preedit_draw_call(XIC xic EINA_UNUSED,
- XPointer client_data,
- XIMPreeditDrawCallbackStruct *call_data)
-{
- Eina_Bool ret = EINA_FALSE;
- Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- XIMText *t = call_data->text;
- char *tmp;
- Eina_Unicode *new_text = NULL;
- Eina_UStrbuf *preedit_bufs = NULL;
- int new_text_length;
- int i = 0;
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- preedit_bufs = eina_ustrbuf_new();
- if (imf_context_data->preedit_chars)
- {
- ret = eina_ustrbuf_append(preedit_bufs, imf_context_data->preedit_chars);
- if (ret == EINA_FALSE) goto done;
- }
-
- new_text_length = _ecore_imf_xim_text_to_utf8(ctx, t, &tmp);
- if (tmp)
- {
- int tmp_len;
- new_text = eina_unicode_utf8_to_unicode(tmp, &tmp_len);
- free(tmp);
- }
-
- if (t == NULL)
- {
- /* delete string */
- ret = eina_ustrbuf_remove(preedit_bufs,
- call_data->chg_first, call_data->chg_length);
- }
- else if (call_data->chg_length == 0)
- {
- /* insert string */
- ret = eina_ustrbuf_insert(preedit_bufs, new_text, call_data->chg_first);
- }
- else if (call_data->chg_length > 0)
- {
- /* replace string */
- ret = eina_ustrbuf_remove(preedit_bufs,
- call_data->chg_first, call_data->chg_length);
- if (ret == EINA_FALSE) goto done;
-
- ret = eina_ustrbuf_insert_n(preedit_bufs, new_text,
- new_text_length, call_data->chg_first);
- if (ret == EINA_FALSE) goto done;
- }
- else
- {
- ret = EINA_FALSE;
- }
-
-done:
- if (ret == EINA_TRUE)
- {
- free(imf_context_data->preedit_chars);
- imf_context_data->preedit_chars =
- eina_ustrbuf_string_steal(preedit_bufs);
- imf_context_data->preedit_length =
- eina_unicode_strlen(imf_context_data->preedit_chars);
-
- if (imf_context_data->feedbacks)
- {
- free(imf_context_data->feedbacks);
- imf_context_data->feedbacks = NULL;
- }
-
- if (imf_context_data->preedit_length > 0)
- {
- imf_context_data->feedbacks = calloc(imf_context_data->preedit_length, sizeof(XIMFeedback));
-
- for (i = 0; i < imf_context_data->preedit_length; i++)
- imf_context_data->feedbacks[i] = t->feedback[i];
- }
-
- ecore_imf_context_preedit_changed_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
-
- free(new_text);
- eina_ustrbuf_free(preedit_bufs);
-}
-
-static void
-_ecore_imf_xim_preedit_caret_call(XIC xic EINA_UNUSED,
- XPointer client_data,
- XIMPreeditCaretCallbackStruct *call_data)
-{
- Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- if (call_data->direction == XIMAbsolutePosition)
- {
- imf_context_data->preedit_cursor = call_data->position;
- if (imf_context_data->finalizing == EINA_FALSE)
- {
- ecore_imf_context_preedit_changed_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
- }
-}
-
-static XVaNestedList
-_ecore_imf_xim_preedit_callback_set(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data;
- imf_context_data = ecore_imf_context_data_get(ctx);
-
- imf_context_data->preedit_start_cb.client_data = (XPointer)ctx;
- imf_context_data->preedit_start_cb.callback = (XIMProc)_ecore_imf_xim_preedit_start_call;
-
- imf_context_data->preedit_done_cb.client_data = (XPointer)ctx;
- imf_context_data->preedit_done_cb.callback = (XIMProc)_ecore_imf_xim_preedit_done_call;
-
- imf_context_data->preedit_draw_cb.client_data = (XPointer)ctx;
- imf_context_data->preedit_draw_cb.callback = (XIMProc)_ecore_imf_xim_preedit_draw_call;
-
- imf_context_data->preedit_caret_cb.client_data = (XPointer)ctx;
- imf_context_data->preedit_caret_cb.callback = (XIMProc)_ecore_imf_xim_preedit_caret_call;
-
- return XVaCreateNestedList(0,
- XNPreeditStartCallback,
- &imf_context_data->preedit_start_cb,
- XNPreeditDoneCallback,
- &imf_context_data->preedit_done_cb,
- XNPreeditDrawCallback,
- &imf_context_data->preedit_draw_cb,
- XNPreeditCaretCallback,
- &imf_context_data->preedit_caret_cb,
- NULL);
-}
-
-static XIC
-_ecore_imf_xim_ic_get(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data;
- XIC ic;
- imf_context_data = ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, NULL);
-
- ic = imf_context_data->ic;
- if (!ic)
- {
- XIM_Im_Info *im_info = imf_context_data->im_info;
- XVaNestedList preedit_attr = NULL;
- XIMStyle im_style = 0;
- XPoint spot = { 0, 0 };
- char *name = NULL;
-
- if (!im_info)
- {
- WRN("Could not open XIM.");
- return NULL;
- }
-
- // supported styles
- // "OverTheSpot" = XIMPreeditPosition | XIMStatusNothing
- // "OffTheSpot" = XIMPreeditArea | XIMStatusArea
- // "Root" = XIMPreeditNothing | XIMStatusNothing
-
- if (imf_context_data->use_preedit == EINA_TRUE)
- {
- if (im_info->supports_cursor)
- {
- // kinput2 DOES do this...
- XFontSet fs;
- char **missing_charset_list;
- int missing_charset_count;
- char *def_string;
-
- im_style |= XIMPreeditPosition;
- im_style |= XIMStatusNothing;
- fs = XCreateFontSet(ecore_x_display_get(),
- "fixed",
- &missing_charset_list,
- &missing_charset_count,
- &def_string);
- preedit_attr = XVaCreateNestedList(0,
- XNSpotLocation, &spot,
- XNFontSet, fs,
- NULL);
- }
- else
- {
- im_style |= XIMPreeditCallbacks;
- im_style |= XIMStatusNothing;
- preedit_attr = _ecore_imf_xim_preedit_callback_set(ctx);
- }
- name = XNPreeditAttributes;
- }
- else
- {
- im_style |= XIMPreeditNothing;
- im_style |= XIMStatusNothing;
- }
-
- if (!im_info->xim_styles)
- {
- WRN("No XIM styles supported! Wanted %#llx",
- (unsigned long long)im_style);
- im_style = 0;
- }
- else
- {
- XIMStyle fallback = 0;
- int i;
-
- for (i = 0; i < im_info->xim_styles->count_styles; i++)
- {
- XIMStyle cur = im_info->xim_styles->supported_styles[i];
- if (cur == im_style)
- break;
- else if (cur == (XIMPreeditNothing | XIMStatusNothing))
- /* TODO: fallback is just that or the anyone? */
- fallback = cur;
- }
-
- if (i == im_info->xim_styles->count_styles)
- {
- if (fallback)
- {
- WRN("Wanted XIM style %#llx not found, using fallback %#llx instead.",
- (unsigned long long)im_style,
- (unsigned long long)fallback);
- im_style = fallback;
- }
- else
- {
- WRN("Wanted XIM style %#llx not found, no fallback supported.",
- (unsigned long long)im_style);
- im_style = 0;
- }
- }
- }
-
- if ((im_info->im) && (im_style))
- {
- ic = XCreateIC(im_info->im,
- XNInputStyle, im_style,
- XNClientWindow, imf_context_data->win,
- name, preedit_attr, NULL);
- }
- XFree(preedit_attr);
- if (ic)
- {
- unsigned long mask = 0xaaaaaaaa;
- XGetICValues(ic,
- XNFilterEvents, &mask,
- NULL);
- imf_context_data->mask = mask;
- ecore_x_event_mask_set(imf_context_data->win, mask);
- }
-
- imf_context_data->ic = ic;
- if (ic && imf_context_data->has_focus == EINA_TRUE)
- XSetICFocus(ic);
- }
-
- return ic;
-}
-
-static void
-_ecore_imf_xim_ic_reinitialize(Ecore_IMF_Context *ctx)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- XIC ic = imf_context_data->ic;
- if (ic)
- {
- XDestroyIC(ic);
- imf_context_data->ic = NULL;
- if (imf_context_data->preedit_length)
- {
- imf_context_data->preedit_length = 0;
- free(imf_context_data->preedit_chars);
- imf_context_data->preedit_chars = NULL;
- ecore_imf_context_preedit_changed_event_add(ctx);
- ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
- }
- }
-}
-
-static void
-_ecore_imf_xim_ic_client_window_set(Ecore_IMF_Context *ctx,
- Ecore_X_Window window)
-{
- Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
- Ecore_X_Window old_win;
-
- DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
- EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
-
- /* reinitialize IC */
- _ecore_imf_xim_ic_reinitialize(ctx);
-
- old_win = imf_context_data->win;
- DBG("old_win=%#x, window=%#x", old_win, window);
- if (old_win != 0 && old_win != window) /* XXX how do check window... */
- {
- XIM_Im_Info *info;
- info = imf_context_data->im_info;
- info->ics = eina_list_remove(info->ics, imf_context_data);
- if (imf_context_data->im_info)
- imf_context_data->im_info->user = NULL;
- imf_context_data->im_info = NULL;
- }
-
- imf_context_data->win = window;
-
- if (window) /* XXX */
- {
- XIM_Im_Info *info = NULL;
- info = _ecore_imf_xim_im_get(window, imf_context_data->locale);
- imf_context_data->im_info = info;
- imf_context_data->im_info->ics =
- eina_list_prepend(imf_context_data->im_info->ics,
- imf_context_data);
- if (imf_context_data->im_info)
- imf_context_data->im_info->user = imf_context_data;
- }
-}
-
-static XIM_Im_Info *
-_ecore_imf_xim_im_get(Ecore_X_Window window,
- char *locale)
-{
- Eina_List *l;
- XIM_Im_Info *im_info = NULL;
- XIM_Im_Info *info = NULL;
-
- DBG(" ");
- EINA_LIST_FOREACH (open_ims, l, im_info)
- {
- if (strcmp(im_info->locale, locale) == 0)
- {
- if (im_info->im)
- {
- return im_info;
- }
- else
- {
- info = im_info;
- break;
- }
- }
- }
-
- if (!info)
- {
- info = calloc(1, sizeof(XIM_Im_Info));
- if (!info) return NULL;
- open_ims = eina_list_prepend(open_ims, info);
- info->win = window;
- info->locale = strdup(locale);
- info->reconnecting = EINA_FALSE;
- }
-
- _ecore_imf_xim_info_im_init(info);
- return info;
-}
-
-/* initialize info->im */
-static void
-_ecore_imf_xim_info_im_init(XIM_Im_Info *info)
-{
- Ecore_X_Display *dsp;
-
- assert(info->im == NULL);
- if (info->reconnecting == EINA_TRUE)
- return;
-
- if (XSupportsLocale())
- {
- if (!XSetLocaleModifiers(""))
- WRN("Unable to set locale modifiers with XSetLocaleModifiers()");
- dsp = ecore_x_display_get();
- info->im = XOpenIM(dsp, NULL, NULL, NULL);
- if (!info->im)
- {
- XRegisterIMInstantiateCallback(dsp,
- NULL, NULL, NULL,
- _ecore_imf_xim_instantiate_cb,
- (XPointer)info);
- info->reconnecting = EINA_TRUE;
- return;
- }
- _ecore_imf_xim_im_setup(info);
- }
-}
-
-static void
-_ecore_imf_xim_info_im_shutdown(Ecore_X_Display *display EINA_UNUSED,
- int is_error EINA_UNUSED,
- XIM_Im_Info *info)
-{
- Eina_List *ics, *tmp_list;
- Ecore_IMF_Context *ctx;
-
- open_ims = eina_list_remove(open_ims, info);
-
- ics = info->ics;
- info->ics = NULL;
-
- EINA_LIST_FOREACH (ics, tmp_list, ctx)
- _ecore_imf_xim_ic_client_window_set(ctx, 0);
-
- EINA_LIST_FREE (ics, ctx)
- {
- Ecore_IMF_Context_Data *imf_context_data;
- imf_context_data = ecore_imf_context_data_get(ctx);
- _ecore_imf_xim_context_data_destroy(imf_context_data);
- }
-
- free(info->locale);
-
- if (info->im)
- XCloseIM(info->im);
-
- free(info);
-}
-
-static void
-_ecore_imf_xim_instantiate_cb(Display *display,
- XPointer client_data,
- XPointer call_data EINA_UNUSED)
-{
- XIM_Im_Info *info = (XIM_Im_Info *)client_data;
- XIM im = XOpenIM(display, NULL, NULL, NULL);
- EINA_SAFETY_ON_NULL_RETURN(im);
-
- info->im = im;
- _ecore_imf_xim_im_setup(info);
-
- XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL,
- _ecore_imf_xim_instantiate_cb,
- (XPointer)info);
- info->reconnecting = EINA_FALSE;
-}
-
-static void
-_ecore_imf_xim_im_setup(XIM_Im_Info *info)
-{
- XIMValuesList *ic_values = NULL;
- XIMCallback im_destroy_callback;
-
- if (!info->im)
- return;
-
- im_destroy_callback.client_data = (XPointer)info;
- im_destroy_callback.callback = (XIMProc)_ecore_imf_xim_destroy_cb;
- XSetIMValues(info->im,
- XNDestroyCallback, &im_destroy_callback,
- NULL);
-
- XGetIMValues(info->im,
- XNQueryInputStyle, &info->xim_styles,
- XNQueryICValuesList, &ic_values,
- NULL);
-
- if (ic_values)
- {
- int i;
-
- for (i = 0; i < ic_values->count_values; i++)
- {
- if (!strcmp(ic_values->supported_values[i],
- XNStringConversionCallback))
- info->supports_string_conversion = EINA_TRUE;
- if (!strcmp(ic_values->supported_values[i],
- XNCursor))
- info->supports_cursor = EINA_TRUE;
- }
-
- XFree(ic_values);
- }
-}
-
-static void
-_ecore_imf_xim_destroy_cb(XIM xim EINA_UNUSED,
- XPointer client_data,
- XPointer call_data EINA_UNUSED)
-{
- XIM_Im_Info *info = (XIM_Im_Info *)client_data;
-
- if (info->user) info->user->ic = NULL;
- info->im = NULL;
-// _ecore_imf_xim_ic_reinitialize(ctx);
- _ecore_imf_xim_info_im_init(info);
-
- return;
-}
--- /dev/null
+#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"
+
+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;
+};
+
+typedef struct _KeyEvent KeyEvent;
+
+struct _KeyEvent
+{
+ int keysym;
+ int state;
+};
+
+static Eina_Bool _use_sync_mode = EINA_FALSE;
+
+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 XKeyEvent createXKeyEvent (Window win, Eina_Bool press, int keysym, int modifiers);
+
+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 "Alt") */
+ if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
+ state |= IBUS_SUPER_MASK;
+
+ /**< "AltGr" is pressed */
+ if (modifier & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
+ state |= IBUS_MOD5_MASK;
+
+ return state;
+}
+
+static void
+key_event_put(int keysym, int state)
+{
+ // 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, keysym, state);
+ XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
+ }
+ else
+ {
+ event = createXKeyEvent(winFocus, EINA_TRUE, keysym, state);
+ XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
+ }
+}
+
+static KeyEvent *
+key_event_copy(int keysym, int state)
+{
+ KeyEvent *kev = calloc(1, sizeof(KeyEvent));
+ kev->keysym = keysym;
+ kev->state = state;
+
+ return kev;
+}
+
+IBusIMContext *
+ibus_im_context_new(void)
+{
+ EINA_LOG_DBG("%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;
+}
+
+static void
+_process_key_event_done(GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ IBusInputContext *context = (IBusInputContext *)object;
+ KeyEvent *event = (KeyEvent *)user_data;
+
+ GError *error = NULL;
+ Eina_Bool retval = ibus_input_context_process_key_event_async_finish(context,
+ res,
+ &error);
+
+ if (error != NULL)
+ {
+ g_warning("Process Key Event failed: %s.", error->message);
+ g_error_free(error);
+ }
+
+ if (retval == EINA_FALSE)
+ {
+ key_event_put(event->keysym, event->state);
+ }
+ free(event);
+}
+
+EAPI void
+ibus_im_context_add(Ecore_IMF_Context *ctx)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+
+ char *s = NULL;
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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;
+
+ s = getenv("IBUS_ENABLE_SYNC_MODE");
+ if (s)
+ _use_sync_mode = !!atoi(s);
+
+ 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)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+
+ IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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);
+ if (_focus_im_context == ctx)
+ _focus_im_context = NULL;
+}
+
+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);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ibusimcontext, EINA_FALSE);
+
+ if (type != ECORE_IMF_EVENT_KEY_UP && type != ECORE_IMF_EVENT_KEY_DOWN)
+ return EINA_FALSE;
+
+ EINA_LOG_DBG("%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;
+
+ if (_use_sync_mode)
+ {
+ retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
+ keysym,
+ keycode - 8,
+ state);
+ }
+ else
+ {
+ ibus_input_context_process_key_event_async(ibusimcontext->ibuscontext,
+ keysym,
+ keycode - 8,
+ state,
+ -1,
+ NULL,
+ _process_key_event_done,
+ key_event_copy(keysym, state));
+ retval = EINA_TRUE;
+ }
+ }
+ 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);
+ if (_use_sync_mode)
+ {
+ retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
+ keysym,
+ keycode - 8,
+ state);
+ }
+ else
+ {
+ ibus_input_context_process_key_event_async(ibusimcontext->ibuscontext,
+ keysym,
+ keycode - 8,
+ state,
+ -1,
+ NULL,
+ _process_key_event_done,
+ key_event_copy(keysym, state));
+ retval = EINA_TRUE;
+ }
+ }
+ 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)
+{
+ EINA_LOG_DBG("ctx : %p", ctx);
+
+ IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ EINA_LOG_DBG("ctx : %p", ctx);
+
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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;
+ }
+ EINA_LOG_DBG("str : %s, cursor_pos : %d", *str, *cursor_pos);
+}
+
+EAPI void
+ibus_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
+ char **str,
+ Eina_List **attr EINA_UNUSED,
+ int *cursor_pos)
+{
+ IBusIMContext *ibusimcontext = (IBusIMContext*)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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;
+ }
+ EINA_LOG_DBG("str : %s, cursor_pos : %d", *str, *cursor_pos);
+}
+
+EAPI void
+ibus_im_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
+{
+ EINA_LOG_DBG("canvas : %p", window);
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ EINA_LOG_DBG("canvas : %p", canvas);
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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;
+
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ EINA_LOG_DBG("x : %d, y : %d, w, %d, h :%d", x, y, w, h);
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ EINA_LOG_DBG("preedit : %d", use_preedit);
+ IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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 EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("ibus is connected");
+
+ if (ibusimcontext)
+ _create_input_context(ibusimcontext);
+}
+
+static void
+_ibus_context_commit_text_cb(IBusInputContext *ibuscontext EINA_UNUSED,
+ IBusText *text,
+ IBusIMContext *ibusimcontext)
+{
+ if (!ibusimcontext || !text) return;
+ char *commit_str = text->text ? text->text : "";
+
+ EINA_LOG_DBG("commit string : %s", commit_str);
+
+ 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 EINA_UNUSED,
+ guint keyval,
+ guint state,
+ IBusIMContext *ibusimcontext EINA_UNUSED)
+{
+ EINA_LOG_DBG("keyval : %d, state : %d", keyval, state);
+
+ key_event_put(keyval, state);
+}
+
+static void
+_ibus_context_update_preedit_text_cb(IBusInputContext *ibuscontext EINA_UNUSED,
+ IBusText *text,
+ gint cursor_pos,
+ gboolean visible,
+ IBusIMContext *ibusimcontext)
+{
+ 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;
+
+ EINA_LOG_DBG("string : %s, cursor : %d", ibusimcontext->preedit_string, ibusimcontext->preedit_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 EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("preedit visible : %d", ibusimcontext->preedit_visible);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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 EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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 EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ ibusimcontext->enable = EINA_TRUE;
+}
+
+static void
+_ibus_context_disabled_cb(IBusInputContext *ibuscontext EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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 EINA_UNUSED,
+ IBusIMContext *ibusimcontext)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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)
+{
+ EINA_LOG_DBG("%s", __FUNCTION__);
+ EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
+
+ 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);
+}
--- /dev/null
+#ifndef __IBUS_IM_CONTEXT_H_
+#define __IBUS_IM_CONTEXT_H_
+
+#include <Ecore_IMF.h>
+
+typedef struct _IBusIMContext IBusIMContext;
+
+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);
+#endif
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <Ecore.h>
+#include <Ecore_IMF.h>
+
+#include <ibus.h>
+#include "ibus_imcontext.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 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+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();
+ ibus_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(void)
+{
+ 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);
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define Uses_SCIM_DEBUG
+#define Uses_SCIM_BACKEND
+#define Uses_SCIM_IMENGINE_MODULE
+#define Uses_SCIM_HOTKEY
+#define Uses_SCIM_PANEL_CLIENT
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <Ecore_Evas.h>
+#include <Ecore_X.h>
+#include <Ecore.h>
+#include <Evas.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+
+#include <scim.h>
+#include "scim_imcontext.h"
+
+using namespace scim;
+
+struct _EcoreIMFContextISFImpl
+{
+ EcoreIMFContextISF *parent;
+ IMEngineInstancePointer si;
+ Ecore_X_Window client_window;
+ Evas *client_canvas;
+ Ecore_IMF_Input_Mode input_mode;
+ WideString preedit_string;
+ AttributeList preedit_attrlist;
+ Ecore_IMF_Autocapital_Type autocapital_type;
+ int preedit_caret;
+ int cursor_x;
+ int cursor_y;
+ int cursor_pos;
+ bool use_preedit;
+ bool is_on;
+ bool shared_si;
+ bool preedit_started;
+ bool preedit_updating;
+ bool need_commit_preedit;
+ bool uppercase;
+ bool prediction_allow;
+
+ EcoreIMFContextISFImpl *next;
+};
+
+/* Input Context handling functions. */
+static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
+static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
+static void delete_all_ic_impl (void);
+
+static EcoreIMFContextISF *find_ic (int id);
+
+
+/* private functions */
+static void panel_slot_reload_config (int context);
+static void panel_slot_exit (int context);
+static void panel_slot_update_lookup_table_page_size(int context,
+ int page_size);
+static void panel_slot_lookup_table_page_up (int context);
+static void panel_slot_lookup_table_page_down (int context);
+static void panel_slot_trigger_property (int context,
+ const String &property);
+static void panel_slot_process_helper_event (int context,
+ const String &target_uuid,
+ const String &helper_uuid,
+ const Transaction &trans);
+static void panel_slot_move_preedit_caret (int context,
+ int caret_pos);
+static void panel_slot_select_candidate (int context,
+ int cand_index);
+static void panel_slot_process_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_commit_string (int context,
+ const WideString &wstr);
+static void panel_slot_forward_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_request_help (int context);
+static void panel_slot_request_factory_menu (int context);
+static void panel_slot_change_factory (int context,
+ const String &uuid);
+
+static void panel_req_focus_in (EcoreIMFContextISF *ic);
+static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
+static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
+static void panel_req_show_help (EcoreIMFContextISF *ic);
+static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
+
+/* Panel iochannel handler*/
+static bool panel_initialize (void);
+static void panel_finalize (void);
+static Eina_Bool panel_iochannel_handler (void *data,
+ Ecore_Fd_Handler *fd_handler);
+
+/* utility functions */
+static bool filter_hotkeys (EcoreIMFContextISF *ic,
+ const KeyEvent &key);
+static void turn_on_ic (EcoreIMFContextISF *ic);
+static void turn_off_ic (EcoreIMFContextISF *ic);
+static void set_ic_capabilities (EcoreIMFContextISF *ic);
+
+static void initialize (void);
+static void finalize (void);
+
+static void open_next_factory (EcoreIMFContextISF *ic);
+static void open_previous_factory (EcoreIMFContextISF *ic);
+static void open_specific_factory (EcoreIMFContextISF *ic,
+ const String &uuid);
+static void initialize_modifier_bits (Display *display);
+static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
+static XKeyEvent createKeyEvent (Display *display, Window &win,
+ Window &winRoot, bool press,
+ int keysym, int modifiers);
+static void _x_send_key_event (const KeyEvent &key);
+
+static void attach_instance (const IMEngineInstancePointer &si);
+
+/* slot functions */
+static void slot_show_preedit_string (IMEngineInstanceBase *si);
+static void slot_show_aux_string (IMEngineInstanceBase *si);
+static void slot_show_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_hide_preedit_string (IMEngineInstanceBase *si);
+static void slot_hide_aux_string (IMEngineInstanceBase *si);
+static void slot_hide_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_update_preedit_caret (IMEngineInstanceBase *si,
+ int caret);
+static void slot_update_preedit_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs);
+static void slot_update_aux_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs);
+static void slot_commit_string (IMEngineInstanceBase *si,
+ const WideString &str);
+static void slot_forward_key_event (IMEngineInstanceBase *si,
+ const KeyEvent &key);
+static void slot_update_lookup_table (IMEngineInstanceBase *si,
+ const LookupTable &table);
+
+static void slot_register_properties (IMEngineInstanceBase *si,
+ const PropertyList &properties);
+static void slot_update_property (IMEngineInstanceBase *si,
+ const Property &property);
+static void slot_beep (IMEngineInstanceBase *si);
+static void slot_start_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_stop_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_send_helper_event (IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans);
+static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after);
+static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
+ int offset,
+ int len);
+
+static void reload_config_callback (const ConfigPointer &config);
+
+static void fallback_commit_string_cb (IMEngineInstanceBase *si,
+ const WideString &str);
+
+static void caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force);
+
+/* Local variables declaration */
+static String _language;
+static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
+static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
+static EcoreIMFContextISF *_ic_list = 0;
+
+static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
+static int _valid_key_mask = SCIM_KEY_AllMasks;
+
+static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
+static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
+
+static IMEngineInstancePointer _default_instance;
+
+static ConfigModule *_config_module = 0;
+static ConfigPointer _config;
+static BackEndPointer _backend;
+
+static EcoreIMFContextISF *_focused_ic = 0;
+
+static bool _scim_initialized = false;
+
+static int _instance_count = 0;
+static int _context_count = 0;
+
+static IMEngineFactoryPointer _fallback_factory;
+static IMEngineInstancePointer _fallback_instance;
+static PanelClient _panel_client;
+
+static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
+static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
+
+static Ecore_X_Window _client_window = 0;
+
+static bool _on_the_spot = true;
+static bool _shared_input_method = false;
+
+static Eina_Bool autocap_allow = EINA_FALSE;
+
+static Display *__current_display = 0;
+static int __current_alt_mask = Mod1Mask;
+static int __current_meta_mask = 0;
+static int __current_super_mask = 0;
+static int __current_hyper_mask = 0;
+static int __current_numlock_mask = Mod2Mask;
+
+// A hack to shutdown the immodule cleanly even if im_module_exit() is not called when exiting.
+class FinalizeHandler
+{
+public:
+ FinalizeHandler()
+ {
+ SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler()\n";
+ }
+ ~FinalizeHandler()
+ {
+ SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler()\n";
+ isf_imf_context_shutdown();
+ }
+};
+
+static FinalizeHandler _finalize_handler;
+
+static unsigned int
+utf8_offset_to_index(const char *str, int offset)
+{
+ int index = 0;
+ int i;
+ for (i = 0; i < offset; i++)
+ {
+ eina_unicode_utf8_get_next(str, &index);
+ }
+
+ return index;
+}
+
+static unsigned int
+get_time(void)
+{
+ unsigned int tint;
+ struct timeval tv;
+ struct timezone tz; /* is not used since ages */
+ gettimeofday(&tv, &tz);
+ tint = tv.tv_sec * 1000;
+ tint = tint / 1000 * 1000;
+ tint = tint + tv.tv_usec / 1000;
+ return tint;
+}
+
+/* Function Implementations */
+static EcoreIMFContextISFImpl *
+new_ic_impl(EcoreIMFContextISF *parent)
+{
+ EcoreIMFContextISFImpl *impl = NULL;
+
+ if (_free_ic_impl_list != NULL)
+ {
+ impl = _free_ic_impl_list;
+ _free_ic_impl_list = _free_ic_impl_list->next;
+ }
+ else
+ {
+ impl = new EcoreIMFContextISFImpl;
+ if (impl == NULL)
+ return NULL;
+ }
+
+ impl->uppercase = false;
+ impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
+ impl->next = _used_ic_impl_list;
+ _used_ic_impl_list = impl;
+
+ impl->parent = parent;
+
+ return impl;
+}
+
+static void
+delete_ic_impl(EcoreIMFContextISFImpl *impl)
+{
+ EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
+
+ for (; rec != 0; last = rec, rec = rec->next)
+ {
+ if (rec == impl)
+ {
+ if (last != 0)
+ last->next = rec->next;
+ else
+ _used_ic_impl_list = rec->next;
+
+ rec->next = _free_ic_impl_list;
+ _free_ic_impl_list = rec;
+
+ rec->parent = 0;
+ rec->si.reset();
+ rec->client_window = 0;
+ rec->preedit_string = WideString();
+ rec->preedit_attrlist.clear();
+
+ return;
+ }
+ }
+}
+
+static void
+delete_all_ic_impl(void)
+{
+ EcoreIMFContextISFImpl *it = _used_ic_impl_list;
+
+ while (it != 0)
+ {
+ _used_ic_impl_list = it->next;
+ delete it;
+ it = _used_ic_impl_list;
+ }
+
+ it = _free_ic_impl_list;
+ while (it != 0)
+ {
+ _free_ic_impl_list = it->next;
+ delete it;
+ it = _free_ic_impl_list;
+ }
+}
+
+static EcoreIMFContextISF *
+find_ic(int id)
+{
+ EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
+
+ while (rec != 0)
+ {
+ if (rec->parent && rec->parent->id == id)
+ return rec->parent;
+ rec = rec->next;
+ }
+
+ return 0;
+}
+
+static Eina_Bool
+analyze_surrounding_text(Ecore_IMF_Context *ctx)
+{
+ char *plain_str = NULL;
+ char *markup_str = NULL;
+ const char *puncs[] = {". ", "! ", "? "};
+ Eina_Bool ret = EINA_FALSE;
+ int cursor_pos = 0;
+ int i = 0;
+ Eina_Unicode *tail = NULL;
+ Eina_Unicode *ustr = NULL;
+ const int punc_num = sizeof(puncs) / sizeof(puncs[0]);
+ Eina_Unicode *uni_puncs[punc_num];
+ EcoreIMFContextISF *context_scim;
+
+ if (!ctx) return EINA_FALSE;
+ context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+ if (!context_scim || !context_scim->impl) return EINA_FALSE;
+
+ switch (context_scim->impl->autocapital_type)
+ {
+ case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
+ return EINA_FALSE;
+ case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
+ return EINA_TRUE;
+ default:
+ break;
+ }
+
+ for (i = 0; i < punc_num; i++)
+ uni_puncs[i] = eina_unicode_utf8_to_unicode(puncs[i], NULL);
+
+ ecore_imf_context_surrounding_get(ctx, &markup_str, &cursor_pos);
+ if (!markup_str) goto done;
+
+ if (cursor_pos == 0)
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+
+ // Convert into plain string
+ plain_str = evas_textblock_text_markup_to_utf8(NULL, markup_str);
+ if (!plain_str) goto done;
+
+ // Convert string from UTF-8 to unicode
+ ustr = eina_unicode_utf8_to_unicode(plain_str, NULL);
+ if (!ustr) goto done;
+
+ if (cursor_pos >= 1)
+ {
+ if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
+ {
+ if (ustr[cursor_pos-1] == ' ')
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+ // Check paragraph separator <PS> and carriage return <br>
+ if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n'))
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+ // check punctuation
+ if (cursor_pos >= 2)
+ {
+ tail = eina_unicode_strndup(ustr+cursor_pos-2, 2);
+
+ if (tail)
+ {
+ for (i = 0; i < punc_num; i++)
+ {
+ if (!eina_unicode_strcmp(tail, uni_puncs[i]))
+ {
+ ret = EINA_TRUE;
+ break;
+ }
+ }
+ free(tail);
+ tail = NULL;
+ }
+ }
+
+done:
+ if (ustr) free(ustr);
+ if (markup_str) free(markup_str);
+ if (plain_str) free(plain_str);
+
+ for (i = 0; i < punc_num; i++)
+ if (uni_puncs[i]) free(uni_puncs[i]);
+
+ return ret;
+}
+
+static void
+caps_mode_check(Ecore_IMF_Context *ctx, Eina_Bool force)
+{
+ Eina_Bool uppercase;
+ EcoreIMFContextISF *context_scim;
+
+ if (!ctx) return;
+ context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (autocap_allow == EINA_FALSE)
+ return;
+
+ // Check autocapital type
+ if (!context_scim || !context_scim->impl)
+ return;
+
+ if (analyze_surrounding_text(ctx))
+ uppercase = EINA_TRUE;
+ else
+ uppercase = EINA_FALSE;
+
+ if (force)
+ context_scim->impl->uppercase = uppercase;
+ else
+ if (context_scim->impl->uppercase != uppercase)
+ context_scim->impl->uppercase = uppercase;
+}
+
+static void
+feed_key_event(Evas *evas, const char *str, Eina_Bool fake)
+{
+ char key_string[128] = {0};
+ unsigned int timestamp = 0;
+
+ if (!fake)
+ timestamp = get_time();
+
+ if (strncmp(str, "KeyRelease+", 11) == 0)
+ {
+ strncpy(key_string, str + 11, strlen(str)-11);
+ evas_event_feed_key_up(evas, key_string, key_string, NULL, NULL, timestamp, NULL);
+ SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_up()...\n";
+ }
+ else
+ {
+ strncpy(key_string, str, strlen(str));
+ evas_event_feed_key_down(evas, key_string, key_string, NULL, NULL, timestamp, NULL);
+ SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_down()...\n";
+ }
+}
+
+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;
+}
+
+/* Public functions */
+/**
+ * isf_imf_context_new
+ *
+ * This function will be called by Ecore IMF.
+ * Create a instance of type EcoreIMFContextISF.
+ *
+ * Return value: A pointer to the newly created EcoreIMFContextISF instance
+ */
+EAPI EcoreIMFContextISF *
+isf_imf_context_new(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+ char *env;
+
+ EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
+ if (context_scim == NULL)
+ {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return NULL;
+ }
+
+ context_scim->id = _context_count++;
+
+ if (!_scim_initialized)
+ {
+ initialize();
+ _scim_initialized = true;
+ }
+
+ env = getenv("ECORE_IMF_AUTOCAPITAL_ALLOW");
+ if (env)
+ autocap_allow = !!atoi(env);
+
+ return context_scim;
+}
+
+/**
+ * isf_imf_context_shutdown
+ *
+ * It will be called when the scim im module is unloaded by ecore. It will do some
+ * cleanup job.
+ */
+EAPI void
+isf_imf_context_shutdown(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (_scim_initialized)
+ {
+ _scim_initialized = false;
+ finalize();
+ }
+}
+
+EAPI void
+isf_imf_context_add(Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+
+ if (!context_scim) return;
+
+ context_scim->impl = NULL;
+
+ if (_backend.null())
+ return;
+
+ IMEngineInstancePointer si;
+
+ // Use the default instance if "shared input method" mode is enabled.
+ if (_shared_input_method && !_default_instance.null())
+ {
+ si = _default_instance;
+ SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
+ }
+
+ // Not in "shared input method" mode, or no default instance, create an instance.
+ if (si.null())
+ {
+ IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
+ if (factory.null()) return;
+ si = factory->create_instance("UTF-8", _instance_count++);
+ if (si.null()) return;
+ attach_instance(si);
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
+ }
+
+ // If "shared input method" mode is enabled, and there is no default instance,
+ // then store this instance as default one.
+ if (_shared_input_method && _default_instance.null())
+ {
+ SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
+ _default_instance = si;
+ }
+
+ context_scim->ctx = ctx;
+ context_scim->impl = new_ic_impl(context_scim);
+ if (context_scim->impl == NULL)
+ {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return;
+ }
+
+ context_scim->impl->si = si;
+ context_scim->impl->client_window = 0;
+ context_scim->impl->client_canvas = NULL;
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->cursor_x = 0;
+ context_scim->impl->cursor_y = 0;
+ context_scim->impl->cursor_pos = -1;
+ context_scim->impl->is_on = false;
+ context_scim->impl->shared_si = _shared_input_method;
+ context_scim->impl->use_preedit = _on_the_spot;
+ context_scim->impl->preedit_started = false;
+ context_scim->impl->preedit_updating = false;
+ context_scim->impl->need_commit_preedit = false;
+
+ if (!_ic_list)
+ context_scim->next = NULL;
+ else
+ context_scim->next = _ic_list;
+ _ic_list = context_scim;
+
+ if (_shared_input_method)
+ context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+
+ _panel_client.prepare(context_scim->id);
+ _panel_client.register_input_context(context_scim->id, si->get_factory_uuid());
+ set_ic_capabilities(context_scim);
+ _panel_client.send();
+
+ SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
+}
+
+EAPI void
+isf_imf_context_del(Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (!_ic_list) return;
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+
+ if (context_scim)
+ {
+ if (context_scim->id != _ic_list->id)
+ {
+ EcoreIMFContextISF * pre = _ic_list;
+ EcoreIMFContextISF * cur = _ic_list->next;
+ while (cur != NULL)
+ {
+ if (cur->id == context_scim->id)
+ {
+ pre->next = cur->next;
+ break;
+ }
+ pre = cur;
+ cur = cur->next;
+ }
+ }
+ else
+ _ic_list = _ic_list->next;
+ }
+
+ if (context_scim && context_scim->impl)
+ {
+ _panel_client.prepare(context_scim->id);
+
+ if (context_scim == _focused_ic)
+ context_scim->impl->si->focus_out();
+
+ // Delete the instance.
+ EcoreIMFContextISF *old_focused = _focused_ic;
+ _focused_ic = context_scim;
+ context_scim->impl->si.reset();
+ _focused_ic = old_focused;
+
+ if (context_scim == _focused_ic)
+ {
+ _panel_client.turn_off(context_scim->id);
+ _panel_client.focus_out(context_scim->id);
+ }
+
+ _panel_client.remove_input_context(context_scim->id);
+ _panel_client.send();
+
+ if (context_scim->impl->client_window)
+ isf_imf_context_client_window_set(ctx, NULL);
+
+ if (context_scim->impl)
+ {
+ delete_ic_impl(context_scim->impl);
+ context_scim->impl = 0;
+ }
+ }
+
+ if (context_scim == _focused_ic)
+ _focused_ic = 0;
+
+ if (context_scim)
+ {
+ delete context_scim;
+ context_scim = 0;
+ }
+}
+
+/**
+ * isf_imf_context_client_canvas_set
+ * @ctx: a #Ecore_IMF_Context
+ * @canvas: the client canvas
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set the client canvas for the Input Method Context; this is the canvas
+ * in which the input appears.
+ *
+ * The canvas type can be determined by using the context canvas type.
+ * Actually only canvas with type "evas" (Evas *) is supported. This canvas
+ * may be used in order to correctly position status windows, and may also
+ * be used for purposes internal to the Input Method Context.
+ */
+EAPI void
+isf_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas)
+ context_scim->impl->client_canvas = (Evas*)canvas;
+}
+
+/**
+ * isf_imf_context_client_window_set
+ * @ctx: a #Ecore_IMF_Context
+ * @window: the client window
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set the client window for the Input Method Context; this is the Ecore_X_Window
+ * when using X11, Ecore_Win32_Window when using Win32, etc.
+ *
+ * This window is used in order to correctly position status windows,
+ * and may also be used for purposes internal to the Input Method Context.
+ */
+EAPI void
+isf_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window))
+ {
+ context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
+
+ if ((context_scim->impl->client_window != 0) &&
+ (context_scim->impl->client_window != _client_window))
+ _client_window = context_scim->impl->client_window;
+ }
+}
+
+/**
+ * isf_imf_context_reset
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change such as a change in cursor
+ * position has been made. This will typically cause the Input Method Context
+ * to clear the preedit state.
+ */
+EAPI void
+isf_imf_context_reset(Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ WideString wstr = context_scim->impl->preedit_string;
+
+ _panel_client.prepare(context_scim->id);
+ context_scim->impl->si->reset();
+ _panel_client.send();
+
+ if (context_scim->impl->need_commit_preedit)
+ {
+ if (wstr.length())
+ {
+ ecore_imf_context_commit_event_add(context_scim->ctx, utf8_wcstombs(wstr).c_str());
+ ecore_imf_context_event_callback_call(context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
+ }
+ _panel_client.prepare(context_scim->id);
+ _panel_client.send();
+ }
+ }
+}
+
+/**
+ * isf_imf_context_focus_in
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that the widget to which its correspond has gained focus.
+ */
+EAPI void
+isf_imf_context_focus_in(Ecore_IMF_Context *ctx)
+{
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (!context_scim)
+ return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
+
+ if (_focused_ic)
+ {
+ if (_focused_ic == context_scim)
+ {
+ SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
+ return;
+ }
+ SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
+ if (_focused_ic->ctx)
+ isf_imf_context_focus_out(_focused_ic->ctx);
+ }
+
+ bool need_cap = false;
+ bool need_reset = false;
+ bool need_reg = false;
+
+ if (context_scim && context_scim->impl)
+ {
+ _focused_ic = context_scim;
+ _panel_client.prepare(context_scim->id);
+
+ // Handle the "Shared Input Method" mode.
+ if (_shared_input_method)
+ {
+ SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
+ if (!factory.null())
+ {
+ if (_default_instance.null() || _default_instance->get_factory_uuid() != factory->get_uuid())
+ {
+ _default_instance = factory->create_instance("UTF-8", _default_instance.null() ? _instance_count++ : _default_instance->get_id());
+ attach_instance(_default_instance);
+ SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id() << " " << _default_instance->get_factory_uuid() << "\n";
+ }
+
+ context_scim->impl->shared_si = true;
+ context_scim->impl->si = _default_instance;
+
+ context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+ context_scim->impl->preedit_string.clear();
+ context_scim->impl->preedit_attrlist.clear();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ need_cap = true;
+ need_reset = true;
+ need_reg = true;
+ }
+ }
+ else if (context_scim->impl->shared_si)
+ {
+ SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
+ if (!factory.null())
+ {
+ context_scim->impl->si = factory->create_instance("UTF-8", _instance_count++);
+ context_scim->impl->preedit_string.clear();
+ context_scim->impl->preedit_attrlist.clear();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ attach_instance(context_scim->impl->si);
+ need_cap = true;
+ need_reg = true;
+ context_scim->impl->shared_si = false;
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id() << " " << context_scim->impl->si->get_factory_uuid() << "\n";
+ }
+ }
+
+ context_scim->impl->si->set_frontend_data(static_cast <void*>(context_scim));
+
+ if (need_reg) _panel_client.register_input_context(context_scim->id, context_scim->impl->si->get_factory_uuid());
+ if (need_cap) set_ic_capabilities(context_scim);
+ if (need_reset) context_scim->impl->si->reset();
+
+ panel_req_focus_in(context_scim);
+ panel_req_update_spot_location(context_scim);
+ panel_req_update_factory_info(context_scim);
+
+ if (context_scim->impl->is_on)
+ {
+ _panel_client.turn_on(context_scim->id);
+ _panel_client.hide_preedit_string(context_scim->id);
+ _panel_client.hide_aux_string(context_scim->id);
+ _panel_client.hide_lookup_table(context_scim->id);
+ context_scim->impl->si->focus_in();
+ }
+ else
+ {
+ _panel_client.turn_off(context_scim->id);
+ }
+
+ _panel_client.send();
+ }
+
+ if (ecore_imf_context_input_panel_enabled_get(ctx))
+ ecore_imf_context_input_panel_show(ctx);
+}
+
+/**
+ * isf_imf_context_focus_out
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that the widget to which its correspond has lost focus.
+ */
+EAPI void
+isf_imf_context_focus_out(Ecore_IMF_Context *ctx)
+{
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (!context_scim) return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ WideString wstr = context_scim->impl->preedit_string;
+
+ if (context_scim->impl->need_commit_preedit)
+ {
+ if (wstr.length())
+ {
+ ecore_imf_context_commit_event_add(context_scim->ctx, utf8_wcstombs(wstr).c_str());
+ ecore_imf_context_event_callback_call(context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
+ }
+ _panel_client.prepare(context_scim->id);
+ _panel_client.send();
+ }
+
+ _panel_client.prepare(context_scim->id);
+ context_scim->impl->si->focus_out();
+ context_scim->impl->si->reset();
+ _panel_client.turn_off(context_scim->id);
+ _panel_client.focus_out(context_scim->id);
+ _panel_client.send();
+ _focused_ic = 0;
+ }
+
+ if (ecore_imf_context_input_panel_enabled_get(ctx))
+ ecore_imf_context_input_panel_hide(ctx);
+}
+
+/**
+ * isf_imf_context_cursor_location_set
+ * @ctx: a #Ecore_IMF_Context
+ * @x: x position of New cursor.
+ * @y: y position of New cursor.
+ * @w: the width of New cursor.
+ * @h: the height of New cursor.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change in the cursor location has been made.
+ */
+EAPI void
+isf_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+ Ecore_Evas *ee;
+ int canvas_x, canvas_y;
+ int new_cursor_x, new_cursor_y;
+
+ if (cw == 0 && ch == 0)
+ return;
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ if (context_scim->impl->client_canvas)
+ {
+ ee = ecore_evas_ecore_evas_get(context_scim->impl->client_canvas);
+ if (!ee) return;
+
+ ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
+ }
+ else
+ {
+ if (context_scim->impl->client_window)
+ window_to_screen_geometry_get(context_scim->impl->client_window, &canvas_x, &canvas_y);
+ else
+ return;
+ }
+
+ new_cursor_x = canvas_x + cx;
+ new_cursor_y = canvas_y + cy + ch;
+
+ // Don't update spot location while updating preedit string.
+ if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
+ return;
+
+ if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y)
+ {
+ context_scim->impl->cursor_x = new_cursor_x;
+ context_scim->impl->cursor_y = new_cursor_y;
+ _panel_client.prepare(context_scim->id);
+ panel_req_update_spot_location(context_scim);
+ _panel_client.send();
+ SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
+ }
+ }
+}
+
+/**
+ * isf_imf_context_use_preedit_set
+ * @ctx: a #Ecore_IMF_Context
+ * @use_preedit: Whether the IM context should use the preedit string.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set whether the IM context should use the preedit string to display feedback.
+ * If is 0 (default is 1), then the IM context may use some other method to
+ * display feedback, such as displaying it in a child of the root window.
+ */
+EAPI void
+isf_imf_context_use_preedit_set(Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit ? "true" : "false") << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+
+ if (!_on_the_spot) return;
+
+ if (context_scim && context_scim->impl)
+ {
+ bool old = context_scim->impl->use_preedit;
+ context_scim->impl->use_preedit = use_preedit;
+ if (context_scim == _focused_ic)
+ {
+ _panel_client.prepare(context_scim->id);
+
+ if (old != use_preedit)
+ set_ic_capabilities(context_scim);
+
+ if (context_scim->impl->preedit_string.length())
+ slot_show_preedit_string(context_scim->impl->si);
+
+ _panel_client.send();
+ }
+ }
+}
+
+EAPI void
+isf_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->is_on)
+ {
+ String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
+
+ if (str)
+ {
+ if (mbs.length())
+ *str = strdup(mbs.c_str());
+ else
+ *str = strdup("");
+ }
+
+ if (cursor_pos)
+ {
+ *cursor_pos = context_scim->impl->preedit_caret;
+ }
+
+ if (attrs)
+ {
+ if (mbs.length())
+ {
+ int start_index, end_index;
+ int wlen = context_scim->impl->preedit_string.length();
+
+ Ecore_IMF_Preedit_Attr *attr = NULL;
+ AttributeList::const_iterator i;
+ bool *attrs_flag = new bool [mbs.length()];
+ memset(attrs_flag, 0, mbs.length() *sizeof(bool));
+
+ for (i = context_scim->impl->preedit_attrlist.begin();
+ i != context_scim->impl->preedit_attrlist.end(); ++i)
+ {
+ start_index = i->get_start();
+ end_index = i->get_end();
+
+ if (end_index <= wlen && start_index < end_index && i->get_type() != SCIM_ATTR_DECORATE_NONE)
+ {
+ start_index = utf8_offset_to_index(mbs.c_str(), i->get_start());
+ end_index = utf8_offset_to_index(mbs.c_str(), i->get_end());
+
+ if (i->get_type() == SCIM_ATTR_DECORATE)
+ {
+ attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+ if (attr == NULL)
+ continue;
+ attr->start_index = start_index;
+ attr->end_index = end_index;
+
+ if (i->get_value() == SCIM_ATTR_DECORATE_UNDERLINE)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else if (i->get_value() == SCIM_ATTR_DECORATE_REVERSE)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else if (i->get_value() == SCIM_ATTR_DECORATE_HIGHLIGHT)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else
+ {
+ free(attr);
+ }
+
+ switch(i->get_value())
+ {
+ case SCIM_ATTR_DECORATE_UNDERLINE:
+ case SCIM_ATTR_DECORATE_REVERSE:
+ case SCIM_ATTR_DECORATE_HIGHLIGHT:
+ // Record which character has attribute.
+ for (int pos = start_index; pos < end_index; ++pos)
+ attrs_flag [pos] = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (i->get_type() == SCIM_ATTR_FOREGROUND)
+ {
+ SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
+ }
+ else if (i->get_type() == SCIM_ATTR_BACKGROUND)
+ {
+ SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
+ }
+ }
+ }
+
+ // Add underline for all characters which don't have attribute.
+ for (unsigned int pos = 0; pos < mbs.length(); ++pos)
+ {
+ if (!attrs_flag [pos])
+ {
+ int begin_pos = pos;
+
+ while (pos < mbs.length() && !attrs_flag[pos])
+ ++pos;
+
+ // use REVERSE style as default
+ attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+ if (attr == NULL)
+ continue;
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+ attr->start_index = begin_pos;
+ attr->end_index = pos;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ }
+
+ delete [] attrs_flag;
+ }
+ }
+ }
+ else
+ {
+ if (str)
+ *str = strdup("");
+
+ if (cursor_pos)
+ *cursor_pos = 0;
+
+ if (attrs)
+ *attrs = NULL;
+ }
+}
+
+/**
+ * isf_imf_context_preedit_string_get
+ * @ctx: a #Ecore_IMF_Context
+ * @str: the preedit string
+ * @cursor_pos: the cursor position
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * To get the preedit string of the input method.
+ */
+EAPI void
+isf_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->is_on)
+ {
+ String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
+
+ if (str)
+ {
+ if (mbs.length())
+ *str = strdup(mbs.c_str());
+ else
+ *str = strdup("");
+ }
+
+ if (cursor_pos)
+ *cursor_pos = context_scim->impl->preedit_caret;
+ }
+ else
+ {
+ if (str)
+ *str = strdup("");
+
+ if (cursor_pos)
+ *cursor_pos = 0;
+ }
+}
+
+/**
+ * isf_imf_context_cursor_position_set
+ * @ctx: a #Ecore_IMF_Context
+ * @cursor_pos: New cursor position in characters.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change in the cursor position has been made.
+ */
+EAPI void
+isf_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ // Don't update spot location while updating preedit string.
+ if (context_scim->impl->preedit_updating)
+ return;
+
+ if (context_scim->impl->cursor_pos != cursor_pos)
+ {
+ context_scim->impl->cursor_pos = cursor_pos;
+ caps_mode_check(ctx, EINA_FALSE);
+ }
+ }
+}
+
+/**
+ * isf_imf_context_input_mode_set
+ * @ctx: a #Ecore_IMF_Context
+ * @input_mode: the input mode
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
+ * is in Ecore_IMF.h.
+ */
+EAPI void
+isf_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+ if (context_scim && context_scim->impl)
+ context_scim->impl->input_mode = input_mode;
+}
+
+/**
+ * isf_imf_context_prediction_allow_set
+ * @ctx: a #Ecore_IMF_Context
+ * @use_prediction: Whether the IM context should use the prediction.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set whether the IM context should use the prediction.
+ */
+EAPI void
+isf_imf_context_prediction_allow_set(Ecore_IMF_Context* ctx, Eina_Bool prediction)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction ? "true" : "false") << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction)
+ context_scim->impl->prediction_allow = prediction;
+}
+
+EAPI void
+isf_imf_context_autocapital_type_set(Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type)
+ context_scim->impl->autocapital_type = autocapital_type;
+}
+
+/**
+ * isf_imf_context_filter_event
+ * @ctx: a #Ecore_IMF_Context
+ * @type: The type of event defined by Ecore_IMF_Event_Type.
+ * @event: The event itself.
+ * Return value: %TRUE if the input method handled the key event.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Allow an Ecore Input Context to internally handle an event. If this function
+ * returns 1, then no further processing should be done for this event. Input
+ * methods must be able to accept all types of events (simply returning 0 if
+ * the event was not handled), but there is no obligation of any events to be
+ * submitted to this function.
+ */
+EAPI Eina_Bool
+isf_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+ Eina_Bool ret = EINA_FALSE;
+
+ if (ic == NULL || ic->impl == NULL)
+ return ret;
+
+ KeyEvent key;
+
+ if (type == ECORE_IMF_EVENT_KEY_DOWN)
+ {
+ Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
+ scim_string_to_key(key, ev->key);
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
+ }
+ else if (type == ECORE_IMF_EVENT_KEY_UP)
+ {
+ Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
+ scim_string_to_key(key, ev->key);
+ key.mask = SCIM_KEY_ReleaseMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
+ }
+ else
+ {
+ return ret;
+ }
+
+ key.mask &= _valid_key_mask;
+
+ _panel_client.prepare(ic->id);
+
+ ret = EINA_TRUE;
+ if (!filter_hotkeys(ic, key))
+ {
+ if (!_focused_ic || !_focused_ic->impl->is_on ||
+ !_focused_ic->impl->si->process_key_event(key))
+ ret = EINA_FALSE;
+ }
+
+ _panel_client.send();
+
+ return ret;
+}
+
+EAPI void
+isf_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+ if (ic == NULL || ic->impl == NULL)
+ return;
+
+ ecore_x_e_virtual_keyboard_state_set
+ (ic->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
+}
+
+EAPI void
+isf_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
+ if (ic == NULL || ic->impl == NULL)
+ return;
+
+ ecore_x_e_virtual_keyboard_state_set
+ (ic->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
+}
+
+/* Panel Slot functions */
+static void
+panel_slot_reload_config(int context EINA_UNUSED)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+ _config->reload();
+}
+
+static void
+panel_slot_exit(int /* context */)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ finalize();
+}
+
+static void
+panel_slot_update_lookup_table_page_size(int context, int page_size)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->update_lookup_table_page_size(page_size);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_up(int context)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->lookup_table_page_up();
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_down(int context)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->lookup_table_page_down();
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_trigger_property(int context, const String &property)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->trigger_property(property);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_process_helper_event(int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
+ << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic ? ic->impl : 0) << " ic-uuid="
+ << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid() : "" ) << "\n";
+ if (ic && ic->impl && ic->impl->si->get_factory_uuid() == target_uuid)
+ {
+ _panel_client.prepare(ic->id);
+ SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
+ ic->impl->si->process_helper_event(helper_uuid, trans);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_move_preedit_caret(int context, int caret_pos)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->move_preedit_caret(caret_pos);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_select_candidate(int context, int cand_index)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ ic->impl->si->select_candidate(cand_index);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_process_key_event(int context, const KeyEvent &key)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
+
+ if (key.is_key_press())
+ ecore_x_test_fake_key_press(key.get_key_string().c_str());
+}
+
+static void
+panel_slot_commit_string(int context, const WideString &wstr)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs(wstr) << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ if (_focused_ic != ic)
+ return;
+
+ ecore_imf_context_commit_event_add(ic->ctx, utf8_wcstombs(wstr).c_str());
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
+ }
+}
+
+static void
+panel_slot_forward_key_event(int context, const KeyEvent &key)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
+
+ if (ic && ic->impl && ic->impl->client_canvas)
+ feed_key_event(ic->impl->client_canvas, key.get_key_string().c_str(), EINA_TRUE);
+}
+
+static void
+panel_slot_request_help(int context)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ panel_req_show_help(ic);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_request_factory_menu(int context)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare(ic->id);
+ panel_req_show_factory_menu(ic);
+ _panel_client.send();
+ }
+}
+
+static void
+panel_slot_change_factory(int context, const String &uuid)
+{
+ EcoreIMFContextISF *ic = find_ic(context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ ic->impl->si->reset();
+ _panel_client.prepare(ic->id);
+ open_specific_factory(ic, uuid);
+ _panel_client.send();
+ }
+}
+
+/* Panel Requestion functions. */
+static void
+panel_req_show_help(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String help;
+
+ help = String("Smart Common Input Method platform ") +
+ //String(SCIM_VERSION) +
+ String("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n");
+
+ if (ic && ic->impl)
+ {
+ IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
+ if (sf)
+ {
+ help += utf8_wcstombs(sf->get_name());
+ help += String(":\n\n");
+
+ help += utf8_wcstombs(sf->get_help());
+ help += String("\n\n");
+
+ help += utf8_wcstombs(sf->get_credits());
+ }
+ _panel_client.show_help(ic->id, help);
+ }
+}
+
+static void
+panel_req_show_factory_menu(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ std::vector<IMEngineFactoryPointer> factories;
+ std::vector <PanelFactoryInfo> menu;
+
+ _backend->get_factories_for_encoding(factories, "UTF-8");
+
+ for (size_t i = 0; i < factories.size(); ++ i)
+ {
+ menu.push_back(PanelFactoryInfo(
+ factories [i]->get_uuid(),
+ utf8_wcstombs(factories [i]->get_name()),
+ factories [i]->get_language(),
+ factories [i]->get_icon_file()));
+ }
+
+ if (menu.size())
+ _panel_client.show_factory_menu(ic->id, menu);
+}
+
+static void
+panel_req_update_factory_info(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic == _focused_ic)
+ {
+ PanelFactoryInfo info;
+ if (ic->impl->is_on)
+ {
+ IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
+ if (sf)
+ info = PanelFactoryInfo(sf->get_uuid(), utf8_wcstombs(sf->get_name()), sf->get_language(), sf->get_icon_file());
+ }
+ else
+ {
+ info = PanelFactoryInfo(String(""), String("English/Keyboard"), String("C"), "");
+ }
+ _panel_client.update_factory_info(ic->id, info);
+ }
+}
+
+static void
+panel_req_focus_in(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.focus_in(ic->id, ic->impl->si->get_factory_uuid());
+}
+
+static void
+panel_req_update_spot_location(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.update_spot_location(ic->id, ic->impl->cursor_x, ic->impl->cursor_y);
+}
+
+static bool
+filter_hotkeys(EcoreIMFContextISF *ic, const KeyEvent &key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ bool ret = false;
+
+ _frontend_hotkey_matcher.push_key_event(key);
+ _imengine_hotkey_matcher.push_key_event(key);
+
+ FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result();
+
+ if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER)
+ {
+ if (!ic->impl->is_on)
+ turn_on_ic(ic);
+ else
+ turn_off_ic(ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON)
+ {
+ if (!ic->impl->is_on)
+ turn_on_ic(ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF)
+ {
+ if (ic->impl->is_on)
+ turn_off_ic(ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY)
+ {
+ open_next_factory(ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY)
+ {
+ open_previous_factory(ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU)
+ {
+ panel_req_show_factory_menu(ic);
+ ret = true;
+ }
+ else if (_imengine_hotkey_matcher.is_matched())
+ {
+ String sfid = _imengine_hotkey_matcher.get_match_result();
+ open_specific_factory(ic, sfid);
+ ret = true;
+ }
+ return ret;
+}
+
+static bool
+panel_initialize(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String display_name;
+ {
+ const char *p = getenv("DISPLAY");
+ if (p) display_name = String(p);
+ }
+
+ if (_panel_client.open_connection(_config->get_name(), display_name) >= 0)
+ {
+ int fd = _panel_client.get_connection_number();
+
+ _panel_iochannel_read_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
+
+ SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
+
+ return true;
+ }
+ std::cerr << "panel_initialize() failed!!!\n";
+ return false;
+}
+
+static void
+panel_finalize(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.close_connection();
+
+ if (_panel_iochannel_read_handler)
+ {
+ ecore_main_fd_handler_del(_panel_iochannel_read_handler);
+ _panel_iochannel_read_handler = 0;
+ }
+
+ if (_panel_iochannel_err_handler)
+ {
+ ecore_main_fd_handler_del(_panel_iochannel_err_handler);
+ _panel_iochannel_err_handler = 0;
+ }
+}
+
+static Eina_Bool
+panel_iochannel_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (fd_handler == _panel_iochannel_read_handler)
+ {
+ if (!_panel_client.filter_event())
+ {
+ panel_finalize();
+ panel_initialize();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ }
+ else if (fd_handler == _panel_iochannel_err_handler)
+ {
+ panel_finalize();
+ panel_initialize();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+turn_on_ic(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && !ic->impl->is_on)
+ {
+ ic->impl->is_on = true;
+
+ if (ic == _focused_ic)
+ {
+ panel_req_focus_in(ic);
+ panel_req_update_spot_location(ic);
+ panel_req_update_factory_info(ic);
+ _panel_client.turn_on(ic->id);
+ _panel_client.hide_preedit_string(ic->id);
+ _panel_client.hide_aux_string(ic->id);
+ _panel_client.hide_lookup_table(ic->id);
+ ic->impl->si->focus_in();
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length())
+ {
+ ecore_imf_context_preedit_start_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ ic->impl->preedit_started = true;
+ }
+ }
+}
+
+static void
+turn_off_ic(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic->impl->is_on)
+ {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic)
+ {
+ ic->impl->si->focus_out();
+
+ panel_req_update_factory_info(ic);
+ _panel_client.turn_off(ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length())
+ {
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ ecore_imf_context_preedit_end_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+ ic->impl->preedit_started = false;
+ }
+ }
+}
+
+static void
+set_ic_capabilities(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl)
+ {
+ unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
+
+ if (!_on_the_spot || !ic->impl->use_preedit)
+ cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
+
+ ic->impl->si->update_client_capabilities(cap);
+ }
+}
+
+static bool
+check_socket_frontend(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ SocketAddress address;
+ SocketClient client;
+
+ uint32 magic;
+
+ address.set_address(scim_get_default_socket_frontend_address());
+
+ if (!client.connect(address))
+ return false;
+
+ if (!scim_socket_open_connection(magic,
+ String("ConnectionTester"),
+ String("SocketFrontEnd"),
+ client,
+ 1000))
+ return false;
+
+ return true;
+}
+
+void
+initialize(void)
+{
+ std::vector<String> config_list;
+ std::vector<String> engine_list;
+ std::vector<String> load_engine_list;
+
+ std::vector<String>::iterator it;
+
+ bool manual = false;
+
+ bool socket = true;
+
+ String config_module_name = "simple";
+
+ printf("Initializing Ecore SCIM IMModule...\n");
+
+ SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore SCIM IMModule...\n";
+
+ // Get system language.
+ _language = scim_get_locale_language(scim_get_current_locale());
+
+ if (socket)
+ {
+ // If no Socket FrontEnd is running, then launch one.
+ // And set manual to false.
+ bool check_result = check_socket_frontend();
+ if (!check_result)
+ {
+ std::cerr << "Launching a SCIM daemon with Socket FrontEnd...\n";
+ //get modules list
+ scim_get_imengine_module_list(engine_list);
+
+ for (it = engine_list.begin(); it != engine_list.end(); it++)
+ {
+ if (*it != "socket")
+ load_engine_list.push_back(*it);
+ }
+
+ const char *new_argv [] = { "--no-stay", 0 };
+ scim_launch(true,
+ config_module_name,
+ (load_engine_list.size() ? scim_combine_string_list(load_engine_list, ',') : "none"),
+ "socket",
+ (char **)new_argv);
+ manual = false;
+ }
+
+ // If there is one Socket FrontEnd running and it's not manual mode,
+ // then just use this Socket Frontend.
+ if (!manual)
+ {
+ for (int i = 0; i < 200; ++i)
+ {
+ if (check_result)
+ {
+ config_module_name = "socket";
+ load_engine_list.clear();
+ load_engine_list.push_back("socket");
+ break;
+ }
+ scim_usleep(50000);
+ check_result = check_socket_frontend();
+ }
+ }
+ }
+
+ if (config_module_name != "dummy")
+ {
+ //load config module
+ SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
+ _config_module = new ConfigModule(config_module_name);
+
+ //create config instance
+ if (_config_module != NULL && _config_module->valid())
+ _config = _config_module->create_config();
+ }
+
+ if (_config.null())
+ {
+ SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
+
+ if (_config_module) delete _config_module;
+ _config_module = NULL;
+
+ _config = new DummyConfig();
+ config_module_name = "dummy";
+ }
+
+ reload_config_callback(_config);
+ _config->signal_connect_reload(slot(reload_config_callback));
+
+ // create backend
+ _backend = new CommonBackEnd(_config, load_engine_list.size() ? load_engine_list : engine_list);
+
+ if (_backend.null())
+ std::cerr << "Cannot create BackEnd Object!\n";
+ else
+ _fallback_factory = _backend->get_factory(SCIM_COMPOSE_KEY_FACTORY_UUID);
+
+ if (_fallback_factory.null())
+ _fallback_factory = new DummyIMEngineFactory();
+
+ _fallback_instance = _fallback_factory->create_instance(String("UTF-8"), 0);
+ _fallback_instance->signal_connect_commit_string(slot(fallback_commit_string_cb));
+
+ // Attach Panel Client signal.
+ _panel_client.signal_connect_reload_config (slot(panel_slot_reload_config));
+ _panel_client.signal_connect_exit (slot(panel_slot_exit));
+ _panel_client.signal_connect_update_lookup_table_page_size(slot(panel_slot_update_lookup_table_page_size));
+ _panel_client.signal_connect_lookup_table_page_up (slot(panel_slot_lookup_table_page_up));
+ _panel_client.signal_connect_lookup_table_page_down (slot(panel_slot_lookup_table_page_down));
+ _panel_client.signal_connect_trigger_property (slot(panel_slot_trigger_property));
+ _panel_client.signal_connect_process_helper_event (slot(panel_slot_process_helper_event));
+ _panel_client.signal_connect_move_preedit_caret (slot(panel_slot_move_preedit_caret));
+ _panel_client.signal_connect_select_candidate (slot(panel_slot_select_candidate));
+ _panel_client.signal_connect_process_key_event (slot(panel_slot_process_key_event));
+ _panel_client.signal_connect_commit_string (slot(panel_slot_commit_string));
+ _panel_client.signal_connect_forward_key_event (slot(panel_slot_forward_key_event));
+ _panel_client.signal_connect_request_help (slot(panel_slot_request_help));
+ _panel_client.signal_connect_request_factory_menu (slot(panel_slot_request_factory_menu));
+ _panel_client.signal_connect_change_factory (slot(panel_slot_change_factory));
+
+ if (!panel_initialize())
+ std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
+}
+
+static void
+finalize(void)
+{
+ SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
+
+ // Reset this first so that the shared instance could be released correctly afterwards.
+ _default_instance.reset();
+
+ SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
+ while (_used_ic_impl_list)
+ {
+ // In case in "shared input method" mode,
+ // all contexts share only one instance,
+ // so we need point the reference pointer correctly before finalizing.
+ _used_ic_impl_list->si->set_frontend_data(static_cast <void*>(_used_ic_impl_list->parent));
+ isf_imf_context_del(_used_ic_impl_list->parent->ctx);
+ }
+
+ delete_all_ic_impl();
+
+ _fallback_instance.reset();
+ _fallback_factory.reset();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
+ _backend.reset();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
+ _config.reset();
+
+ if (_config_module)
+ {
+ SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
+ delete _config_module;
+ _config_module = 0;
+ }
+
+ _focused_ic = NULL;
+ _ic_list = NULL;
+
+ _scim_initialized = false;
+
+ panel_finalize();
+}
+
+static void
+open_next_factory(EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_next_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
+
+ if (!sf.null())
+ {
+ turn_off_ic(ic);
+ ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
+ ic->impl->si->set_frontend_data(static_cast <void*>(ic));
+ ic->impl->preedit_string = WideString();
+ ic->impl->preedit_caret = 0;
+ attach_instance(ic->impl->si);
+ _backend->set_default_factory(_language, sf->get_uuid());
+ _panel_client.register_input_context(ic->id, sf->get_uuid());
+ set_ic_capabilities(ic);
+ turn_on_ic(ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+}
+
+static void
+open_previous_factory(EcoreIMFContextISF *ic)
+{
+ if (ic == NULL)
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_previous_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
+
+ if (!sf.null())
+ {
+ turn_off_ic(ic);
+ ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
+ ic->impl->si->set_frontend_data(static_cast <void*>(ic));
+ ic->impl->preedit_string = WideString();
+ ic->impl->preedit_caret = 0;
+ attach_instance(ic->impl->si);
+ _backend->set_default_factory(_language, sf->get_uuid());
+ _panel_client.register_input_context(ic->id, sf->get_uuid());
+ set_ic_capabilities(ic);
+ turn_on_ic(ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+}
+
+static void
+open_specific_factory(EcoreIMFContextISF *ic,
+ const String &uuid)
+{
+ if (ic == NULL)
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+
+ // The same input method is selected, just turn on the IC.
+ if (ic->impl->si->get_factory_uuid() == uuid)
+ {
+ turn_on_ic(ic);
+ return;
+ }
+
+ IMEngineFactoryPointer sf = _backend->get_factory(uuid);
+
+ if (uuid.length() && !sf.null())
+ {
+ turn_off_ic(ic);
+ ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
+ ic->impl->si->set_frontend_data(static_cast <void*>(ic));
+ ic->impl->preedit_string = WideString();
+ ic->impl->preedit_caret = 0;
+ attach_instance(ic->impl->si);
+ _backend->set_default_factory(_language, sf->get_uuid());
+ _panel_client.register_input_context(ic->id, sf->get_uuid());
+ set_ic_capabilities(ic);
+ turn_on_ic(ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+ else
+ {
+ // turn_off_ic comment out panel_req_update_factory_info()
+ turn_off_ic(ic);
+ if (ic && ic->impl->is_on)
+ {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic)
+ {
+ ic->impl->si->focus_out();
+
+ panel_req_update_factory_info(ic);
+ _panel_client.turn_off(ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length())
+ {
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ ecore_imf_context_preedit_end_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+ ic->impl->preedit_started = false;
+ }
+ }
+ }
+}
+
+static void initialize_modifier_bits(Display *display)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (__current_display == display)
+ return;
+
+ __current_display = display;
+
+ if (display == 0)
+ {
+ __current_alt_mask = Mod1Mask;
+ __current_meta_mask = ShiftMask | Mod1Mask;
+ __current_super_mask = 0;
+ __current_hyper_mask = 0;
+ __current_numlock_mask = Mod2Mask;
+ return;
+ }
+
+ XModifierKeymap *mods = NULL;
+
+ ::KeyCode ctrl_l = XKeysymToKeycode(display, XK_Control_L);
+ ::KeyCode ctrl_r = XKeysymToKeycode(display, XK_Control_R);
+ ::KeyCode meta_l = XKeysymToKeycode(display, XK_Meta_L);
+ ::KeyCode meta_r = XKeysymToKeycode(display, XK_Meta_R);
+ ::KeyCode alt_l = XKeysymToKeycode(display, XK_Alt_L);
+ ::KeyCode alt_r = XKeysymToKeycode(display, XK_Alt_R);
+ ::KeyCode super_l = XKeysymToKeycode(display, XK_Super_L);
+ ::KeyCode super_r = XKeysymToKeycode(display, XK_Super_R);
+ ::KeyCode hyper_l = XKeysymToKeycode(display, XK_Hyper_L);
+ ::KeyCode hyper_r = XKeysymToKeycode(display, XK_Hyper_R);
+ ::KeyCode numlock = XKeysymToKeycode(display, XK_Num_Lock);
+
+ int i, j;
+
+ mods = XGetModifierMapping(display);
+ if (mods == NULL)
+ return;
+
+ __current_alt_mask = 0;
+ __current_meta_mask = 0;
+ __current_super_mask = 0;
+ __current_hyper_mask = 0;
+ __current_numlock_mask = 0;
+
+ /* We skip the first three sets for Shift, Lock, and Control. The
+ remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
+ for (i = 3; i < 8; i++)
+ {
+ for (j = 0; j < mods->max_keypermod; j++)
+ {
+ ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
+ if (! code) continue;
+ if (code == alt_l || code == alt_r)
+ __current_alt_mask |= (1 << i);
+ else if (code == meta_l || code == meta_r)
+ __current_meta_mask |= (1 << i);
+ else if (code == super_l || code == super_r)
+ __current_super_mask |= (1 << i);
+ else if (code == hyper_l || code == hyper_r)
+ __current_hyper_mask |= (1 << i);
+ else if (code == numlock)
+ __current_numlock_mask |= (1 << i);
+ }
+ }
+
+ /* Check whether there is a combine keys mapped to Meta */
+ if (__current_meta_mask == 0)
+ {
+ char buf [32];
+ XKeyEvent xkey;
+ KeySym keysym_l, keysym_r;
+
+ xkey.type = KeyPress;
+ xkey.display = display;
+ xkey.serial = 0L;
+ xkey.send_event = False;
+ xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
+ xkey.time = 0;
+ xkey.same_screen = False;
+ xkey.subwindow = None;
+ xkey.window = None;
+ xkey.root = DefaultRootWindow(display);
+ xkey.state = ShiftMask;
+
+ xkey.keycode = meta_l;
+ XLookupString(&xkey, buf, 32, &keysym_l, 0);
+ xkey.keycode = meta_r;
+ XLookupString(&xkey, buf, 32, &keysym_r, 0);
+
+ if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
+ __current_meta_mask = ShiftMask + __current_alt_mask;
+ else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
+ __current_meta_mask = ShiftMask + ControlMask;
+ }
+
+ XFreeModifiermap(mods);
+}
+
+static unsigned int scim_x11_keymask_scim_to_x11(Display *display, uint16 scimkeymask)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ unsigned int state = 0;
+
+ initialize_modifier_bits(display);
+
+ if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
+ if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
+ if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
+ if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
+ if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
+ if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
+ if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
+ if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
+
+ return state;
+}
+
+static XKeyEvent createKeyEvent(Display *display, Window &win,
+ Window &winRoot, bool press,
+ int keysym, int modifiers)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ XKeyEvent event;
+
+ event.display = display;
+ event.window = win;
+ event.root = winRoot;
+ event.subwindow = None;
+ event.time = CurrentTime;
+ 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 _x_send_key_event(const KeyEvent &key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ // Obtain the X11 display.
+ Display *display = (Display *)ecore_x_display_get();
+ if (display == NULL)
+ {
+ std::cerr << "ecore_x_display_get() failed\n";
+ return;
+ }
+
+ // Get the root window for the current display.
+ Window winRoot = 0;
+
+ // Find the window which has the current keyboard focus.
+ Window winFocus = 0;
+ int revert = RevertToParent;
+
+ XGetInputFocus(display, &winFocus, &revert);
+
+ unsigned int modifier = scim_x11_keymask_scim_to_x11(display, key.mask);
+ XKeyEvent event;
+ if (key.is_key_press())
+ {
+ event = createKeyEvent(display, winFocus, winRoot, true, key.code, modifier);
+ XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
+ }
+ else
+ {
+ event = createKeyEvent(display, winFocus, winRoot, false, key.code, modifier);
+ XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
+ }
+}
+
+static void
+attach_instance(const IMEngineInstancePointer &si)
+{
+ si->signal_connect_show_preedit_string(
+ slot(slot_show_preedit_string));
+ si->signal_connect_show_aux_string(
+ slot(slot_show_aux_string));
+ si->signal_connect_show_lookup_table(
+ slot(slot_show_lookup_table));
+
+ si->signal_connect_hide_preedit_string(
+ slot(slot_hide_preedit_string));
+ si->signal_connect_hide_aux_string(
+ slot(slot_hide_aux_string));
+ si->signal_connect_hide_lookup_table(
+ slot(slot_hide_lookup_table));
+
+ si->signal_connect_update_preedit_caret(
+ slot(slot_update_preedit_caret));
+ si->signal_connect_update_preedit_string(
+ slot(slot_update_preedit_string));
+ si->signal_connect_update_aux_string(
+ slot(slot_update_aux_string));
+ si->signal_connect_update_lookup_table(
+ slot(slot_update_lookup_table));
+
+ si->signal_connect_commit_string(
+ slot(slot_commit_string));
+
+ si->signal_connect_forward_key_event(
+ slot(slot_forward_key_event));
+
+ si->signal_connect_register_properties(
+ slot(slot_register_properties));
+
+ si->signal_connect_update_property(
+ slot(slot_update_property));
+
+ si->signal_connect_beep(
+ slot(slot_beep));
+
+ si->signal_connect_start_helper(
+ slot(slot_start_helper));
+
+ si->signal_connect_stop_helper(
+ slot(slot_stop_helper));
+
+ si->signal_connect_send_helper_event(
+ slot(slot_send_helper_event));
+
+ si->signal_connect_get_surrounding_text(
+ slot(slot_get_surrounding_text));
+
+ si->signal_connect_delete_surrounding_text(
+ slot(slot_delete_surrounding_text));
+}
+
+// Implementation of slot functions
+static void
+slot_show_preedit_string(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add(_focused_ic->ctx);
+ ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
+ ic->impl->preedit_started = true;
+ }
+ }
+ else
+ _panel_client.show_preedit_string(ic->id);
+ }
+}
+
+static void
+slot_show_aux_string(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_aux_string(ic->id);
+}
+
+static void
+slot_show_lookup_table(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_lookup_table(ic->id);
+}
+
+static void
+slot_hide_preedit_string(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ bool emit = false;
+ if (ic->impl->preedit_string.length())
+ {
+ ic->impl->preedit_string = WideString();
+ ic->impl->preedit_caret = 0;
+ ic->impl->preedit_attrlist.clear();
+ emit = true;
+ }
+ if (ic->impl->use_preedit)
+ {
+ if (emit)
+ {
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+ if (ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_end_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+ ic->impl->preedit_started = false;
+ }
+ }
+ else
+ _panel_client.hide_preedit_string(ic->id);
+ }
+}
+
+static void
+slot_hide_aux_string(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_aux_string(ic->id);
+}
+
+static void
+slot_hide_lookup_table(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_lookup_table(ic->id);
+}
+
+static void
+slot_update_preedit_caret(IMEngineInstanceBase *si, int caret)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret)
+ {
+ ic->impl->preedit_caret = caret;
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
+ ic->impl->preedit_started = true;
+ }
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+ else
+ _panel_client.update_preedit_caret(ic->id, caret);
+ }
+}
+
+static void
+slot_update_preedit_string(IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length()))
+ {
+ ic->impl->preedit_string = str;
+ ic->impl->preedit_attrlist = attrs;
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add(_focused_ic->ctx);
+ ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
+ ic->impl->preedit_started = true;
+ }
+ ic->impl->preedit_caret = str.length();
+ ic->impl->preedit_updating = true;
+ ecore_imf_context_preedit_changed_event_add(ic->ctx);
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ ic->impl->preedit_updating = false;
+ }
+ else
+ {
+ _panel_client.update_preedit_string(ic->id, str, attrs);
+ }
+ }
+}
+
+static void
+slot_update_aux_string(IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_aux_string(ic->id, str, attrs);
+}
+
+static void
+slot_commit_string(IMEngineInstanceBase *si,
+ const WideString & str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->ctx)
+ {
+ ecore_imf_context_commit_event_add(ic->ctx, utf8_wcstombs(str).c_str());
+ ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());
+ }
+}
+
+static void
+slot_forward_key_event(IMEngineInstanceBase *si,
+ const KeyEvent & key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && _focused_ic == ic)
+ {
+ if (!_fallback_instance->process_key_event(key))
+ _x_send_key_event(key);
+ }
+}
+
+static void
+slot_update_lookup_table(IMEngineInstanceBase *si,
+ const LookupTable & table)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_lookup_table(ic->id, table);
+}
+
+static void
+slot_register_properties(IMEngineInstanceBase *si,
+ const PropertyList & properties)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.register_properties(ic->id, properties);
+}
+
+static void
+slot_update_property(IMEngineInstanceBase *si,
+ const Property & property)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_property(ic->id, property);
+}
+
+static void
+slot_beep(IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ ecore_x_bell(0);
+}
+
+static void
+slot_start_helper(IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic ) ? ic->impl->si->get_factory_uuid() : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.start_helper(ic->id, helper_uuid);
+}
+
+static void
+slot_stop_helper(IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic ? ic->id : -1) << " ic=" << ic << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.stop_helper(ic->id, helper_uuid);
+}
+
+static void
+slot_send_helper_event(IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic) ? ic->impl->si->get_factory_uuid() : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.send_helper_event(ic->id, helper_uuid, trans);
+}
+
+static bool
+slot_get_surrounding_text(IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ char *surrounding = NULL;
+ int cursor_index;
+ if (ecore_imf_context_surrounding_get(_focused_ic->ctx, &surrounding, &cursor_index))
+ {
+ SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
+ SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
+ WideString before(utf8_mbstowcs(String(surrounding, surrounding + cursor_index)));
+ WideString after(utf8_mbstowcs(String(surrounding + cursor_index)));
+ if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length())
+ before = WideString(before.begin() + (before.length() - maxlen_before), before.end());
+ else if (maxlen_before == 0) before = WideString();
+ if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length())
+ after = WideString(after.begin(), after.begin() + maxlen_after);
+ else if (maxlen_after == 0) after = WideString();
+ text = before + after;
+ cursor = before.length();
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+slot_delete_surrounding_text(IMEngineInstanceBase *si,
+ int offset,
+ int len)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ Ecore_IMF_Event_Delete_Surrounding ev;
+ ev.ctx = _focused_ic->ctx;
+ ev.n_chars = len;
+ ev.offset = offset;
+ ecore_imf_context_delete_surrounding_event_add(_focused_ic->ctx, offset, len);
+ ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
+ return true;
+ }
+ return false;
+}
+
+static void
+reload_config_callback(const ConfigPointer &config)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _frontend_hotkey_matcher.load_hotkeys(config);
+ _imengine_hotkey_matcher.load_hotkeys(config);
+
+ KeyEvent key;
+
+ scim_string_to_key(key,
+ config->read(String(SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
+ String("Shift+Control+Alt+Lock")));
+
+ _valid_key_mask = (key.mask > 0)?(key.mask):0xFFFF;
+ _valid_key_mask |= SCIM_KEY_ReleaseMask;
+ // Special treatment for two backslash keys on jp106 keyboard.
+ _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
+
+ _on_the_spot = config->read(String(SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
+ _shared_input_method = config->read(String(SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
+
+ // Get keyboard layout setting
+ // Flush the global config first, in order to load the new configs from disk.
+ scim_global_config_flush();
+
+ _keyboard_layout = scim_get_default_keyboard_layout();
+}
+
+static void
+fallback_commit_string_cb(IMEngineInstanceBase *si EINA_UNUSED,
+ const WideString &str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (_focused_ic && _focused_ic->impl)
+ {
+ ecore_imf_context_commit_event_add(_focused_ic->ctx, utf8_wcstombs(str).c_str());
+ ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());
+ }
+}
+
--- /dev/null
+#ifndef __ISF_IMF_CONTEXT_H
+#define __ISF_IMF_CONTEXT_H
+
+#include <Ecore_IMF.h>
+
+typedef struct _EcoreIMFContextISF EcoreIMFContextISF;
+typedef struct _EcoreIMFContextISFImpl EcoreIMFContextISFImpl;
+
+struct _EcoreIMFContextISF {
+ Ecore_IMF_Context *ctx;
+
+ EcoreIMFContextISFImpl *impl;
+
+ int id; /* Input Context id*/
+ struct _EcoreIMFContextISF *next;
+};
+
+void isf_imf_context_add (Ecore_IMF_Context *ctx);
+void isf_imf_context_del (Ecore_IMF_Context *ctx);
+void isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window);
+void isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *window);
+void isf_imf_context_focus_in (Ecore_IMF_Context *ctx);
+void isf_imf_context_focus_out (Ecore_IMF_Context *ctx);
+void isf_imf_context_reset (Ecore_IMF_Context *ctx);
+void isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos);
+void isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int x, int y, int w, int h);
+void isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
+void isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos);
+void isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos);
+void isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit);
+Eina_Bool isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
+void isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction);
+void isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type);
+void isf_imf_context_input_panel_layout_set (Ecore_IMF_Context* ctx, Ecore_IMF_Input_Panel_Layout layout);
+void isf_imf_context_input_panel_show(Ecore_IMF_Context *ctx);
+void isf_imf_context_input_panel_hide(Ecore_IMF_Context *ctx);
+
+EcoreIMFContextISF* isf_imf_context_new (void);
+void isf_imf_context_shutdown (void);
+
+#endif /* __ISF_IMF_CONTEXT_H */
+
--- /dev/null
+#include <stdio.h>
+#include "scim_imcontext.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ static const Ecore_IMF_Context_Info isf_imf_info = {
+ "scim", /* ID */
+ "SCIM immodule for Ecore", /* Description */
+ "*", /* Default locales */
+ NULL, /* Canvas type */
+ 0 /* Canvas required */
+ };
+
+ static Ecore_IMF_Context_Class isf_imf_class = {
+ isf_imf_context_add, /* add */
+ isf_imf_context_del, /* del */
+ isf_imf_context_client_window_set, /* client_window_set */
+ isf_imf_context_client_canvas_set, /* client_canvas_set */
+ isf_imf_context_input_panel_show, /* input_panel_show, - show */
+ isf_imf_context_input_panel_hide, /* input_panel_hide, - hide */
+ isf_imf_context_preedit_string_get, /* get_preedit_string */
+ isf_imf_context_focus_in, /* focus_in */
+ isf_imf_context_focus_out, /* focus_out */
+ isf_imf_context_reset, /* reset */
+ isf_imf_context_cursor_position_set, /* cursor_position_set */
+ isf_imf_context_use_preedit_set, /* use_preedit_set */
+ isf_imf_context_input_mode_set, /* input_mode_set */
+ isf_imf_context_filter_event, /* filter_event */
+ isf_imf_context_preedit_string_with_attributes_get, /* preedit_string_with_attribute_get */
+ isf_imf_context_prediction_allow_set, /* prediction_allow_set */
+ isf_imf_context_autocapital_type_set, /* autocapital_type_set */
+ NULL, /* control panel show */
+ NULL, /* control panel hide */
+ NULL, /* input_panel_layout_set */
+ NULL, /* isf_imf_context_input_panel_layout_get, */
+ NULL, /* isf_imf_context_input_panel_language_set, */
+ NULL, /* isf_imf_context_input_panel_language_get, */
+ isf_imf_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 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ static Ecore_IMF_Context *imf_module_create (void);
+ static Ecore_IMF_Context *imf_module_exit (void);
+
+ static Eina_Bool imf_module_init (void)
+ {
+ ecore_imf_module_register (&isf_imf_info, imf_module_create, imf_module_exit);
+ return EINA_TRUE;
+ }
+
+ static void imf_module_shutdown (void)
+ {
+ isf_imf_context_shutdown ();
+ }
+
+ static Ecore_IMF_Context *imf_module_create (void)
+ {
+ Ecore_IMF_Context *ctx = NULL;
+ EcoreIMFContextISF *ctxd = NULL;
+
+ ctxd = isf_imf_context_new ();
+ if (!ctxd)
+ {
+ printf ("isf_imf_context_new () failed!!!\n");
+ return NULL;
+ }
+
+ ctx = ecore_imf_context_new (&isf_imf_class);
+ if (!ctx)
+ {
+ delete ctxd;
+ return NULL;
+ }
+
+ ecore_imf_context_data_set (ctx, ctxd);
+
+ return ctx;
+ }
+
+ static Ecore_IMF_Context *imf_module_exit (void)
+ {
+ return NULL;
+ }
+
+ EINA_MODULE_INIT(imf_module_init);
+ EINA_MODULE_SHUTDOWN(imf_module_shutdown);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Input.h>
+#include <Ecore_IMF.h>
+#include <Ecore_X.h>
+#include <X11/Xlib.h>
+#include <X11/Xlocale.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <langinfo.h>
+#include <assert.h>
+
+static int _ecore_imf_xim_log_dom = -1;
+
+#ifdef CRITICAL
+#undef CRITICAL
+#endif
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_ecore_imf_xim_log_dom, __VA_ARGS__)
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_imf_xim_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+#undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_imf_xim_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_imf_xim_log_dom, __VA_ARGS__)
+
+
+static Eina_List *open_ims = NULL;
+
+#define FEEDBACK_MASK (XIMReverse | XIMUnderline | XIMHighlight)
+
+typedef struct _XIM_Im_Info XIM_Im_Info;
+
+typedef struct _Ecore_IMF_Context_Data Ecore_IMF_Context_Data;
+
+struct _XIM_Im_Info
+{
+ Ecore_X_Window win;
+ Ecore_IMF_Context_Data *user;
+ char *locale;
+ XIM im;
+ Eina_List *ics;
+ Eina_Bool reconnecting;
+ XIMStyles *xim_styles;
+ Eina_Bool supports_string_conversion : 1;
+ Eina_Bool supports_cursor : 1;
+};
+
+struct _Ecore_IMF_Context_Data
+{
+ Ecore_X_Window win;
+ long mask;
+ XIC ic; /* Input context for composed characters */
+ char *locale;
+ XIM_Im_Info *im_info;
+ int preedit_length;
+ int preedit_cursor;
+ Eina_Unicode *preedit_chars;
+ Eina_Bool use_preedit;
+ Eina_Bool finalizing;
+ Eina_Bool has_focus;
+ Eina_Bool in_toplevel;
+ XIMFeedback *feedbacks;
+
+ XIMCallback destroy_cb;
+
+ XIMCallback preedit_start_cb;
+ XIMCallback preedit_done_cb;
+ XIMCallback preedit_draw_cb;
+ XIMCallback preedit_caret_cb;
+};
+
+/* prototype */
+static Ecore_IMF_Context_Data *_ecore_imf_xim_context_data_new(void);
+static void _ecore_imf_xim_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data);
+
+static void _ecore_imf_xim_feedback_attr_add(Eina_List **attrs,
+ const char *str,
+ XIMFeedback feedback,
+ int start_pos,
+ int end_pos);
+
+static void _ecore_imf_xim_ic_reinitialize(Ecore_IMF_Context *ctx);
+static void _ecore_imf_xim_ic_client_window_set(Ecore_IMF_Context *ctx,
+ Ecore_X_Window window);
+static int _ecore_imf_xim_preedit_start_call(XIC xic,
+ XPointer client_data,
+ XPointer call_data);
+static void _ecore_imf_xim_preedit_done_call(XIC xic,
+ XPointer client_data,
+ XPointer call_data);
+static void _ecore_imf_xim_preedit_draw_call(XIC xic,
+ XPointer client_data,
+ XIMPreeditDrawCallbackStruct *call_data);
+static void _ecore_imf_xim_preedit_caret_call(XIC xic,
+ XPointer client_data,
+ XIMPreeditCaretCallbackStruct *call_data);
+
+static int _ecore_imf_xim_text_to_utf8(Ecore_IMF_Context *ctx,
+ XIMText *xim_text,
+ char **text);
+
+static XVaNestedList _ecore_imf_xim_preedit_callback_set(Ecore_IMF_Context *ctx);
+static XIC _ecore_imf_xim_ic_get(Ecore_IMF_Context *ctx);
+static XIM_Im_Info *_ecore_imf_xim_im_get(Ecore_X_Window window,
+ char *locale);
+static void _ecore_imf_xim_info_im_init(XIM_Im_Info *info);
+static void _ecore_imf_xim_info_im_shutdown(Ecore_X_Display *display,
+ int is_error,
+ XIM_Im_Info *info);
+static void _ecore_imf_xim_instantiate_cb(Display *display,
+ XPointer client_data,
+ XPointer call_data);
+static void _ecore_imf_xim_destroy_cb(XIM xim,
+ XPointer client_data,
+ XPointer call_data);
+static void _ecore_imf_xim_im_setup(XIM_Im_Info *info);
+
+static unsigned int
+_ecore_imf_xim_utf8_offset_to_index(const char *str, int offset)
+{
+ int idx = 0;
+ int i;
+ for (i = 0; i < offset; i++)
+ {
+ eina_unicode_utf8_get_next(str, &idx);
+ }
+
+ return idx;
+}
+
+static void
+_ecore_imf_context_xim_add(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = _ecore_imf_xim_context_data_new();
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ imf_context_data->use_preedit = EINA_TRUE;
+ imf_context_data->finalizing = EINA_FALSE;
+ imf_context_data->has_focus = EINA_FALSE;
+ imf_context_data->in_toplevel = EINA_FALSE;
+
+ ecore_imf_context_data_set(ctx, imf_context_data);
+}
+
+static void
+_ecore_imf_context_xim_del(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ imf_context_data->finalizing = EINA_TRUE;
+ if (imf_context_data->im_info && !imf_context_data->im_info->ics->next)
+ {
+ if (imf_context_data->im_info->reconnecting == EINA_TRUE)
+ {
+ Ecore_X_Display *dsp;
+ dsp = ecore_x_display_get();
+ XUnregisterIMInstantiateCallback(dsp,
+ NULL, NULL, NULL,
+ _ecore_imf_xim_instantiate_cb,
+ (XPointer)imf_context_data->im_info);
+ }
+ else if (imf_context_data->im_info->im)
+ {
+ XIMCallback im_destroy_callback;
+ im_destroy_callback.client_data = NULL;
+ im_destroy_callback.callback = NULL;
+ XSetIMValues(imf_context_data->im_info->im,
+ XNDestroyCallback, &im_destroy_callback,
+ NULL);
+ }
+ }
+
+ _ecore_imf_xim_ic_client_window_set(ctx, 0);
+
+ _ecore_imf_xim_context_data_destroy(imf_context_data);
+}
+
+static void
+_ecore_imf_context_xim_client_window_set(Ecore_IMF_Context *ctx,
+ void *window)
+{
+ DBG("ctx=%p, window=%p", ctx, window);
+ _ecore_imf_xim_ic_client_window_set(ctx, (Ecore_X_Window)((unsigned long)window));
+}
+
+static void
+_ecore_imf_context_xim_preedit_string_get(Ecore_IMF_Context *ctx,
+ char **str,
+ int *cursor_pos)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ char *utf8;
+ int len;
+
+ DBG("ctx=%p, imf_context_data=%p, str=%p, cursor_pos=%p",
+ ctx, imf_context_data, str, cursor_pos);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ if (imf_context_data->preedit_chars)
+ {
+ utf8 = eina_unicode_unicode_to_utf8(imf_context_data->preedit_chars,
+ &len);
+ if (str)
+ *str = utf8;
+ else
+ free(utf8);
+ }
+ else
+ {
+ if (str)
+ *str = NULL;
+ if (cursor_pos)
+ *cursor_pos = 0;
+ }
+
+ if (cursor_pos)
+ *cursor_pos = imf_context_data->preedit_cursor;
+}
+
+static void
+_ecore_imf_context_xim_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
+ char **str,
+ Eina_List **attrs,
+ int *cursor_pos)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+ DBG("ctx=%p, imf_context_data=%p, str=%p, attrs=%p, cursor_pos=%p",
+ ctx, imf_context_data, str, attrs, cursor_pos);
+
+ _ecore_imf_context_xim_preedit_string_get(ctx, str, cursor_pos);
+
+ if (!attrs) return;
+ if (!imf_context_data || !imf_context_data->feedbacks) return;
+
+ int i = 0;
+ XIMFeedback last_feedback = 0;
+ int start = -1;
+
+ for (i = 0; i < imf_context_data->preedit_length; i++)
+ {
+ XIMFeedback new_feedback = imf_context_data->feedbacks[i] & FEEDBACK_MASK;
+
+ if (new_feedback != last_feedback)
+ {
+ if (start >= 0)
+ _ecore_imf_xim_feedback_attr_add(attrs, *str, last_feedback, start, i);
+
+ last_feedback = new_feedback;
+ start = i;
+ }
+ }
+
+ if (start >= 0)
+ _ecore_imf_xim_feedback_attr_add(attrs, *str, last_feedback, start, i);
+}
+
+static void
+_ecore_imf_context_xim_focus_in(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIC ic;
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ ic = imf_context_data->ic;
+ imf_context_data->has_focus = EINA_TRUE;
+
+ if (ecore_imf_context_input_panel_enabled_get(ctx))
+ ecore_imf_context_input_panel_show(ctx);
+
+ if (ic)
+ {
+ char *str;
+
+#ifdef X_HAVE_UTF8_STRING
+ if ((str = Xutf8ResetIC(ic)))
+#else
+ if ((str = XmbResetIC(ic)))
+#endif
+ XFree(str);
+
+ XSetICFocus(ic);
+ }
+}
+
+static void
+_ecore_imf_context_xim_focus_out(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIC ic;
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ if (imf_context_data->has_focus == EINA_TRUE)
+ {
+ imf_context_data->has_focus = EINA_FALSE;
+ ic = imf_context_data->ic;
+ if (ic)
+ XUnsetICFocus(ic);
+
+ if (ecore_imf_context_input_panel_enabled_get(ctx))
+ ecore_imf_context_input_panel_hide(ctx);
+ }
+}
+
+static void
+_ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIC ic;
+ char *result;
+ /* restore conversion state after resetting ic later */
+ XIMPreeditState preedit_state = XIMPreeditUnKnown;
+ XVaNestedList preedit_attr;
+ Eina_Bool have_preedit_state = EINA_FALSE;
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ ic = imf_context_data->ic;
+ if (!ic)
+ return;
+
+ if (imf_context_data->preedit_length == 0)
+ return;
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNPreeditState, &preedit_state,
+ NULL);
+ if (!XGetICValues(ic,
+ XNPreeditAttributes, preedit_attr,
+ NULL))
+ have_preedit_state = EINA_TRUE;
+
+ XFree(preedit_attr);
+
+ result = XmbResetIC(ic);
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNPreeditState, preedit_state,
+ NULL);
+ if (have_preedit_state)
+ XSetICValues(ic,
+ XNPreeditAttributes, preedit_attr,
+ NULL);
+
+ XFree(preedit_attr);
+
+ if (imf_context_data->feedbacks)
+ {
+ free(imf_context_data->feedbacks);
+ imf_context_data->feedbacks = NULL;
+ }
+
+ if (imf_context_data->preedit_length)
+ {
+ imf_context_data->preedit_length = 0;
+ free(imf_context_data->preedit_chars);
+ imf_context_data->preedit_chars = NULL;
+
+ ecore_imf_context_preedit_changed_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+
+ if (result)
+ {
+ char *result_utf8 = strdup(result);
+ if (result_utf8)
+ {
+ ecore_imf_context_commit_event_add(ctx, result_utf8);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, result_utf8);
+ free(result_utf8);
+ }
+ }
+
+ XFree(result);
+}
+
+static void
+_ecore_imf_context_xim_use_preedit_set(Ecore_IMF_Context *ctx,
+ Eina_Bool use_preedit)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+ DBG("ctx=%p, imf_context_data=%p, use_preedit=%hhu", ctx, imf_context_data, use_preedit);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ use_preedit = use_preedit != EINA_FALSE;
+
+ if (imf_context_data->use_preedit != use_preedit)
+ {
+ imf_context_data->use_preedit = use_preedit;
+ _ecore_imf_xim_ic_reinitialize(ctx);
+ }
+}
+
+static void
+_ecore_imf_xim_feedback_attr_add(Eina_List **attrs,
+ const char *str,
+ XIMFeedback feedback,
+ int start_pos,
+ int end_pos)
+{
+ Ecore_IMF_Preedit_Attr *attr;
+ unsigned int start_index = _ecore_imf_xim_utf8_offset_to_index(str, start_pos);
+ unsigned int end_index = _ecore_imf_xim_utf8_offset_to_index(str, end_pos);
+
+ if (feedback & FEEDBACK_MASK)
+ {
+ attr = calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+ attr->start_index = start_index;
+ attr->end_index = end_index;
+ *attrs = eina_list_append(*attrs, attr);
+ }
+ else
+ return;
+
+ if (feedback & XIMUnderline)
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
+
+ if (feedback & XIMReverse)
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+
+ if (feedback & XIMHighlight)
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
+}
+
+static void
+_ecore_imf_context_xim_cursor_location_set(Ecore_IMF_Context *ctx,
+ int x, int y, int w, int h)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIC ic;
+ XVaNestedList preedit_attr;
+ XPoint spot;
+
+ DBG("ctx=%p, imf_context_data=%p, location=(%d, %d, %d, %d)",
+ ctx, imf_context_data, x, y, w, h);
+
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+ ic = imf_context_data->ic;
+ if (!ic)
+ return;
+
+ spot.x = x;
+ spot.y = y + h;
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ NULL);
+ XSetICValues(ic,
+ XNPreeditAttributes, preedit_attr,
+ NULL);
+
+ XFree(preedit_attr);
+}
+
+static void
+_ecore_imf_context_xim_input_panel_show(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ ecore_x_e_virtual_keyboard_state_set
+ (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
+}
+
+static void
+_ecore_imf_context_xim_input_panel_hide(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ ecore_x_e_virtual_keyboard_state_set
+ (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
+}
+
+static unsigned int
+_ecore_x_event_reverse_modifiers(unsigned int state)
+{
+ unsigned int modifiers = 0;
+
+ /**< "Control" is pressed */
+ if (state & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
+ modifiers |= ECORE_X_MODIFIER_CTRL;
+
+ /**< "Alt" is pressed */
+ if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
+ modifiers |= ECORE_X_MODIFIER_ALT;
+
+ /**< "Shift" is pressed */
+ if (state & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
+ modifiers |= ECORE_X_MODIFIER_SHIFT;
+
+ /**< "Win" (between "Ctrl" and "Alt") is pressed */
+ if (state & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
+ modifiers |= ECORE_X_MODIFIER_WIN;
+
+ /**< "AltGr" is pressed */
+ if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
+ modifiers |= ECORE_X_MODIFIER_ALTGR;
+
+ return modifiers;
+}
+
+static unsigned int
+_ecore_x_event_reverse_locks(unsigned int state)
+{
+ unsigned int locks = 0;
+
+ /**< "Num" lock is active */
+ if (state & ECORE_IMF_KEYBOARD_LOCK_NUM)
+ locks |= ECORE_X_LOCK_NUM;
+
+ if (state & ECORE_IMF_KEYBOARD_LOCK_CAPS)
+ locks |= ECORE_X_LOCK_CAPS;
+
+ if (state & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
+ locks |= ECORE_X_LOCK_SCROLL;
+
+ return locks;
+}
+
+static KeyCode
+_ecore_imf_xim_keycode_get(Ecore_X_Display *dsp,
+ const char *keyname)
+{
+ KeyCode keycode;
+
+ //DBG("keyname=%s keysym=%lu", keyname, XStringToKeysym(keyname));
+ if (strcmp(keyname, "Keycode-0") == 0)
+ keycode = 0;
+ else
+ keycode = XKeysymToKeycode(dsp, XStringToKeysym(keyname));
+
+ return keycode;
+}
+
+static Eina_Bool
+_ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx,
+ Ecore_IMF_Event_Type type,
+ Ecore_IMF_Event *event)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIC ic;
+ Ecore_X_Display *dsp;
+ Ecore_X_Window win;
+
+ int val;
+ char compose_buffer[256];
+ KeySym sym;
+ char *compose = NULL;
+ char *tmp = NULL;
+ Eina_Bool result = EINA_FALSE;
+
+ DBG("ctx=%p, imf_context_data=%p, type=%d, event=%p",
+ ctx, imf_context_data, type, event);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, EINA_FALSE);
+ ic = imf_context_data->ic;
+ if (!ic)
+ ic = _ecore_imf_xim_ic_get(ctx);
+
+ if (type == ECORE_IMF_EVENT_KEY_DOWN)
+ {
+ XKeyPressedEvent xev;
+ Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
+ DBG("ECORE_IMF_EVENT_KEY_DOWN");
+
+ dsp = ecore_x_display_get();
+ win = imf_context_data->win;
+
+ xev.type = KeyPress;
+ xev.serial = 0; /* hope it doesn't matter */
+ xev.send_event = 0;
+ xev.display = dsp;
+ xev.window = win;
+ xev.root = ecore_x_window_root_get(win);
+ xev.subwindow = win;
+ xev.time = ev->timestamp;
+ xev.x = xev.x_root = 0;
+ xev.y = xev.y_root = 0;
+ xev.state = 0;
+ xev.state |= _ecore_x_event_reverse_modifiers(ev->modifiers);
+ xev.state |= _ecore_x_event_reverse_locks(ev->locks);
+ xev.keycode = _ecore_imf_xim_keycode_get(dsp, ev->keyname);
+ xev.same_screen = True;
+
+ if (ic)
+ {
+ Status mbstatus;
+#ifdef X_HAVE_UTF8_STRING
+ val = Xutf8LookupString(ic,
+ &xev,
+ compose_buffer,
+ sizeof(compose_buffer) - 1,
+ &sym,
+ &mbstatus);
+#else /* ifdef X_HAVE_UTF8_STRING */
+ val = XmbLookupString(ic,
+ &xev,
+ compose_buffer,
+ sizeof(compose_buffer) - 1,
+ &sym,
+ &mbstatus);
+#endif /* ifdef X_HAVE_UTF8_STRING */
+ if (mbstatus == XBufferOverflow)
+ {
+ tmp = malloc(sizeof (char) * (val + 1));
+ if (!tmp)
+ return EINA_FALSE;
+
+ compose = tmp;
+
+#ifdef X_HAVE_UTF8_STRING
+ val = Xutf8LookupString(ic,
+ &xev,
+ tmp,
+ val,
+ &sym,
+ &mbstatus);
+#else /* ifdef X_HAVE_UTF8_STRING */
+ val = XmbLookupString(ic,
+ &xev,
+ tmp,
+ val,
+ &sym,
+ &mbstatus);
+#endif /* ifdef X_HAVE_UTF8_STRING */
+ if (val > 0)
+ {
+ tmp[val] = '\0';
+#ifndef X_HAVE_UTF8_STRING
+ compose = eina_str_convert(nl_langinfo(CODESET),
+ "UTF-8", tmp);
+ free(tmp);
+ tmp = compose;
+#endif /* ifndef X_HAVE_UTF8_STRING */
+ }
+ else
+ compose = NULL;
+ }
+ else if (val > 0)
+ {
+ compose_buffer[val] = '\0';
+#ifdef X_HAVE_UTF8_STRING
+ compose = strdup(compose_buffer);
+#else /* ifdef X_HAVE_UTF8_STRING */
+ compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8",
+ compose_buffer);
+#endif /* ifdef X_HAVE_UTF8_STRING */
+ }
+ }
+ else
+ {
+ compose = strdup(ev->compose);
+ }
+
+ if (compose)
+ {
+ Eina_Unicode *unicode;
+ int len;
+ unicode = eina_unicode_utf8_to_unicode(compose, &len);
+ if (!unicode) abort();
+ if (unicode[0] >= 0x20 && unicode[0] != 0x7f)
+ {
+ ecore_imf_context_commit_event_add(ctx, compose);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, compose);
+ result = EINA_TRUE;
+ }
+ free(compose);
+ free(unicode);
+ }
+ }
+
+ return result;
+}
+
+static const Ecore_IMF_Context_Info xim_info = {
+ .id = "xim",
+ .description = "X input method",
+ .default_locales = "ko:ja:th:zh",
+ .canvas_type = "evas",
+ .canvas_required = 1,
+};
+
+static Ecore_IMF_Context_Class xim_class = {
+ .add = _ecore_imf_context_xim_add,
+ .del = _ecore_imf_context_xim_del,
+ .client_window_set = _ecore_imf_context_xim_client_window_set,
+ .client_canvas_set = NULL,
+ .show = _ecore_imf_context_xim_input_panel_show,
+ .hide = _ecore_imf_context_xim_input_panel_hide,
+ .preedit_string_get = _ecore_imf_context_xim_preedit_string_get,
+ .focus_in = _ecore_imf_context_xim_focus_in,
+ .focus_out = _ecore_imf_context_xim_focus_out,
+ .reset = _ecore_imf_context_xim_reset,
+ .cursor_position_set = NULL,
+ .use_preedit_set = _ecore_imf_context_xim_use_preedit_set,
+ .input_mode_set = NULL,
+ .filter_event = _ecore_imf_context_xim_filter_event,
+ .preedit_string_with_attributes_get = _ecore_imf_context_xim_preedit_string_with_attributes_get,
+ .prediction_allow_set = NULL,
+ .autocapital_type_set = NULL,
+ .control_panel_show = NULL,
+ .control_panel_hide = NULL,
+ .input_panel_layout_set = NULL,
+ .input_panel_layout_get = NULL,
+ .input_panel_language_set = NULL,
+ .input_panel_language_get = NULL,
+ .cursor_location_set = _ecore_imf_context_xim_cursor_location_set,
+ .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 = NULL
+};
+
+static Ecore_IMF_Context *
+xim_imf_module_create(void)
+{
+ Ecore_IMF_Context *ctx = ecore_imf_context_new(&xim_class);
+ DBG("ctx=%p", ctx);
+ return ctx;
+}
+
+static Ecore_IMF_Context *
+xim_imf_module_exit(void)
+{
+ DBG(" ");
+ return NULL;
+}
+
+static Eina_Bool
+_ecore_imf_xim_init(void)
+{
+ eina_init();
+
+ _ecore_imf_xim_log_dom = eina_log_domain_register("ecore_imf_xim", NULL);
+ if (_ecore_imf_xim_log_dom < 0)
+ {
+ EINA_LOG_ERR("Could not register log domain: ecore_imf_xim");
+ return EINA_FALSE;
+ }
+
+ DBG(" ");
+
+ ecore_x_init(NULL);
+ ecore_imf_module_register(&xim_info,
+ xim_imf_module_create,
+ xim_imf_module_exit);
+
+ return EINA_TRUE;
+}
+
+static void
+_ecore_imf_xim_shutdown(void)
+{
+ while (open_ims)
+ {
+ XIM_Im_Info *info = open_ims->data;
+ Ecore_X_Display *display = ecore_x_display_get();
+
+ _ecore_imf_xim_info_im_shutdown(display, EINA_FALSE, info);
+ }
+
+ ecore_x_shutdown();
+
+ if (_ecore_imf_xim_log_dom > 0)
+ {
+ eina_log_domain_unregister(_ecore_imf_xim_log_dom);
+ _ecore_imf_xim_log_dom = -1;
+ }
+
+ eina_shutdown();
+}
+
+EINA_MODULE_INIT(_ecore_imf_xim_init);
+EINA_MODULE_SHUTDOWN(_ecore_imf_xim_shutdown);
+
+/*
+ * internal functions
+ */
+static Ecore_IMF_Context_Data *
+_ecore_imf_xim_context_data_new(void)
+{
+ Ecore_IMF_Context_Data *imf_context_data = NULL;
+ char *locale;
+
+ locale = setlocale(LC_CTYPE, "");
+ if (!locale) return NULL;
+
+ if (!XSupportsLocale()) return NULL;
+
+ imf_context_data = calloc(1, sizeof(Ecore_IMF_Context_Data));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, NULL);
+
+ imf_context_data->locale = strdup(locale);
+ if (!imf_context_data->locale) goto error;
+
+ return imf_context_data;
+error:
+ _ecore_imf_xim_context_data_destroy(imf_context_data);
+ return NULL;
+}
+
+static void
+_ecore_imf_xim_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data)
+{
+ if (!imf_context_data)
+ return;
+
+ if (imf_context_data->ic)
+ XDestroyIC(imf_context_data->ic);
+
+ free(imf_context_data->preedit_chars);
+
+ if (imf_context_data->feedbacks)
+ {
+ free(imf_context_data->feedbacks);
+ imf_context_data->feedbacks = NULL;
+ }
+
+ free(imf_context_data->locale);
+ free(imf_context_data);
+}
+
+static int
+_ecore_imf_xim_preedit_start_call(XIC xic EINA_UNUSED,
+ XPointer client_data,
+ XPointer call_data EINA_UNUSED)
+{
+ Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, -1);
+
+ if (imf_context_data->finalizing == EINA_FALSE)
+ {
+ ecore_imf_context_preedit_start_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
+ }
+ return -1;
+}
+
+static void
+_ecore_imf_xim_preedit_done_call(XIC xic EINA_UNUSED,
+ XPointer client_data,
+ XPointer call_data EINA_UNUSED)
+{
+ Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ if (imf_context_data->preedit_length)
+ {
+ imf_context_data->preedit_length = 0;
+ free(imf_context_data->preedit_chars);
+ imf_context_data->preedit_chars = NULL;
+ ecore_imf_context_preedit_changed_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+
+ if (imf_context_data->finalizing == EINA_FALSE)
+ {
+ ecore_imf_context_preedit_end_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+ }
+}
+
+/* FIXME */
+static int
+_ecore_imf_xim_text_to_utf8(Ecore_IMF_Context *ctx EINA_UNUSED,
+ XIMText *xim_text,
+ char **text)
+{
+ int text_length = 0;
+ char *result = NULL;
+
+ if (xim_text && xim_text->string.multi_byte)
+ {
+ if (xim_text->encoding_is_wchar)
+ {
+ WRN("Wide character return from Xlib not currently supported");
+ *text = NULL;
+ return 0;
+ }
+
+ /* XXX Convert to UTF-8 */
+ result = strdup(xim_text->string.multi_byte);
+ if (result)
+ {
+ text_length = eina_unicode_utf8_get_len(result);
+ if (text_length != xim_text->length)
+ {
+ WRN("Size mismatch when converting text from input method: supplied length = %d, result length = %d",
+ xim_text->length, text_length);
+ }
+ }
+ else
+ {
+ WRN("Error converting text from IM to UCS-4");
+ *text = NULL;
+ return 0;
+ }
+
+ *text = result;
+ return text_length;
+ }
+ else
+ {
+ *text = NULL;
+ return 0;
+ }
+}
+
+static void
+_ecore_imf_xim_preedit_draw_call(XIC xic EINA_UNUSED,
+ XPointer client_data,
+ XIMPreeditDrawCallbackStruct *call_data)
+{
+ Eina_Bool ret = EINA_FALSE;
+ Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ XIMText *t = call_data->text;
+ char *tmp;
+ Eina_Unicode *new_text = NULL;
+ Eina_UStrbuf *preedit_bufs = NULL;
+ int new_text_length;
+ int i = 0;
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ preedit_bufs = eina_ustrbuf_new();
+ if (imf_context_data->preedit_chars)
+ {
+ ret = eina_ustrbuf_append(preedit_bufs, imf_context_data->preedit_chars);
+ if (ret == EINA_FALSE) goto done;
+ }
+
+ new_text_length = _ecore_imf_xim_text_to_utf8(ctx, t, &tmp);
+ if (tmp)
+ {
+ int tmp_len;
+ new_text = eina_unicode_utf8_to_unicode(tmp, &tmp_len);
+ free(tmp);
+ }
+
+ if (t == NULL)
+ {
+ /* delete string */
+ ret = eina_ustrbuf_remove(preedit_bufs,
+ call_data->chg_first, call_data->chg_length);
+ }
+ else if (call_data->chg_length == 0)
+ {
+ /* insert string */
+ ret = eina_ustrbuf_insert(preedit_bufs, new_text, call_data->chg_first);
+ }
+ else if (call_data->chg_length > 0)
+ {
+ /* replace string */
+ ret = eina_ustrbuf_remove(preedit_bufs,
+ call_data->chg_first, call_data->chg_length);
+ if (ret == EINA_FALSE) goto done;
+
+ ret = eina_ustrbuf_insert_n(preedit_bufs, new_text,
+ new_text_length, call_data->chg_first);
+ if (ret == EINA_FALSE) goto done;
+ }
+ else
+ {
+ ret = EINA_FALSE;
+ }
+
+done:
+ if (ret == EINA_TRUE)
+ {
+ free(imf_context_data->preedit_chars);
+ imf_context_data->preedit_chars =
+ eina_ustrbuf_string_steal(preedit_bufs);
+ imf_context_data->preedit_length =
+ eina_unicode_strlen(imf_context_data->preedit_chars);
+
+ if (imf_context_data->feedbacks)
+ {
+ free(imf_context_data->feedbacks);
+ imf_context_data->feedbacks = NULL;
+ }
+
+ if (imf_context_data->preedit_length > 0)
+ {
+ imf_context_data->feedbacks = calloc(imf_context_data->preedit_length, sizeof(XIMFeedback));
+
+ for (i = 0; i < imf_context_data->preedit_length; i++)
+ imf_context_data->feedbacks[i] = t->feedback[i];
+ }
+
+ ecore_imf_context_preedit_changed_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+
+ free(new_text);
+ eina_ustrbuf_free(preedit_bufs);
+}
+
+static void
+_ecore_imf_xim_preedit_caret_call(XIC xic EINA_UNUSED,
+ XPointer client_data,
+ XIMPreeditCaretCallbackStruct *call_data)
+{
+ Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ if (call_data->direction == XIMAbsolutePosition)
+ {
+ imf_context_data->preedit_cursor = call_data->position;
+ if (imf_context_data->finalizing == EINA_FALSE)
+ {
+ ecore_imf_context_preedit_changed_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+ }
+}
+
+static XVaNestedList
+_ecore_imf_xim_preedit_callback_set(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data;
+ imf_context_data = ecore_imf_context_data_get(ctx);
+
+ imf_context_data->preedit_start_cb.client_data = (XPointer)ctx;
+ imf_context_data->preedit_start_cb.callback = (XIMProc)_ecore_imf_xim_preedit_start_call;
+
+ imf_context_data->preedit_done_cb.client_data = (XPointer)ctx;
+ imf_context_data->preedit_done_cb.callback = (XIMProc)_ecore_imf_xim_preedit_done_call;
+
+ imf_context_data->preedit_draw_cb.client_data = (XPointer)ctx;
+ imf_context_data->preedit_draw_cb.callback = (XIMProc)_ecore_imf_xim_preedit_draw_call;
+
+ imf_context_data->preedit_caret_cb.client_data = (XPointer)ctx;
+ imf_context_data->preedit_caret_cb.callback = (XIMProc)_ecore_imf_xim_preedit_caret_call;
+
+ return XVaCreateNestedList(0,
+ XNPreeditStartCallback,
+ &imf_context_data->preedit_start_cb,
+ XNPreeditDoneCallback,
+ &imf_context_data->preedit_done_cb,
+ XNPreeditDrawCallback,
+ &imf_context_data->preedit_draw_cb,
+ XNPreeditCaretCallback,
+ &imf_context_data->preedit_caret_cb,
+ NULL);
+}
+
+static XIC
+_ecore_imf_xim_ic_get(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data;
+ XIC ic;
+ imf_context_data = ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(imf_context_data, NULL);
+
+ ic = imf_context_data->ic;
+ if (!ic)
+ {
+ XIM_Im_Info *im_info = imf_context_data->im_info;
+ XVaNestedList preedit_attr = NULL;
+ XIMStyle im_style = 0;
+ XPoint spot = { 0, 0 };
+ char *name = NULL;
+
+ if (!im_info)
+ {
+ WRN("Could not open XIM.");
+ return NULL;
+ }
+
+ // supported styles
+ // "OverTheSpot" = XIMPreeditPosition | XIMStatusNothing
+ // "OffTheSpot" = XIMPreeditArea | XIMStatusArea
+ // "Root" = XIMPreeditNothing | XIMStatusNothing
+
+ if (imf_context_data->use_preedit == EINA_TRUE)
+ {
+ if (im_info->supports_cursor)
+ {
+ // kinput2 DOES do this...
+ XFontSet fs;
+ char **missing_charset_list;
+ int missing_charset_count;
+ char *def_string;
+
+ im_style |= XIMPreeditPosition;
+ im_style |= XIMStatusNothing;
+ fs = XCreateFontSet(ecore_x_display_get(),
+ "fixed",
+ &missing_charset_list,
+ &missing_charset_count,
+ &def_string);
+ preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ XNFontSet, fs,
+ NULL);
+ }
+ else
+ {
+ im_style |= XIMPreeditCallbacks;
+ im_style |= XIMStatusNothing;
+ preedit_attr = _ecore_imf_xim_preedit_callback_set(ctx);
+ }
+ name = XNPreeditAttributes;
+ }
+ else
+ {
+ im_style |= XIMPreeditNothing;
+ im_style |= XIMStatusNothing;
+ }
+
+ if (!im_info->xim_styles)
+ {
+ WRN("No XIM styles supported! Wanted %#llx",
+ (unsigned long long)im_style);
+ im_style = 0;
+ }
+ else
+ {
+ XIMStyle fallback = 0;
+ int i;
+
+ for (i = 0; i < im_info->xim_styles->count_styles; i++)
+ {
+ XIMStyle cur = im_info->xim_styles->supported_styles[i];
+ if (cur == im_style)
+ break;
+ else if (cur == (XIMPreeditNothing | XIMStatusNothing))
+ /* TODO: fallback is just that or the anyone? */
+ fallback = cur;
+ }
+
+ if (i == im_info->xim_styles->count_styles)
+ {
+ if (fallback)
+ {
+ WRN("Wanted XIM style %#llx not found, using fallback %#llx instead.",
+ (unsigned long long)im_style,
+ (unsigned long long)fallback);
+ im_style = fallback;
+ }
+ else
+ {
+ WRN("Wanted XIM style %#llx not found, no fallback supported.",
+ (unsigned long long)im_style);
+ im_style = 0;
+ }
+ }
+ }
+
+ if ((im_info->im) && (im_style))
+ {
+ ic = XCreateIC(im_info->im,
+ XNInputStyle, im_style,
+ XNClientWindow, imf_context_data->win,
+ name, preedit_attr, NULL);
+ }
+ XFree(preedit_attr);
+ if (ic)
+ {
+ unsigned long mask = 0xaaaaaaaa;
+ XGetICValues(ic,
+ XNFilterEvents, &mask,
+ NULL);
+ imf_context_data->mask = mask;
+ ecore_x_event_mask_set(imf_context_data->win, mask);
+ }
+
+ imf_context_data->ic = ic;
+ if (ic && imf_context_data->has_focus == EINA_TRUE)
+ XSetICFocus(ic);
+ }
+
+ return ic;
+}
+
+static void
+_ecore_imf_xim_ic_reinitialize(Ecore_IMF_Context *ctx)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ XIC ic = imf_context_data->ic;
+ if (ic)
+ {
+ XDestroyIC(ic);
+ imf_context_data->ic = NULL;
+ if (imf_context_data->preedit_length)
+ {
+ imf_context_data->preedit_length = 0;
+ free(imf_context_data->preedit_chars);
+ imf_context_data->preedit_chars = NULL;
+ ecore_imf_context_preedit_changed_event_add(ctx);
+ ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
+ }
+ }
+}
+
+static void
+_ecore_imf_xim_ic_client_window_set(Ecore_IMF_Context *ctx,
+ Ecore_X_Window window)
+{
+ Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+ Ecore_X_Window old_win;
+
+ DBG("ctx=%p, imf_context_data=%p", ctx, imf_context_data);
+ EINA_SAFETY_ON_NULL_RETURN(imf_context_data);
+
+ /* reinitialize IC */
+ _ecore_imf_xim_ic_reinitialize(ctx);
+
+ old_win = imf_context_data->win;
+ DBG("old_win=%#x, window=%#x", old_win, window);
+ if (old_win != 0 && old_win != window) /* XXX how do check window... */
+ {
+ XIM_Im_Info *info;
+ info = imf_context_data->im_info;
+ info->ics = eina_list_remove(info->ics, imf_context_data);
+ if (imf_context_data->im_info)
+ imf_context_data->im_info->user = NULL;
+ imf_context_data->im_info = NULL;
+ }
+
+ imf_context_data->win = window;
+
+ if (window) /* XXX */
+ {
+ XIM_Im_Info *info = NULL;
+ info = _ecore_imf_xim_im_get(window, imf_context_data->locale);
+ imf_context_data->im_info = info;
+ imf_context_data->im_info->ics =
+ eina_list_prepend(imf_context_data->im_info->ics,
+ imf_context_data);
+ if (imf_context_data->im_info)
+ imf_context_data->im_info->user = imf_context_data;
+ }
+}
+
+static XIM_Im_Info *
+_ecore_imf_xim_im_get(Ecore_X_Window window,
+ char *locale)
+{
+ Eina_List *l;
+ XIM_Im_Info *im_info = NULL;
+ XIM_Im_Info *info = NULL;
+
+ DBG(" ");
+ EINA_LIST_FOREACH (open_ims, l, im_info)
+ {
+ if (strcmp(im_info->locale, locale) == 0)
+ {
+ if (im_info->im)
+ {
+ return im_info;
+ }
+ else
+ {
+ info = im_info;
+ break;
+ }
+ }
+ }
+
+ if (!info)
+ {
+ info = calloc(1, sizeof(XIM_Im_Info));
+ if (!info) return NULL;
+ open_ims = eina_list_prepend(open_ims, info);
+ info->win = window;
+ info->locale = strdup(locale);
+ info->reconnecting = EINA_FALSE;
+ }
+
+ _ecore_imf_xim_info_im_init(info);
+ return info;
+}
+
+/* initialize info->im */
+static void
+_ecore_imf_xim_info_im_init(XIM_Im_Info *info)
+{
+ Ecore_X_Display *dsp;
+
+ assert(info->im == NULL);
+ if (info->reconnecting == EINA_TRUE)
+ return;
+
+ if (XSupportsLocale())
+ {
+ if (!XSetLocaleModifiers(""))
+ WRN("Unable to set locale modifiers with XSetLocaleModifiers()");
+ dsp = ecore_x_display_get();
+ info->im = XOpenIM(dsp, NULL, NULL, NULL);
+ if (!info->im)
+ {
+ XRegisterIMInstantiateCallback(dsp,
+ NULL, NULL, NULL,
+ _ecore_imf_xim_instantiate_cb,
+ (XPointer)info);
+ info->reconnecting = EINA_TRUE;
+ return;
+ }
+ _ecore_imf_xim_im_setup(info);
+ }
+}
+
+static void
+_ecore_imf_xim_info_im_shutdown(Ecore_X_Display *display EINA_UNUSED,
+ int is_error EINA_UNUSED,
+ XIM_Im_Info *info)
+{
+ Eina_List *ics, *tmp_list;
+ Ecore_IMF_Context *ctx;
+
+ open_ims = eina_list_remove(open_ims, info);
+
+ ics = info->ics;
+ info->ics = NULL;
+
+ EINA_LIST_FOREACH (ics, tmp_list, ctx)
+ _ecore_imf_xim_ic_client_window_set(ctx, 0);
+
+ EINA_LIST_FREE (ics, ctx)
+ {
+ Ecore_IMF_Context_Data *imf_context_data;
+ imf_context_data = ecore_imf_context_data_get(ctx);
+ _ecore_imf_xim_context_data_destroy(imf_context_data);
+ }
+
+ free(info->locale);
+
+ if (info->im)
+ XCloseIM(info->im);
+
+ free(info);
+}
+
+static void
+_ecore_imf_xim_instantiate_cb(Display *display,
+ XPointer client_data,
+ XPointer call_data EINA_UNUSED)
+{
+ XIM_Im_Info *info = (XIM_Im_Info *)client_data;
+ XIM im = XOpenIM(display, NULL, NULL, NULL);
+ EINA_SAFETY_ON_NULL_RETURN(im);
+
+ info->im = im;
+ _ecore_imf_xim_im_setup(info);
+
+ XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL,
+ _ecore_imf_xim_instantiate_cb,
+ (XPointer)info);
+ info->reconnecting = EINA_FALSE;
+}
+
+static void
+_ecore_imf_xim_im_setup(XIM_Im_Info *info)
+{
+ XIMValuesList *ic_values = NULL;
+ XIMCallback im_destroy_callback;
+
+ if (!info->im)
+ return;
+
+ im_destroy_callback.client_data = (XPointer)info;
+ im_destroy_callback.callback = (XIMProc)_ecore_imf_xim_destroy_cb;
+ XSetIMValues(info->im,
+ XNDestroyCallback, &im_destroy_callback,
+ NULL);
+
+ XGetIMValues(info->im,
+ XNQueryInputStyle, &info->xim_styles,
+ XNQueryICValuesList, &ic_values,
+ NULL);
+
+ if (ic_values)
+ {
+ int i;
+
+ for (i = 0; i < ic_values->count_values; i++)
+ {
+ if (!strcmp(ic_values->supported_values[i],
+ XNStringConversionCallback))
+ info->supports_string_conversion = EINA_TRUE;
+ if (!strcmp(ic_values->supported_values[i],
+ XNCursor))
+ info->supports_cursor = EINA_TRUE;
+ }
+
+ XFree(ic_values);
+ }
+}
+
+static void
+_ecore_imf_xim_destroy_cb(XIM xim EINA_UNUSED,
+ XPointer client_data,
+ XPointer call_data EINA_UNUSED)
+{
+ XIM_Im_Info *info = (XIM_Im_Info *)client_data;
+
+ if (info->user) info->user->ic = NULL;
+ info->im = NULL;
+// _ecore_imf_xim_ic_reinitialize(ctx);
+ _ecore_imf_xim_info_im_init(info);
+
+ return;
+}