move input handling to win.c

This commit is contained in:
Boris Faure 2018-02-05 00:07:47 +01:00
parent e5c580aa26
commit d7432a52d6
7 changed files with 464 additions and 315 deletions

View File

@ -102,9 +102,9 @@ keyin_compose_seq_reset(Keys_Handler *khdl)
#include "tty_keys.h" #include "tty_keys.h"
static void void
_handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev, keyin_handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev,
int alt, int shift, int ctrl) const int alt, const int shift, const int ctrl)
{ {
if (!ev->key) if (!ev->key)
return; return;
@ -228,92 +228,24 @@ key_binding_lookup(const char *keyname,
} }
Eina_Bool Eina_Bool
keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, 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 ctrl, Eina_Bool alt, Eina_Bool shift,
Eina_Bool meta, Eina_Bool hyper) Eina_Bool win, Eina_Bool meta, Eina_Bool hyper)
{ {
Key_Binding *kb; Key_Binding *kb;
kb = key_binding_lookup(ev->keyname, ctrl, alt, shift, win, meta, hyper); kb = key_binding_lookup(ev->keyname, ctrl, alt, shift, win, meta, hyper);
if (kb) if (kb)
{ {
if (kb->cb(ty->obj)) if (kb->cb(termio))
{ {
keyin_compose_seq_reset(khdl);
return EINA_TRUE; 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; return EINA_FALSE;
} }
Eina_Bool Eina_Bool
key_is_modifier(const char *key) key_is_modifier(const char *key)
{ {

View File

@ -11,12 +11,19 @@ struct _Keys_Handler
unsigned char composing : 1; 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); void keyin_compose_seq_reset(Keys_Handler *khdl);
Eina_Bool key_is_modifier(const char *key); Eina_Bool key_is_modifier(const char *key);
Eina_Bool Eina_Bool
keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, 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 ctrl, Eina_Bool alt, Eina_Bool shift,
Eina_Bool meta, Eina_Bool hyper); Eina_Bool win, Eina_Bool meta, Eina_Bool hyper);
void keyin_handle_up(Keys_Handler *khdl, Evas_Event_Key_Up *ev); void keyin_handle_up(Keys_Handler *khdl, Evas_Event_Key_Up *ev);

View File

@ -86,12 +86,10 @@ struct _Termio
Evas_Object *win, *theme, *glayer; Evas_Object *win, *theme, *glayer;
Config *config; Config *config;
const char *sel_str; const char *sel_str;
const char *preedit_str;
Eina_List *cur_chids; Eina_List *cur_chids;
Ecore_Job *sel_reset_job; Ecore_Job *sel_reset_job;
double set_sel_at; double set_sel_at;
Elm_Sel_Type sel_type; Elm_Sel_Type sel_type;
Keys_Handler khdl;
unsigned char jump_on_change : 1; unsigned char jump_on_change : 1;
unsigned char jump_on_keypress : 1; unsigned char jump_on_keypress : 1;
unsigned char have_sel : 1; unsigned char have_sel : 1;
@ -1983,72 +1981,6 @@ _block_obj_del(Termblock *blk)
blk->obj = NULL; 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 */ /* {{{ Selection */
@ -3496,16 +3428,19 @@ termio_event_feed_mouse_in(Evas_Object *obj)
evas_event_feed_mouse_in(e, 0, NULL); evas_event_feed_mouse_in(e, 0, NULL);
} }
static void void
_imf_cursor_set(Termio *sd) 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; 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); evas_object_geometry_get(sd->cursor.obj, &cx, &cy, &cw, &ch);
if (sd->khdl.imf) ecore_imf_context_cursor_location_set(imf, cx, cy, cw, ch);
ecore_imf_context_cursor_location_set(sd->khdl.imf, cx, cy, cw, ch); ecore_imf_context_cursor_position_set(imf, (sd->cursor.y * sd->grid.w) + sd->cursor.x);
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_position_set(sd->imf, 0); // how to get it? ecore_imf_context_cursor_position_set(sd->imf, 0); // how to get it?
*/ */
@ -3522,14 +3457,6 @@ termio_focus_in(Evas_Object *termio)
else else
edje_object_signal_emit(sd->cursor.obj, "focus,in", "terminology"); edje_object_signal_emit(sd->cursor.obj, "focus,in", "terminology");
if (!sd->win) return; 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 void
@ -3542,14 +3469,6 @@ termio_focus_out(Evas_Object *termio)
edje_object_signal_emit(sd->cursor.obj, "focus,out", "terminology"); edje_object_signal_emit(sd->cursor.obj, "focus,out", "terminology");
if (!sd->win) return; if (!sd->win) return;
sd->pty->selection.last_click = 0; 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) if (!sd->ctxpopup)
_remove_links(sd, termio); _remove_links(sd, termio);
term_unfocus(sd->term); term_unfocus(sd->term);
@ -4807,6 +4726,7 @@ _smart_apply(Evas_Object *obj)
Eina_List *l, *ln; Eina_List *l, *ln;
Termblock *blk; Termblock *blk;
int x, y, ch1 = 0, ch2 = 0, inv = 0, preedit_x = 0, preedit_y = 0; int x, y, ch1 = 0, ch2 = 0, inv = 0, preedit_x = 0, preedit_y = 0;
char *preedit_str;
ssize_t w; ssize_t w;
EINA_SAFETY_ON_NULL_RETURN(sd); 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, evas_object_textgrid_update_add(sd->grid.obj, ch1, y,
ch2 - ch1 + 1, 1); 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; Eina_Unicode *uni, g;
int len = 0, i, jump, xx, backx; int len = 0, i, jump, xx, backx;
@ -5001,7 +4923,7 @@ _smart_apply(Evas_Object *obj)
Evas_Textgrid_Cell *tc; Evas_Textgrid_Cell *tc;
x = sd->cursor.x, y = sd->cursor.y; 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) if (uni)
{ {
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
@ -5251,52 +5173,8 @@ _cursor_cb_move(void *data,
{ {
Termio *sd = evas_object_smart_data_get(data); Termio *sd = evas_object_smart_data_get(data);
EINA_SAFETY_ON_NULL_RETURN(sd); EINA_SAFETY_ON_NULL_RETURN(sd);
_imf_cursor_set(sd); /* TODO: boris */
} //_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);
} }
@ -5370,58 +5248,6 @@ _smart_add(Evas_Object *obj)
sd->link.suspend = 1; 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); terms = eina_list_append(terms, obj);
} }
@ -5434,12 +5260,6 @@ _smart_del(Evas_Object *obj)
EINA_SAFETY_ON_NULL_RETURN(sd); EINA_SAFETY_ON_NULL_RETURN(sd);
terms = eina_list_remove(terms, obj); 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->cursor.obj) evas_object_del(sd->cursor.obj);
if (sd->event) if (sd->event)
{ {
@ -5495,13 +5315,10 @@ _smart_del(Evas_Object *obj)
} }
sd->sendfile.active = EINA_FALSE; sd->sendfile.active = EINA_FALSE;
} }
keyin_compose_seq_reset(&sd->khdl);
if (sd->sel_str) eina_stringshare_del(sd->sel_str); 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); if (sd->sel_reset_job) ecore_job_del(sd->sel_reset_job);
EINA_LIST_FREE(sd->cur_chids, chid) eina_stringshare_del(chid); EINA_LIST_FREE(sd->cur_chids, chid) eina_stringshare_del(chid);
sd->sel_str = NULL; sd->sel_str = NULL;
sd->preedit_str = NULL;
sd->sel_reset_job = NULL; sd->sel_reset_job = NULL;
sd->link.down.dndobj = NULL; sd->link.down.dndobj = NULL;
sd->cursor.obj = NULL; sd->cursor.obj = NULL;
@ -5513,10 +5330,8 @@ _smart_del(Evas_Object *obj)
sd->delayed_size_timer = NULL; sd->delayed_size_timer = NULL;
sd->font.name = NULL; sd->font.name = NULL;
sd->pty = NULL; sd->pty = NULL;
sd->khdl.imf = NULL;
sd->win = NULL; sd->win = NULL;
sd->glayer = NULL; sd->glayer = NULL;
ecore_imf_shutdown();
_parent_sc.del(obj); _parent_sc.del(obj);
} }
@ -6274,13 +6089,20 @@ termio_add(Evas_Object *win, Config *config,
} }
void 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 EINA_SAFETY_ON_NULL_RETURN(sd);
termio_key_up(Evas_Object *termio, void *event) if (sd->jump_on_keypress)
{ {
_smart_cb_key_up(termio, NULL, NULL, event); 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");
} }

