From 10da478689fe1658f49b09bd399924f35caeb959 Mon Sep 17 00:00:00 2001 From: raster Date: Wed, 18 Jan 2012 04:38:04 +0000 Subject: [PATCH] Create and use syncronous ecore_imf API rev.67290 Change-Id: I849452242f78298deb4c2c7fd2e1e9c48918d2ec --- src/lib/ecore_imf/Ecore_IMF.h | 14 +++ src/lib/ecore_imf/ecore_imf_context.c | 136 ++++++++++++++++++++++++++ src/lib/ecore_imf/ecore_imf_private.h | 10 +- src/modules/immodules/scim/scim_imcontext.cpp | 45 +++++++-- src/modules/immodules/xim/ecore_imf_xim.c | 22 ++++- 5 files changed, 215 insertions(+), 12 deletions(-) diff --git a/src/lib/ecore_imf/Ecore_IMF.h b/src/lib/ecore_imf/Ecore_IMF.h index fc9694a..5f5610b 100644 --- a/src/lib/ecore_imf/Ecore_IMF.h +++ b/src/lib/ecore_imf/Ecore_IMF.h @@ -101,6 +101,17 @@ EAPI extern int ECORE_IMF_EVENT_PREEDIT_CHANGED; EAPI extern int ECORE_IMF_EVENT_COMMIT; EAPI extern int ECORE_IMF_EVENT_DELETE_SURROUNDING; +typedef void (*Ecore_IMF_Event_Cb) (void *data, Ecore_IMF_Context *ctx, void *event_info); + +typedef enum +{ + ECORE_IMF_CALLBACK_PREEDIT_START, + ECORE_IMF_CALLBACK_PREEDIT_END, + ECORE_IMF_CALLBACK_PREEDIT_CHANGED, + ECORE_IMF_CALLBACK_COMMIT, + ECORE_IMF_CALLBACK_DELETE_SURROUNDING +} Ecore_IMF_Callback_Type; + typedef enum { ECORE_IMF_EVENT_MOUSE_DOWN, @@ -443,6 +454,9 @@ EAPI void ecore_imf_context_preedit_end_event_add(Ecore EAPI void ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx); EAPI void ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str); EAPI void ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars); +EAPI void ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data); +EAPI void *ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func); +EAPI void ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info); EAPI void ecore_imf_context_prediction_allow_set(Ecore_IMF_Context *ctx, Eina_Bool prediction); EAPI Eina_Bool ecore_imf_context_prediction_allow_get(Ecore_IMF_Context *ctx); EAPI void ecore_imf_context_autocapital_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type); diff --git a/src/lib/ecore_imf/ecore_imf_context.c b/src/lib/ecore_imf/ecore_imf_context.c index eb06f83..954f3f4 100644 --- a/src/lib/ecore_imf/ecore_imf_context.c +++ b/src/lib/ecore_imf/ecore_imf_context.c @@ -224,6 +224,7 @@ EAPI void ecore_imf_context_del(Ecore_IMF_Context *ctx) { void *data; + Ecore_IMF_Func_Node *fn; if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) { @@ -232,6 +233,13 @@ ecore_imf_context_del(Ecore_IMF_Context *ctx) return; } if (ctx->klass->del) ctx->klass->del(ctx); + + if (ctx->callbacks) + { + EINA_LIST_FREE(ctx->callbacks, fn) + free(fn); + } + ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE); EINA_LIST_FREE(ctx->private_key_list, data) @@ -1031,6 +1039,134 @@ ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offse } /** + * Add (register) a callback function to a given context event. + * + * This function adds a function callback to the context @p ctx when the + * event of type @p type occurs on it. The function pointer is @p + * func. + * + * The event type @p type to trigger the function may be one of + * #ECORE_IMF_CALLBACK_PREEDIT_START, #ECORE_IMF_CALLBACK_PREEDIT_END, + * #ECORE_IMF_CALLBACK_PREEDIT_CHANGED, #ECORE_IMF_CALLBACK_COMMIT and + * #ECORE_IMF_CALLBACK_DELETE_SURROUNDING. + * + * @param ctx Ecore_IMF_Context to attach a callback to. + * @param type The type of event that will trigger the callback + * @param func The (callback) function to be called when the event is + * triggered + * @param data The data pointer to be passed to @p func + * @ingroup Ecore_IMF_Context_Module_Group + * @since 1.2.0 + */ +EAPI void +ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data) +{ + Ecore_IMF_Func_Node *fn = NULL; + + if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) + { + ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, + "ecore_imf_context_event_callback_add"); + return; + } + + if (!func) return; + + fn = calloc(1, sizeof (Ecore_IMF_Func_Node)); + if (!fn) return; + + fn->func = func; + fn->data = data; + fn->type = type; + + ctx->callbacks = eina_list_append(ctx->callbacks, fn); +} + +/** + * Delete (unregister) a callback function registered to a given + * context event. + * + * This function removes a function callback from the context @p ctx when the + * event of type @p type occurs on it. The function pointer is @p + * func. + * + * @see ecore_imf_context_event_callback_add() for more details + * + * @param ctx Ecore_IMF_Context to remove a callback from. + * @param type The type of event that was trigerring the callback + * @param func The (callback) function that was to be called when the event was triggered + * @return the data pointer + * @ingroup Ecore_IMF_Context_Module_Group + * @since 1.2.0 + */ +EAPI void * +ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func) +{ + Eina_List *l = NULL; + Eina_List *l_next = NULL; + Ecore_IMF_Func_Node *fn = NULL; + + if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) + { + ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, + "ecore_imf_context_event_callback_del"); + return; + } + + if (!func) return NULL; + if (!ctx->callbacks) return NULL; + + EINA_LIST_FOREACH_SAFE(ctx->callbacks, l, l_next, fn) + { + if ((fn) && (fn->func == func) && (fn->type == type)) + { + void *tmp = fn->data; + free(fn); + ctx->callbacks = eina_list_remove_list(ctx->callbacks, l); + return tmp; + } + } + return NULL; +} + +/** + * Call a given callback on the context @p ctx. + * + * ecore_imf_context_preedit_start_event_add, ecore_imf_context_preedit_end_event_add, + * ecore_imf_context_preedit_changed_event_add, ecore_imf_context_commit_event_add and + * ecore_imf_context_delete_surrounding_event_add APIs are asynchronous + * because those API adds each event to the event queue. + * + * This API provides the way to call each callback function immediately. + * + * @param ctx Ecore_IMF_Context. + * @param type The type of event that will trigger the callback + * @param event_info The pointer to event specific struct or information to + * pass to the callback functions registered on this event + * @ingroup Ecore_IMF_Context_Module_Group + * @since 1.2.0 + */ +EAPI void +ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info) +{ + Ecore_IMF_Func_Node *fn = NULL; + Eina_List *l = NULL; + + if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT)) + { + ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT, + "ecore_imf_context_event_callback_call"); + return; + } + + EINA_LIST_FOREACH(ctx->callbacks, l, fn) + { + if ((fn) && (fn->type == type) && (fn->func)) + fn->func(fn->data, ctx, event_info); + } +} + +/** * Ask the Input Method Context to show the control panel of using Input Method. * * @param ctx An #Ecore_IMF_Context. diff --git a/src/lib/ecore_imf/ecore_imf_private.h b/src/lib/ecore_imf/ecore_imf_private.h index c288f9f..b659e08 100644 --- a/src/lib/ecore_imf/ecore_imf_private.h +++ b/src/lib/ecore_imf/ecore_imf_private.h @@ -35,6 +35,7 @@ extern int _ecore_imf_log_dom; #define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_imf_log_dom, __VA_ARGS__) typedef struct _Ecore_IMF_Module Ecore_IMF_Module; +typedef struct _Ecore_IMF_Func_Node Ecore_IMF_Func_Node; struct _Ecore_IMF_Context { @@ -47,10 +48,10 @@ struct _Ecore_IMF_Context void *client_canvas; Eina_Bool (*retrieve_surrounding_func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos); void *retrieve_surrounding_data; + Eina_List *callbacks; Ecore_IMF_Autocapital_Type autocapital_type; Ecore_IMF_Input_Panel_Layout input_panel_layout; Ecore_IMF_Input_Panel_Lang input_panel_lang; - Eina_List *callbacks; Eina_List *disabled_key_list; Eina_List *private_key_list; Eina_Bool allow_prediction : 1; @@ -64,6 +65,13 @@ struct _Ecore_IMF_Module Ecore_IMF_Context *(*exit)(void); }; +struct _Ecore_IMF_Func_Node +{ + void (*func) (); + const void *data; + Ecore_IMF_Callback_Type type; +}; + void ecore_imf_module_init(void); void ecore_imf_module_shutdown(void); Eina_List *ecore_imf_module_available_get(void); diff --git a/src/modules/immodules/scim/scim_imcontext.cpp b/src/modules/immodules/scim/scim_imcontext.cpp index b4edfe4..6cb72c2 100644 --- a/src/modules/immodules/scim/scim_imcontext.cpp +++ b/src/modules/immodules/scim/scim_imcontext.cpp @@ -806,8 +806,10 @@ isf_imf_context_reset (Ecore_IMF_Context *ctx) 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_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 (); } @@ -951,8 +953,10 @@ isf_imf_context_focus_out (Ecore_IMF_Context *ctx) 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_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 (); } @@ -1520,6 +1524,7 @@ panel_slot_commit_string (int context, const WideString &wstr) 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()); } } @@ -1818,7 +1823,9 @@ turn_on_ic (EcoreIMFContextISF *ic) 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; } } @@ -1848,7 +1855,9 @@ turn_off_ic (EcoreIMFContextISF *ic) 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; } } @@ -2183,7 +2192,9 @@ open_specific_factory (EcoreIMFContextISF *ic, 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; } } @@ -2452,6 +2463,7 @@ slot_show_preedit_string (IMEngineInstanceBase *si) 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; } } @@ -2502,10 +2514,14 @@ slot_hide_preedit_string (IMEngineInstanceBase *si) if (ic->impl->use_preedit) { if (emit) - ecore_imf_context_preedit_changed_event_add (ic->ctx); + { + 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; } } @@ -2551,9 +2567,11 @@ slot_update_preedit_caret (IMEngineInstanceBase *si, int caret) 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); @@ -2578,11 +2596,13 @@ slot_update_preedit_string (IMEngineInstanceBase *si, 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 @@ -2614,7 +2634,10 @@ slot_commit_string (IMEngineInstanceBase *si, EcoreIMFContextISF *ic = static_cast (si->get_frontend_data ()); if (ic && ic->ctx) - ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ()); + { + 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 @@ -2761,7 +2784,12 @@ slot_delete_surrounding_text (IMEngineInstanceBase *si, 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; @@ -2803,6 +2831,9 @@ fallback_commit_string_cb (IMEngineInstanceBase *si __UNUSED__, 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_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()); + } } diff --git a/src/modules/immodules/xim/ecore_imf_xim.c b/src/modules/immodules/xim/ecore_imf_xim.c index e81e486..ea7ee7f 100644 --- a/src/modules/immodules/xim/ecore_imf_xim.c +++ b/src/modules/immodules/xim/ecore_imf_xim.c @@ -389,6 +389,7 @@ _ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx) 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) @@ -397,6 +398,7 @@ _ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx) 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); } } @@ -707,6 +709,7 @@ _ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx, 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); @@ -872,8 +875,10 @@ preedit_start_callback(XIC xic __UNUSED__, imf_context_data = ecore_imf_context_data_get(ctx); if (imf_context_data->finalizing == EINA_FALSE) - ecore_imf_context_preedit_start_event_add(ctx); - + { + ecore_imf_context_preedit_start_event_add(ctx); + ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL); + } return -1; } @@ -893,10 +898,14 @@ preedit_done_callback(XIC xic __UNUSED__, 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_preedit_end_event_add(ctx); + ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL); + } } /* FIXME */ @@ -1023,6 +1032,7 @@ done: } ecore_imf_context_preedit_changed_event_add(ctx); + ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL); } free(new_text); @@ -1044,7 +1054,10 @@ preedit_caret_callback(XIC xic __UNUSED__, // printf("call_data->position:%d\n", call_data->position); 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_preedit_changed_event_add(ctx); + ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL); + } } } @@ -1210,6 +1223,7 @@ reinitialize_ic(Ecore_IMF_Context *ctx) 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); } } } -- 2.7.4