From 9940c3c0234055f40292b8c879d4a053ac4d5433 Mon Sep 17 00:00:00 2001 From: andrunko Date: Mon, 19 Nov 2007 18:42:40 +0000 Subject: [PATCH] Added support for Ecore_IMF on E_Entry. SVN revision: 32777 --- configure.in | 1 + src/bin/e_entry.c | 182 ++++++++++++++++++++++++++++++++++++++++++++-- src/bin/e_main.c | 4 + 3 files changed, 181 insertions(+), 6 deletions(-) diff --git a/configure.in b/configure.in index 065485c71..e09e71cd4 100644 --- a/configure.in +++ b/configure.in @@ -174,6 +174,7 @@ PKG_CHECK_MODULES(E, [ ecore-con ecore-job ecore-txt + ecore-im edje eet embryo diff --git a/src/bin/e_entry.c b/src/bin/e_entry.c index 471097a2d..8a7be3117 100644 --- a/src/bin/e_entry.c +++ b/src/bin/e_entry.c @@ -3,6 +3,8 @@ */ #include "e.h" +#include + typedef struct _E_Entry_Smart_Data E_Entry_Smart_Data; struct _E_Entry_Smart_Data @@ -11,6 +13,7 @@ struct _E_Entry_Smart_Data Evas_Object *editable_object; E_Menu *popup; Ecore_Event_Handler *selection_handler; + Ecore_IMF_Context *imf_context; int enabled; int focused; @@ -23,6 +26,7 @@ struct _E_Entry_Smart_Data /* local subsystem functions */ static void _e_entry_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _e_entry_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_entry_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_entry_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_entry_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); @@ -47,6 +51,9 @@ static void _e_entry_cb_copy(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_entry_cb_paste(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_entry_cb_select_all(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_entry_cb_delete(void *data, E_Menu *m, E_Menu_Item *mi); +static int _e_entry_cb_imf_retrieve_surrounding(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos); +static int _e_entry_cb_imf_event_commit(void *data, int type, void *event); +static int _e_entry_cb_imf_event_delete_surrounding(void *data, int type, void *event); /* local subsystem globals */ static Evas_Smart *_e_entry_smart = NULL; @@ -171,6 +178,10 @@ e_entry_password_set(Evas_Object *entry, int password_mode) if ((!entry) || (!(sd = evas_object_smart_data_get(entry)))) return; e_editable_password_set(sd->editable_object, password_mode); + if (sd->imf_context) + ecore_imf_context_input_mode_set(sd->imf_context, + password_mode ? ECORE_IMF_INPUT_MODE_FULL & ECORE_IMF_INPUT_MODE_INVISIBLE : + ECORE_IMF_INPUT_MODE_FULL); } /** @@ -214,11 +225,22 @@ e_entry_focus(Evas_Object *entry) if (!sd->selection_dragging) { e_editable_cursor_move_to_end(sd->editable_object); + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_cursor_position_set(sd->imf_context, + e_editable_cursor_pos_get(sd->editable_object)); + } e_editable_selection_move_to_end(sd->editable_object); } if (sd->enabled) e_editable_cursor_show(sd->editable_object); e_editable_selection_show(sd->editable_object); + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_focus_in(sd->imf_context); + } sd->focused = 1; } @@ -243,6 +265,11 @@ e_entry_unfocus(Evas_Object *entry) edje_object_signal_emit(sd->entry_object, "e,state,unfocused", "e"); e_editable_cursor_hide(sd->editable_object); e_editable_selection_hide(sd->editable_object); + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_focus_out(sd->imf_context); + } sd->focused = 0; } @@ -295,12 +322,34 @@ e_entry_disable(Evas_Object *entry) static void _e_entry_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) { + E_Entry_Smart_Data *sd; + + if ((!obj) || (!(sd = evas_object_smart_data_get(obj)))) + return; + + if (sd->imf_context && + ecore_imf_context_filter_event(sd->imf_context, EVAS_CALLBACK_KEY_DOWN, event_info)) + return; + if (_e_entry_emacs_keybindings) _e_entry_key_down_emacs(obj, event_info); else _e_entry_key_down_windows(obj, event_info); } +/* Called when a key has been released by the user */ +static void +_e_entry_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + E_Entry_Smart_Data *sd; + + if ((!obj) || (!(sd = evas_object_smart_data_get(obj)))) + return; + + if (sd->imf_context) + ecore_imf_context_filter_event(sd->imf_context, EVAS_CALLBACK_KEY_UP, event_info); +} + /* Called when the entry object is pressed by the mouse */ static void _e_entry_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) @@ -314,7 +363,11 @@ _e_entry_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) return; if (!(event = event_info)) return; - + + if (sd->imf_context && + ecore_imf_context_filter_event(sd->imf_context, EVAS_CALLBACK_MOUSE_DOWN, event_info)) + return; + evas_object_geometry_get(sd->editable_object, &ox, &oy, NULL, NULL); pos = e_editable_pos_get_from_coords(sd->editable_object, event->canvas.x - ox, @@ -446,6 +499,13 @@ _e_entry_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) E_MENU_POP_DIRECTION_DOWN, event->timestamp); e_util_evas_fake_mouse_up_later(e, event->button); } + + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_cursor_position_set(sd->imf_context, + e_editable_cursor_pos_get(sd->editable_object)); + } } /* Called when the entry object is released by the mouse */ @@ -457,6 +517,10 @@ _e_entry_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) if ((!obj) || (!(sd = evas_object_smart_data_get(obj)))) return; + if (sd->imf_context && + ecore_imf_context_filter_event(sd->imf_context, EVAS_CALLBACK_MOUSE_UP, event_info)) + return; + if (sd->selection_dragging) { sd->selection_dragging = 0; @@ -477,7 +541,11 @@ _e_entry_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) return; if (!(event = event_info)) return; - + + if (sd->imf_context && + ecore_imf_context_filter_event(sd->imf_context, EVAS_CALLBACK_MOUSE_MOVE, event_info)) + return; + if (sd->selection_dragging) { evas_object_geometry_get(sd->editable_object, &ox, &oy, NULL, NULL); @@ -485,6 +553,12 @@ _e_entry_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) event->cur.canvas.x - ox, event->cur.canvas.y - oy); e_editable_cursor_pos_set(sd->editable_object, pos); + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_cursor_position_set(sd->imf_context, + pos); + } } } @@ -715,7 +789,14 @@ _e_entry_key_down_windows(Evas_Object *entry, Evas_Event_Key_Down *event) changed |= e_editable_delete(editable, start_pos, end_pos); changed |= e_editable_insert(editable, start_pos, event->string); } - + + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_cursor_position_set(sd->imf_context, + e_editable_cursor_pos_get(editable)); + } + if (changed) evas_object_smart_callback_call(entry, "changed", NULL); if (selection_changed) @@ -859,8 +940,14 @@ _e_entry_key_down_emacs(Evas_Object *entry, Evas_Event_Key_Down *event) ((strlen(event->string) != 1) || (event->string[0] >= 0x20 && event->string[0] != 0x7f))) changed = e_editable_insert(editable, cursor_pos, event->string); - - + + if (sd->imf_context) + { + ecore_imf_context_reset(sd->imf_context); + ecore_imf_context_cursor_position_set(sd->imf_context, + e_editable_cursor_pos_get(editable)); + } + if (changed) evas_object_smart_callback_call(entry, "changed", NULL); if (selection_changed) @@ -884,7 +971,23 @@ _e_entry_smart_add(Evas_Object *object) if (!sd) return; evas_object_smart_data_set(object, sd); - + + sd->imf_context = ecore_imf_context_add(ecore_imf_context_default_id_get()); + if (sd->imf_context) + { + ecore_imf_context_client_window_set(sd->imf_context, + ecore_evas_window_get(ecore_evas_ecore_evas_get(evas))); + ecore_imf_context_retrieve_surrounding_callback_set(sd->imf_context, + _e_entry_cb_imf_retrieve_surrounding, + sd); + ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, + _e_entry_cb_imf_event_commit, + object); + ecore_event_handler_add(ECORE_IMF_EVENT_DELETE_SURROUNDIND, + _e_entry_cb_imf_event_delete_surrounding, + sd); + } + sd->enabled = 1; sd->focused = 0; sd->selection_dragging = 0; @@ -908,6 +1011,8 @@ _e_entry_smart_add(Evas_Object *object) evas_object_event_callback_add(object, EVAS_CALLBACK_KEY_DOWN, _e_entry_key_down_cb, NULL); + evas_object_event_callback_add(object, EVAS_CALLBACK_KEY_UP, + _e_entry_key_up_cb, NULL); evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_DOWN, _e_entry_mouse_down_cb, NULL); evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_UP, @@ -928,8 +1033,13 @@ _e_entry_smart_del(Evas_Object *object) if ((!object) || !(sd = evas_object_smart_data_get(object))) return; + if (sd->imf_context) + ecore_imf_context_del(sd->imf_context); + evas_object_event_callback_del(object, EVAS_CALLBACK_KEY_DOWN, _e_entry_key_down_cb); + evas_object_event_callback_del(object, EVAS_CALLBACK_KEY_DOWN, + _e_entry_key_up_cb); evas_object_event_callback_del(object, EVAS_CALLBACK_MOUSE_DOWN, _e_entry_mouse_down_cb); evas_object_event_callback_del(object, EVAS_CALLBACK_MOUSE_UP, @@ -1153,3 +1263,63 @@ _e_entry_cb_delete(void *data, E_Menu *m, E_Menu_Item *mi) free(range); } } + +static int + _e_entry_cb_imf_retrieve_surrounding(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos) +{ + E_Entry_Smart_Data *sd; + + sd = data; + + if (text) + { + const char *str; + + str = e_editable_text_get(sd->editable_object); + *text = str ? strdup(str) : strdup(""); + } + + if (cursor_pos) + *cursor_pos = e_editable_cursor_pos_get(sd->editable_object); + + return 1; +} + +static int +_e_entry_cb_imf_event_commit(void *data, int type, void *event) +{ + Evas_Object *entry; + E_Entry_Smart_Data *sd; + Ecore_IMF_Event_Commit *ev = event; + + if ((!(entry = data)) || (!(sd = evas_object_smart_data_get(entry)))) + return 1; + + if (sd->imf_context != ev->ctx) + return 1; + + e_entry_text_set(entry, ev->str); + return 0; +} + +static int +_e_entry_cb_imf_event_delete_surrounding(void *data, int type, void *event) +{ + E_Entry_Smart_Data *sd; + Ecore_IMF_Event_Delete_Surrounding *ev = event; + Evas_Object *editable; + int cursor_pos; + + sd = data; + + if (sd->imf_context != ev->ctx) + return 1; + + editable = sd->editable_object; + cursor_pos = e_editable_cursor_pos_get(editable); + e_editable_delete(editable, + cursor_pos + ev->offset, + cursor_pos + ev->offset + ev->n_chars); + + return 0; +} diff --git a/src/bin/e_main.c b/src/bin/e_main.c index fc1ea8b4c..ee4e39f34 100644 --- a/src/bin/e_main.c +++ b/src/bin/e_main.c @@ -3,6 +3,8 @@ */ #include "e.h" +#include + EAPI int e_precache_end = 0; /* local subsystem functions */ @@ -311,6 +313,8 @@ main(int argc, char **argv) "Perhaps you are out of memory?")); exit(-1); } + ecore_im_init(); + _e_main_shutdown_push(ecore_im_shutdown); // FIXME: SEGV's on shutdown if fm2 windows up - disable for now. // _e_main_shutdown_push(ecore_shutdown); ecore_job_init();