#include "xkbswitch.h" typedef struct _Instance { Evas_Object *o_main; Evas_Object *o_xkbswitch; Evas_Object *o_xkbflag; Evas_Object *menu; Evas_Object *popup; E_Gadget_Site_Orient orient; E_Config_XKB_Layout *layout; } Instance; static Eina_List *ginstances = NULL; static Ecore_Event_Handler *xkbg_change_handle = NULL; void _xkbg_update_icon(int cur_group) { Instance *inst; Eina_List *l; E_Config_XKB_Layout *cl; EINA_SAFETY_ON_NULL_RETURN(e_config->xkb.used_layouts); //INF("ui: %d", cur_group); cl = eina_list_nth(e_config->xkb.used_layouts, cur_group); EINA_SAFETY_ON_NULL_RETURN(cl); if (!e_config_xkb_layout_eq(cl, e_config->xkb.current_layout)) { e_config_xkb_layout_free(e_config->xkb.current_layout); e_config->xkb.current_layout = e_config_xkb_layout_dup(cl); } if (e_config->xkb.only_label) { EINA_LIST_FOREACH(ginstances, l, inst) { if (!e_config_xkb_layout_eq(e_config->xkb.current_layout, inst->layout)) inst->layout = e_config->xkb.current_layout; E_FREE_FUNC(inst->o_xkbflag, evas_object_del); e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/noflag"); elm_layout_text_set(inst->o_xkbswitch, "e.text.label", cl->name); } } else { EINA_LIST_FOREACH(ginstances, l, inst) { if (!e_config_xkb_layout_eq(e_config->xkb.current_layout, inst->layout)) inst->layout = e_config->xkb.current_layout; if (!inst->o_xkbflag) inst->o_xkbflag = e_icon_add(evas_object_evas_get(inst->o_xkbswitch)); e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/main"); e_xkb_e_icon_flag_setup(inst->o_xkbflag, cl->name); elm_layout_content_set(inst->o_xkbswitch, "e.swallow.flag", inst->o_xkbflag); elm_layout_text_set(inst->o_xkbswitch, "e.text.label", e_xkb_layout_name_reduce(cl->name)); } } } static Eina_Bool _xkbg_changed_state(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED) { _xkbg_update_icon(e_config->xkb.cur_group); return ECORE_CALLBACK_PASS_ON; } static Evas_Object * _xkbg_gadget_configure(Evas_Object *g EINA_UNUSED) { if (e_configure_registry_exists("keyboard_and_mouse/xkbswitch")) { e_configure_registry_call("keyboard_and_mouse/xkbswitch", NULL, NULL); } return NULL; } static void _xkbg_cb_menu_set(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) { Instance *inst = evas_object_data_get(obj, "inst"); Eina_List *l; int cur_group = -1, grp = -1; E_Config_XKB_Layout *cl2, *cl = data; if (inst->popup) elm_ctxpopup_dismiss(inst->popup); EINA_LIST_FOREACH(e_config->xkb.used_layouts, l, cl2) { grp++; if (cl2 == cl) cur_group = grp; } if (cur_group == -1) return; e_xkb_layout_set(cl); e_config_xkb_layout_free(e_config->xkb.sel_layout); e_config->xkb.sel_layout = e_config_xkb_layout_dup(cl); } static void _xkbg_popup_dismissed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Instance *inst = data; E_FREE_FUNC(obj, evas_object_del); inst->popup = NULL; } static void _xkbg_popup_deleted(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Instance *inst = data; inst->popup = NULL; } static void _xkbg_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) { Evas_Event_Mouse_Down *ev = event; Instance *inst = data; if (!inst) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; if (ev->button == 3) { ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; e_gadget_configure(inst->o_main); } else if ((ev->button == 1) && (inst->popup)) { elm_ctxpopup_dismiss(inst->popup); return; } else if ((ev->button == 1) && (!inst->popup)) /* Left-click layout menu */ { if (!e_config->xkb.dont_touch_my_damn_keyboard) { E_Config_XKB_Layout *cl, *cur; Eina_List *l; Elm_Object_Item *mi; char buf[4096], buf2[4096]; cur = e_xkb_layout_get(); inst->popup = elm_ctxpopup_add(e_comp->elm); elm_object_style_set(inst->popup, "noblock"); evas_object_smart_callback_add(inst->popup, "dismissed", _xkbg_popup_dismissed, inst); evas_object_event_callback_add(inst->popup, EVAS_CALLBACK_DEL, _xkbg_popup_deleted, inst); inst->menu = elm_list_add(inst->popup); elm_list_select_mode_set(inst->menu, ELM_OBJECT_SELECT_MODE_ALWAYS); evas_object_data_set(inst->menu, "inst", inst); elm_object_content_set(inst->popup, inst->menu); E_EXPAND(inst->menu); E_FILL(inst->menu); /* Append all the layouts */ EINA_LIST_FOREACH(e_config->xkb.used_layouts, l, cl) { const char *name = cl->name; Evas_Object *ic; e_xkb_flag_file_get(buf, sizeof(buf), name); if (cl->variant) snprintf(buf2, sizeof(buf2), "%s (%s, %s)", cl->name, cl->model, cl->variant); else snprintf(buf2, sizeof(buf2), "%s (%s)", cl->name, cl->model); ic = elm_icon_add(inst->menu); E_EXPAND(ic); E_FILL(ic); elm_image_file_set(ic, buf, NULL); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); evas_object_show(ic); mi = elm_list_item_append(inst->menu, buf2, ic, NULL, _xkbg_cb_menu_set, cl); if (e_config_xkb_layout_eq(cur, cl)) elm_list_item_selected_set(mi, EINA_TRUE); } evas_object_show(inst->menu); evas_object_size_hint_min_set(inst->popup, 200 * e_scale, 100 * e_scale); e_gadget_util_ctxpopup_place(inst->o_main, inst->popup, inst->o_xkbswitch); evas_object_show(inst->popup); } } else if (ev->button == 2) e_xkb_layout_next(); } static void _xkbg_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) { //Evas_Coord w, h; Instance *inst = data; /* This does not work properly yet edje_object_parts_extends_calc(elm_layout_edje_get(inst->o_xkbswitch), 0, 0, &w, &h); evas_object_size_hint_aspect_set(inst->o_xkbswitch, EVAS_ASPECT_CONTROL_BOTH, w, h);*/ evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1); } static void _xkbg_gadget_created_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Instance *inst = data; if (inst->o_main) { e_gadget_configure_cb_set(inst->o_main, _xkbg_gadget_configure); inst->o_xkbswitch = elm_layout_add(inst->o_main); E_EXPAND(inst->o_xkbswitch); E_FILL(inst->o_xkbswitch); inst->layout = e_xkb_layout_get(); if (e_config->xkb.only_label || (!inst->layout)) { if (inst->orient == E_GADGET_SITE_ORIENT_VERTICAL) e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/noflag_vert"); else e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/noflag"); } else { if (inst->orient == E_GADGET_SITE_ORIENT_VERTICAL) e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/main_vert"); else e_theme_edje_object_set(inst->o_xkbswitch, "base/theme/modules/xkbswitch", "e/modules/xkbswitch/main"); } elm_layout_text_set(inst->o_xkbswitch, "e.text.label", inst->layout ? e_xkb_layout_name_reduce(inst->layout->name) : _("NONE")); if (inst->layout && (!e_config->xkb.only_label)) { inst->o_xkbflag = e_icon_add(evas_object_evas_get(inst->o_xkbswitch)); e_xkb_e_icon_flag_setup(inst->o_xkbflag, inst->layout->name); elm_layout_content_set(inst->o_xkbswitch, "e.swallow.flag", inst->o_xkbflag); } else inst->o_xkbflag = NULL; evas_object_event_callback_add(inst->o_xkbswitch, EVAS_CALLBACK_MOUSE_DOWN, _xkbg_cb_mouse_down, inst); evas_object_event_callback_add(inst->o_xkbswitch, EVAS_CALLBACK_RESIZE, _xkbg_resize_cb, inst); elm_box_pack_end(inst->o_main, inst->o_xkbswitch); evas_object_show(inst->o_xkbswitch); } evas_object_smart_callback_del_full(obj, "gadget_created", _xkbg_gadget_created_cb, data); } static void xkbg_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Instance *inst = data; if (inst->popup) elm_ctxpopup_dismiss(inst->popup); ginstances = eina_list_remove(ginstances, inst); free(inst); } EINTERN Evas_Object * xkbg_gadget_create(Evas_Object *parent, int *id EINA_UNUSED, E_Gadget_Site_Orient orient) { Instance *inst; inst = E_NEW(Instance, 1); inst->o_main = elm_box_add(parent); inst->orient = orient; E_EXPAND(inst->o_main); E_FILL(inst->o_main); evas_object_smart_callback_add(parent, "gadget_created", _xkbg_gadget_created_cb, inst); evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, xkbg_del, inst); ginstances = eina_list_append(ginstances, inst); return inst->o_main; } EINTERN void xkbg_init(void) { xkbg_change_handle = ecore_event_handler_add(E_EVENT_XKB_CHANGED, _xkbg_changed_state, NULL); } EINTERN void xkbg_shutdown(void) { if (_xkbg.evh) ecore_event_handler_del(_xkbg.evh); if (_xkbg.cfd) e_object_del(E_OBJECT(_xkbg.cfd)); _xkbg.cfd = NULL; ecore_event_handler_del(xkbg_change_handle); }