From d7432a52d6a38bc5d8fbb47b58bfa3fd41cd0d3f Mon Sep 17 00:00:00 2001 From: Boris Faure Date: Mon, 5 Feb 2018 00:07:47 +0100 Subject: [PATCH] move input handling to win.c --- src/bin/keyin.c | 84 +--------- src/bin/keyin.h | 13 +- src/bin/termio.c | 240 ++++----------------------- src/bin/termio.h | 6 +- src/bin/termpty.c | 24 +++ src/bin/win.c | 409 +++++++++++++++++++++++++++++++++++++++++++--- src/bin/win.h | 3 + 7 files changed, 464 insertions(+), 315 deletions(-) diff --git a/src/bin/keyin.c b/src/bin/keyin.c index 78601afc..c5bc7f24 100644 --- a/src/bin/keyin.c +++ b/src/bin/keyin.c @@ -102,9 +102,9 @@ keyin_compose_seq_reset(Keys_Handler *khdl) #include "tty_keys.h" -static void -_handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev, - int alt, int shift, int ctrl) +void +keyin_handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev, + const int alt, const int shift, const int ctrl) { if (!ev->key) return; @@ -228,92 +228,24 @@ key_binding_lookup(const char *keyname, } Eina_Bool -keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, - Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, Eina_Bool win, - Eina_Bool meta, Eina_Bool hyper) +keyin_handle_key_binding(Evas_Object *termio, const Evas_Event_Key_Down *ev, + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, + Eina_Bool win, Eina_Bool meta, Eina_Bool hyper) { Key_Binding *kb; kb = key_binding_lookup(ev->keyname, ctrl, alt, shift, win, meta, hyper); if (kb) { - if (kb->cb(ty->obj)) + if (kb->cb(termio)) { - keyin_compose_seq_reset(khdl); return EINA_TRUE; } } - - /* composing */ - if (khdl->imf) - { - // EXCEPTION. Don't filter modifiers alt+shift -> breaks emacs - // and jed (alt+shift+5 for search/replace for example) - // Don't filter modifiers alt, is used by shells - if ((!alt) && (!ctrl)) - { - Ecore_IMF_Event_Key_Down imf_ev; - - ecore_imf_evas_event_key_down_wrap((Evas_Event_Key_Down*)ev, &imf_ev); - if (!khdl->composing) - { - if (ecore_imf_context_filter_event - (khdl->imf, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_ev)) - goto end; - } - } - } - - // if term app asked for kbd lock - dont handle here - if (ty->termstate.kbd_lock) return EINA_TRUE; - // if app asked us to not do autorepeat - ignore press if is it is the same - // timestamp as last one - if ((ty->termstate.no_autorepeat) && - (ev->timestamp == khdl->last_keyup)) return EINA_TRUE; - if (!khdl->composing) - { - Ecore_Compose_State state; - char *compres = NULL; - - keyin_compose_seq_reset(khdl); - khdl->seq = eina_list_append(khdl->seq, eina_stringshare_add(ev->key)); - state = ecore_compose_get(khdl->seq, &compres); - if (state == ECORE_COMPOSE_MIDDLE) khdl->composing = EINA_TRUE; - else khdl->composing = EINA_FALSE; - if (!khdl->composing) keyin_compose_seq_reset(khdl); - else goto end; - } - else - { - Ecore_Compose_State state; - char *compres = NULL; - - if (key_is_modifier(ev->key)) goto end; - khdl->seq = eina_list_append(khdl->seq, eina_stringshare_add(ev->key)); - state = ecore_compose_get(khdl->seq, &compres); - if (state == ECORE_COMPOSE_NONE) keyin_compose_seq_reset(khdl); - else if (state == ECORE_COMPOSE_DONE) - { - keyin_compose_seq_reset(khdl); - if (compres) - { - termpty_write(ty, compres, strlen(compres)); - free(compres); - compres = NULL; - } - goto end; - } - else goto end; - } - - - _handle_key_to_pty(ty, ev, alt, shift, ctrl); - - -end: return EINA_FALSE; } + Eina_Bool key_is_modifier(const char *key) { diff --git a/src/bin/keyin.h b/src/bin/keyin.h index d9127a17..ccfa644d 100644 --- a/src/bin/keyin.h +++ b/src/bin/keyin.h @@ -11,12 +11,19 @@ struct _Keys_Handler unsigned char composing : 1; }; +void +keyin_handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev, + const int alt, const int shift, const int ctrl); +Eina_Bool +termpty_can_handle_key(const Termpty *ty, + const Keys_Handler *khdl, + const Evas_Event_Key_Down *ev); void keyin_compose_seq_reset(Keys_Handler *khdl); Eina_Bool key_is_modifier(const char *key); Eina_Bool -keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, - Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, Eina_Bool win, - Eina_Bool meta, Eina_Bool hyper); +keyin_handle_key_binding(Evas_Object *termio, const Evas_Event_Key_Down *ev, + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, + Eina_Bool win, Eina_Bool meta, Eina_Bool hyper); void keyin_handle_up(Keys_Handler *khdl, Evas_Event_Key_Up *ev); diff --git a/src/bin/termio.c b/src/bin/termio.c index 01e5227c..f7f178e1 100644 --- a/src/bin/termio.c +++ b/src/bin/termio.c @@ -86,12 +86,10 @@ struct _Termio Evas_Object *win, *theme, *glayer; Config *config; const char *sel_str; - const char *preedit_str; Eina_List *cur_chids; Ecore_Job *sel_reset_job; double set_sel_at; Elm_Sel_Type sel_type; - Keys_Handler khdl; unsigned char jump_on_change : 1; unsigned char jump_on_keypress : 1; unsigned char have_sel : 1; @@ -1983,72 +1981,6 @@ _block_obj_del(Termblock *blk) blk->obj = NULL; } -/* }}} */ -/* {{{ Keys */ - -static void -_smart_cb_key_up(void *data, - Evas *_e EINA_UNUSED, - Evas_Object *_obj EINA_UNUSED, - void *event) -{ - Evas_Event_Key_Up *ev = event; - Termio *sd = evas_object_smart_data_get(data); - - EINA_SAFETY_ON_NULL_RETURN(sd); - - keyin_handle_up(&sd->khdl, ev); -} - -static void -_smart_cb_key_down(void *data, - Evas *_e EINA_UNUSED, - Evas_Object *_obj EINA_UNUSED, - void *event) -{ - const Evas_Event_Key_Down *ev = event; - Termio *sd = evas_object_smart_data_get(data); - int ctrl, alt, shift, win, meta, hyper; - - EINA_SAFETY_ON_NULL_RETURN(sd); - EINA_SAFETY_ON_NULL_RETURN(ev->key); - - if (miniview_handle_key(term_miniview_get(sd->term), ev)) - return; - - if (term_has_popmedia(sd->term) && !strcmp(ev->key, "Escape")) - { - term_popmedia_close(sd->term); - return; - } - - ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); - alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); - shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); - win = evas_key_modifier_is_set(ev->modifiers, "Super"); - meta = evas_key_modifier_is_set(ev->modifiers, "Meta") || - evas_key_modifier_is_set(ev->modifiers, "AltGr") || - evas_key_modifier_is_set(ev->modifiers, "ISO_Level3_Shift"); - hyper = evas_key_modifier_is_set(ev->modifiers, "Hyper"); - ERR("ctrl:%d alt:%d shift:%d win:%d meta:%d hyper:%d", - ctrl, alt, shift, win, meta, hyper); - - if (keyin_handle(&sd->khdl, sd->pty, ev, ctrl, alt, shift, win, meta, hyper)) - goto end; - - if (sd->jump_on_keypress) - { - if (!key_is_modifier(ev->key)) - { - sd->scroll = 0; - _smart_update_queue(data, sd); - } - } -end: - if (sd->config->flicker_on_key) - edje_object_signal_emit(sd->cursor.obj, "key,down", "terminology"); -} - /* }}} */ /* {{{ Selection */ @@ -3496,16 +3428,19 @@ termio_event_feed_mouse_in(Evas_Object *obj) evas_event_feed_mouse_in(e, 0, NULL); } -static void -_imf_cursor_set(Termio *sd) +void +termio_imf_cursor_set(Evas_Object *obj, Ecore_IMF_Context *imf) { - /* TODO */ + Termio *sd = evas_object_smart_data_get(obj); Evas_Coord cx, cy, cw, ch; + + if (!imf) + return; + + EINA_SAFETY_ON_NULL_RETURN(sd); evas_object_geometry_get(sd->cursor.obj, &cx, &cy, &cw, &ch); - if (sd->khdl.imf) - ecore_imf_context_cursor_location_set(sd->khdl.imf, cx, cy, cw, ch); - if (sd->khdl.imf) ecore_imf_context_cursor_position_set - (sd->khdl.imf, (sd->cursor.y * sd->grid.w) + sd->cursor.x); + ecore_imf_context_cursor_location_set(imf, cx, cy, cw, ch); + ecore_imf_context_cursor_position_set(imf, (sd->cursor.y * sd->grid.w) + sd->cursor.x); /* ecore_imf_context_cursor_position_set(sd->imf, 0); // how to get it? */ @@ -3522,14 +3457,6 @@ termio_focus_in(Evas_Object *termio) else edje_object_signal_emit(sd->cursor.obj, "focus,in", "terminology"); if (!sd->win) return; - elm_win_keyboard_mode_set(sd->win, ELM_WIN_KEYBOARD_TERMINAL); - if (sd->khdl.imf) - { - ecore_imf_context_input_panel_show(sd->khdl.imf); - ecore_imf_context_reset(sd->khdl.imf); - ecore_imf_context_focus_in(sd->khdl.imf); - _imf_cursor_set(sd); - } } void @@ -3542,14 +3469,6 @@ termio_focus_out(Evas_Object *termio) edje_object_signal_emit(sd->cursor.obj, "focus,out", "terminology"); if (!sd->win) return; sd->pty->selection.last_click = 0; - elm_win_keyboard_mode_set(sd->win, ELM_WIN_KEYBOARD_OFF); - if (sd->khdl.imf) - { - ecore_imf_context_reset(sd->khdl.imf); - _imf_cursor_set(sd); - ecore_imf_context_focus_out(sd->khdl.imf); - ecore_imf_context_input_panel_hide(sd->khdl.imf); - } if (!sd->ctxpopup) _remove_links(sd, termio); term_unfocus(sd->term); @@ -4807,6 +4726,7 @@ _smart_apply(Evas_Object *obj) Eina_List *l, *ln; Termblock *blk; int x, y, ch1 = 0, ch2 = 0, inv = 0, preedit_x = 0, preedit_y = 0; + char *preedit_str; ssize_t w; EINA_SAFETY_ON_NULL_RETURN(sd); @@ -4993,7 +4913,9 @@ _smart_apply(Evas_Object *obj) evas_object_textgrid_update_add(sd->grid.obj, ch1, y, ch2 - ch1 + 1, 1); } - if (sd->preedit_str && sd->preedit_str[0]) + + preedit_str = term_preedit_str_get(sd->term); + if (preedit_str && preedit_str[0]) { Eina_Unicode *uni, g; int len = 0, i, jump, xx, backx; @@ -5001,7 +4923,7 @@ _smart_apply(Evas_Object *obj) Evas_Textgrid_Cell *tc; x = sd->cursor.x, y = sd->cursor.y; - uni = eina_unicode_utf8_to_unicode(sd->preedit_str, &len); + uni = eina_unicode_utf8_to_unicode(preedit_str, &len); if (uni) { for (i = 0; i < len; i++) @@ -5251,52 +5173,8 @@ _cursor_cb_move(void *data, { Termio *sd = evas_object_smart_data_get(data); EINA_SAFETY_ON_NULL_RETURN(sd); - _imf_cursor_set(sd); -} - -static void -_imf_event_commit_cb(void *data, - Ecore_IMF_Context *_ctx EINA_UNUSED, - void *event) -{ - Termio *sd = data; - char *str = event; - DBG("IMF committed '%s'", str); - if (!str) return; - termpty_write(sd->pty, str, strlen(str)); - if (sd->preedit_str) - { - eina_stringshare_del(sd->preedit_str); - sd->preedit_str = NULL; - } - _smart_update_queue(sd->self, sd); -} - -static void -_imf_event_delete_surrounding_cb(void *data, - Ecore_IMF_Context *_ctx EINA_UNUSED, - void *event) -{ - Termio *sd = data; - Ecore_IMF_Event_Delete_Surrounding *ev = event; - DBG("IMF del surrounding %p %i %i", sd, ev->offset, ev->n_chars); -} - -static void -_imf_event_preedit_changed_cb(void *data, - Ecore_IMF_Context *ctx, - void *_event EINA_UNUSED) -{ - Termio *sd = data; - char *preedit_string; - int cursor_pos; - ecore_imf_context_preedit_string_get(ctx, &preedit_string, &cursor_pos); - if (!preedit_string) return; - DBG("IMF preedit str '%s'", preedit_string); - if (sd->preedit_str) eina_stringshare_del(sd->preedit_str); - sd->preedit_str = eina_stringshare_add(preedit_string); - _smart_update_queue(sd->self, sd); - free(preedit_string); + /* TODO: boris */ + //_imf_cursor_set(sd); } @@ -5370,58 +5248,6 @@ _smart_add(Evas_Object *obj) sd->link.suspend = 1; - if (ecore_imf_init()) - { - const char *imf_id = ecore_imf_context_default_id_get(); - Evas *e; - - if (!imf_id) sd->khdl.imf = NULL; - else - { - const Ecore_IMF_Context_Info *imf_info; - - imf_info = ecore_imf_context_info_by_id_get(imf_id); - if ((!imf_info->canvas_type) || - (strcmp(imf_info->canvas_type, "evas") == 0)) - sd->khdl.imf = ecore_imf_context_add(imf_id); - else - { - imf_id = ecore_imf_context_default_id_by_canvas_type_get("evas"); - if (imf_id) sd->khdl.imf = ecore_imf_context_add(imf_id); - } - } - - if (!sd->khdl.imf) goto imf_done; - - e = evas_object_evas_get(o); - ecore_imf_context_client_window_set - (sd->khdl.imf, (void *)ecore_evas_window_get(ecore_evas_ecore_evas_get(e))); - ecore_imf_context_client_canvas_set(sd->khdl.imf, e); - - ecore_imf_context_event_callback_add - (sd->khdl.imf, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb, sd); - ecore_imf_context_event_callback_add - (sd->khdl.imf, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _imf_event_delete_surrounding_cb, sd); - ecore_imf_context_event_callback_add - (sd->khdl.imf, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _imf_event_preedit_changed_cb, sd); - /* make IMF usable by a terminal - no preedit, prediction... */ - ecore_imf_context_prediction_allow_set - (sd->khdl.imf, EINA_FALSE); - ecore_imf_context_autocapital_type_set - (sd->khdl.imf, ECORE_IMF_AUTOCAPITAL_TYPE_NONE); - ecore_imf_context_input_panel_layout_set - (sd->khdl.imf, ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL); - ecore_imf_context_input_mode_set - (sd->khdl.imf, ECORE_IMF_INPUT_MODE_FULL); - ecore_imf_context_input_panel_language_set - (sd->khdl.imf, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET); - ecore_imf_context_input_panel_return_key_type_set - (sd->khdl.imf, ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT); -imf_done: - if (sd->khdl.imf) DBG("Ecore IMF Setup"); - else WRN(_("Ecore IMF failed")); - - } terms = eina_list_append(terms, obj); } @@ -5434,12 +5260,6 @@ _smart_del(Evas_Object *obj) EINA_SAFETY_ON_NULL_RETURN(sd); terms = eina_list_remove(terms, obj); - if (sd->khdl.imf) - { - ecore_imf_context_event_callback_del - (sd->khdl.imf, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb); - ecore_imf_context_del(sd->khdl.imf); - } if (sd->cursor.obj) evas_object_del(sd->cursor.obj); if (sd->event) { @@ -5495,13 +5315,10 @@ _smart_del(Evas_Object *obj) } sd->sendfile.active = EINA_FALSE; } - keyin_compose_seq_reset(&sd->khdl); if (sd->sel_str) eina_stringshare_del(sd->sel_str); - if (sd->preedit_str) eina_stringshare_del(sd->preedit_str); if (sd->sel_reset_job) ecore_job_del(sd->sel_reset_job); EINA_LIST_FREE(sd->cur_chids, chid) eina_stringshare_del(chid); sd->sel_str = NULL; - sd->preedit_str = NULL; sd->sel_reset_job = NULL; sd->link.down.dndobj = NULL; sd->cursor.obj = NULL; @@ -5513,10 +5330,8 @@ _smart_del(Evas_Object *obj) sd->delayed_size_timer = NULL; sd->font.name = NULL; sd->pty = NULL; - sd->khdl.imf = NULL; sd->win = NULL; sd->glayer = NULL; - ecore_imf_shutdown(); _parent_sc.del(obj); } @@ -6274,13 +6089,20 @@ termio_add(Evas_Object *win, Config *config, } void -termio_key_down(Evas_Object *termio, void *event) +termio_key_down(Evas_Object *termio, + const Evas_Event_Key_Down *ev) { - _smart_cb_key_down(termio, NULL, NULL, event); -} + Termio *sd = evas_object_smart_data_get(termio); -void -termio_key_up(Evas_Object *termio, void *event) -{ - _smart_cb_key_up(termio, NULL, NULL, event); + EINA_SAFETY_ON_NULL_RETURN(sd); + if (sd->jump_on_keypress) + { + if (!key_is_modifier(ev->key)) + { + sd->scroll = 0; + _smart_update_queue(termio, sd); + } + } + if (sd->config->flicker_on_key) + edje_object_signal_emit(sd->cursor.obj, "key,down", "terminology"); } diff --git a/src/bin/termio.h b/src/bin/termio.h index 7ee9c85b..5e4a4031 100644 --- a/src/bin/termio.h +++ b/src/bin/termio.h @@ -49,12 +49,14 @@ Eina_Bool termio_file_send_ok(const Evas_Object *obj, const char *file); void termio_file_send_cancel(const Evas_Object *obj); double termio_file_send_progress_get(const Evas_Object *obj); +void +termio_imf_cursor_set(Evas_Object *obj, Ecore_IMF_Context *imf); + Termpty *termio_pty_get(const Evas_Object *obj); Evas_Object * termio_miniview_get(const Evas_Object *obj); Term* termio_term_get(const Evas_Object *obj); -void termio_key_down(Evas_Object *termio, void *event); -void termio_key_up(Evas_Object *termio, void *event); +void termio_key_down(Evas_Object *termio, const Evas_Event_Key_Down *ev); void termio_focus_in(Evas_Object *termio); void termio_focus_out(Evas_Object *termio); diff --git a/src/bin/termpty.c b/src/bin/termpty.c index 4251e8aa..e8576769 100644 --- a/src/bin/termpty.c +++ b/src/bin/termpty.c @@ -1,10 +1,14 @@ #include "private.h" #include +#include +#include +#include #include "termpty.h" #include "termptyesc.h" #include "termptyops.h" #include "termptysave.h" #include "termio.h" +#include "keyin.h" #include #include #include @@ -54,6 +58,26 @@ termpty_shutdown(void) _termpty_log_dom = -1; } + +Eina_Bool +termpty_can_handle_key(const Termpty *ty, + const Keys_Handler *khdl, + const Evas_Event_Key_Down *ev) +{ + // if term app asked for kbd lock - dont handle here + if (ty->termstate.kbd_lock) + return EINA_FALSE; + // if app asked us to not do autorepeat - ignore press if is it is the same + // timestamp as last one + if ((ty->termstate.no_autorepeat) && + (ev->timestamp == khdl->last_keyup)) + return EINA_FALSE; + return EINA_TRUE; +} + + + + void termpty_handle_buf(Termpty *ty, const Eina_Unicode *codepoints, int len) { diff --git a/src/bin/win.c b/src/bin/win.c index 399d9d5c..41e2d219 100644 --- a/src/bin/win.c +++ b/src/bin/win.c @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "win.h" #include "termcmd.h" #include "config.h" @@ -12,6 +15,7 @@ #include "private.h" #include "sel.h" #include "controls.h" +#include "keyin.h" #include "term_container.h" @@ -154,8 +158,10 @@ struct _Split struct _Win { - Term_Container tc; + Term_Container tc; /* has to be first field */ + Keys_Handler khdl; + const char *preedit_str; Term_Container *child; Evas_Object *win; Evas_Object *conform; @@ -195,6 +201,7 @@ static Tab_Item* tab_item_new(Tabs *tabs, Term_Container *child); static void _tabs_refresh(Tabs *tabs); static void _term_tabregion_free(Term *term); static void _set_trans(Config *config, Evas_Object *bg, Evas_Object *base); +static void _imf_event_commit_cb(void *data, Ecore_IMF_Context *_ctx EINA_UNUSED, void *event); /* {{{ Solo */ @@ -749,8 +756,20 @@ win_free(Win *wn) evas_object_event_callback_del_full(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn); evas_object_del(wn->win); } - if (wn->size_job) ecore_job_del(wn->size_job); - if (wn->config) config_del(wn->config); + if (wn->size_job) + ecore_job_del(wn->size_job); + if (wn->config) + config_del(wn->config); + if (wn->preedit_str) + eina_stringshare_del(wn->preedit_str); + keyin_compose_seq_reset(&wn->khdl); + if (wn->khdl.imf) + { + ecore_imf_context_event_callback_del + (wn->khdl.imf, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb); + ecore_imf_context_del(wn->khdl.imf); + } + ecore_imf_shutdown(); free(wn); } @@ -958,9 +977,25 @@ _win_focus(Term_Container *tc, Term_Container *relative) DBG("tc:%p tc->is_focused:%d from_child:%d", tc, tc->is_focused, wn->child == relative); if (relative != wn->child) - wn->child->focus(wn->child, tc); + { + wn->child->focus(wn->child, tc); + elm_win_keyboard_mode_set(wn->win, ELM_WIN_KEYBOARD_TERMINAL); + if (wn->khdl.imf) + { + Term *focused; - if (!tc->is_focused) elm_win_urgent_set(wn->win, EINA_FALSE); + ecore_imf_context_input_panel_show(wn->khdl.imf); + ecore_imf_context_reset(wn->khdl.imf); + ecore_imf_context_focus_in(wn->khdl.imf); + + focused = tc->focused_term_get(tc); + if (focused) + termio_imf_cursor_set(focused->termio, wn->khdl.imf); + } + } + + if (!tc->is_focused) + elm_win_urgent_set(wn->win, EINA_FALSE); tc->is_focused = EINA_TRUE; } @@ -974,8 +1009,20 @@ _win_unfocus(Term_Container *tc, Term_Container *relative) DBG("tc:%p tc->is_focused:%d from_child:%d", tc, tc->is_focused, wn->child == relative); + elm_win_keyboard_mode_set(wn->win, ELM_WIN_KEYBOARD_OFF); if (relative != wn->child && wn->child) { + if (wn->khdl.imf) + { + Term *focused; + + ecore_imf_context_reset(wn->khdl.imf); + focused = tc->focused_term_get(tc); + if (focused) + termio_imf_cursor_set(focused->termio, wn->khdl.imf); + ecore_imf_context_focus_out(wn->khdl.imf); + ecore_imf_context_input_panel_hide(wn->khdl.imf); + } tc->is_focused = EINA_FALSE; wn->child->unfocus(wn->child, tc); @@ -1108,26 +1155,55 @@ static void _cb_win_key_up(void *data, Evas *_e EINA_UNUSED, Evas_Object *_obj EINA_UNUSED, - void *event_info) + void *event) { Win *wn = data; - Eina_List *l; - Term *term; - const Evas_Event_Key_Up *ev = event_info; - - if (wn->on_options) - return; + Evas_Event_Key_Up *ev = event; DBG("GROUP key up (%p) (ctrl:%d)", wn, evas_key_modifier_is_set(ev->modifiers, "Control")); + keyin_handle_up(&wn->khdl, ev); +} + +char * +term_preedit_str_get(Term *term) +{ + Win *wn = term->wn; + Term_Container *tc = (Term_Container*) wn; + + if (wn->on_options) + return NULL; + tc = (Term_Container*) wn; + term = tc->focused_term_get(tc); + if (term) + { + return wn->preedit_str; + } + return NULL; +} + +static void +_imf_event_commit_cb(void *data, + Ecore_IMF_Context *_ctx EINA_UNUSED, + void *event) +{ + Eina_List *l; + Term *term; + Win *wn = data; + Termpty *ty; + char *str = event; + int len; + DBG("IMF committed '%s'", str); + if (!str) + return; + len = strlen(str); if (wn->group_input) { - wn->group_once_handled = EINA_FALSE; EINA_LIST_FOREACH(wn->terms, l, term) { - termio_key_up(term->termio, event_info); - if (!wn->group_input) - return; + ty = termio_pty_get(term->termio); + if (ty) + termpty_write(ty, str, len); } } else @@ -1136,10 +1212,51 @@ _cb_win_key_up(void *data, term = tc->focused_term_get(tc); if (term) - termio_key_up(term->termio, event_info); + { + ty = termio_pty_get(term->termio); + if (ty) + termpty_write(ty, str, len); + } + } + if (wn->preedit_str) + { + eina_stringshare_del(wn->preedit_str); + wn->preedit_str = NULL; } } + + +static void +_imf_event_delete_surrounding_cb(void *data, + Ecore_IMF_Context *_ctx EINA_UNUSED, + void *event) +{ + Win *wn = data; + Ecore_IMF_Event_Delete_Surrounding *ev = event; + DBG("IMF del surrounding %p %i %i", wn, ev->offset, ev->n_chars); +} + +static void +_imf_event_preedit_changed_cb(void *data, + Ecore_IMF_Context *ctx, + void *_event EINA_UNUSED) +{ + Win *wn = data; + char *preedit_string; + int cursor_pos; + + ecore_imf_context_preedit_string_get(ctx, &preedit_string, &cursor_pos); + if (!preedit_string) + return; + DBG("IMF preedit str '%s'", preedit_string); + if (wn->preedit_str) + eina_stringshare_del(wn->preedit_str); + wn->preedit_str = eina_stringshare_add(preedit_string); + free(preedit_string); +} + + static void _cb_win_key_down(void *data, Evas *_e EINA_UNUSED, @@ -1147,9 +1264,12 @@ _cb_win_key_down(void *data, void *event_info) { Win *wn = data; - Eina_List *l; - Term *term; - const Evas_Event_Key_Down *ev = event_info; + Eina_List *l = NULL; + Term *term = NULL; + Termpty *ty = NULL; + Evas_Event_Key_Down *ev = event_info; + Eina_Bool done = EINA_FALSE; + int ctrl, alt, shift, win, meta, hyper; DBG("GROUP key down (%p) (ctrl:%d)", wn, evas_key_modifier_is_set(ev->modifiers, "Control")); @@ -1157,7 +1277,6 @@ _cb_win_key_down(void *data, if (wn->on_options) return; - int ctrl, alt, shift, win, meta, hyper; ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); @@ -1169,13 +1288,12 @@ _cb_win_key_down(void *data, DBG("ctrl:%d alt:%d shift:%d win:%d meta:%d hyper:%d", ctrl, alt, shift, win, meta, hyper); - + /* 1st/ Miniview */ if (wn->group_input) { - wn->group_once_handled = EINA_FALSE; EINA_LIST_FOREACH(wn->terms, l, term) { - termio_key_down(term->termio, event_info); + done = miniview_handle_key(term_miniview_get(term), ev); if (!wn->group_input) return; } @@ -1185,8 +1303,191 @@ _cb_win_key_down(void *data, Term_Container *tc = (Term_Container*) wn; term = tc->focused_term_get(tc); + if (!term) + return; + done = miniview_handle_key(term_miniview_get(term), ev); + } + if (done) + { + keyin_compose_seq_reset(&wn->khdl); + goto end; + } + + + /* 2nd/ PopMedia */ + done = EINA_FALSE; + if (wn->group_input) + { + EINA_LIST_FOREACH(wn->terms, l, term) + { + if (term_has_popmedia(term) && !strcmp(ev->key, "Escape")) + { + term_popmedia_close(term); + done = EINA_TRUE; + } + } + } + else + { + Term_Container *tc = (Term_Container*) wn; + + term = tc->focused_term_get(tc); + if (!term) + return; + if (term_has_popmedia(term) && !strcmp(ev->key, "Escape")) + { + term_popmedia_close(term); + done = EINA_TRUE; + } + } + if (done) + { + keyin_compose_seq_reset(&wn->khdl); + goto end; + } + + /* 3rd/ Handle key bindings */ + done = EINA_FALSE; + if (wn->group_input) + { + wn->group_once_handled = EINA_FALSE; + EINA_LIST_FOREACH(wn->terms, l, term) + { + done = keyin_handle_key_binding(term->termio, ev, ctrl, alt, + shift, win, meta, hyper); + if (!wn->group_input) + return; + } + } + else + { + Term_Container *tc = (Term_Container*) wn; + + term = tc->focused_term_get(tc); + if (!term) + return; + done = keyin_handle_key_binding(term->termio, ev, ctrl, alt, + shift, win, meta, hyper); + } + if (done) + { + keyin_compose_seq_reset(&wn->khdl); + goto end; + } + done = EINA_FALSE; + + /* 4th/ Composing */ + /* composing */ + if (&wn->khdl.imf) + { + // EXCEPTION. Don't filter modifiers alt+shift -> breaks emacs + // and jed (alt+shift+5 for search/replace for example) + // Don't filter modifiers alt, is used by shells + if ((!alt) && (!ctrl)) + { + Ecore_IMF_Event_Key_Down imf_ev; + + ecore_imf_evas_event_key_down_wrap(ev, &imf_ev); + if (!wn->khdl.composing) + { + if (ecore_imf_context_filter_event(wn->khdl.imf, + ECORE_IMF_EVENT_KEY_DOWN, + (Ecore_IMF_Event *)&imf_ev)) + goto end; + } + } + } + if (!wn->khdl.composing) + { + Ecore_Compose_State state; + char *compres = NULL; + + keyin_compose_seq_reset(&wn->khdl); + wn->khdl.seq = eina_list_append(wn->khdl.seq, + eina_stringshare_add(ev->key)); + state = ecore_compose_get(wn->khdl.seq, &compres); + if (state == ECORE_COMPOSE_MIDDLE) + wn->khdl.composing = EINA_TRUE; + else + wn->khdl.composing = EINA_FALSE; + if (!wn->khdl.composing) + keyin_compose_seq_reset(&wn->khdl); + else + goto end; + } + else + { + Ecore_Compose_State state; + char *compres = NULL; + + if (key_is_modifier(ev->key)) + goto end; + wn->khdl.seq = eina_list_append(wn->khdl.seq, + eina_stringshare_add(ev->key)); + state = ecore_compose_get(wn->khdl.seq, &compres); + if (state == ECORE_COMPOSE_NONE) + keyin_compose_seq_reset(&wn->khdl); + else if (state == ECORE_COMPOSE_DONE) + { + keyin_compose_seq_reset(&wn->khdl); + if (compres) + { + int len = strlen(compres); + if (wn->group_input) + { + EINA_LIST_FOREACH(wn->terms, l, term) + { + ty = termio_pty_get(term->termio); + if (ty && termpty_can_handle_key(ty, &wn->khdl, ev)) + termpty_write(ty, compres, len); + } + } + else + { + ty = termio_pty_get(term->termio); + if (ty && termpty_can_handle_key(ty, &wn->khdl, ev)) + termpty_write(ty, compres, len); + } + free(compres); + compres = NULL; + } + goto end; + } + else + goto end; + } + + /* 5th/ send key to pty */ + if (wn->group_input) + { + EINA_LIST_FOREACH(wn->terms, l, term) + { + ty = termio_pty_get(term->termio); + if (ty && termpty_can_handle_key(ty, &wn->khdl, ev)) + keyin_handle_key_to_pty(ty, ev, alt, shift, ctrl); + } + } + else + { + ty = termio_pty_get(term->termio); + if (ty && termpty_can_handle_key(ty, &wn->khdl, ev)) + keyin_handle_key_to_pty(ty, ev, alt, shift, ctrl); + } + + /* 6th: specifics: jump on keypress / flicker on key */ +end: + if (wn->group_input) + { + EINA_LIST_FOREACH(wn->terms, l, term) + { + if (term) + termio_key_down(term->termio, ev); + } + } + else + { if (term) - termio_key_down(term->termio, event_info); + termio_key_down(term->termio, ev); } } @@ -1369,6 +1670,64 @@ win_new(const char *name, const char *role, const char *title, _cb_win_mouse_move, wn); + if (ecore_imf_init()) + { + const char *imf_id = ecore_imf_context_default_id_get(); + Evas *e; + + if (!imf_id) + wn->khdl.imf = NULL; + else + { + const Ecore_IMF_Context_Info *imf_info; + + imf_info = ecore_imf_context_info_by_id_get(imf_id); + if ((!imf_info->canvas_type) || + (strcmp(imf_info->canvas_type, "evas") == 0)) + wn->khdl.imf = ecore_imf_context_add(imf_id); + else + { + imf_id = ecore_imf_context_default_id_by_canvas_type_get("evas"); + if (imf_id) + wn->khdl.imf = ecore_imf_context_add(imf_id); + } + } + + if (!wn->khdl.imf) + goto imf_done; + + e = evas_object_evas_get(o); + ecore_imf_context_client_window_set + (wn->khdl.imf, (void *)ecore_evas_window_get(ecore_evas_ecore_evas_get(e))); + ecore_imf_context_client_canvas_set(wn->khdl.imf, e); + + ecore_imf_context_event_callback_add + (wn->khdl.imf, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb, wn); + ecore_imf_context_event_callback_add + (wn->khdl.imf, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _imf_event_delete_surrounding_cb, wn); + ecore_imf_context_event_callback_add + (wn->khdl.imf, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _imf_event_preedit_changed_cb, wn); + /* make IMF usable by a terminal - no preedit, prediction... */ + ecore_imf_context_prediction_allow_set + (wn->khdl.imf, EINA_FALSE); + ecore_imf_context_autocapital_type_set + (wn->khdl.imf, ECORE_IMF_AUTOCAPITAL_TYPE_NONE); + ecore_imf_context_input_panel_layout_set + (wn->khdl.imf, ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL); + ecore_imf_context_input_mode_set + (wn->khdl.imf, ECORE_IMF_INPUT_MODE_FULL); + ecore_imf_context_input_panel_language_set + (wn->khdl.imf, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET); + ecore_imf_context_input_panel_return_key_type_set + (wn->khdl.imf, ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT); +imf_done: + if (wn->khdl.imf) + DBG("Ecore IMF Setup"); + else + WRN(_("Ecore IMF failed")); + + } + wins = eina_list_append(wins, wn); return wn; } diff --git a/src/bin/win.h b/src/bin/win.h index 113ed71c..4c7aa7d4 100644 --- a/src/bin/win.h +++ b/src/bin/win.h @@ -66,6 +66,9 @@ void term_down(Term *term); void term_left(Term *term); void term_right(Term *term); +char * +term_preedit_str_get(Term *term); + void win_font_size_set(Win *wn, int new_size); void win_font_update(Term *term);