2 * Ecore example illustrating how to use ecore imf.
5 * gcc -o ecore_imf_example ecore_imf_example.c `pkg-config --cflags --libs ecore evas ecore-evas ecore-imf ecore-imf-evas`
10 #include <Ecore_Evas.h>
11 #include <Ecore_IMF.h>
12 #include <Ecore_IMF_Evas.h>
16 typedef struct _Entry Entry;
22 Evas_Textblock_Style *txt_style;
23 Evas_Textblock_Cursor *cursor;
24 Evas_Textblock_Cursor *preedit_start;
25 Evas_Textblock_Cursor *preedit_end;
26 Ecore_IMF_Context *imf_context;
27 Eina_Bool have_preedit : 1;
31 _mouse_up_cb(void *data, Evas *e, Evas_Object *o, void *event_info)
36 evas_object_focus_set(en->rect, EINA_TRUE);
40 _entry_focus_in_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
46 ecore_imf_context_focus_in(en->imf_context);
50 _entry_focus_out_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
57 ecore_imf_context_reset(en->imf_context);
58 ecore_imf_context_focus_out(en->imf_context);
63 _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
65 Evas_Object *obj = evas_focus_get(e);
67 _entry_focus_in_cb(obj, NULL, NULL, NULL);
71 _canvas_focus_out_cb(void *data, Evas *e, void *event_info)
73 Evas_Object *obj = evas_focus_get(e);
75 _entry_focus_out_cb(obj, NULL, NULL, NULL);
79 _imf_cursor_info_set(Entry *en)
81 Evas_Coord x, y, w, h;
82 Evas_Coord cx, cy, cw, ch; // cursor geometry
83 int cursor_pos; // cursor position in chars (Not bytes)
87 // get cursor geometry
88 evas_object_geometry_get(en->txt_obj, &x, &y, &w, &h);
89 evas_textblock_cursor_geometry_get(en->cursor, &cx, &cy, &cw, &ch, NULL, EVAS_TEXTBLOCK_CURSOR_BEFORE);
91 // get cursor position
92 cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
94 ecore_imf_context_cursor_position_set(en->imf_context, cursor_pos);
95 ecore_imf_context_cursor_location_set(en->imf_context, x + cx, y + cy, cw, ch);
99 _preedit_del(Entry *en)
101 if (!en || !en->have_preedit) return;
102 if (!en->preedit_start || !en->preedit_end) return;
103 if (!evas_textblock_cursor_compare(en->preedit_start, en->preedit_end)) return;
105 /* delete the preedit characters */
106 evas_textblock_cursor_range_delete(en->preedit_start, en->preedit_end);
110 _preedit_clear(Entry *en)
112 if (en->preedit_start)
114 evas_textblock_cursor_free(en->preedit_start);
115 en->preedit_start = NULL;
120 evas_textblock_cursor_free(en->preedit_end);
121 en->preedit_end = NULL;
124 en->have_preedit = EINA_FALSE;
128 _ecore_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
130 /* This callback will be called when the Input Method Context module requests the surrounding context. */
136 str = evas_object_textblock_text_markup_get(en->txt_obj);
137 *text = str ? strdup(str) : strdup("");
139 /* get the current position of cursor */
141 *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
147 _ecore_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx, void *event_info)
149 /* called when the input method needs to delete all or part of the context surrounding the cursor */
151 Ecore_IMF_Event_Delete_Surrounding *ev = event_info;
152 Evas_Textblock_Cursor *del_start, *del_end;
157 cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
159 del_start = evas_object_textblock_cursor_new(en->txt_obj);
160 evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
162 del_end = evas_object_textblock_cursor_new(en->txt_obj);
163 evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
165 /* implement function to delete character(s) from 'cursor_pos+ev->offset' cursor position to 'cursor_pos + ev->offset + ev->n_chars' */
166 evas_textblock_cursor_range_delete(del_start, del_end);
168 evas_textblock_cursor_free(del_start);
169 evas_textblock_cursor_free(del_end);
173 _ecore_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx, void *event_info)
176 char *commit_str = (char *)event_info;
179 /* delete preedit string */
183 printf("commit string : %s\n", commit_str);
185 evas_object_textblock_text_markup_prepend(en->cursor, commit_str);
187 /* notify cursor information */
188 _imf_cursor_info_set(en);
194 _ecore_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx, void *event_info)
196 /* example how to get preedit string */
198 char *preedit_string;
200 Eina_List *attrs = NULL;
202 Ecore_IMF_Preedit_Attr *attr;
203 Ecore_IMF_Context *imf_context = ctx;
204 int preedit_start_pos, preedit_end_pos;
206 Eina_Bool preedit_end_state = EINA_FALSE;
210 /* get preedit string, attributes */
211 ecore_imf_context_preedit_string_with_attributes_get(imf_context, &preedit_string, &attrs, &cursor_pos);
212 printf("preedit string : %s\n", preedit_string);
214 if (!strcmp(preedit_string, ""))
215 preedit_end_state = EINA_TRUE;
220 preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
222 /* insert preedit character(s) */
223 if (strlen(preedit_string) > 0)
227 EINA_LIST_FOREACH(attrs, l, attr)
229 if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB1) // style type
231 /* apply appropriate style such as underline */
233 else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB2 || attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3)
235 /* apply appropriate style such as underline */
239 /* insert code to display preedit string in your editor */
240 evas_object_textblock_text_markup_prepend(en->cursor, preedit_string);
244 if (!preedit_end_state)
246 /* set preedit start cursor */
247 if (!en->preedit_start)
248 en->preedit_start = evas_object_textblock_cursor_new(en->txt_obj);
249 evas_textblock_cursor_copy(en->cursor, en->preedit_start);
251 /* set preedit end cursor */
252 if (!en->preedit_end)
253 en->preedit_end = evas_object_textblock_cursor_new(en->txt_obj);
254 evas_textblock_cursor_copy(en->cursor, en->preedit_end);
256 preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
258 for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
260 evas_textblock_cursor_char_prev(en->preedit_start);
263 en->have_preedit = EINA_TRUE;
265 /* set cursor position */
266 evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
269 /* notify cursor information */
270 _imf_cursor_info_set(en);
272 EINA_LIST_FREE(attrs, attr)
275 free(preedit_string);
279 _key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
282 Evas_Event_Key_Down *ev = event_info;
283 Eina_Bool control, alt, shift;
285 Eina_Bool cursor_changed;
287 if (!ev->key) return;
291 Ecore_IMF_Event_Key_Down ecore_ev;
292 ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
293 if (ecore_imf_context_filter_event(en->imf_context,
294 ECORE_IMF_EVENT_KEY_DOWN,
295 (Ecore_IMF_Event *)&ecore_ev))
299 control = evas_key_modifier_is_set(ev->modifiers, "Control");
300 alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
301 shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
303 if ((!strcmp(ev->keyname, "Escape")) ||
304 (!strcmp(ev->keyname, "Return")) || (!strcmp(ev->keyname, "KP_Enter")))
305 ecore_imf_context_reset(en->imf_context);
307 if (!strcmp(ev->key, "BackSpace"))
309 if (evas_textblock_cursor_char_prev(en->cursor))
310 evas_textblock_cursor_char_delete(en->cursor);
314 else if (!strcmp(ev->key, "Delete") ||
315 (!strcmp(ev->key, "KP_Delete") && !ev->string))
319 else if ((control) && (!strcmp(ev->key, "v")))
324 else if ((control) && (!strcmp(ev->key, "a")))
329 else if ((control) && (!strcmp(ev->key, "A")))
334 else if ((control) && ((!strcmp(ev->key, "c") || (!strcmp(ev->key, "Insert")))))
339 else if ((control) && ((!strcmp(ev->key, "x") || (!strcmp(ev->key, "m")))))
344 else if ((control) && (!strcmp(ev->key, "z")))
349 else if ((control) && (!strcmp(ev->key, "y")))
354 else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
362 printf("key down string : %s\n", ev->string);
363 evas_object_textblock_text_markup_prepend(en->cursor, ev->string);
367 /* notify cursor information */
368 _imf_cursor_info_set(en);
372 _key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
375 Evas_Event_Key_Up *ev = event_info;
381 Ecore_IMF_Event_Key_Up ecore_ev;
383 ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
384 if (ecore_imf_context_filter_event(en->imf_context,
385 ECORE_IMF_EVENT_KEY_UP,
386 (Ecore_IMF_Event *)&ecore_ev))
392 create_input_field(Evas *evas, Entry *en, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
396 /* create background for text input field */
397 en->rect = evas_object_rectangle_add(evas);
398 evas_object_color_set(en->rect, 150, 150, 150, 255); /* gray */
399 evas_object_move(en->rect, x, y);
400 evas_object_resize(en->rect, w, h);
401 evas_object_show(en->rect);
403 /* create text object for displaying text */
404 en->txt_obj = evas_object_textblock_add(evas);
405 evas_object_color_set(en->txt_obj, 0, 0, 0, 255);
406 evas_object_pass_events_set(en->txt_obj, EINA_TRUE);
407 evas_object_move(en->txt_obj, x, y);
408 evas_object_resize(en->txt_obj, w, h);
409 evas_object_show(en->txt_obj);
411 /* set style on textblock */
412 static const char *style_buf =
413 "DEFAULT='font=Sans font_size=30 color=#000 text_class=entry'"
415 "b='+ font=Sans:style=bold'";
416 en->txt_style = evas_textblock_style_new();
417 evas_textblock_style_set(en->txt_style, style_buf);
418 evas_object_textblock_style_set(en->txt_obj, en->txt_style);
421 en->cursor = evas_object_textblock_cursor_new(en->txt_obj);
423 /* create input context */
424 const char *default_id = ecore_imf_context_default_id_get();
428 en->imf_context = ecore_imf_context_add(default_id);
429 ecore_imf_context_client_window_set(en->imf_context, (void *)ecore_evas_window_get(ecore_evas_ecore_evas_get(evas)));
430 ecore_imf_context_client_canvas_set(en->imf_context, evas);
432 evas_object_event_callback_add(en->rect, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, en);
433 evas_object_event_callback_add(en->rect, EVAS_CALLBACK_KEY_UP, _key_up_cb, en);
434 evas_object_event_callback_add(en->rect, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, en);
435 evas_object_event_callback_add(en->rect, EVAS_CALLBACK_FOCUS_IN, _entry_focus_in_cb, en);
436 evas_object_event_callback_add(en->rect, EVAS_CALLBACK_FOCUS_OUT, _entry_focus_out_cb, en);
438 en->have_preedit = EINA_FALSE;
439 en->preedit_start = NULL;
440 en->preedit_end = NULL;
442 /* register retrieve surrounding callback */
443 ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context, _ecore_imf_retrieve_surrounding_cb, en);
445 /* register commit event callback */
446 ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _ecore_imf_event_commit_cb, en);
448 /* register preedit changed event handler */
449 ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _ecore_imf_event_preedit_changed_cb, en);
451 /* register surrounding delete event callback */
452 ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _ecore_imf_event_delete_surrounding_cb, en);
456 delete_input_field(Entry *en)
462 evas_object_del(en->rect);
468 evas_textblock_cursor_free(en->cursor);
472 if (en->preedit_start)
474 evas_textblock_cursor_free(en->preedit_start);
475 en->preedit_start = NULL;
480 evas_textblock_cursor_free(en->preedit_end);
481 en->preedit_end = NULL;
486 evas_object_del(en->txt_obj);
492 evas_textblock_style_free(en->txt_style);
493 en->txt_style = NULL;
498 ecore_imf_context_del(en->imf_context);
499 en->imf_context = NULL;
504 main(int argc, char *argv[])
510 if (!ecore_evas_init())
512 fprintf(stderr, "failed to call ecore_evas_init()\n");
518 // create a new window, with size=480x800 and default engine
519 ee = ecore_evas_new(NULL, 0, 0, 480, 800, NULL);
523 fprintf(stderr, "failed to call ecore_evas_new\n");
529 // get the canvas off just-created window
530 evas = ecore_evas_get(ee);
533 fprintf(stderr, "failed to ccall ecore_evas_get\n");
537 // create input field rectangle
538 Evas_Object *bg = evas_object_rectangle_add(evas);
539 evas_object_move(bg, 0, 0);
540 evas_object_resize(bg, 480, 800);
541 evas_object_color_set(bg, 255, 255, 255, 255);
542 evas_object_show(bg);
544 evas_event_callback_add(evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
545 evas_event_callback_add(evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _canvas_focus_out_cb, NULL);
547 // create input field 1
548 create_input_field(evas, &en1, 40, 60, 400, 80);
550 // create input field 2
551 create_input_field(evas, &en2, 40, 180, 400, 80);
553 // give focus to input field 1
554 evas_object_focus_set(en1.rect, EINA_TRUE);
556 ecore_main_loop_begin(); // begin mainloop
558 delete_input_field(&en1); // delete input field 1
559 delete_input_field(&en2); // delete input field 2
561 evas_event_callback_del_full(evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
562 evas_event_callback_del_full(evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _canvas_focus_out_cb, NULL);
566 ecore_imf_shutdown();
567 ecore_evas_shutdown();