billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=d7432a52d6a38bc5d8fbb47b58bfa3fd41cd0d3f

commit d7432a52d6a38bc5d8fbb47b58bfa3fd41cd0d3f
Author: Boris Faure <[email protected]>
Date:   Mon Feb 5 00:07:47 2018 +0100

    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     | 405 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/bin/win.h     |   3 +
 7 files changed, 462 insertions(+), 313 deletions(-)

diff --git a/src/bin/keyin.c b/src/bin/keyin.c
index 78601af..c5bc7f2 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 d9127a1..ccfa644 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 01e5227..f7f178e 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;
@@ -1984,72 +1982,6 @@ _block_obj_del(Termblock *blk)
 }
 
 /* }}} */
-/* {{{ 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 */
 
 static Eina_Bool
@@ -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 7ee9c85..5e4a403 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 4251e8a..e857676 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -1,10 +1,14 @@
 #include "private.h"
 #include <Elementary.h>
+#include <Ecore_Input.h>
+#include <Ecore_IMF.h>
+#include <Ecore_IMF_Evas.h>
 #include "termpty.h"
 #include "termptyesc.h"
 #include "termptyops.h"
 #include "termptysave.h"
 #include "termio.h"
+#include "keyin.h"
 #include <sys/types.h>
 #include <signal.h>
 #include <sys/wait.h>
@@ -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 399d9d5..41e2d21 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -1,5 +1,8 @@
 #include <assert.h>
 #include <Elementary.h>
+#include <Ecore_Input.h>
+#include <Ecore_IMF.h>
+#include <Ecore_IMF_Evas.h>
 #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,73 @@ _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)
+     {
+        EINA_LIST_FOREACH(wn->terms, l, term)
+          {
+             done = miniview_handle_key(term_miniview_get(term), ev);
+             if (!wn->group_input)
+               return;
+          }
+     }
+   else
+     {
+        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)
           {
-             termio_key_down(term->termio, event_info);
+             done = keyin_handle_key_binding(term->termio, ev, ctrl, alt,
+                                             shift, win, meta, hyper);
              if (!wn->group_input)
                return;
           }
@@ -1185,8 +1364,130 @@ _cb_win_key_down(void *data,
         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 113ed71..4c7aa7d 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);
 

-- 


Reply via email to