View File

@ -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); void termio_file_send_cancel(const Evas_Object *obj);
double termio_file_send_progress_get(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); Termpty *termio_pty_get(const Evas_Object *obj);
Evas_Object * termio_miniview_get(const Evas_Object *obj); Evas_Object * termio_miniview_get(const Evas_Object *obj);
Term* termio_term_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_down(Evas_Object *termio, const Evas_Event_Key_Down *ev);
void termio_key_up(Evas_Object *termio, void *event);
void termio_focus_in(Evas_Object *termio); void termio_focus_in(Evas_Object *termio);
void termio_focus_out(Evas_Object *termio); void termio_focus_out(Evas_Object *termio);

View File

@ -1,10 +1,14 @@
#include "private.h" #include "private.h"
#include <Elementary.h> #include <Elementary.h>
#include <Ecore_Input.h>
#include <Ecore_IMF.h>
#include <Ecore_IMF_Evas.h>
#include "termpty.h" #include "termpty.h"
#include "termptyesc.h" #include "termptyesc.h"
#include "termptyops.h" #include "termptyops.h"
#include "termptysave.h" #include "termptysave.h"
#include "termio.h" #include "termio.h"
#include "keyin.h"
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -54,6 +58,26 @@ termpty_shutdown(void)
_termpty_log_dom = -1; _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 void
termpty_handle_buf(Termpty *ty, const Eina_Unicode *codepoints, int len) termpty_handle_buf(Termpty *ty, const Eina_Unicode *codepoints, int len)
{ {

View File

@ -1,5 +1,8 @@
#include <assert.h> #include <assert.h>
#include <Elementary.h> #include <Elementary.h>
#include <Ecore_Input.h>
#include <Ecore_IMF.h>
#include <Ecore_IMF_Evas.h>
#include "win.h" #include "win.h"
#include "termcmd.h" #include "termcmd.h"
#include "config.h" #include "config.h"
@ -12,6 +15,7 @@
#include "private.h" #include "private.h"
#include "sel.h" #include "sel.h"
#include "controls.h" #include "controls.h"
#include "keyin.h"
#include "term_container.h" #include "term_container.h"
@ -154,8 +158,10 @@ struct _Split
struct _Win struct _Win
{ {
Term_Container tc; Term_Container tc; /* has to be first field */
Keys_Handler khdl;
const char *preedit_str;
Term_Container *child; Term_Container *child;
Evas_Object *win; Evas_Object *win;
Evas_Object *conform; 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 _tabs_refresh(Tabs *tabs);
static void _term_tabregion_free(Term *term); static void _term_tabregion_free(Term *term);
static void _set_trans(Config *config, Evas_Object *bg, Evas_Object *base); 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 */ /* {{{ 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_event_callback_del_full(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn);
evas_object_del(wn->win); evas_object_del(wn->win);
} }
if (wn->size_job) ecore_job_del(wn->size_job); if (wn->size_job)
if (wn->config) config_del(wn->config); 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); free(wn);
} }
@ -958,9 +977,25 @@ _win_focus(Term_Container *tc, Term_Container *relative)
DBG("tc:%p tc->is_focused:%d from_child:%d", DBG("tc:%p tc->is_focused:%d from_child:%d",
tc, tc->is_focused, wn->child == relative); tc, tc->is_focused, wn->child == relative);
if (relative != wn->child) 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; 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", DBG("tc:%p tc->is_focused:%d from_child:%d",
tc, tc->is_focused, wn->child == relative); 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 (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; tc->is_focused = EINA_FALSE;
wn->child->unfocus(wn->child, tc); wn->child->unfocus(wn->child, tc);
@ -1108,26 +1155,55 @@ static void
_cb_win_key_up(void *data, _cb_win_key_up(void *data,
Evas *_e EINA_UNUSED, Evas *_e EINA_UNUSED,
Evas_Object *_obj EINA_UNUSED, Evas_Object *_obj EINA_UNUSED,
void *event_info) void *event)
{ {
Win *wn = data; Win *wn = data;
Eina_List *l; Evas_Event_Key_Up *ev = event;
Term *term;
const Evas_Event_Key_Up *ev = event_info;
if (wn->on_options)
return;
DBG("GROUP key up (%p) (ctrl:%d)", DBG("GROUP key up (%p) (ctrl:%d)",
wn, evas_key_modifier_is_set(ev->modifiers, "Control")); 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) if (wn->group_input)
{ {
wn->group_once_handled = EINA_FALSE;
EINA_LIST_FOREACH(wn->terms, l, term) EINA_LIST_FOREACH(wn->terms, l, term)
{ {
termio_key_up(term->termio, event_info); ty = termio_pty_get(term->termio);
if (!wn->group_input) if (ty)
return; termpty_write(ty, str, len);
} }
} }
else else
@ -1136,10 +1212,51 @@ _cb_win_key_up(void *data,
term = tc->focused_term_get(tc); term = tc->focused_term_get(tc);
if (term) 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 static void
_cb_win_key_down(void *data, _cb_win_key_down(void *data,
Evas *_e EINA_UNUSED, Evas *_e EINA_UNUSED,
@ -1147,9 +1264,12 @@ _cb_win_key_down(void *data,
void *event_info) void *event_info)
{ {
Win *wn = data; Win *wn = data;
Eina_List *l; Eina_List *l = NULL;
Term *term; Term *term = NULL;
const Evas_Event_Key_Down *ev = event_info; 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)", DBG("GROUP key down (%p) (ctrl:%d)",
wn, evas_key_modifier_is_set(ev->modifiers, "Control")); wn, evas_key_modifier_is_set(ev->modifiers, "Control"));
@ -1157,7 +1277,6 @@ _cb_win_key_down(void *data,
if (wn->on_options) if (wn->on_options)
return; return;
int ctrl, alt, shift, win, meta, hyper;
ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); ctrl = evas_key_modifier_is_set(ev->modifiers, "Control");
alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); 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", DBG("ctrl:%d alt:%d shift:%d win:%d meta:%d hyper:%d",
ctrl, alt, shift, win, meta, hyper); ctrl, alt, shift, win, meta, hyper);
/* 1st/ Miniview */
if (wn->group_input) if (wn->group_input)
{ {
wn->group_once_handled = EINA_FALSE;
EINA_LIST_FOREACH(wn->terms, l, term) 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) if (!wn->group_input)
return; return;
} }
@ -1185,8 +1303,191 @@ _cb_win_key_down(void *data,
Term_Container *tc = (Term_Container*) wn; Term_Container *tc = (Term_Container*) wn;
term = tc->focused_term_get(tc); 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) 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, _cb_win_mouse_move,
wn); 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); wins = eina_list_append(wins, wn);
return wn; return wn;
} }

View File

@ -66,6 +66,9 @@ void term_down(Term *term);
void term_left(Term *term); void term_left(Term *term);
void term_right(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_size_set(Win *wn, int new_size);
void win_font_update(Term *term); void win_font_update(Term *term);