forked from enlightenment/terminology
move input handling to win.c
This commit is contained in:
parent
e5c580aa26
commit
d7432a52d6
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
240
src/bin/termio.c
240
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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
409
src/bin/win.c
409
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,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue