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"
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)
{

View File

@ -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);

View File

@ -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");
}

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);
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);

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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);