enlightenment/src/modules/everything/evry.c

3153 lines
78 KiB
C
Raw Normal View History

#include "e.h"
#include "e_mod_main.h"
/* TODO
* - keybinding configuration
*/
#define DRAG_OFF_WINDOW
#define INPUTLEN 256
#define MATCH_LAG 0.15
#define INITIAL_MATCH_LAG 0.3
#if defined (CHECK_TIME) || defined (CHECK_REFS)
#undef DBG
#define DBG(...) ERR(__VA_ARGS__)
#else
#undef DBG
#define DBG(...)
#endif
static Eina_Bool _evry_cb_desklock(Evry_Window *win, int type EINA_UNUSED, E_Event_Desklock *ev);
static void _evry_matches_update(Evry_Selector *sel, int async);
static void _evry_plugin_action(Evry_Selector *sel, int finished);
static void _evry_plugin_select(Evry_State *s, Evry_Plugin *p);
static void _evry_plugin_list_insert(Evry_State *s, Evry_Plugin *p);
static int _evry_backspace(Evry_Selector *sel);
static void _evry_update(Evry_Selector *sel, int fetch);
static void _evry_update_text_label(Evry_State *s);
static int _evry_clear(Evry_Selector *sel);
static Eina_Bool _evry_cb_update_timer(void *data);
static Evry_State *_evry_state_new(Evry_Selector *sel, Eina_List *plugins);
static void _evry_state_pop(Evry_Selector *sel, int immediate);
static void _evry_state_clear(Evry_Window *win);
static void _evry_hide_func(Evry_Window *win, int finished);
static Evry_Selector *_evry_selector_new(Evry_Window *win, int type);
static void _evry_selector_free(Evry_Selector *sel);
static void _evry_selector_activate(Evry_Selector *sel, int slide);
static void _evry_selector_update(Evry_Selector *sel);
static int _evry_selector_plugins_get(Evry_Selector *sel, Evry_Item *it, const char *plugin_name);
static void _evry_selector_update_actions(Evry_Selector *sel);
static void _evry_selector_item_update(Evry_Selector *sel);
static void _evry_selector_item_clear(Evry_Selector *sel);
static void _evry_selector_label_set(Evry_Selector *sel, const char *part, const char *label);
static void _evry_selector_signal_emit(Evry_Selector *sel, const char *msg);
static int _evry_selectors_shift(Evry_Window *win, int dir);
static int _evry_selectors_switch(Evry_Window *win, int dir);
static Evry_Window *_evry_window_new(E_Zone *zone, E_Zone_Edge edge);
static void _evry_cb_win_delete(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
static void _evry_window_free(Evry_Window *win);
static void _evry_list_win_show(Evry_Window *win);
static void _evry_list_win_hide(Evry_Window *win);
static void _evry_list_win_update(Evry_State *s);
static int _evry_view_create(Evry_State *s);
static void _evry_view_clear(Evry_State *s);
static int _evry_view_update(Evry_Window *win, Evry_State *s);
static int _evry_view_key_press(Evry_State *s, Ecore_Event_Key *ev);
static void _evry_view_show(Evry_Window *win, Evry_View *v, int slide);
static void _evry_view_hide(Evry_Window *win, Evry_View *v, int slide);
static void _evry_item_desel(Evry_State *s);
static void _evry_item_sel(Evry_State *s, Evry_Item *it);
static void _evry_cb_show(Evry_Window *win, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
static Eina_Bool _evry_cb_key_down(void *data, int type, void *event);
static Eina_Bool _evry_cb_selection_notify(void *data, int type, void *event);
static Eina_Bool _evry_cb_mouse(void *data, int type, void *event);
static Eina_Bool _evry_delay_hide_timer(void *data);
static Eina_Bool _evry_focus_out_timer(void *data);
static Eina_List *windows = NULL;
#ifdef CHECK_TIME
double _evry_time;
#endif
#ifdef CHECK_REFS
static int _item_cnt = 0;
Eina_List *_refd = NULL;
#endif
#define SUBJ_SEL win->selectors[0]
#define ACTN_SEL win->selectors[1]
#define OBJ_SEL win->selectors[2]
#define CUR_SEL win->selector
int
evry_init(void)
{
return 1;
}
int
evry_shutdown(void)
{
while (windows)
evry_hide(windows->data, 0);
return 1;
}
static int
_evry_aggregator_fetch(Evry_State *s)
{
Eina_List *l;
if (!s)
{
ERR("no state");
return 0;
}
if (s->aggregator->fetch(s->aggregator, s->input))
{
l = eina_list_data_find_list(s->cur_plugins, s->aggregator);
if (!l)
s->cur_plugins = eina_list_prepend(s->cur_plugins, s->aggregator);
else
s->cur_plugins = eina_list_promote_list(s->cur_plugins, l);
return 1;
}
s->cur_plugins = eina_list_remove(s->cur_plugins, s->aggregator);
return 1;
}
2010-05-15 20:22:17 -07:00
static Eina_Bool
_evry_cb_item_changed(EINA_UNUSED void *data, EINA_UNUSED int type, void *event)
{
Evry_Event_Item_Changed *ev = event;
Evry_Selector *sel;
Evry_Item *it = ev->item;
if (!it || !it->plugin || !it->plugin->state)
return ECORE_CALLBACK_PASS_ON;
sel = it->plugin->state->selector;
if (sel->state && sel->state->cur_item == it)
{
_evry_selector_update(sel);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_evry_focus_out_timer(void *data)
{
Evry_Window *win = data;
E_Client *ec;
win->delay_hide_action = NULL;
ec = e_win_client_get(win->ewin);
if (ec && (!e_object_is_del(E_OBJECT(ec))))
evry_hide(win, 0);
return ECORE_CALLBACK_CANCEL;
}
static void
_evry_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evry_Window *win = data;
if (!win->grab) return;
if (win->delay_hide_action)
ecore_timer_del(win->delay_hide_action);
win->delay_hide_action = ecore_timer_loop_add(0.0, _evry_focus_out_timer, win);
}
static void
_evry_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evry_Window *win = data;
if (!win->grab) return;
E_FREE_FUNC(win->delay_hide_action, ecore_timer_del);
}
Evry_Window *
evry_show(E_Zone *zone, E_Zone_Edge edge, const char *params, Eina_Bool popup)
{
Evry_Window *win;
Evry_Selector *sel;
#ifdef CHECK_TIME
_evry_time = ecore_time_get();
DBG("_____evry_show______");
#endif
E_OBJECT_CHECK_RETURN(zone, 0);
E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, 0);
if (popup)
{
// only one popup please
Eina_List *l;
EINA_LIST_FOREACH(windows, l, win)
if (win->grab)
return NULL;
}
if (!(win = _evry_window_new(zone, edge)))
return NULL;
if (popup)
{
E_Client *ec;
ecore_evas_name_class_set(e_win_ee_get(win->ewin), "E", "everything");
evas_object_show(win->ewin);
ec = e_win_client_get(win->ewin);
if (ec)
{
#ifndef HAVE_WAYLAND_ONLY
2015-03-13 12:41:21 -07:00
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
ecore_x_netwm_window_type_set(elm_win_window_id_get(win->ewin),
ECORE_X_WINDOW_TYPE_UTILITY);
#endif
ec->netwm.state.skip_taskbar = 1;
EC_CHANGED(ec);
2016-05-05 06:33:55 -07:00
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_FOCUS_OUT, _evry_focus_out, win);
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_FOCUS_IN, _evry_focus_in, win);
}
2009-08-12 12:00:25 -07:00
win->grab = 1;
}
evry_history_load();
if (params)
win->plugin_dedicated = EINA_TRUE;
win->sel_list = E_NEW(Evry_Selector *, 4);
win->sel_list[3] = NULL;
win->selectors = win->sel_list;
_evry_selector_new(win, EVRY_PLUGIN_SUBJECT);
_evry_selector_new(win, EVRY_PLUGIN_ACTION);
_evry_selector_new(win, EVRY_PLUGIN_OBJECT);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_KEY_DOWN, _evry_cb_key_down, win);
#ifndef HAVE_WAYLAND_ONLY
2015-01-22 12:05:58 -08:00
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_SELECTION_NOTIFY, _evry_cb_selection_notify, win);
#endif
evas_object_event_callback_add(e_win_client_get(win->ewin)->frame, EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_evry_cb_show, win);
E_LIST_HANDLER_APPEND(win->handlers, _evry_events[EVRY_EVENT_ITEM_CHANGED], _evry_cb_item_changed, win);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _evry_cb_mouse, win);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _evry_cb_mouse, win);
E_LIST_HANDLER_APPEND(win->handlers, E_EVENT_DESKLOCK, _evry_cb_desklock, win);
#if 0
E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_MOVE, _evry_cb_mouse, win);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_WHEEL, _evry_cb_mouse, win);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_MOUSE_IN, _evry_cb_mouse_in, win);
E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_MOUSE_OUT, _evry_cb_mouse_out, win);
#endif
_evry_selector_plugins_get(SUBJ_SEL, NULL, params);
_evry_selector_update(SUBJ_SEL);
windows = eina_list_append(windows, win);
_evry_selector_activate(SUBJ_SEL, 0);
if ((!evry_conf->hide_list) || (edge))
{
sel = CUR_SEL;
if (sel && sel->state && evry_conf->views)
{
/* if (evry_conf->first_run)
* {
* evry_view_toggle(sel->state, "?");
* evry_conf->first_run = EINA_FALSE;
* } */
edje_object_signal_emit(win->o_main, "list:e,state,list_show", "e");
edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
win->visible = EINA_TRUE;
}
}
win->func.hide = &_evry_hide_func;
win->delay_hide_action = ecore_timer_loop_add(0.2, _evry_delay_hide_timer, win);
return win;
}
static Eina_Bool
_evry_delay_hide_timer(void *data)
{
Evry_Window *win = data;
win->delay_hide_action = NULL;
return ECORE_CALLBACK_CANCEL;
}
static void
_evry_hide_func(Evry_Window *win, int finished)
{
if ((finished) && (win->grab))
evry_hide(win, 0);
}
void
evry_hide(Evry_Window *win, int clear)
{
Ecore_Event_Handler *ev;
int i;
2009-08-12 12:00:25 -07:00
if (!win) return;
evas_object_event_callback_del(win->ewin, EVAS_CALLBACK_DEL, _evry_cb_win_delete);
evas_object_event_callback_del(e_win_client_get(win->ewin)->frame,
EVAS_CALLBACK_FOCUS_OUT,
_evry_focus_out);
evas_object_hide(win->ewin);
_evry_state_clear(win);
if ((clear && CUR_SEL) &&
/* pop states */
((eina_list_count((SUBJ_SEL)->states) > 1) ||
/* move to subject selector */
(CUR_SEL != SUBJ_SEL) ||
/* clear input */
(((CUR_SEL)->state) && ((CUR_SEL)->state->input[0]))))
{
int slide = 0;
Evry_Selector *sel;
Evry_State *s;
if (CUR_SEL != SUBJ_SEL)
{
if (CUR_SEL == ACTN_SEL)
_evry_selectors_switch(win, -1);
else if (CUR_SEL == OBJ_SEL)
_evry_selectors_switch(win, 1);
}
/* just to be sure */
CUR_SEL = SUBJ_SEL;
while ((CUR_SEL)->states->next)
{
slide = SLIDE_RIGHT;
_evry_state_pop(CUR_SEL, 1);
}
sel = CUR_SEL;
s = sel->state;
_evry_clear(sel);
_evry_clear(sel);
_evry_aggregator_fetch(s);
_evry_selector_update(sel);
_evry_update_text_label(s);
if (s->view)
{
_evry_view_show(win, s->view, slide);
s->view->update(s->view);
}
return;
}
if (_evry_selectors_shift(win, -1))
return;
2010-05-15 20:22:17 -07:00
win->visible = EINA_FALSE;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
if (win->sel_list)
{
for (i = 0; win->sel_list[i]; i++)
_evry_selector_free(win->sel_list[i]);
}
2010-05-15 20:22:17 -07:00
E_FREE(win->sel_list);
EINA_LIST_FREE (win->handlers, ev)
2010-05-15 20:22:17 -07:00
ecore_event_handler_del(ev);
if (win->delay_hide_action)
ecore_timer_del(win->delay_hide_action);
if (win->grab)
e_grabinput_release(elm_win_window_id_get(win->ewin),
elm_win_window_id_get(win->ewin));
2010-05-15 20:22:17 -07:00
windows = eina_list_remove(windows, win);
_evry_window_free(win);
2010-05-15 20:22:17 -07:00
evry_history_unload();
#ifdef CHECK_REFS
Evry_Item *_it;
int _cnt = eina_list_count(_refd);
Eina_List *_l;
printf("__________________________");
EINA_LIST_FOREACH (_refd, _l, _it)
printf("%d %s\n", _it->ref, _it->label);
printf("sum: %d", _cnt);
#endif
2010-05-15 20:22:17 -07:00
}
static int
_evry_selectors_shift(Evry_Window *win, int dir)
2010-05-15 20:22:17 -07:00
{
if ((dir > 0) && (win->level == 0))
2010-05-15 20:22:17 -07:00
{
void *new_sel;
Evry_Selector *sel;
Evry_State *s;
int i;
for (i = 1; i < 3; i++)
_evry_selector_item_clear(win->selectors[i]);
2010-05-15 20:22:17 -07:00
if (!(new_sel = realloc(win->sel_list, sizeof(Evry_Selector *) * 6)))
return 0;
2010-05-15 20:22:17 -07:00
win->sel_list = new_sel;
2010-05-15 20:22:17 -07:00
edje_object_signal_emit(win->o_main,
"e,state,object_selector_hide", "e");
2010-05-15 20:22:17 -07:00
win->sel_list[5] = NULL;
win->selectors = win->sel_list + 2;
_evry_selector_new(win, EVRY_PLUGIN_ACTION);
_evry_selector_new(win, EVRY_PLUGIN_OBJECT);
2010-05-15 20:22:17 -07:00
CUR_SEL = SUBJ_SEL;
sel = CUR_SEL;
2010-05-15 20:22:17 -07:00
_evry_selector_signal_emit(sel, "e,state,selected");
_evry_selector_item_update(SUBJ_SEL);
_evry_selector_item_update(ACTN_SEL);
_evry_selector_item_update(OBJ_SEL);
2010-05-15 20:22:17 -07:00
/* was checked before. anyway */
if ((s = sel->state) && (s->cur_item))
_evry_selector_update_actions(sel);
2010-05-15 20:22:17 -07:00
win->level++;
2010-05-15 20:22:17 -07:00
return 1;
2010-05-15 20:22:17 -07:00
}
else if ((dir < 0) && (win->level > 0))
{
_evry_selector_item_clear(SUBJ_SEL);
_evry_selector_free(ACTN_SEL);
_evry_selector_free(OBJ_SEL);
win->selectors = win->sel_list;
win->sel_list[3] = NULL;
CUR_SEL = NULL;
edje_object_signal_emit(win->o_main,
"e,state,object_selector_show", "e");
_evry_selector_item_update(SUBJ_SEL);
_evry_selector_item_update(ACTN_SEL);
_evry_selector_item_update(OBJ_SEL);
_evry_selector_activate(OBJ_SEL, 0);
win->level = 0;
return 1;
2010-05-15 20:22:17 -07:00
}
2010-05-15 20:22:17 -07:00
return 0;
}
Evry_Item *
evry_item_new(Evry_Item *it, Evry_Plugin *p, const char *label,
Evas_Object *(*icon_get)(Evry_Item * it, Evas * e),
void (*cb_free)(Evry_Item *item))
{
if (!it)
{
it = E_NEW(Evry_Item, 1);
if (!it) return NULL;
}
2009-08-12 12:00:25 -07:00
if (p && EVRY_ITEM(p)->subtype)
it->type = EVRY_ITEM(p)->subtype;
it->plugin = p;
if (label) it->label = eina_stringshare_add(label);
it->free = cb_free;
it->icon_get = icon_get;
it->ref = 1;
#ifdef CHECK_REFS
_item_cnt++;
_refd = eina_list_append(_refd, it);
#endif
#ifdef PRINT_REFS
printf("%d, %d\t new : %s\n", it->ref, _item_cnt, it->label);
#endif
return it;
}
void
evry_item_free(Evry_Item *it)
{
if (!it) return;
it->ref--;
#ifdef PRINT_REFS
printf("%d, %d\t unref: %s\n", it->ref, _item_cnt, it->label);
#endif
if (it->ref > 0) return;
#ifdef CHECK_REFS
_item_cnt--;
_refd = eina_list_remove(_refd, it);
#endif
IF_RELEASE(it->label);
IF_RELEASE(it->id);
IF_RELEASE(it->context);
IF_RELEASE(it->detail);
IF_RELEASE(it->icon);
if (it->free)
it->free(it);
else
E_FREE(it);
}
void
evry_item_ref(Evry_Item *it)
{
it->ref++;
#ifdef PRINT_REFS
printf("%d, %d\t ref : %s\n", it->ref, _item_cnt, it->label);
#endif
}
static int
_evry_selector_update_actions_do(Evry_Selector *sel)
{
Evry_State *s;
Evry_Window *win = sel->win;
if (sel->action_timer)
{
ecore_timer_del(sel->action_timer);
sel->action_timer = NULL;
}
if ((s = (SUBJ_SEL)->state))
_evry_selector_plugins_get(sel, s->cur_item, NULL);
_evry_selector_update(sel);
return 1;
}
static Eina_Bool
_evry_timer_cb_actions_get(void *data)
{
Evry_Selector *sel = data;
Evry_Window *win = sel->win;
Evry_State *s;
_evry_selector_update_actions_do(sel);
if ((CUR_SEL == sel) && (s = sel->state))
{
if (_evry_view_update(win, s))
_evry_view_show(win, s->view, 0);
}
return ECORE_CALLBACK_CANCEL;
}
static void
_evry_selector_update_actions(Evry_Selector *sel)
{
if (sel->action_timer)
ecore_timer_del(sel->action_timer);
_evry_selector_item_clear(sel);
sel->action_timer = ecore_timer_loop_add(0.2, _evry_timer_cb_actions_get, sel);
}
void
evry_item_select(const Evry_State *state, Evry_Item *it)
{
Evry_State *s = (Evry_State *)state;
Evry_Selector *sel;
Evry_Window *win;
if ((!s) || (s->delete_me))
return;
sel = s->selector;
win = sel->win;
s->plugin_auto_selected = EINA_FALSE;
s->item_auto_selected = EINA_FALSE;
_evry_item_sel(s, it);
if (s == sel->state)
{
_evry_selector_update(sel);
if (CUR_SEL == SUBJ_SEL)
_evry_selector_update_actions(ACTN_SEL);
if (CUR_SEL == ACTN_SEL)
{
while (OBJ_SEL->state)
_evry_state_pop(OBJ_SEL, 1);
}
}
}
void
evry_item_mark(const Evry_State *state, Evry_Item *it, Eina_Bool mark)
{
Evry_State *s = (Evry_State *)state;
if ((!s) || (s->delete_me))
return;
if (mark && !it->marked)
{
it->marked = EINA_TRUE;
s->sel_items = eina_list_append(s->sel_items, it);
}
else if (it->marked)
{
it->marked = EINA_FALSE;
s->sel_items = eina_list_remove(s->sel_items, it);
}
}
void
evry_plugin_update(Evry_Plugin *p, int action)
{
Evry_State *s;
Evry_Selector *sel;
Evry_Window *win;
if (!(s = p->state) || (s->delete_me))
return;
if (!(sel = s->selector))
return;
if (!(win = sel->win))
return;
if (sel->state->request != p->request)
return;
DBG("update %d %d %s", s->request, p->request, p->name);
if (action == EVRY_UPDATE_ADD)
{
/* clear marked items */
if (s->sel_items)
{
eina_list_free(s->sel_items);
s->sel_items = NULL;
}
if ((!p->items) && (!s->trigger_active))
{
/* remove plugin */
if (!(eina_list_data_find(s->cur_plugins, p)))
return;
s->cur_plugins = eina_list_remove(s->cur_plugins, p);
if (p == s->plugin)
_evry_plugin_select(s, NULL);
}
else
{
/* add plugin to current plugins*/
_evry_plugin_list_insert(s, p);
}
if (sel->state == s)
{
_evry_aggregator_fetch(s);
/* select first plugin */
if ((!s->plugin) || (s->plugin_auto_selected) ||
!(eina_list_data_find(s->cur_plugins, s->plugin)))
{
_evry_plugin_select(s, NULL);
}
if ((s->plugin && (sel->state == s)) &&
/* plugin is current */
((s->plugin == p) ||
/* plugin items are shown in aggregator */
((s->plugin == s->aggregator) && p->config->aggregate)))
{
_evry_selector_update(sel);
if (_evry_view_update(win, s))
/* XXX when there is a case where view disappears
check this one! is swallow always visible ? */
_evry_view_show(win, s->view, 0);
}
/* switch back to subject selector when no current items */
if ((sel == SUBJ_SEL) &&
(!(s->plugin) || !(s->plugin->items)) &&
(CUR_SEL == ACTN_SEL))
{
_evry_selectors_switch(win, -1);
_evry_clear(SUBJ_SEL);
}
}
}
else if (action == EVRY_UPDATE_REFRESH)
{
_evry_view_clear(s);
_evry_view_update(win, s);
}
}
static void
_evry_list_win_show(Evry_Window *win)
{
if (win->visible) return;
win->visible = EINA_TRUE;
_evry_list_win_update((CUR_SEL)->state);
edje_object_signal_emit(win->o_main, "list:e,state,list_show", "e");
edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
}
static void
_evry_list_win_hide(Evry_Window *win)
{
Evry_Selector *sel = CUR_SEL;
if (!win->visible)
return;
if (!evry_conf->hide_list)
return;
if (sel->state)
_evry_view_clear(sel->state);
win->visible = EINA_FALSE;
edje_object_signal_emit(win->o_main, "list:e,state,list_hide", "e");
if (evry_conf->hide_input && (!(sel->state) || (sel->state->input[0])))
edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
}
static void
_evry_cb_win_delete(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
evry_hide(data, 0);
}
static Evry_Window *
_evry_window_new(E_Zone *zone, E_Zone_Edge edge)
{
int x, y, mw, mh, h, w;
Evry_Window *win;
Evas_Object *o;
const char *tmp;
int offset_s = 0;
win = E_NEW(Evry_Window, 1);
win->ewin = elm_win_add(NULL, NULL, ELM_WIN_UTILITY);
elm_win_borderless_set(win->ewin, 1);
e_win_no_remember_set(win->ewin, 1);
e_win_placed_set(win->ewin, 1);
elm_win_override_set(win->ewin, 1);
win->evas = evas_object_evas_get(win->ewin);
win->zone = zone;
evas_object_data_set(win->ewin, "evry_win", win);
o = edje_object_add(win->evas);
win->o_main = o;
elm_win_resize_object_add(win->ewin, o);
E_EXPAND(o);
E_FILL(o);
e_theme_edje_object_set(o, "base/theme/modules/everything",
"e/modules/everything/main");
edje_object_signal_emit(o, "e,state,composited", "e");
edje_object_signal_emit(o, "list:e,state,composited", "e");
edje_object_message_signal_process(o);
edje_object_calc_force(o);
tmp = edje_object_data_get(o, "shadow_offset");
offset_s = tmp ? atoi(tmp) : 0;
edje_object_size_min_calc(o, &mw, &mh);
if (edge == E_ZONE_EDGE_NONE)
{
w = evry_conf->width;
h = evry_conf->height;
}
else
{
w = evry_conf->edge_width;
h = evry_conf->edge_height;
}
evas_object_size_hint_min_set(win->ewin, mw, mh);
evry_conf->min_w = mw;
if (w > mw) mw = w;
evry_conf->min_h = mh;
if (h > mh) mh = h;
if (edge == E_ZONE_EDGE_NONE)
{
mw += offset_s * 2;
mh += offset_s * 2;
x = (zone->x + (zone->w * evry_conf->rel_x)) - (mw / 2);
y = (zone->y + (zone->h * evry_conf->rel_y)) - (mh / 2);
}
else
{
int to_side = 0;
switch (edge)
{
case E_ZONE_EDGE_TOP_LEFT:
x = to_side - offset_s;
y = to_side - offset_s;
break;
case E_ZONE_EDGE_TOP_RIGHT:
x = zone->w - (mw + offset_s + to_side);
y = to_side - offset_s;
break;
case E_ZONE_EDGE_BOTTOM_RIGHT:
x = zone->w - (mw + offset_s + to_side);
y = zone->h - (mh + offset_s + to_side);
break;
case E_ZONE_EDGE_BOTTOM_LEFT:
x = to_side - offset_s;
y = zone->h - (mh + offset_s + to_side);
break;
default:
mw += offset_s * 2;
mh += offset_s * 2;
x = (zone->w * evry_conf->rel_x) - (mw / 2);
y = (zone->h * evry_conf->rel_y) - (mh / 2);
break;
}
x += zone->x;
y += zone->y;
mw += offset_s * 2;
mh += offset_s * 2;
}
evas_object_geometry_set(win->ewin, x, y, mw, mh);
2009-08-12 12:00:25 -07:00
evas_object_show(o);
evas_event_feed_mouse_in(win->evas, 0, NULL);
evas_event_feed_mouse_move(win->evas, -1000000, -1000000, 0, NULL);
evas_object_event_callback_add(win->ewin, EVAS_CALLBACK_DEL, _evry_cb_win_delete, win);
return win;
}
#if 0
static void
_evry_cb_drag_finished(E_Drag *drag, int dropped)
{
E_FREE(drag->data);
}
#endif
static Eina_Bool
_evry_cb_desklock(Evry_Window *win, int type EINA_UNUSED, E_Event_Desklock *ev)
{
if (ev->on) evry_hide(win, 0);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_evry_cb_mouse(void *data, int type, void *event)
{
Ecore_Event_Mouse_Button *ev;
Evry_Window *win = data;
Evas_Object *ewin;
int x, y, w, h;
ev = event;
if (!win->grab)
return ECORE_CALLBACK_PASS_ON;
if ((ev->event_window != ecore_evas_window_get(e_comp->ee)) &&
(ev->event_window != elm_win_window_id_get(win->ewin)))
return ECORE_CALLBACK_PASS_ON;
ewin = win->ewin;
#if 0
if (type == ECORE_EVENT_MOUSE_MOVE)
{
Ecore_Event_Mouse_Move *ev = event;
Evry_State *s;
if ((win->mouse_button == 3) &&
(s = (CUR_SEL)->state) && (s->cur_item) &&
(CHECK_TYPE(s->cur_item, EVRY_TYPE_FILE)) &&
(!E_INSIDE(ev->x, ev->y,
win->zone->x,
win->zone->y,
ewin->w, ewin->h)))
{
const char *drag_types[] = { "text/uri-list" };
E_Drag *d;
Evas_Object *o;
const char *uri;
int s_len, sel_length = 0;
char *tmp, *sel = NULL;
GET_FILE(file, s->cur_item);
if (!(uri = evry_file_url_get(file)))
return ECORE_CALLBACK_PASS_ON;
s_len = strlen(uri);
if (!(tmp = realloc(sel, sel_length + s_len + 2 + 1)))
return ECORE_CALLBACK_PASS_ON;
sel = tmp;
memcpy(sel + sel_length, uri, s_len);
memcpy(sel + sel_length + s_len, "\r\n", 2);
sel_length += s_len + 2;
2015-03-13 13:28:08 -07:00
d = e_drag_new(e_comp),
ev->x, ev->y,
drag_types, 1, sel, sel_length, NULL,
_evry_cb_drag_finished);
e_drag_resize(d, 128, 128);
o = evry_util_icon_get(s->cur_item, e_drag_evas_get(d));
e_drag_object_set(d, o);
e_drag_xdnd_start(d, ev->x, ev->y);
evry_hide(win, 0);
return ECORE_CALLBACK_PASS_ON;
}
}
else if (type == ECORE_EVENT_MOUSE_WHEEL)
{
Ecore_Event_Mouse_Wheel *ev = event;
}
else
#endif
evas_object_geometry_get(ewin, &x, &y, &w, &h);
if (type == ECORE_EVENT_MOUSE_BUTTON_DOWN)
{
win->mouse_out = 0;
if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
{
if (ev->event_window == ecore_evas_window_get(e_comp->ee))
{
if (!E_INSIDE(e_comp_canvas_x_root_adjust(ev->root.x),
e_comp_canvas_y_root_adjust(ev->root.y), x, y, w, h))
win->mouse_out = 1;
}
}
else if (!E_INSIDE(e_comp_canvas_x_root_adjust(ev->root.x),
e_comp_canvas_y_root_adjust(ev->root.y), x, y, w, h))
win->mouse_out = 1;
if (win->mouse_out)
return ECORE_CALLBACK_PASS_ON;
win->mouse_button = ev->buttons;
}
else if (type == ECORE_EVENT_MOUSE_BUTTON_UP)
{
win->mouse_button = 0;
if (win->mouse_out)
{
evry_hide(win, 0);
return ECORE_CALLBACK_PASS_ON;
}
}
return ECORE_CALLBACK_PASS_ON;
}
static void
_evry_window_free(Evry_Window *win)
{
evas_event_freeze(win->evas);
remove show callback from evry win on deletion ==22088== Invalid read of size 1 ==22088== at 0x2C9FE7B1: _evry_cb_show (evry.c:3046) ==22088== by 0x5BE9918: _eo_evas_object_cb (evas_callbacks.c:65) ==22088== by 0x69A16F4: _eo_base_event_callback_call (eo_base_class.c:715) ==22088== by 0x69A3041: eo_event_callback_call (in /usr/lib/libeo.so.1.17.99) ==22088== by 0x5BEA0B3: evas_object_event_callback_call (evas_callbacks.c:240) ==22088== by 0x5C2577C: evas_object_inform_call_show (evas_object_inform.c:12) ==22088== by 0x5C1ED24: _show (evas_object_main.c:1360) ==22088== by 0x5C1EADA: _evas_object_efl_gfx_base_visible_set (evas_object_main.c:1313) ==22088== by 0x575D80A: efl_gfx_visible_set (in /usr/lib/libefl.so.1.17.99) ==22088== by 0x5C1EA58: evas_object_show (evas_object_main.c:1291) ==22088== by 0x479FCF: _e_comp_intercept_show_helper (e_comp_object.c:1616) ==22088== by 0x47A02A: _e_comp_intercept_show (e_comp_object.c:1630) ==22088== Address 0x17621591 is 81 bytes inside a block of size 120 free'd ==22088== at 0x4C2AE6B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22088== by 0x2C9F95A8: _evry_window_free (evry.c:993) ==22088== by 0x2C9F8065: evry_hide (evry.c:366) ==22088== by 0x2C9FB9A2: _evry_cb_key_down (evry.c:1926) ==22088== by 0x8F6ED4A: _ecore_call_handler_cb (ecore_private.h:316) ==22088== by 0x8F6FC92: _ecore_event_call (ecore_events.c:518) ==22088== by 0x8F7A15A: _ecore_main_loop_iterate_internal (ecore_main.c:2339) ==22088== by 0x8F784A8: ecore_main_loop_begin (ecore_main.c:1284) ==22088== by 0x4403F6: main (e_main.c:1087) ==22088== Block was alloc'd at ==22088== at 0x4C2BBD5: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22088== by 0x2C9F8D7D: _evry_window_new (evry.c:758) ==22088== by 0x2C9F772D: evry_show (evry.c:177) ==22088== by 0x2C9F711C: _e_mod_run_defer_cb (e_mod_main.c:537) ==22088== by 0x8F75267: _ecore_call_task_cb (ecore_private.h:282) ==22088== by 0x8F7574E: _ecore_idle_enterer_call (ecore_idle_enterer.c:174) ==22088== by 0x8F7A05B: _ecore_main_loop_iterate_internal (ecore_main.c:2261) ==22088== by 0x8F784A8: ecore_main_loop_begin (ecore_main.c:1284) ==22088== by 0x4403F6: main (e_main.c:1087)
2016-03-09 11:25:16 -08:00
evas_object_event_callback_del(e_win_client_get(win->ewin)->frame,
EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_evry_cb_show);
evas_object_del(win->ewin);
free(win);
}
static void
_evry_selector_cb_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Down *ev = event_info;
Evry_Selector *sel = data;
if (ev->button == 1)
{
if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
evry_plugin_action(sel->win, 1);
}
}
static void
_evry_selector_cb_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Wheel *ev = event_info;
Evry_Selector *sel = data;
Evry_Window *win = sel->win;
if (ev->z > 0)
{
/* FIXME dont loose selector 2 state until state 0 changed: */
if (CUR_SEL != OBJ_SEL)
_evry_selectors_switch(sel->win, 1);
}
else if (ev->z < 0)
{
_evry_selectors_switch(sel->win, -1);
}
}
static void
_evry_selector_cb_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Up *ev = event_info;
Evry_Selector *sel = data;
Evry_Window *win = sel->win;
if (sel == CUR_SEL)
return;
if (ev->button == 3)
{
evry_plugin_action(win, 0);
}
else if (ev->button == 1)
{
if (sel == SUBJ_SEL)
{
if (CUR_SEL == ACTN_SEL)
_evry_selectors_switch(win, -1);
else
_evry_selectors_switch(win, 1);
}
else if (sel == ACTN_SEL)
{
if (CUR_SEL == SUBJ_SEL)
_evry_selectors_switch(win, 1);
else
_evry_selectors_switch(win, -1);
}
else if (sel == OBJ_SEL)
{
if (CUR_SEL == ACTN_SEL)
_evry_selectors_switch(win, 1);
}
}
}
static Evry_Selector *
_evry_selector_new(Evry_Window *win, int type)
{
Plugin_Config *pc;
Eina_List *l, *pcs = NULL;
Evry_Selector *sel = E_NEW(Evry_Selector, 1);
const Evas_Object *o = NULL;
sel->aggregator = evry_aggregator_new(type);
if (type == EVRY_PLUGIN_SUBJECT)
{
pcs = evry_conf->conf_subjects;
sel->edje_part = "subject_selector";
}
else if (type == EVRY_PLUGIN_ACTION)
{
pcs = evry_conf->conf_actions;
sel->edje_part = "action_selector";
}
else if (type == EVRY_PLUGIN_OBJECT)
{
pcs = evry_conf->conf_objects;
sel->edje_part = "object_selector";
}
if ((o = edje_object_part_object_get(win->o_main, sel->edje_part)))
{
sel->event_object = o;
evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_DOWN,
_evry_selector_cb_down, sel);
evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_UP,
_evry_selector_cb_up, sel);
evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_WHEEL,
_evry_selector_cb_wheel, sel);
}
EINA_LIST_FOREACH (pcs, l, pc)
{
if (!pc->plugin) continue;
if (pc->plugin == sel->aggregator) continue;
sel->plugins = eina_list_append(sel->plugins, pc->plugin);
}
2009-08-12 12:00:25 -07:00
win->selectors[type] = sel;
sel->win = win;
return sel;
}
static void
_evry_selector_free(Evry_Selector *sel)
{
Evry_Window *win = sel->win;
if (sel->event_object)
{
evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_DOWN,
_evry_selector_cb_down, sel);
evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_UP,
_evry_selector_cb_up, sel);
evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_WHEEL,
_evry_selector_cb_wheel, sel);
}
2010-05-18 18:24:26 -07:00
_evry_selector_item_clear(sel);
if (win->visible && (sel == CUR_SEL))
_evry_view_clear(sel->state);
while (sel->states)
_evry_state_pop(sel, 1);
EVRY_PLUGIN_FREE(sel->aggregator);
if (sel->plugins) eina_list_free(sel->plugins);
if (sel->update_timer)
ecore_timer_del(sel->update_timer);
if (sel->action_timer)
ecore_timer_del(sel->action_timer);
E_FREE(sel);
}
static void
_evry_selector_signal_emit(Evry_Selector *sel, const char *msg)
{
Evry_Window *win = sel->win;
char buf[128];
snprintf(buf, sizeof(buf), "%s:%s", sel->edje_part, msg);
edje_object_signal_emit(win->o_main, buf, "e");
}
static void
_evry_selector_label_set(Evry_Selector *sel, const char *part, const char *label)
{
Evry_Window *win = sel->win;
char buf[128];
snprintf(buf, sizeof(buf), "%s:%s", sel->edje_part, part);
edje_object_part_text_set(win->o_main, buf, label);
}
static void
_evry_selector_activate(Evry_Selector *sel, int slide)
{
Evry_Window *win;
Evry_State *s;
if (!sel)
{
ERR("selector == NULL");
return;
}
win = sel->win;
if (CUR_SEL)
{
Evry_Selector *cur = CUR_SEL;
_evry_selector_signal_emit(cur, "e,state,unselected");
if (cur->state && cur->state->view)
_evry_view_hide(win, cur->state->view, slide);
if (!slide && evry_conf->hide_list)
_evry_list_win_hide(win);
}
2009-08-12 12:00:25 -07:00
CUR_SEL = sel;
_evry_selector_signal_emit(sel, "e,state,selected");
/* do delayed actions fetch now */
if (sel->action_timer)
_evry_selector_update_actions_do(sel);
if ((s = sel->state))
{
_evry_update_text_label(s);
if (s->cur_item)
_evry_selector_label_set(sel, "e.text.plugin",
EVRY_ITEM(s->cur_item->plugin)->label);
if (_evry_view_create(s))
{
_evry_view_show(win, s->view, slide);
s->view->update(s->view);
}
}
}
static void
_evry_selector_thumb_gen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evas_Coord w, h;
Evry_Selector *sel = data;
Evry_Window *win = sel->win;
char buf[64];
if (sel->o_icon)
{
evas_object_del(sel->o_icon);
sel->o_icon = NULL;
}
e_icon_size_get(sel->o_thumb, &w, &h);
evas_object_size_hint_aspect_set(sel->o_thumb, EVAS_ASPECT_CONTROL_BOTH, w, h);
snprintf(buf, sizeof(buf), "%s:e.swallow.thumb", sel->edje_part);
edje_object_part_swallow(win->o_main, buf, sel->o_thumb);
evas_object_show(sel->o_thumb);
_evry_selector_signal_emit(sel, "e,action,thumb,show");
/* edje_object_signal_emit(sel->o_main, "e,action,thumb,show", "e"); */
sel->do_thumb = EINA_FALSE;
}
static int
_evry_selector_thumb(Evry_Selector *sel, const Evry_Item *it)
{
Evry_Window *win = sel->win;
char *suffix = NULL;
if (sel->do_thumb)
e_thumb_icon_end(sel->o_thumb);
if (sel->o_thumb)
evas_object_del(sel->o_thumb);
sel->o_thumb = NULL;
if (it->type != EVRY_TYPE_FILE)
return 0;
GET_FILE(file, it);
if (!file->mime)
return 0;
if (!(evry_file_path_get(file)))
return 0;
if ((!strncmp(file->mime, "image/", 6)) ||
((suffix = strrchr(file->path, '.')) && (!strncmp(suffix, ".edj", 4))))
{
sel->o_thumb = e_thumb_icon_add(win->evas);
e_thumb_icon_size_set(sel->o_thumb, 128, 128);
evas_object_smart_callback_add(sel->o_thumb, "e_thumb_gen",
_evry_selector_thumb_gen, sel);
if (suffix)
{
e_thumb_icon_file_set(sel->o_thumb, file->path, "e/desktop/background");
e_thumb_icon_size_set(sel->o_thumb, 128, 80);
}
else
e_thumb_icon_file_set(sel->o_thumb, file->path, NULL);
e_thumb_icon_begin(sel->o_thumb);
sel->do_thumb = EINA_TRUE;
return 1;
}
return 0;
}
static void
2010-05-18 18:24:26 -07:00
_evry_selector_item_clear(Evry_Selector *sel)
{
if (sel->o_icon)
{
evas_object_del(sel->o_icon);
sel->o_icon = NULL;
}
2010-05-18 18:24:26 -07:00
if (sel->o_thumb)
{
if (sel->do_thumb)
e_thumb_icon_end(sel->o_thumb);
2010-05-18 18:24:26 -07:00
evas_object_del(sel->o_thumb);
sel->o_thumb = NULL;
}
2010-05-18 18:24:26 -07:00
}
static void
_evry_selector_item_update(Evry_Selector *sel)
{
Evry_State *s = sel->state;
Evry_Item *it = NULL;
Evas_Object *o = NULL;
Evry_Window *win = sel->win;
2010-05-18 18:24:26 -07:00
_evry_selector_item_clear(sel);
if ((!s) || !(s->cur_item))
{
/* no items for this state - clear selector */
_evry_selector_label_set(sel, "e.text.label", "");
if (sel == CUR_SEL && s && s->plugin)
_evry_selector_label_set(sel, "e.text.plugin",
EVRY_ITEM(s->plugin)->label);
else
_evry_selector_label_set(sel, "e.text.plugin", "");
if (!s) return;
}
2010-05-18 18:24:26 -07:00
if ((it = s->cur_item))
{
_evry_selector_label_set(sel, "e.text.label", it->label);
_evry_selector_label_set(sel, "e.text.plugin",
EVRY_ITEM(it->plugin)->label);
if (!_evry_selector_thumb(sel, it))
{
o = evry_util_icon_get(it, win->evas);
if ((!o) && it->plugin)
o = evry_util_icon_get(EVRY_ITEM(it->plugin), win->evas);
}
}
if ((!o) && (s->plugin && (EVRY_ITEM(s->plugin)->icon)))
{
o = evry_icon_theme_get(EVRY_ITEM(s->plugin)->icon, win->evas);
}
if (o)
{
char buf[64];
snprintf(buf, sizeof(buf), "%s:e.swallow.icons", sel->edje_part);
edje_object_part_swallow(win->o_main, buf, o);
evas_object_show(o);
sel->o_icon = o;
}
}
static void
_evry_selector_update(Evry_Selector *sel)
{
Evry_State *s = sel->state;
Evry_Item *it = NULL;
Eina_Bool item_changed = EINA_FALSE;
Evry_Window *win = sel->win;
DBG("%p", sel);
if (!s)
{
_evry_selector_item_update(sel);
return;
}
if ((it = s->cur_item))
{
if (!s->plugin || !eina_list_data_find_list(s->plugin->items, it))
{
_evry_item_desel(s);
item_changed = EINA_TRUE;
}
}
/* get first item */
if (s->plugin && ((!s->cur_item) || s->item_auto_selected))
{
it = eina_list_data_get(s->plugin->items);
s->item_auto_selected = EINA_TRUE;
if (!s->cur_plugins || (it != s->cur_item))
item_changed = EINA_TRUE;
_evry_item_sel(s, it);
}
2009-08-12 12:00:25 -07:00
_evry_selector_item_update(sel);
2009-08-12 12:00:25 -07:00
if ((sel == SUBJ_SEL) && (item_changed))
_evry_selector_update_actions(ACTN_SEL);
}
static void
_evry_list_win_update(Evry_State *s)
{
Evry_Window *win = s->selector->win;
if (s != (CUR_SEL)->state) return;
if (!win->visible) return;
2009-08-12 12:00:25 -07:00
if (_evry_view_update(win, s))
_evry_view_show(win, s->view, 0);
}
static int
_evry_selector_plugins_get(Evry_Selector *sel, Evry_Item *it, const char *plugin_name)
{
Eina_List *l, *plugins = NULL;
Evry_Plugin *p, *pp;
Evry_Window *win = sel->win;
Evry_Action *act = NULL;
while (sel->state)
_evry_state_pop(sel, 1);
if ((sel != SUBJ_SEL) && (!it))
return 0;
if (it && CHECK_TYPE(it, EVRY_TYPE_ACTION))
act = (Evry_Action *)it;
EINA_LIST_FOREACH (sel->plugins, l, p)
{
if (!p->config->enabled && !win->plugin_dedicated)
continue;
if (plugin_name && strcmp(plugin_name, p->name))
continue;
if (act && (!CHECK_SUBTYPE(p, act->it2.type)))
continue;
if (p->begin && (pp = p->begin(p, it)))
plugins = eina_list_append(plugins, pp);
}
2009-08-12 12:00:25 -07:00
_evry_state_new(sel, plugins);
if (plugins)
_evry_matches_update(sel, 1);
return 1;
}
static Evry_State *
_evry_state_new(Evry_Selector *sel, Eina_List *plugins)
{
Evry_State *s = E_NEW(Evry_State, 1);
Eina_List *l;
Evry_Plugin *p;
if (!s) return NULL;
s->inp = calloc(1, INPUTLEN);
s->inp[0] = 0;
s->input = s->inp;
s->plugins = plugins;
s->selector = sel;
sel->states = eina_list_prepend(sel->states, s);
sel->state = s;
2009-08-12 12:00:25 -07:00
p = sel->aggregator->begin(sel->aggregator, NULL);
s->plugins = eina_list_append(s->plugins, p);
s->aggregator = p;
EINA_LIST_FOREACH (s->plugins, l, p)
p->state = s;
return s;
}
static void
_evry_state_pop(Evry_Selector *sel, int immediate)
{
Evry_Plugin *p;
Evry_State *prev;
Evry_Window *win = sel->win;
Evry_State *s = sel->state;
_evry_item_desel(s);
if (sel->update_timer)
{
ecore_timer_del(sel->update_timer);
sel->update_timer = NULL;
}
if (sel->action_timer)
{
ecore_timer_del(sel->action_timer);
sel->action_timer = NULL;
}
if (s->view)
{
if (immediate)
{
s->view->destroy(s->view);
}
else
{
_evry_view_hide(win, s->view, SLIDE_RIGHT);
/* XXX delay free state? is it possible that
view can receive events here? */
s->delete_me = EINA_TRUE;
}
}
if (s->sel_items)
eina_list_free(s->sel_items);
2011-08-24 18:27:52 -07:00
if (s->cur_plugins)
eina_list_free(s->cur_plugins);
2011-08-24 18:27:52 -07:00
sel->states = eina_list_remove_list(sel->states, sel->states);
prev = eina_list_data_get(sel->states);
EINA_LIST_FREE (s->plugins, p)
{
/* skip non top-level plugins */
if (prev && eina_list_data_find(prev->plugins, p))
{
p->state = prev;
continue;
}
EVRY_ITEM_FREE(p);
}
if (!s->delete_me)
{
if (win->state_clearing == s)
win->state_clearing = NULL;
ecore_timer_del(s->clear_timer);
E_FREE(s->inp);
E_FREE(s);
}
2009-08-12 12:00:25 -07:00
sel->state = prev;
}
int
evry_state_push(Evry_Selector *sel, Eina_List *plugins)
{
Evry_State *s, *new_state;
Eina_List *l;
Evry_Plugin *p;
Evry_View *view = NULL;
Evry_Window *win = sel->win;
s = sel->state;
if (!(new_state = _evry_state_new(sel, plugins)))
{
DBG("no new state");
return 0;
}
EINA_LIST_FOREACH (plugins, l, p)
p->state = new_state;
if (s && s->view)
{
_evry_view_hide(win, s->view, SLIDE_LEFT);
view = s->view;
}
_evry_matches_update(sel, 1);
s = new_state;
_evry_selector_update(sel);
if (view && win->visible)
{
s->view = view->create(view, s, win->o_main);
if (s->view)
{
s->view->state = s;
_evry_view_show(win, s->view, SLIDE_LEFT);
s->view->update(s->view);
}
}
_evry_update_text_label(sel->state);
return 1;
}
int
evry_browse_item(Evry_Item *it)
{
Evry_State *s, *new_state;
Evry_Selector *sel;
Eina_List *l, *plugins = NULL;
Evry_Plugin *p, *pp, *pref = NULL;
Evry_View *view = NULL;
int browse_aggregator = 0;
Evry_Window *win;
if (!(it) || !(it->plugin) || !(it->browseable))
{
DBG("no item");
return 0;
}
if (!(s = it->plugin->state))
{
DBG("no state");
return 0;
}
2009-08-12 12:00:25 -07:00
sel = s->selector;
win = sel->win;
/* aggregator */
if (CHECK_TYPE(it, EVRY_TYPE_PLUGIN))
{
browse_aggregator = 1;
plugins = eina_list_append(plugins, it);
}
else
{
if ((it->plugin->browse) && (pp = it->plugin->browse(it->plugin, it)))
{
plugins = eina_list_append(plugins, pp);
pref = pp;
}
2009-08-12 12:00:25 -07:00
/* items of type NONE can only be browsed by their own plugin */
if (!CHECK_TYPE(it, EVRY_TYPE_NONE))
{
EINA_LIST_FOREACH (sel->plugins, l, p)
{
if (!p->browse)
continue;
if ((pref) && (!strcmp(p->name, pref->name)))
continue;
if ((pp = p->browse(p, it)))
plugins = eina_list_append(plugins, pp);
}
}
}
if (!(plugins))
{
DBG("no plugins");
return 0;
}
if (!(new_state = _evry_state_new(sel, plugins)))
{
DBG("no new state");
return 0;
}
if (s->view)
{
_evry_view_hide(win, s->view, SLIDE_LEFT);
view = s->view;
}
if (browse_aggregator)
{
it->hi = NULL;
if (!EVRY_PLUGIN(it)->items)
{
evry_history_item_add(it, NULL, s->input);
s = new_state;
EVRY_PLUGIN(it)->state = s;
_evry_matches_update(sel, 1);
}
else
{
evry_history_item_add(it, NULL, NULL);
strncpy(new_state->input, s->input, INPUTLEN);
s = new_state;
EVRY_PLUGIN(it)->state = s;
s->cur_plugins = eina_list_append(s->cur_plugins, it);
}
_evry_plugin_select(s, EVRY_PLUGIN(it));
}
else
{
if (it->plugin->history)
evry_history_item_add(it, NULL, s->input);
_evry_matches_update(sel, 1);
s = new_state;
_evry_plugin_select(s, pref);
}
_evry_selector_update(sel);
if (view && win->visible)
{
s->view = view->create(view, s, win->o_main);
if (s->view)
{
s->view->state = s;
s->view->update(s->view);
_evry_view_show(win, s->view, SLIDE_LEFT);
}
}
_evry_update_text_label(sel->state);
return 1;
}
int
evry_browse_back(Evry_Selector *sel)
{
Evry_Window *win;
if (!sel) return 0;
if ((!sel) || !(win = sel->win))
return 0;
if ((!sel->state) || (!sel->states->next))
return 0;
2009-08-12 12:00:25 -07:00
_evry_state_pop(sel, 0);
_evry_selector_update(sel);
_evry_update_text_label(sel->state);
if (sel == SUBJ_SEL)
_evry_selector_update_actions(ACTN_SEL);
if (sel->state->view)
{
_evry_view_show(win, sel->state->view, SLIDE_RIGHT);
sel->state->view->update(sel->state->view);
}
return 1;
}
int
evry_selectors_switch(Evry_Window *win, int dir, int slide)
{
Evry_State *s = (CUR_SEL)->state;
2009-08-12 12:00:25 -07:00
if ((CUR_SEL)->update_timer)
{
if ((CUR_SEL == SUBJ_SEL) || (CUR_SEL == ACTN_SEL))
{
_evry_matches_update(CUR_SEL, 0);
_evry_selector_update(CUR_SEL);
}
}
if (CUR_SEL != SUBJ_SEL && dir == 0)
{
edje_object_signal_emit(win->o_main, "e,state,object_selector_hide", "e");
_evry_selector_activate(SUBJ_SEL, (slide * SLIDE_RIGHT));
return 1;
}
if (CUR_SEL == SUBJ_SEL && dir > 0)
{
if (s->cur_item)
{
_evry_selector_activate(ACTN_SEL, slide * SLIDE_LEFT);
return 1;
}
}
else if (CUR_SEL == ACTN_SEL && dir > 0)
{
Evry_Item *it;
if (!s || !(it = s->cur_item) || !(CHECK_TYPE(it, EVRY_TYPE_ACTION)))
return 0;
GET_ACTION(act, it);
if (!act->it2.type)
return 0;
_evry_selector_plugins_get(OBJ_SEL, it, NULL);
_evry_selector_update(OBJ_SEL);
edje_object_signal_emit(win->o_main, "e,state,object_selector_show", "e");
_evry_selector_activate(OBJ_SEL, (slide * SLIDE_LEFT));
return 1;
}
else if (CUR_SEL == ACTN_SEL && dir < 0)
{
_evry_selector_activate(SUBJ_SEL, (slide * SLIDE_RIGHT));
edje_object_signal_emit(win->o_main, "e,state,object_selector_hide", "e");
return 1;
}
else if (CUR_SEL == OBJ_SEL && dir < 0)
{
_evry_selector_activate(ACTN_SEL, (slide * SLIDE_RIGHT));
return 1;
}
return 0;
}
static int
_evry_selectors_switch(Evry_Window *win, int dir)
{
return evry_selectors_switch(win, dir, 0);
}
static int
_evry_input_complete(Evry_State *s)
{
int action = 0;
char *input = NULL;
Evry_Item *it = s->cur_item;
Evry_Window *win = s->selector->win;
if (!it) return 0;
evry_item_ref(it);
s->item_auto_selected = EINA_FALSE;
if (it->plugin->complete)
action = it->plugin->complete(it->plugin, it, &input);
else
evry_browse_item(it);
if (input && action == EVRY_COMPLETE_INPUT)
{
strncpy(s->input, input, INPUTLEN - 1);
_evry_update_text_label(s);
if (CUR_SEL->update_timer)
{
ecore_timer_del(CUR_SEL->update_timer);
CUR_SEL->update_timer = NULL;
}
_evry_cb_update_timer(CUR_SEL);
evry_item_select(s, it);
}
evry_item_free(it);
E_FREE(input);
return 1;
}
static int
_evry_cheat_history(Evry_State *s, int promote, int delete)
{
History_Entry *he;
History_Item *hi;
History_Types *ht;
Eina_List *l, *ll;
Evry_Item *it = s->cur_item;
if (!it) return 0;
if (!(ht = evry_history_types_get(it->type)))
return 1;
if (!(he = eina_hash_find(ht->types, (it->id ? it->id : it->label))))
return 1;
EINA_LIST_FOREACH_SAFE (he->items, l, ll, hi)
{
if (hi->plugin != it->plugin->name)
continue;
if (delete)
{
if (hi->input)
eina_stringshare_del(hi->input);
if (hi->plugin)
eina_stringshare_del(hi->plugin);
if (hi->context)
eina_stringshare_del(hi->context);
E_FREE(hi);
he->items = eina_list_remove_list(he->items, l);
}
else if (promote)
{
hi->count += 5;
hi->last_used = ecore_time_unix_get();
}
else /* demote */
{
hi->count -= 5;
if (hi->count < 0) hi->count = 1;
}
}
if (s->plugin == s->aggregator)
_evry_aggregator_fetch(s);
if (s->view)
s->view->update(s->view);
return 1;
}
static Eina_Bool
_evry_cb_key_down(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Event_Key *ev = event;
Evry_State *s;
Evry_Selector *sel;
Evry_Window *win = data;
const char *old;
if ((win->grab && (ev->event_window != ecore_evas_window_get(e_comp->ee))) &&
(ev->event_window != elm_win_window_id_get(win->ewin)))
return ECORE_CALLBACK_PASS_ON;
if (!strcmp(ev->key, "Escape"))
{
evry_hide(win, 0);
return ECORE_CALLBACK_PASS_ON;
}
#ifdef DRAG_OFF_WINDOW
else if (win->grab && !strcmp(ev->key, "F1"))
{
Evas_Object *ewin = win->ewin;
E_Client *ec;
e_grabinput_release(elm_win_window_id_get(ewin), elm_win_window_id_get(ewin));
ec = e_win_client_get(ewin);
elm_win_borderless_set(ewin, 0);
ec->override = 0;
#ifndef HAVE_WAYLAND_ONLY
2015-03-13 12:41:21 -07:00
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
ecore_x_netwm_window_type_set(elm_win_window_id_get(ewin),
ECORE_X_WINDOW_TYPE_DIALOG);
#endif
evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NORMAL);
EC_CHANGED(ec);
ec->netwm.fetch.type = 1;
ec->netwm.state.skip_taskbar = 0;
ec->netwm.update.state = 1;
ec->internal_no_remember = 1;
e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
win->grab = 0;
return ECORE_CALLBACK_PASS_ON;
}
#endif
else if ((ev->modifiers) && (!win->delay_hide_action))
{
Eina_List *l;
E_Config_Binding_Key *binding;
E_Binding_Modifier mod;
EINA_LIST_FOREACH(e_bindings->key_bindings, l, binding)
{
if (binding->action && strcmp(binding->action, "everything")) continue;
mod = 0;
if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
mod |= E_BINDING_MODIFIER_SHIFT;
if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
mod |= E_BINDING_MODIFIER_CTRL;
if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
mod |= E_BINDING_MODIFIER_ALT;
if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
mod |= E_BINDING_MODIFIER_WIN;
if (!(binding->key && (!strcmp(binding->key, ev->key)) &&
(((unsigned int)binding->modifiers == mod) || (binding->any_mod))))
continue;
if (win->level > 0)
return ECORE_CALLBACK_PASS_ON;
if (!(binding->params) && (CUR_SEL == OBJ_SEL) &&
((CUR_SEL)->state && (CUR_SEL)->state->cur_item))
{
_evry_selectors_shift(win, 1);
return ECORE_CALLBACK_PASS_ON;
}
evry_hide(win, 1);
#if 0 /* FIXME this causes segv when triggering a plugin keybinding twice */
if (win && CUR_SEL && binding->params)
{
Eina_List *ll;
Evry_Plugin *p;
EINA_LIST_FOREACH ((SUBJ_SEL)->plugins, ll, p)
if (!strcmp(binding->params, p->name)) break;
if (p)
{
_evry_plugin_select((CUR_SEL)->state, p);
_evry_selector_update(CUR_SEL);
_evry_view_update(win, (CUR_SEL)->state);
}
}
#endif
return ECORE_CALLBACK_PASS_ON;
}
}
old = ev->key;
win->request_selection = EINA_FALSE;
if (!strcmp(ev->key, "KP_Enter"))
{
ev->key = "Return";
}
else if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
{
if (!strcmp(ev->key, "Tab"))
{
ev->key = "Down";
}
else if (!strcmp(ev->key, "ISO_Left_Tab") || (!strcmp(ev->key, "Tab") &&
(ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)))
{
ev->key = "Up";
ev->modifiers = 0;
}
else if (!strcmp(ev->key, "q"))
{
evry_hide(win, 0);
return 1;
}
else if (!strcmp(ev->key, "w"))
{
ev->key = "Return";
ev->modifiers = 0;
}
else if (evry_conf->quick_nav == 1)
{
if (!strcmp(ev->key, "k") || (!strcmp(ev->key, "K")))
ev->key = "Up";
else if (!strcmp(ev->key, "j") || (!strcmp(ev->key, "J")))
ev->key = "Down";
else if (!strcmp(ev->key, "n") || (!strcmp(ev->key, "N")))
ev->key = "Next";
else if (!strcmp(ev->key, "p") || (!strcmp(ev->key, "P")))
ev->key = "Prior";
else if (!strcmp(ev->key, "l") || (!strcmp(ev->key, "L")))
ev->key = "Right";
else if (!strcmp(ev->key, "h") || (!strcmp(ev->key, "H")))
ev->key = "Left";
else if (!strcmp(ev->key, "i") || (!strcmp(ev->key, "I")))
ev->key = "Tab";
else if (!strcmp(ev->key, "m") || (!strcmp(ev->key, "M")))
ev->key = "Return";
}
else if (evry_conf->quick_nav == 3)
{
if (!strcmp(ev->key, "p") || (!strcmp(ev->key, "P")))
ev->key = "Up";
else if (!strcmp(ev->key, "n") || (!strcmp(ev->key, "N")))
ev->key = "Down";
else if (!strcmp(ev->key, "f") || (!strcmp(ev->key, "F")))
ev->key = "Right";
else if (!strcmp(ev->key, "b") || (!strcmp(ev->key, "B")))
ev->key = "Left";
else if (!strcmp(ev->key, "i") || (!strcmp(ev->key, "I")))
ev->key = "Tab";
else if (!strcmp(ev->key, "m") || (!strcmp(ev->key, "M")))
ev->key = "Return";
}
}
if (!(sel = CUR_SEL))
goto end;
if (!strcmp(ev->key, "Tab") &&
!((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) ||
(ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)))
{
if (!_evry_selectors_switch(win, 1))
_evry_selectors_switch(win, 0);
goto end;
}
if (!(s = sel->state))
goto end;
if (!win->visible && (!strcmp(ev->key, "Down")))
{
_evry_list_win_show(win);
goto end;
}
else if ((!strcmp(ev->key, "ISO_Left_Tab") ||
(((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) ||
(ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)) &&
(!strcmp(ev->key, "Tab")))))
{
_evry_input_complete(s);
goto end;
}
else if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
(!strcmp(ev->key, "Delete") || !strcmp(ev->key, "Insert")))
{
int delete = (!strcmp(ev->key, "Delete") &&
(ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT));
int promote = (!strcmp(ev->key, "Insert"));
_evry_cheat_history(s, promote, delete);
goto end;
}
else if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
{
if (!strcmp(ev->key, "u"))
{
if (!_evry_clear(sel))
evry_browse_back(sel);
goto end;
}
else if (!strcmp(ev->key, "1"))
evry_view_toggle(s, NULL);
else if (!strcmp(ev->key, "Return"))
_evry_plugin_action(sel, 0);
else if (!strcmp(ev->key, "v"))
{
#ifndef HAVE_WAYLAND_ONLY
2015-01-22 12:05:58 -08:00
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
{
win->request_selection = EINA_TRUE;
ecore_x_selection_primary_request
(elm_win_window_id_get(win->ewin), ECORE_X_SELECTION_TARGET_UTF8_STRING);
}
#endif
}
else
{
_evry_view_key_press(s, ev);
}
goto end;
}
if ((s->plugin && s->plugin->cb_key_down) &&
(s->plugin->cb_key_down(s->plugin, ev)))
{
/* let plugin intercept keypress */
goto end;
}
else if (_evry_view_key_press(s, ev))
{
/* let view intercept keypress */
goto end;
}
else if (!strcmp(ev->key, "Right"))
{
if (!evry_browse_item(sel->state->cur_item))
evry_selectors_switch(win, 1, EINA_TRUE);
}
else if (!strcmp(ev->key, "Left"))
{
if (!evry_browse_back(sel))
evry_selectors_switch(win, -1, EINA_TRUE);
}
else if (!strcmp(ev->key, "Return"))
{
if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
{
_evry_plugin_action(sel, 0);
}
else if (s->cur_item && s->cur_item->browseable)
{
evry_browse_item(sel->state->cur_item);
}
else
{
_evry_plugin_action(sel, 1);
}
}
else if (!strcmp(ev->key, "BackSpace"))
{
if (!_evry_backspace(sel))
evry_browse_back(sel);
}
else if ((ev->compose && !(ev->modifiers & ECORE_EVENT_MODIFIER_ALT)))
{
unsigned int len = strlen(s->inp);
if (len == 0 && (evry_view_toggle(s, ev->compose)))
goto end;
if (len < (INPUTLEN - strlen(ev->compose)))
{
strcat(s->inp, ev->compose);
_evry_update(sel, 1);
}
}
end:
ev->key = old;
return ECORE_CALLBACK_PASS_ON;
}
static int
_evry_backspace(Evry_Selector *sel)
{
Evry_State *s = sel->state;
int len, val, pos;
if (!(len = strlen(s->inp)))
return 0;
pos = evas_string_char_prev_get(s->inp, len, &val);
if ((pos < len) && (pos >= 0))
{
val = *(s->inp + pos);
s->inp[pos] = 0;
if (s->trigger_active && s->inp[0] != 0)
s->input = s->inp + 1;
else
s->input = s->inp;
if (pos == 0)
s->trigger_active = EINA_FALSE;
if ((pos == 0) || !isspace(val))
_evry_update(sel, 1);
return 1;
}
return 0;
}
static void
_evry_update_text_label(Evry_State *s)
{
Evry_Window *win = s->selector->win;
if (!win->visible && evry_conf->hide_input)
{
if (strlen(s->inp) > 0)
edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
else
edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
}
edje_object_part_text_set(win->o_main, "list:e.text.label", s->inp);
}
static void
_evry_update(Evry_Selector *sel, int fetch)
{
Evry_State *s = sel->state;
Evry_Window *win = sel->win;
_evry_update_text_label(s);
2009-08-12 12:00:25 -07:00
if (fetch)
{
if (sel->update_timer)
ecore_timer_del(sel->update_timer);
sel->update_timer =
ecore_timer_loop_add(MATCH_LAG, _evry_cb_update_timer, sel);
edje_object_signal_emit(win->o_main, "list:e,signal,update", "e");
}
}
static Eina_Bool
_evry_cb_update_timer(void *data)
{
Evry_Selector *sel = data;
_evry_matches_update(sel, 1);
_evry_selector_update(sel);
_evry_list_win_update(sel->state);
sel->update_timer = NULL;
return ECORE_CALLBACK_CANCEL;
}
static int
_evry_clear(Evry_Selector *sel)
{
Evry_State *s = sel->state;
Evry_Window *win = sel->win;
if (!(s->inp) || (s->inp[0] == 0))
return 0;
if (s->trigger_active && s->inp[1] != 0)
{
s->inp[1] = 0;
s->input = s->inp + 1;
}
else
{
s->inp[0] = 0;
s->input = s->inp;
s->trigger_active = EINA_FALSE;
}
_evry_update(sel, 1);
if (!win->visible && evry_conf->hide_input)
edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
return 1;
}
static void
_evry_cb_free_action_performed(void *data EINA_UNUSED, void *event)
{
Evry_Event_Action_Performed *ev = event;
if (ev->it1)
EVRY_ITEM_FREE(ev->it1);
if (ev->it2)
EVRY_ITEM_FREE(ev->it2);
IF_RELEASE(ev->action);
E_FREE(ev);
}
static int
_evry_action_do(Evry_Action *act)
{
Evry_Event_Action_Performed *ev;
int ret;
if ((ret = act->action(act)))
{
ev = E_NEW(Evry_Event_Action_Performed, 1);
ev->action = eina_stringshare_ref(act->name);
ev->it1 = act->it1.item;
ev->it2 = act->it2.item;
if (ev->it1)
EVRY_ITEM_REF(ev->it1);
if (ev->it2)
EVRY_ITEM_REF(ev->it2);
ecore_event_add(_evry_events[EVRY_EVENT_ACTION_PERFORMED], ev,
_evry_cb_free_action_performed, NULL);
return ret;
}
return 0;
}
void
evry_plugin_action(Evry_Window *win, int finished)
{
_evry_plugin_action(CUR_SEL, finished);
}
static void
_evry_plugin_action(Evry_Selector *sel, int finished)
2009-08-12 12:00:25 -07:00
{
Evry_State *s_subj, *s_act, *s_obj = NULL;
Evry_Item *it, *it_subj, *it_act, *it_obj = NULL;
Evry_Window *win = sel->win;
Eina_List *l;
int ret = 0;
if ((SUBJ_SEL)->update_timer)
{
_evry_matches_update(SUBJ_SEL, 0);
_evry_selector_update(SUBJ_SEL);
}
/* do delayed fetch actions now */
if ((ACTN_SEL)->action_timer)
_evry_selector_update_actions_do(ACTN_SEL);
if (!(s_subj = (SUBJ_SEL)->state))
return;
if (!(it_subj = s_subj->cur_item))
return;
if ((CUR_SEL == SUBJ_SEL) && (ACTN_SEL)->update_timer)
{
/* _evry_selector_actions_get(it_subj); */
_evry_selector_plugins_get(ACTN_SEL, it_subj, NULL);
if (!(ACTN_SEL)->state)
return;
_evry_selector_update(ACTN_SEL);
}
if (!(s_act = (ACTN_SEL)->state))
return;
if (!(it_act = s_act->cur_item))
return;
if (CHECK_TYPE(it_act, EVRY_TYPE_ACTION) ||
CHECK_SUBTYPE(it_act, EVRY_TYPE_ACTION))
{
GET_ACTION(act, it_act);
if (!act->action)
return;
/* get object item for action, when required */
if (act->it2.type)
{
/* check if object is provided */
if ((s_obj = (OBJ_SEL)->state) && (!s_obj->delete_me))
{
it_obj = s_obj->cur_item;
}
if (!it_obj)
{
if (SUBJ_SEL == CUR_SEL)
_evry_selectors_switch(win, 1);
if (ACTN_SEL == CUR_SEL)
_evry_selectors_switch(win, 1);
return;
}
act->it2.item = it_obj;
}
if (s_obj && s_obj->sel_items && !(act->it2.accept_list))
{
if (!(act->it1.item && CHECK_TYPE(act->it1.item, EVRY_TYPE_PLUGIN)))
act->it1.item = it_subj;
EINA_LIST_FOREACH (s_obj->sel_items, l, it)
{
if (it->type != act->it2.type)
continue;
act->it2.item = it;
_evry_action_do(act);
}
}
else if (s_subj->sel_items && !(act->it1.accept_list))
{
EINA_LIST_FOREACH (s_subj->sel_items, l, it)
{
if (it->type != act->it1.type)
continue;
act->it1.item = it;
_evry_action_do(act);
}
}
else
{
if (!(act->it1.item && CHECK_TYPE(act->it1.item, EVRY_TYPE_PLUGIN)))
{
act->it1.item = it_subj;
act->it1.items = s_subj->sel_items;
}
if (s_obj)
act->it2.items = s_obj->sel_items;
ret = _evry_action_do(act);
if (ret == EVRY_ACTION_OTHER)
return;
}
}
else return;
if (s_subj && it_subj && it_subj->plugin->history)
evry_history_item_add(it_subj, NULL, s_subj->input);
if (s_act && it_act && it_act->plugin->history)
evry_history_item_add(it_act, it_subj->context, s_act->input);
if (s_obj && it_obj && it_obj->plugin->history)
evry_history_item_add(it_obj, it_act->context, s_obj->input);
if (ret == EVRY_ACTION_CONTINUE)
return;
if (ret == EVRY_ACTION_CLEAR)
{
_evry_clear(CUR_SEL);
}
else
{
win->func.hide(win, finished);
}
}
static void
_evry_view_list_swallow_set(Evas_Object *obj, const char *part, Evas_Object *swallow)
{
Evas_Object *o;
o = edje_object_part_swallow_get(obj, part);
if (o != swallow)
{
evas_object_hide(o);
edje_object_part_unswallow(obj, o);
edje_object_part_unswallow(obj, swallow);
edje_object_part_swallow(obj, part, swallow);
evas_object_show(swallow);
}
}
static void
_evry_view_show(Evry_Window *win, Evry_View *v, int slide)
{
if (!v) return;
if (v->o_bar)
{
edje_object_part_swallow(win->o_main, "list:e.swallow.bar", v->o_bar);
evas_object_show(v->o_bar);
}
if (!v->o_list)
return;
if (slide == SLIDE_LEFT)
{
_evry_view_list_swallow_set(win->o_main, "list:e.swallow.list2", v->o_list);
edje_object_signal_emit(win->o_main, "list:e,action,slide,left", "e");
edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
}
else if (slide == SLIDE_RIGHT)
{
_evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
edje_object_signal_emit(win->o_main, "list:e,action,slide,right", "e");
edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
}
else
{
_evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
edje_object_signal_emit(win->o_main, "list:e,action,slide,default", "e");
edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
}
}
static Eina_Bool
_clear_timer(void *data)
{
_evry_state_clear(data);
return ECORE_CALLBACK_CANCEL;
}
static void
_evry_state_clear(Evry_Window *win)
{
Evry_State *s;
Evry_View *v;
if (!win->state_clearing)
return;
s = win->state_clearing;
win->state_clearing = NULL;
ecore_timer_del(s->clear_timer);
s->clear_timer = NULL;
if (s->delete_me)
{
if (s->view) s->view->destroy(s->view);
s->clear_timer = NULL;
E_FREE(s->inp);
E_FREE(s);
}
else if ((v = s->view))
{
v->clear(v);
if (v->o_list)
{
evas_object_hide(v->o_list);
edje_object_part_unswallow(win->o_main, v->o_list);
}
}
/* replay mouse down to allow direct sliding back */
if (win->mouse_button)
evas_event_feed_mouse_down(win->evas, win->mouse_button, 0, 0, NULL);
}
static void
_evry_view_hide(Evry_Window *win, Evry_View *v, int slide)
{
_evry_state_clear(win);
if (!v || v->state->delete_me) return;
if (slide && v->o_list)
{
win->state_clearing = v->state;
if (slide == SLIDE_RIGHT)
{
_evry_view_list_swallow_set(win->o_main, "list:e.swallow.list2", v->o_list);
}
else /* if (slide == SLIDE_LEFT) */
{
_evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
}
edje_object_signal_emit(v->o_list, "e,action,hide,list", "e");
/* FIXME get signal from theme when anim finished */
v->state->clear_timer = ecore_timer_loop_add(1.5, _clear_timer, win);
if (v->o_bar)
{
evas_object_hide(v->o_bar);
edje_object_part_unswallow(win->o_main, v->o_bar);
}
return;
}
v->clear(v);
if (v->o_list)
{
evas_object_hide(v->o_list);
edje_object_part_unswallow(win->o_main, v->o_list);
}
if (v->o_bar)
{
evas_object_hide(v->o_bar);
edje_object_part_unswallow(win->o_main, v->o_bar);
}
}
static int
_evry_view_create(Evry_State *s)
{
Evry_View *view;
2009-08-12 12:00:25 -07:00
if (s->view)
return 1;
if (s->plugin && s->plugin->view)
view = s->plugin->view;
else
view = eina_list_data_get(evry_conf->views);
s->view = view->create(view, s, s->selector->win->o_main);
if (s->view)
{
s->view->state = s;
return 1;
}
return 0;
}
static int
_evry_view_update(Evry_Window *win, Evry_State *s)
{
if (!win->visible) return 0;
/* TODO check this again !!!!*/
if (s->view)
{
s->view->update(s->view);
return 0;
}
if (_evry_view_create(s))
{
s->view->update(s->view);
return 1;
}
return 0;
}
static void
_evry_view_clear(Evry_State *s)
{
if (!s || !s->view) return;
s->view->clear(s->view);
}
static int
_evry_view_key_press(Evry_State *s, Ecore_Event_Key *ev)
{
if (!s || !s->view || !s->view->cb_key_down) return 0;
return s->view->cb_key_down(s->view, ev);
}
int
evry_view_toggle(Evry_State *s, const char *trigger)
{
Evry_View *view, *v = NULL;
Eina_List *l, *ll;
Eina_Bool triggered = EINA_FALSE;
Evry_Window *win = s->selector->win;
if (trigger)
{
EINA_LIST_FOREACH (evry_conf->views, ll, view)
{
if (view->trigger && !strncmp(trigger, view->trigger, 1) &&
(!s->view || (view->id != s->view->id)) &&
(v = view->create(view, s, win->o_main)))
{
triggered = EINA_TRUE;
goto found;
}
}
}
else
{
if (s->view)
l = eina_list_data_find_list(evry_conf->views, s->view->id);
else
{
view = evry_conf->views->data;
v = view->create(view, s, win->o_main);
goto found;
}
if (l && l->next)
l = l->next;
else
l = evry_conf->views;
EINA_LIST_FOREACH (l, ll, view)
{
if ((!view->trigger) &&
((!s->view || (view->id != s->view->id)) &&
(v = view->create(view, s, win->o_main))))
goto found;
}
}
found:
if (!v) return 0;
_evry_list_win_show(win);
if (s->view)
{
_evry_view_hide(win, s->view, 0);
s->view->destroy(s->view);
}
s->view = v;
s->view->state = s;
_evry_view_show(win, s->view, 0);
view->update(s->view);
return triggered;
}
static void
_evry_matches_update(Evry_Selector *sel, int async)
{
Evry_State *s = sel->state;
Evry_Plugin *p;
Eina_List *l;
Evry_Item *it;
Evry_Window *win = sel->win;
const char *input = NULL;
2011-11-14 13:07:29 -08:00
size_t len_inp = 0;
s->changed = 1;
s->request++;
#ifdef CHECK_TIME
DBG("matches update %f", ecore_time_get() - _evry_time);
#endif
if (sel->update_timer)
{
ecore_timer_del(sel->update_timer);
sel->update_timer = NULL;
}
if (s->sel_items)
{
eina_list_free(s->sel_items);
s->sel_items = NULL;
}
if (s->inp[0])
{
len_inp = strlen(s->inp);
input = s->inp;
}
/* use current plugins */
if (s->trigger_active)
{
s->plugin_auto_selected = EINA_FALSE;
EINA_LIST_FOREACH (s->cur_plugins, l, p)
{
p->request = s->request;
p->fetch(p, s->input);
}
goto found;
}
EINA_LIST_FREE (s->cur_plugins, p) ;
/* check if input matches plugin trigger */
if (input)
{
size_t len_trigger = 0;
EINA_LIST_FOREACH (s->plugins, l, p)
{
size_t len;
if (!p->config->trigger) continue;
len = strlen(p->config->trigger);
if (len_trigger && len != len_trigger)
continue;
if ((len_inp >= len) &&
(!strncmp(s->inp, p->config->trigger, len)))
{
len_trigger = len;
s->cur_plugins = eina_list_append(s->cur_plugins, p);
p->request = s->request;
if (len_inp == len)
p->fetch(p, NULL);
else
p->fetch(p, s->input + len);
}
}
if (s->cur_plugins)
{
s->trigger_active = EINA_TRUE;
/* replace trigger with indicator */
if (len_trigger > 1)
{
s->inp[0] = ':';
if (s->inp[len_trigger])
strcpy(s->inp + 1, s->inp + len_trigger);
else
s->inp[1] = 0;
}
s->input = s->inp + 1;
_evry_update_text_label(s);
goto found;
}
}
/* query all other plugins for this state */
EINA_LIST_FOREACH (s->plugins, l, p)
{
p->request = s->request;
if (p == s->aggregator)
goto next;
/* dont wait for async plugin. use their current items */
if (!async && p->async_fetch && p->items)
{
s->cur_plugins = eina_list_append(s->cur_plugins, p);
goto next;
}
if (!((sel->states->next) ||
((CUR_SEL == SUBJ_SEL) &&
(win->plugin_dedicated))))
{
/* skip plugins in toplevel which trigger-only */
if ((sel == SUBJ_SEL) &&
(p->config->top_level) &&
(p->config->trigger_only))
goto next;
/* skip non-toplevel plugins when input < min_query */
if ((!p->config->top_level) &&
((size_t) p->config->min_query > len_inp))
goto next;
}
if (p->fetch(p, input))
{
#ifdef CHECK_TIME
DBG("fetch %s %f", p->name, ecore_time_get() - _evry_time);
#endif
s->cur_plugins = eina_list_append(s->cur_plugins, p);
continue;
}
next:
if (s->plugin == p)
s->plugin = NULL;
}
found:
_evry_aggregator_fetch(s);
if (s->plugin_auto_selected)
s->plugin = NULL;
_evry_plugin_select(s, s->plugin);
if (!s->plugin)
return;
EINA_LIST_FOREACH (s->plugin->items, l, it)
if (it->marked)
s->sel_items = eina_list_append(s->sel_items, it);
}
static void
_evry_item_desel(Evry_State *s)
{
Evry_Item *it = s->cur_item;
if (it)
{
it->selected = EINA_FALSE;
evry_item_free(it);
}
s->cur_item = NULL;
}
static void
_evry_item_sel(Evry_State *s, Evry_Item *it)
{
if (s->cur_item == it) return;
_evry_item_desel(s);
evry_item_ref(it);
it->selected = EINA_TRUE;
s->cur_item = it;
}
static void
_evry_plugin_select(Evry_State *s, Evry_Plugin *p)
{
if (!s) return;
if (p)
{
s->plugin_auto_selected = EINA_FALSE;
}
else
{
p = eina_list_data_get(s->cur_plugins);
s->plugin_auto_selected = EINA_TRUE;
}
s->plugin = p;
if ((s->view && s->plugin && s->plugin->view) &&
(s->view->name != s->plugin->view->name))
{
s->view->destroy(s->view);
s->view = NULL;
if (_evry_view_create(s))
{
_evry_view_show(s->selector->win, s->view, 0);
s->view->update(s->view);
}
}
}
static void
_evry_cb_free_plugin_selected(void *data EINA_UNUSED, void *event)
{
Evry_Event_Item_Selected *ev = event;
evry_item_free(ev->item);
E_FREE(ev);
}
void
evry_plugin_select(Evry_Plugin *p)
{
Evry_Event_Item_Selected *ev;
if (!p) return;
if (!p->state)
{
ERR("no state!");
return;
}
_evry_plugin_select(p->state, p);
_evry_selector_update(p->state->selector);
ev = E_NEW(Evry_Event_Item_Selected, 1);
ev->item = EVRY_ITEM(p);
EVRY_ITEM_REF(p);
ecore_event_add(_evry_events[EVRY_EVENT_PLUGIN_SELECTED], ev,
_evry_cb_free_plugin_selected, NULL);
}
static void
_evry_plugin_list_insert(Evry_State *s, Evry_Plugin *p)
{
Eina_List *l;
Evry_Plugin *p2;
EINA_LIST_FOREACH (s->cur_plugins, l, p2)
{
if (p == p2)
return;
if (p->config->priority < p2->config->priority)
break;
}
if (l)
s->cur_plugins = eina_list_prepend_relative_list(s->cur_plugins, p, l);
else
s->cur_plugins = eina_list_append(s->cur_plugins, p);
}
static void
_evry_cb_show(Evry_Window *win, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (win->grab)
e_grabinput_get(elm_win_window_id_get(win->ewin), 0, elm_win_window_id_get(win->ewin));
}
#ifndef HAVE_WAYLAND_ONLY
static Eina_Bool
_evry_cb_selection_notify(void *data, int type EINA_UNUSED, void *event)
{
Ecore_X_Event_Selection_Notify *ev;
Evry_Window *win = data;
Evry_State *s = (CUR_SEL)->state;
if (!s || (data != win)) return ECORE_CALLBACK_PASS_ON;
if (!win->request_selection) return ECORE_CALLBACK_PASS_ON;
win->request_selection = EINA_FALSE;
ev = event;
if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
(ev->selection == ECORE_X_SELECTION_PRIMARY))
{
if (strcmp(ev->target, ECORE_X_SELECTION_TARGET_UTF8_STRING) == 0)
{
Ecore_X_Selection_Data_Text *text_data;
text_data = ev->data;
strncat(s->input, text_data->text, (INPUTLEN - strlen(s->input)) - 1);
_evry_update(CUR_SEL, 1);
}
}
return ECORE_CALLBACK_PASS_ON;
}
#endif
void
evry_item_app_free(Evry_Item_App *app)
{
efreet_desktop_free(app->desktop);
eina_stringshare_del(app->file);
free(app);
}
void
evry_item_file_free(Evry_Item_File *file)
{
eina_stringshare_del(file->url);
eina_stringshare_del(file->path);
eina_stringshare_del(file->mime);
free(file);
}