ibus-immodule: support async mode. especially there is problem when korean input in sync mode. It's known issue in ibus

SVN revision: 73111
This commit is contained in:
Jihoon Kim 2012-07-01 12:57:52 +00:00
parent 9a5adec16f
commit ad0427d107
1 changed files with 117 additions and 26 deletions

View File

@ -45,8 +45,18 @@ struct _IBusIMContext
int caps; 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 Ecore_IMF_Context *_focus_im_context = NULL;
static IBusBus *_bus = NULL; static IBusBus *_bus = NULL;
/* functions prototype */ /* functions prototype */
/* static methods*/ /* static methods*/
@ -55,6 +65,7 @@ static void _set_cursor_location_internal
(Ecore_IMF_Context *ctx); (Ecore_IMF_Context *ctx);
static void _bus_connected_cb (IBusBus *bus, static void _bus_connected_cb (IBusBus *bus,
IBusIMContext *context); IBusIMContext *context);
static XKeyEvent createXKeyEvent (Window win, Eina_Bool press, int keysym, int modifiers);
static void static void
_window_to_screen_geometry_get(Ecore_X_Window client_win, int *x, int *y) _window_to_screen_geometry_get(Ecore_X_Window client_win, int *x, int *y)
@ -108,6 +119,38 @@ _ecore_imf_modifier_to_ibus_modifier(unsigned int modifier)
return state; 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 * IBusIMContext *
ibus_im_context_new(void) ibus_im_context_new(void)
{ {
@ -131,11 +174,39 @@ ibus_im_context_new(void)
return context; 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 EAPI void
ibus_im_context_add(Ecore_IMF_Context *ctx) ibus_im_context_add(Ecore_IMF_Context *ctx)
{ {
EINA_LOG_DBG("%s", __FUNCTION__); EINA_LOG_DBG("%s", __FUNCTION__);
char *s = NULL;
IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx); IBusIMContext *ibusimcontext = (IBusIMContext *)ecore_imf_context_data_get(ctx);
EINA_SAFETY_ON_NULL_RETURN(ibusimcontext); EINA_SAFETY_ON_NULL_RETURN(ibusimcontext);
@ -161,6 +232,10 @@ ibus_im_context_add(Ecore_IMF_Context *ctx)
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT; ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
ibusimcontext->ctx = ctx; ibusimcontext->ctx = ctx;
s = getenv("IBUS_ENABLE_SYNC_MODE");
if (s)
_use_sync_mode = !!atoi(s);
if (ibus_bus_is_connected(_bus)) if (ibus_bus_is_connected(_bus))
_create_input_context (ibusimcontext); _create_input_context (ibusimcontext);
@ -215,10 +290,26 @@ ibus_im_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type,
keycode = ecore_x_keysym_keycode_get(ev->key); keycode = ecore_x_keysym_keycode_get(ev->key);
keysym = XStringToKeysym(ev->key); keysym = XStringToKeysym(ev->key);
state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers) | IBUS_RELEASE_MASK; state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers) | IBUS_RELEASE_MASK;
retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
keysym, if (_use_sync_mode)
keycode - 8, {
state); 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) else if (type == ECORE_IMF_EVENT_KEY_DOWN)
{ {
@ -229,10 +320,26 @@ ibus_im_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type,
keycode = ecore_x_keysym_keycode_get(ev->key); keycode = ecore_x_keysym_keycode_get(ev->key);
keysym = XStringToKeysym(ev->key); keysym = XStringToKeysym(ev->key);
state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers); state = _ecore_imf_modifier_to_ibus_modifier(ev->modifiers);
retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext, if (_use_sync_mode)
keysym, {
keycode - 8, retval = ibus_input_context_process_key_event(ibusimcontext->ibuscontext,
state); 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 else
retval = EINA_FALSE; retval = EINA_FALSE;
@ -509,23 +616,7 @@ _ibus_context_forward_key_event_cb(IBusInputContext *ibuscontext __UNUSED__,
{ {
EINA_LOG_DBG("keyval : %d, state : %d", keyval, state); EINA_LOG_DBG("keyval : %d, state : %d", keyval, state);
// Find the window which has the current keyboard focus. key_event_put(keyval, state);
Window winFocus = 0;
int revert = RevertToParent;
XGetInputFocus(ecore_x_display_get(), &winFocus, &revert);
XKeyEvent event;
if (state & IBUS_RELEASE_MASK)
{
event = createXKeyEvent(winFocus, EINA_FALSE, keyval, state);
XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
}
else
{
event = createXKeyEvent(winFocus, EINA_TRUE, keyval, state);
XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
}
} }
static void static void