From 8758acd64de625d47f5b81ad07bfcb85c0a6a4ae Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Wed, 13 May 2009 13:29:30 +0000 Subject: [PATCH] ecore_imf input method support for edjeentry - on-screen kbds only at the moment. will fix for kbd input. no ecore_imf module tho... yet SVN revision: 40619 --- legacy/edje/configure.ac | 18 ++ legacy/edje/edje.pc.in | 2 +- legacy/edje/src/lib/edje_entry.c | 380 ++++++++++++++++++++++++++++- legacy/edje/src/lib/edje_private.h | 4 +- 4 files changed, 401 insertions(+), 3 deletions(-) diff --git a/legacy/edje/configure.ac b/legacy/edje/configure.ac index 97363d5d91..557d3360b9 100644 --- a/legacy/edje/configure.ac +++ b/legacy/edje/configure.ac @@ -164,11 +164,27 @@ PKG_CHECK_MODULES([EDJE], eet >= 1.0.1 evas >= 0.9.9 ecore >= 0.9.9 + ecore-imf >= 0.9.9 + ecore-imf-evas >= 0.9.9 ecore-job >= 0.9.9 embryo >= 0.9.1 ] ) +have_ecore_imf="no" +PKG_CHECK_MODULES([ECORE_IMF], + [ + ecore-imf >= 0.9.9 + ecore-imf-evas >= 0.9.9 + ], + [ + AC_DEFINE(HAVE_ECORE_IMF, 1, [Input Method Support for Edje Entry]) + have_ecore_imf="yes" + requirement_edje="ecore-imf ecore-imf-evas ${requirement_edje}" + ], + [have_ecore_imf="yes"] +) + requirement_edje="embryo ecore-job ecore evas eet eina-0 ${requirement_edje}" # Dependencies for the binaries @@ -271,3 +287,5 @@ echo " Installation.........: make install" echo echo " prefix.............: $prefix" echo +echo " Ecore IMF............: $have_ecore_imf" +echo diff --git a/legacy/edje/edje.pc.in b/legacy/edje/edje.pc.in index d589e9ac2f..7d2d4bf9d0 100644 --- a/legacy/edje/edje.pc.in +++ b/legacy/edje/edje.pc.in @@ -10,5 +10,5 @@ Description: Enlightened graphical design and layout engine. Requires: @requirement_edje@ Version: @VERSION@ Libs: -L${libdir} -ledje -Libs.private: @EDJE_LIBS@ @EVIL_LIBS@ +Libs.private: @EDJE_LIBS@ @EVIL_LIBS@ @ECORE_IMF_LIBS@ Cflags: -I${includedir} diff --git a/legacy/edje/src/lib/edje_entry.c b/legacy/edje/src/lib/edje_entry.c index 1f99cd0777..26f3d04a48 100644 --- a/legacy/edje/src/lib/edje_entry.c +++ b/legacy/edje/src/lib/edje_entry.c @@ -27,6 +27,11 @@ void *alloca (size_t); #include "edje_private.h" +static int _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos); +static int _edje_entry_imf_event_commit_cb(void *data, int type, void *event); +static int _edje_entry_imf_event_changed_cb(void *data, int type, void *event); +static int _edje_entry_imf_event_delete_surrounding_cb(void *data, int type, void *event); + typedef struct _Entry Entry; typedef struct _Sel Sel; typedef struct _Anchor Anchor; @@ -49,6 +54,16 @@ struct _Entry Evas_Bool select_mod_start : 1; Evas_Bool select_mod_end : 1; Evas_Bool had_sel : 1; + +#ifdef ECORE_IMF + int comp_len; + + Ecore_IMF_Context *imf_context; + + Ecore_Event_Handler *imf_ee_handler_commit; + Ecore_Event_Handler *imf_ee_handler_delete; + Ecore_Event_Handler *imf_ee_handler_changed; +#endif }; struct _Sel @@ -65,18 +80,96 @@ struct _Anchor Eina_List *sel; }; +#ifdef ECORE_IMF +static void +_edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission, const char *source) +{ + Edje_Real_Part *rp = data; + if (!rp) return; + Entry *en = rp->entry_data; + + if (!en) return; + + if (!rp->edje || !rp->edje->obj) return; + + if (!en->imf_context) return; + + if (evas_object_focus_get(rp->edje->obj)) + { + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_focus_in(en->imf_context); + } +} + +static void +_edje_entry_focus_out_cb(void *data, Evas_Object *o, const char *emission, const char *source) +{ + Edje_Real_Part *rp = data; + if (!rp) return; + Entry *en = rp->entry_data; + if (!en) return; + + if (!en->imf_context) return; + + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_cursor_position_set(en->imf_context, evas_textblock_cursor_pos_get(en->cursor)); + ecore_imf_context_focus_out(en->imf_context); +} +#endif + static void _edje_focus_in_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) { Edje *ed = data; +#ifdef ECORE_IMF + Edje_Real_Part *rp; + Entry *en; +#endif + _edje_emit(ed, "focus,in", ""); +#ifdef ECORE_IMF + rp = ed->focused_part; + if (rp == NULL) return; + + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE)) + return; + + if (en->imf_context) + { + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_focus_in(en->imf_context); + } +#endif } static void _edje_focus_out_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) { Edje *ed = data; +#ifdef ECORE_IMF + Edje_Real_Part *rp = ed->focused_part; + Entry *en; +#endif + _edje_emit(ed, "focus,out", ""); + +#ifdef ECORE_IMF + if (!rp) return; + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE)) + return; + + if (en->imf_context) + { + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_cursor_position_set(en->imf_context, + evas_textblock_cursor_pos_get(en->cursor)); + ecore_imf_context_focus_out(en->imf_context); + } +#endif } static void @@ -801,6 +894,20 @@ _edje_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE)) return; if (!ev->key) return; + +#ifdef ECORE_IMF +#if 0 // FIXME -- keyboard activated IMF + if (en->imf_context) + { + Ecore_IMF_Event_Key_Down ecore_ev; + ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev); + if (ecore_imf_context_filter_event(en->imf_context, + ECORE_IMF_EVENT_KEY_DOWN, + (Ecore_IMF_Event *)&ecore_ev)) + return; + } +#endif +#endif tc = evas_object_textblock_cursor_new(rp->object); evas_textblock_cursor_copy(en->cursor, tc); @@ -1065,6 +1172,16 @@ _edje_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) } if ((evas_textblock_cursor_compare(tc, en->cursor)) && (!cursor_changed)) _edje_emit(ed, "cursor,changed", rp->part->name); + +#ifdef ECORE_IMF + if (en->imf_context) + { + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_cursor_position_set(en->imf_context, + evas_textblock_cursor_pos_get(en->cursor)); + } +#endif + evas_textblock_cursor_free(tc); _edje_entry_real_part_configure(rp); } @@ -1080,6 +1197,21 @@ _edje_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE)) return; + +#ifdef ECORE_IMF +#if 0 // FIXME key activation imf + if (en->imf_context) + { + Ecore_IMF_Event_Key_Up ecore_ev; + ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev); + if (ecore_imf_context_filter_event(en->imf_context, + ECORE_IMF_EVENT_KEY_UP, + (Ecore_IMF_Event *)&ecore_ev)) + return; + } +#endif +#endif + } static void @@ -1127,7 +1259,7 @@ _edje_part_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info { Evas_Coord lx, ly, lw, lh; int line; - + line = evas_textblock_cursor_line_coord_set(en->cursor, en->cy); if (line == -1) _curs_end(en->cursor, rp->object, en); @@ -1139,6 +1271,14 @@ _edje_part_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info else _curs_lin_end(en->cursor, rp->object, en); } + line = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh); + } + else + { + Evas_Coord lx, ly, lw, lh; + int line; + + line = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh); } if (dosel) { @@ -1196,6 +1336,16 @@ _edje_part_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info } if (evas_textblock_cursor_compare(tc, en->cursor)) _edje_emit(rp->edje, "cursor,changed", rp->part->name); + +#ifdef ECORE_IMF + if (en->imf_context) + { + ecore_imf_context_reset(en->imf_context); + ecore_imf_context_cursor_position_set(en->imf_context, + evas_textblock_cursor_pos_get(en->cursor)); + } +#endif + evas_textblock_cursor_free(tc); _edje_entry_real_part_configure(rp); } @@ -1346,6 +1496,11 @@ void _edje_entry_real_part_init(Edje_Real_Part *rp) { Entry *en; +#ifdef ECORE_IMF + const char *ctx_id; + const Ecore_IMF_Context_Info *ctx_info; + Evas *evas; +#endif en = calloc(1, sizeof(Entry)); if (!en) return; @@ -1387,6 +1542,52 @@ _edje_entry_real_part_init(Edje_Real_Part *rp) evas_object_show(en->cursor_fg); } en->cursor = evas_object_textblock_cursor_get(rp->object); + +#ifdef ECORE_IMF + if (!ecore_imf_module_available_get()) + { + en->imf_context = NULL; + return; + } + + edje_object_signal_callback_add(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp); + edje_object_signal_callback_add(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp); + + ctx_id = ecore_imf_context_default_id_get(); + if (ctx_id) + { + ctx_info = ecore_imf_context_info_by_id_get(ctx_id); + if (!ctx_info->canvas_type || + strcmp(ctx_info->canvas_type, "evas") == 0) + { + en->imf_context = ecore_imf_context_add(ctx_id); + } + + else + { + ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas"); + if (ctx_id) + { + en->imf_context = ecore_imf_context_add(ctx_id); + } + } + } + else + en->imf_context = NULL; + + if (!en->imf_context) return; + + ecore_imf_context_client_window_set(en->imf_context, rp->object); + ecore_imf_context_client_canvas_set(en->imf_context, rp->edje->evas); + + ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context, _edje_entry_imf_retrieve_surrounding_cb, rp); + en->imf_ee_handler_commit = ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _edje_entry_imf_event_commit_cb, rp->edje); + en->imf_ee_handler_delete = ecore_event_handler_add(ECORE_IMF_EVENT_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, rp); + en->imf_ee_handler_changed = ecore_event_handler_add(ECORE_IMF_EVENT_PREEDIT_CHANGED, _edje_entry_imf_event_changed_cb, rp->edje); + ecore_imf_context_input_mode_set(en->imf_context, + rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ? + ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL); +#endif } void @@ -1401,6 +1602,33 @@ _edje_entry_real_part_shutdown(Edje_Real_Part *rp) rp->edje->subobjs = eina_list_remove(rp->edje->subobjs, en->cursor_fg); evas_object_del(en->cursor_bg); evas_object_del(en->cursor_fg); + +#ifdef ECORE_IMF + if (en->imf_context) + { + if (en->imf_ee_handler_commit) + { + ecore_event_handler_del(en->imf_ee_handler_commit); + en->imf_ee_handler_commit = NULL; + } + + if (en->imf_ee_handler_delete) + { + ecore_event_handler_del(en->imf_ee_handler_delete); + en->imf_ee_handler_delete = NULL; + } + + if (en->imf_ee_handler_changed) + { + ecore_event_handler_del(en->imf_ee_handler_changed); + en->imf_ee_handler_changed = NULL; + } + + ecore_imf_context_del(en->imf_context); + en->imf_context = NULL; + } +#endif + free(en); } @@ -1600,3 +1828,153 @@ _edje_entry_select_abort(Edje_Real_Part *rp) _edje_entry_real_part_configure(rp); } } + +#ifdef ECORE_IMF +static int +_edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos) +{ + Edje_Real_Part *rp = data; + Entry *en; + const char *str; + + if (!rp) return 0; + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE)) + return 0; + + if (text) + { + str = _edje_entry_text_get(rp); + *text = str ? strdup(str) : strdup(""); + } + + if (cursor_pos) + { + *cursor_pos = evas_textblock_cursor_pos_get(en->cursor); + } + + return 1; +} + +static int +_edje_entry_imf_event_commit_cb(void *data, int type, void *event) +{ + Edje* ed = data; + Edje_Real_Part *rp = ed->focused_part; + Entry *en; + Ecore_IMF_Event_Commit *ev = event; + int cursor_pos, composition_pos; + int start_pos, end_pos; + Evas_Bool selecting; + Evas_Bool changed = 0; + int i; + + if (!rp) return 1; + + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE)) + return 1; + + if (en->imf_context != ev->ctx) return 1; + + if (en->have_selection) + { + for (i = 0; i < en->comp_len; i++) + _backspace(en->cursor, rp->object, en); + _sel_clear(en->cursor, rp->object, en); + } + + evas_textblock_cursor_text_prepend(en->cursor, ev->str); + + _curs_update_from_curs(en->cursor, rp->object, en); + _anchors_get(en->cursor, rp->object, en); + _edje_emit(rp->edje, "entry,changed", rp->part->name); + _edje_emit(ed, "cursor,changed", rp->part->name); + + return 0; +} + +static int +_edje_entry_imf_event_changed_cb(void *data, int type, void *event) +{ + Edje* ed = data; + Edje_Real_Part *rp = ed->focused_part; + Entry *en; + int cursor_pos; + int composition_pos, length; + int start_pos, end_pos; + Evas_Bool selecting = 0; + Evas_Bool changed = 0; + Ecore_IMF_Event_Commit *ev = event; + Evas_Textblock_Cursor *start_cur, *end_cur; + int i; + char *preedit_string; + + if (!rp) return 1; + + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE)) + return 1; + + if (!en->imf_context) return 1; + + if (en->imf_context != ev->ctx) return 1; + + ecore_imf_context_preedit_string_get(en->imf_context, &preedit_string, &length); + + // FIXME : check the maximum length of evas_textblock + if ( 0 /* check the maximum length of evas_textblock */ ) + return 1; + + cursor_pos = evas_textblock_cursor_pos_get(en->cursor); + + if (en->have_selection) + { + // delete the composing characters + for (i = 0;i < en->comp_len; i++) + _backspace(en->cursor, rp->object, en); + } + + en->comp_len = length; + + _sel_clear(en->cursor, rp->object, en); + _sel_enable(en->cursor, rp->object, en); + _sel_start(en->cursor, rp->object, en); + + evas_textblock_cursor_text_prepend(en->cursor, preedit_string); + + _sel_extend(en->cursor, rp->object, en); + + _curs_update_from_curs(en->cursor, rp->object, en); + _anchors_get(en->cursor, rp->object, en); + _edje_emit(rp->edje, "entry,changed", rp->part->name); + _edje_emit(ed, "cursor,changed", rp->part->name); + + return 0; +} + +static int +_edje_entry_imf_event_delete_surrounding_cb(void *data, int type, void *event) +{ + Edje *ed = data; + Edje_Real_Part *rp = ed->focused_part; + Entry *en; + Ecore_IMF_Event_Delete_Surrounding *ev = event; + int cursor_pos; + + if (!rp) return 1; + en = rp->entry_data; + if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) || + (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE)) + return 1; + + if (en->imf_context != ev->ctx) return 1; + + cursor_pos = evas_textblock_cursor_pos_get(en->cursor); + + return 0; +} +#endif diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 7cdace856d..d580ab6e30 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -20,7 +20,9 @@ #include "Edje.h" #include "Edje_Edit.h" - +#ifdef HAVE_ECORE_IMF +#include +#endif #ifdef __GNUC__ # if __GNUC__ >= 4