Create and use syncronous ecore_imf API rev.67290
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 18 Jan 2012 04:38:04 +0000 (04:38 +0000)
committerJihoon Kim <jihoon48.kim@samsung.com>
Mon, 30 Jan 2012 10:44:04 +0000 (19:44 +0900)
Change-Id: I849452242f78298deb4c2c7fd2e1e9c48918d2ec

src/lib/ecore_imf/Ecore_IMF.h
src/lib/ecore_imf/ecore_imf_context.c
src/lib/ecore_imf/ecore_imf_private.h
src/modules/immodules/scim/scim_imcontext.cpp
src/modules/immodules/xim/ecore_imf_xim.c

index fc9694a..5f5610b 100644 (file)
@@ -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);
index eb06f83..954f3f4 100644 (file)
@@ -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.
index c288f9f..b659e08 100644 (file)
@@ -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);
index b4edfe4..6cb72c2 100644 (file)
@@ -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<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_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());
+     }
 }
 
index e81e486..ea7ee7f 100644 (file)
@@ -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);
           }
      }
 }