efl/legacy/ecore/src/modules/immodules/ibus/ibus_imcontext.c

821 lines
25 KiB
C

#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);
}
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 __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 __UNUSED__,
IBusIMContext *ibusimcontext)
{
EINA_LOG_DBG("ibus is connected");
if (ibusimcontext)
_create_input_context(ibusimcontext);
}
static void
_ibus_context_commit_text_cb(IBusInputContext *ibuscontext __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 __UNUSED__,
guint keyval,
guint state,
IBusIMContext *ibusimcontext __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 __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 __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 __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 __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 __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 __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);
}