1 #include "e.h"
2 #include "e_mod_main.h"
3 
4 /* TODO
5  * - keybinding configuration
6  */
7 
8 #define DRAG_OFF_WINDOW
9 
10 #define INPUTLEN          256
11 #define MATCH_LAG         0.15
12 #define INITIAL_MATCH_LAG 0.3
13 
14 #if defined (CHECK_TIME) || defined (CHECK_REFS)
15 #undef DBG
16 #define DBG(...) ERR(__VA_ARGS__)
17 #else
18 #undef DBG
19 #define DBG(...)
20 #endif
21 
22 static Eina_Bool     _evry_cb_desklock(Evry_Window *win, int type EINA_UNUSED, E_Event_Desklock *ev);
23 static void           _evry_matches_update(Evry_Selector *sel, int async);
24 static void           _evry_plugin_action(Evry_Selector *sel, int finished);
25 static void           _evry_plugin_select(Evry_State *s, Evry_Plugin *p);
26 static void           _evry_plugin_list_insert(Evry_State *s, Evry_Plugin *p);
27 static int            _evry_backspace(Evry_Selector *sel);
28 static void           _evry_update(Evry_Selector *sel, int fetch);
29 static void           _evry_update_text_label(Evry_State *s);
30 static int            _evry_clear(Evry_Selector *sel);
31 static Eina_Bool      _evry_cb_update_timer(void *data);
32 
33 static Evry_State    *_evry_state_new(Evry_Selector *sel, Eina_List *plugins);
34 static void           _evry_state_pop(Evry_Selector *sel, int immediate);
35 static void           _evry_state_clear(Evry_Window *win);
36 static void           _evry_hide_func(Evry_Window *win, int finished);
37 
38 static Evry_Selector *_evry_selector_new(Evry_Window *win, int type);
39 static void           _evry_selector_free(Evry_Selector *sel);
40 static void           _evry_selector_activate(Evry_Selector *sel, int slide);
41 static void           _evry_selector_update(Evry_Selector *sel);
42 static int            _evry_selector_plugins_get(Evry_Selector *sel, Evry_Item *it, const char *plugin_name);
43 static void           _evry_selector_update_actions(Evry_Selector *sel);
44 static void           _evry_selector_item_update(Evry_Selector *sel);
45 static void           _evry_selector_item_clear(Evry_Selector *sel);
46 static void           _evry_selector_label_set(Evry_Selector *sel, const char *part, const char *label);
47 static void           _evry_selector_signal_emit(Evry_Selector *sel, const char *msg);
48 static int            _evry_selectors_shift(Evry_Window *win, int dir);
49 static int            _evry_selectors_switch(Evry_Window *win, int dir);
50 
51 static Evry_Window   *_evry_window_new(E_Zone *zone, E_Zone_Edge edge);
52 static void           _evry_cb_win_delete(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
53 static void           _evry_window_free(Evry_Window *win);
54 static void           _evry_list_win_show(Evry_Window *win);
55 static void           _evry_list_win_hide(Evry_Window *win);
56 static void           _evry_list_win_update(Evry_State *s);
57 
58 static int            _evry_view_create(Evry_State *s);
59 static void           _evry_view_clear(Evry_State *s);
60 static int            _evry_view_update(Evry_Window *win, Evry_State *s);
61 static int            _evry_view_key_press(Evry_State *s, Ecore_Event_Key *ev);
62 static void           _evry_view_show(Evry_Window *win, Evry_View *v, int slide);
63 static void           _evry_view_hide(Evry_Window *win, Evry_View *v, int slide);
64 
65 static void           _evry_item_desel(Evry_State *s);
66 static void           _evry_item_sel(Evry_State *s, Evry_Item *it);
67 
68 static void           _evry_cb_show(Evry_Window *win, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
69 static Eina_Bool      _evry_cb_key_down(void *data, int type, void *event);
70 static Eina_Bool      _evry_cb_selection_notify(void *data, int type, void *event);
71 static Eina_Bool      _evry_cb_mouse(void *data, int type, void *event);
72 
73 static Eina_Bool      _evry_delay_hide_timer(void *data);
74 static Eina_Bool      _evry_focus_out_timer(void *data);
75 
76 static Eina_List *windows = NULL;
77 
78 #ifdef CHECK_TIME
79 double _evry_time;
80 #endif
81 
82 #ifdef CHECK_REFS
83 static int _item_cnt = 0;
84 Eina_List *_refd = NULL;
85 #endif
86 
87 #define SUBJ_SEL win->selectors[0]
88 #define ACTN_SEL win->selectors[1]
89 #define OBJ_SEL  win->selectors[2]
90 #define CUR_SEL  win->selector
91 
92 int
evry_init(void)93 evry_init(void)
94 {
95    return 1;
96 }
97 
98 int
evry_shutdown(void)99 evry_shutdown(void)
100 {
101    while (windows)
102      evry_hide(windows->data, 0);
103 
104    return 1;
105 }
106 
107 static int
_evry_aggregator_fetch(Evry_State * s)108 _evry_aggregator_fetch(Evry_State *s)
109 {
110    Eina_List *l;
111 
112    if (!s)
113      {
114         ERR("no state");
115         return 0;
116      }
117 
118    if (s->aggregator->fetch(s->aggregator, s->input))
119      {
120         l = eina_list_data_find_list(s->cur_plugins, s->aggregator);
121 
122         if (!l)
123           s->cur_plugins = eina_list_prepend(s->cur_plugins, s->aggregator);
124         else
125           s->cur_plugins = eina_list_promote_list(s->cur_plugins, l);
126 
127         return 1;
128      }
129 
130    s->cur_plugins = eina_list_remove(s->cur_plugins, s->aggregator);
131 
132    return 1;
133 }
134 
135 static Eina_Bool
_evry_cb_item_changed(EINA_UNUSED void * data,EINA_UNUSED int type,void * event)136 _evry_cb_item_changed(EINA_UNUSED void *data, EINA_UNUSED int type, void *event)
137 {
138    Evry_Event_Item_Changed *ev = event;
139    Evry_Selector *sel;
140    Evry_Item *it = ev->item;
141 
142    if (!it || !it->plugin || !it->plugin->state)
143      return ECORE_CALLBACK_PASS_ON;
144 
145    sel = it->plugin->state->selector;
146 
147    if (sel->state && sel->state->cur_item == it)
148      {
149         _evry_selector_update(sel);
150      }
151 
152    return ECORE_CALLBACK_PASS_ON;
153 }
154 
155 static Eina_Bool
_evry_focus_out_timer(void * data)156 _evry_focus_out_timer(void *data)
157 {
158    Evry_Window *win = data;
159    E_Client *ec;
160 
161    win->delay_hide_action = NULL;
162 
163    ec = e_win_client_get(win->ewin);
164    if (ec && (!e_object_is_del(E_OBJECT(ec))))
165      evry_hide(win, 0);
166 
167    return ECORE_CALLBACK_CANCEL;
168 }
169 
170 static void
_evry_focus_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)171 _evry_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
172 {
173    Evry_Window *win = data;
174 
175    if (!win->grab) return;
176 
177    if (win->delay_hide_action)
178      ecore_timer_del(win->delay_hide_action);
179 
180    win->delay_hide_action = ecore_timer_loop_add(0.0, _evry_focus_out_timer, win);
181 }
182 
183 static void
_evry_focus_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)184 _evry_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
185 {
186    Evry_Window *win = data;
187 
188    if (!win->grab) return;
189 
190    E_FREE_FUNC(win->delay_hide_action, ecore_timer_del);
191 }
192 
193 Evry_Window *
evry_show(E_Zone * zone,E_Zone_Edge edge,const char * params,Eina_Bool popup)194 evry_show(E_Zone *zone, E_Zone_Edge edge, const char *params, Eina_Bool popup)
195 {
196    Evry_Window *win;
197    Evry_Selector *sel;
198 
199 #ifdef CHECK_TIME
200    _evry_time = ecore_time_get();
201    DBG("_____evry_show______");
202 #endif
203 
204    E_OBJECT_CHECK_RETURN(zone, 0);
205    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, 0);
206 
207    if (popup)
208      {
209         // only one popup please
210         Eina_List *l;
211         EINA_LIST_FOREACH(windows, l, win)
212           if (win->grab)
213             return NULL;
214      }
215 
216    if (!(win = _evry_window_new(zone, edge)))
217      return NULL;
218 
219    if (popup)
220      {
221         E_Client *ec;
222 
223         ecore_evas_name_class_set(e_win_ee_get(win->ewin), "E", "everything");
224 
225         evas_object_show(win->ewin);
226         ec = e_win_client_get(win->ewin);
227         if (ec)
228           {
229 #ifndef HAVE_WAYLAND_ONLY
230              if (e_comp->comp_type == E_PIXMAP_TYPE_X)
231                ecore_x_netwm_window_type_set(elm_win_window_id_get(win->ewin),
232                                              ECORE_X_WINDOW_TYPE_UTILITY);
233 #endif
234              ec->netwm.state.skip_taskbar = 1;
235              EC_CHANGED(ec);
236              evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_FOCUS_OUT, _evry_focus_out, win);
237              evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_FOCUS_IN, _evry_focus_in, win);
238           }
239 
240         win->grab = 1;
241      }
242 
243    evry_history_load();
244 
245    if (params)
246      win->plugin_dedicated = EINA_TRUE;
247 
248    win->sel_list = E_NEW(Evry_Selector *, 4);
249    win->sel_list[3] = NULL;
250    win->selectors = win->sel_list;
251    _evry_selector_new(win, EVRY_PLUGIN_SUBJECT);
252    _evry_selector_new(win, EVRY_PLUGIN_ACTION);
253    _evry_selector_new(win, EVRY_PLUGIN_OBJECT);
254 
255    E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_KEY_DOWN, _evry_cb_key_down, win);
256 #ifndef HAVE_WAYLAND_ONLY
257    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
258      E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_SELECTION_NOTIFY, _evry_cb_selection_notify, win);
259 #endif
260    evas_object_event_callback_add(e_win_client_get(win->ewin)->frame, EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_evry_cb_show, win);
261 
262    E_LIST_HANDLER_APPEND(win->handlers, _evry_events[EVRY_EVENT_ITEM_CHANGED], _evry_cb_item_changed, win);
263 
264    E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _evry_cb_mouse, win);
265 
266    E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _evry_cb_mouse, win);
267    E_LIST_HANDLER_APPEND(win->handlers, E_EVENT_DESKLOCK, _evry_cb_desklock, win);
268 #if 0
269    E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_MOVE, _evry_cb_mouse, win);
270 
271    E_LIST_HANDLER_APPEND(win->handlers, ECORE_EVENT_MOUSE_WHEEL, _evry_cb_mouse, win);
272 
273    E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_MOUSE_IN, _evry_cb_mouse_in, win);
274 
275    E_LIST_HANDLER_APPEND(win->handlers, ECORE_X_EVENT_MOUSE_OUT, _evry_cb_mouse_out, win);
276 #endif
277    _evry_selector_plugins_get(SUBJ_SEL, NULL, params);
278    _evry_selector_update(SUBJ_SEL);
279 
280    windows = eina_list_append(windows, win);
281 
282    _evry_selector_activate(SUBJ_SEL, 0);
283 
284    if ((!evry_conf->hide_list) || (edge))
285      {
286         sel = CUR_SEL;
287 
288         if (sel && sel->state && evry_conf->views)
289           {
290              /* if (evry_conf->first_run)
291               *   {
292               *      evry_view_toggle(sel->state, "?");
293               *      evry_conf->first_run = EINA_FALSE;
294               *   } */
295 
296              edje_object_signal_emit(win->o_main, "list:e,state,list_show", "e");
297              edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
298              win->visible = EINA_TRUE;
299           }
300      }
301 
302    win->func.hide = &_evry_hide_func;
303 
304    win->delay_hide_action = ecore_timer_loop_add(0.2, _evry_delay_hide_timer, win);
305 
306    return win;
307 }
308 
309 static Eina_Bool
_evry_delay_hide_timer(void * data)310 _evry_delay_hide_timer(void *data)
311 {
312    Evry_Window *win = data;
313    win->delay_hide_action = NULL;
314 
315    return ECORE_CALLBACK_CANCEL;
316 }
317 
318 static void
_evry_hide_func(Evry_Window * win,int finished)319 _evry_hide_func(Evry_Window *win, int finished)
320 {
321    if ((finished) && (win->grab))
322      evry_hide(win, 0);
323 }
324 
325 void
evry_hide(Evry_Window * win,int clear)326 evry_hide(Evry_Window *win, int clear)
327 {
328    Ecore_Event_Handler *ev;
329    int i;
330 
331    if (!win) return;
332 
333    evas_object_event_callback_del(win->ewin, EVAS_CALLBACK_DEL, _evry_cb_win_delete);
334    evas_object_event_callback_del(e_win_client_get(win->ewin)->frame,
335                                                    EVAS_CALLBACK_FOCUS_OUT,
336                                                    _evry_focus_out);
337    evas_object_hide(win->ewin);
338    _evry_state_clear(win);
339 
340    if ((clear && CUR_SEL) &&
341        /* pop states */
342        ((eina_list_count((SUBJ_SEL)->states) > 1) ||
343         /* move to subject selector */
344         (CUR_SEL != SUBJ_SEL) ||
345         /* clear input */
346         (((CUR_SEL)->state) && ((CUR_SEL)->state->input[0]))))
347      {
348         int slide = 0;
349         Evry_Selector *sel;
350         Evry_State *s;
351 
352         if (CUR_SEL != SUBJ_SEL)
353           {
354              if (CUR_SEL == ACTN_SEL)
355                _evry_selectors_switch(win, -1);
356              else if (CUR_SEL == OBJ_SEL)
357                _evry_selectors_switch(win, 1);
358           }
359 
360         /* just to be sure */
361         CUR_SEL = SUBJ_SEL;
362 
363         while ((CUR_SEL)->states->next)
364           {
365              slide = SLIDE_RIGHT;
366              _evry_state_pop(CUR_SEL, 1);
367           }
368 
369         sel = CUR_SEL;
370         s = sel->state;
371         _evry_clear(sel);
372         _evry_clear(sel);
373 
374         _evry_aggregator_fetch(s);
375         _evry_selector_update(sel);
376         _evry_update_text_label(s);
377         if (s->view)
378           {
379              _evry_view_show(win, s->view, slide);
380              s->view->update(s->view);
381           }
382         return;
383      }
384 
385    if (_evry_selectors_shift(win, -1))
386      return;
387 
388    win->visible = EINA_FALSE;
389 
390    if (win->sel_list)
391      {
392         for (i = 0; win->sel_list[i]; i++)
393           _evry_selector_free(win->sel_list[i]);
394      }
395 
396    E_FREE(win->sel_list);
397 
398    EINA_LIST_FREE (win->handlers, ev)
399      ecore_event_handler_del(ev);
400 
401    if (win->delay_hide_action)
402      ecore_timer_del(win->delay_hide_action);
403 
404    if (win->grab)
405      e_grabinput_release(elm_win_window_id_get(win->ewin),
406                          elm_win_window_id_get(win->ewin));
407 
408    windows = eina_list_remove(windows, win);
409 
410    _evry_window_free(win);
411 
412    evry_history_unload();
413 
414 #ifdef CHECK_REFS
415    Evry_Item *_it;
416    int _cnt = eina_list_count(_refd);
417    Eina_List *_l;
418    printf("__________________________");
419    EINA_LIST_FOREACH (_refd, _l, _it)
420      printf("%d %s\n", _it->ref, _it->label);
421    printf("sum: %d", _cnt);
422 #endif
423 }
424 
425 static int
_evry_selectors_shift(Evry_Window * win,int dir)426 _evry_selectors_shift(Evry_Window *win, int dir)
427 {
428    if ((dir > 0) && (win->level == 0))
429      {
430         void *new_sel;
431         Evry_Selector *sel;
432         Evry_State *s;
433         int i;
434 
435         for (i = 1; i < 3; i++)
436           _evry_selector_item_clear(win->selectors[i]);
437 
438         if (!(new_sel = realloc(win->sel_list, sizeof(Evry_Selector *) * 6)))
439           return 0;
440 
441         win->sel_list = new_sel;
442 
443         edje_object_signal_emit(win->o_main,
444                                 "e,state,object_selector_hide", "e");
445 
446         win->sel_list[5] = NULL;
447         win->selectors = win->sel_list + 2;
448         _evry_selector_new(win, EVRY_PLUGIN_ACTION);
449         _evry_selector_new(win, EVRY_PLUGIN_OBJECT);
450 
451         CUR_SEL = SUBJ_SEL;
452         sel = CUR_SEL;
453 
454         _evry_selector_signal_emit(sel, "e,state,selected");
455 
456         _evry_selector_item_update(SUBJ_SEL);
457         _evry_selector_item_update(ACTN_SEL);
458         _evry_selector_item_update(OBJ_SEL);
459 
460         /* was checked before. anyway */
461         if ((s = sel->state) && (s->cur_item))
462           _evry_selector_update_actions(sel);
463 
464         win->level++;
465 
466         return 1;
467      }
468    else if ((dir < 0) && (win->level > 0))
469      {
470         _evry_selector_item_clear(SUBJ_SEL);
471         _evry_selector_free(ACTN_SEL);
472         _evry_selector_free(OBJ_SEL);
473 
474         win->selectors = win->sel_list;
475         win->sel_list[3] = NULL;
476         CUR_SEL = NULL;
477 
478         edje_object_signal_emit(win->o_main,
479                                 "e,state,object_selector_show", "e");
480         _evry_selector_item_update(SUBJ_SEL);
481         _evry_selector_item_update(ACTN_SEL);
482         _evry_selector_item_update(OBJ_SEL);
483         _evry_selector_activate(OBJ_SEL, 0);
484 
485         win->level = 0;
486 
487         return 1;
488      }
489 
490    return 0;
491 }
492 
493 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))494 evry_item_new(Evry_Item *it, Evry_Plugin *p, const char *label,
495               Evas_Object *(*icon_get)(Evry_Item * it, Evas * e),
496               void (*cb_free)(Evry_Item *item))
497 {
498    if (!it)
499      {
500         it = E_NEW(Evry_Item, 1);
501         if (!it) return NULL;
502      }
503 
504    if (p && EVRY_ITEM(p)->subtype)
505      it->type = EVRY_ITEM(p)->subtype;
506 
507    it->plugin = p;
508 
509    if (label) it->label = eina_stringshare_add(label);
510    it->free = cb_free;
511    it->icon_get = icon_get;
512 
513    it->ref = 1;
514 
515 #ifdef CHECK_REFS
516    _item_cnt++;
517    _refd = eina_list_append(_refd, it);
518 #endif
519 #ifdef PRINT_REFS
520    printf("%d, %d\t new : %s\n", it->ref, _item_cnt, it->label);
521 #endif
522    return it;
523 }
524 
525 void
evry_item_free(Evry_Item * it)526 evry_item_free(Evry_Item *it)
527 {
528    if (!it) return;
529 
530    it->ref--;
531 
532 #ifdef PRINT_REFS
533    printf("%d, %d\t unref: %s\n", it->ref, _item_cnt, it->label);
534 #endif
535 
536    if (it->ref > 0) return;
537 
538 #ifdef CHECK_REFS
539    _item_cnt--;
540    _refd = eina_list_remove(_refd, it);
541 #endif
542 
543    IF_RELEASE(it->label);
544    IF_RELEASE(it->id);
545    IF_RELEASE(it->context);
546    IF_RELEASE(it->detail);
547    IF_RELEASE(it->icon);
548 
549    if (it->free)
550      it->free(it);
551    else
552      E_FREE(it);
553 }
554 
555 void
evry_item_ref(Evry_Item * it)556 evry_item_ref(Evry_Item *it)
557 {
558    it->ref++;
559 #ifdef PRINT_REFS
560    printf("%d, %d\t ref : %s\n", it->ref, _item_cnt, it->label);
561 #endif
562 }
563 
564 static int
_evry_selector_update_actions_do(Evry_Selector * sel)565 _evry_selector_update_actions_do(Evry_Selector *sel)
566 {
567    Evry_State *s;
568    Evry_Window *win = sel->win;
569 
570    if (sel->action_timer)
571      {
572         ecore_timer_del(sel->action_timer);
573         sel->action_timer = NULL;
574      }
575 
576    if ((s = (SUBJ_SEL)->state))
577      _evry_selector_plugins_get(sel, s->cur_item, NULL);
578 
579    _evry_selector_update(sel);
580 
581    return 1;
582 }
583 
584 static Eina_Bool
_evry_timer_cb_actions_get(void * data)585 _evry_timer_cb_actions_get(void *data)
586 {
587    Evry_Selector *sel = data;
588    Evry_Window *win = sel->win;
589    Evry_State *s;
590 
591    _evry_selector_update_actions_do(sel);
592 
593    if ((CUR_SEL == sel) && (s = sel->state))
594      {
595         if (_evry_view_update(win, s))
596           _evry_view_show(win, s->view, 0);
597      }
598 
599    return ECORE_CALLBACK_CANCEL;
600 }
601 
602 static void
_evry_selector_update_actions(Evry_Selector * sel)603 _evry_selector_update_actions(Evry_Selector *sel)
604 {
605    if (sel->action_timer)
606      ecore_timer_del(sel->action_timer);
607 
608    _evry_selector_item_clear(sel);
609    sel->action_timer = ecore_timer_loop_add(0.2, _evry_timer_cb_actions_get, sel);
610 }
611 
612 void
evry_item_select(const Evry_State * state,Evry_Item * it)613 evry_item_select(const Evry_State *state, Evry_Item *it)
614 {
615    Evry_State *s = (Evry_State *)state;
616    Evry_Selector *sel;
617    Evry_Window *win;
618 
619    if ((!s) || (s->delete_me))
620      return;
621 
622    sel = s->selector;
623    win = sel->win;
624 
625    s->plugin_auto_selected = EINA_FALSE;
626    s->item_auto_selected = EINA_FALSE;
627 
628    _evry_item_sel(s, it);
629 
630    if (s == sel->state)
631      {
632         _evry_selector_update(sel);
633 
634         if (CUR_SEL == SUBJ_SEL)
635           _evry_selector_update_actions(ACTN_SEL);
636 
637         if (CUR_SEL == ACTN_SEL)
638           {
639              while (OBJ_SEL->state)
640                _evry_state_pop(OBJ_SEL, 1);
641           }
642      }
643 }
644 
645 void
evry_item_mark(const Evry_State * state,Evry_Item * it,Eina_Bool mark)646 evry_item_mark(const Evry_State *state, Evry_Item *it, Eina_Bool mark)
647 {
648    Evry_State *s = (Evry_State *)state;
649 
650    if ((!s) || (s->delete_me))
651      return;
652 
653    if (mark && !it->marked)
654      {
655         it->marked = EINA_TRUE;
656         s->sel_items = eina_list_append(s->sel_items, it);
657      }
658    else if (it->marked)
659      {
660         it->marked = EINA_FALSE;
661         s->sel_items = eina_list_remove(s->sel_items, it);
662      }
663 }
664 
665 void
evry_plugin_update(Evry_Plugin * p,int action)666 evry_plugin_update(Evry_Plugin *p, int action)
667 {
668    Evry_State *s;
669    Evry_Selector *sel;
670    Evry_Window *win;
671 
672    if (!(s = p->state) || (s->delete_me))
673      return;
674 
675    if (!(sel = s->selector))
676      return;
677 
678    if (!(win = sel->win))
679      return;
680 
681    if (sel->state->request != p->request)
682      return;
683 
684    DBG("update %d %d %s", s->request, p->request, p->name);
685 
686    if (action == EVRY_UPDATE_ADD)
687      {
688         /* clear marked items */
689         if (s->sel_items)
690           {
691              eina_list_free(s->sel_items);
692              s->sel_items = NULL;
693           }
694 
695         if ((!p->items) && (!s->trigger_active))
696           {
697              /* remove plugin */
698              if (!(eina_list_data_find(s->cur_plugins, p)))
699                return;
700 
701              s->cur_plugins = eina_list_remove(s->cur_plugins, p);
702 
703              if (p == s->plugin)
704                _evry_plugin_select(s, NULL);
705           }
706         else
707           {
708              /* add plugin to current plugins*/
709              _evry_plugin_list_insert(s, p);
710           }
711 
712         if (sel->state == s)
713           {
714              _evry_aggregator_fetch(s);
715 
716              /* select first plugin */
717              if ((!s->plugin) || (s->plugin_auto_selected) ||
718                  !(eina_list_data_find(s->cur_plugins, s->plugin)))
719                {
720                   _evry_plugin_select(s, NULL);
721                }
722 
723              if ((s->plugin && (sel->state == s)) &&
724                  /* plugin is current */
725                  ((s->plugin == p) ||
726                   /* plugin items are shown in aggregator */
727                   ((s->plugin == s->aggregator) && p->config->aggregate)))
728                {
729                   _evry_selector_update(sel);
730 
731                   if (_evry_view_update(win, s))
732                     /* XXX when there is a case where view disappears
733                        check this one! is swallow always visible ? */
734                     _evry_view_show(win, s->view, 0);
735                }
736 
737              /* switch back to subject selector when no current items */
738              if ((sel == SUBJ_SEL) &&
739                  (!(s->plugin) || !(s->plugin->items)) &&
740                  (CUR_SEL == ACTN_SEL))
741                {
742                   _evry_selectors_switch(win, -1);
743                   _evry_clear(SUBJ_SEL);
744                }
745           }
746      }
747    else if (action == EVRY_UPDATE_REFRESH)
748      {
749         _evry_view_clear(s);
750         _evry_view_update(win, s);
751      }
752 }
753 
754 static void
_evry_list_win_show(Evry_Window * win)755 _evry_list_win_show(Evry_Window *win)
756 {
757    if (win->visible) return;
758 
759    win->visible = EINA_TRUE;
760    _evry_list_win_update((CUR_SEL)->state);
761 
762    edje_object_signal_emit(win->o_main, "list:e,state,list_show", "e");
763    edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
764 }
765 
766 static void
_evry_list_win_hide(Evry_Window * win)767 _evry_list_win_hide(Evry_Window *win)
768 {
769    Evry_Selector *sel = CUR_SEL;
770 
771    if (!win->visible)
772      return;
773 
774    if (!evry_conf->hide_list)
775      return;
776 
777    if (sel->state)
778      _evry_view_clear(sel->state);
779 
780    win->visible = EINA_FALSE;
781    edje_object_signal_emit(win->o_main, "list:e,state,list_hide", "e");
782 
783    if (evry_conf->hide_input && (!(sel->state) || (sel->state->input[0])))
784      edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
785 }
786 
787 static void
_evry_cb_win_delete(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)788 _evry_cb_win_delete(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
789 {
790    evry_hide(data, 0);
791 }
792 
793 static Evry_Window *
_evry_window_new(E_Zone * zone,E_Zone_Edge edge)794 _evry_window_new(E_Zone *zone, E_Zone_Edge edge)
795 {
796    int x, y, mw, mh, h, w;
797    Evry_Window *win;
798    Evas_Object *o;
799    const char *tmp;
800    int offset_s = 0;
801 
802    win = E_NEW(Evry_Window, 1);
803    win->ewin = elm_win_add(NULL, NULL, ELM_WIN_UTILITY);
804    elm_win_borderless_set(win->ewin, 1);
805    e_win_no_remember_set(win->ewin, 1);
806    e_win_placed_set(win->ewin, 1);
807    elm_win_override_set(win->ewin, 1);
808    win->evas = evas_object_evas_get(win->ewin);
809    win->zone = zone;
810    evas_object_data_set(win->ewin, "evry_win", win);
811 
812    o = edje_object_add(win->evas);
813    win->o_main = o;
814    elm_win_resize_object_add(win->ewin, o);
815    E_EXPAND(o);
816    E_FILL(o);
817    e_theme_edje_object_set(o, "base/theme/modules/everything",
818                            "e/modules/everything/main");
819 
820    edje_object_signal_emit(o, "e,state,composited", "e");
821    edje_object_signal_emit(o, "list:e,state,composited", "e");
822    edje_object_message_signal_process(o);
823    edje_object_calc_force(o);
824 
825    tmp = edje_object_data_get(o, "shadow_offset");
826    offset_s = tmp ? atoi(tmp) : 0;
827    edje_object_size_min_calc(o, &mw, &mh);
828 
829    if (edge == E_ZONE_EDGE_NONE)
830      {
831         w = evry_conf->width;
832         h = evry_conf->height;
833      }
834    else
835      {
836         w = evry_conf->edge_width;
837         h = evry_conf->edge_height;
838      }
839    evas_object_size_hint_min_set(win->ewin, mw, mh);
840 
841    evry_conf->min_w = mw;
842    if (w > mw) mw = w;
843 
844    evry_conf->min_h = mh;
845    if (h > mh) mh = h;
846 
847    if (edge == E_ZONE_EDGE_NONE)
848      {
849         mw += offset_s * 2;
850         mh += offset_s * 2;
851 
852         x = (zone->x + (zone->w * evry_conf->rel_x)) - (mw / 2);
853         y = (zone->y + (zone->h * evry_conf->rel_y)) - (mh / 2);
854      }
855    else
856      {
857         int to_side = 0;
858 
859         switch (edge)
860           {
861            case E_ZONE_EDGE_TOP_LEFT:
862              x = to_side - offset_s;
863              y = to_side - offset_s;
864              break;
865 
866            case E_ZONE_EDGE_TOP_RIGHT:
867              x = zone->w - (mw + offset_s + to_side);
868              y = to_side - offset_s;
869              break;
870 
871            case E_ZONE_EDGE_BOTTOM_RIGHT:
872              x = zone->w - (mw + offset_s + to_side);
873              y = zone->h - (mh + offset_s + to_side);
874              break;
875 
876            case E_ZONE_EDGE_BOTTOM_LEFT:
877              x = to_side - offset_s;
878              y = zone->h - (mh + offset_s + to_side);
879              break;
880 
881            default:
882              mw += offset_s * 2;
883              mh += offset_s * 2;
884              x = (zone->w * evry_conf->rel_x) - (mw / 2);
885              y = (zone->h * evry_conf->rel_y) - (mh / 2);
886              break;
887           }
888 
889         x += zone->x;
890         y += zone->y;
891 
892         mw += offset_s * 2;
893         mh += offset_s * 2;
894      }
895 
896    evas_object_geometry_set(win->ewin, x, y, mw, mh);
897 
898    evas_object_show(o);
899 
900    evas_event_feed_mouse_in(win->evas, 0, NULL);
901    evas_event_feed_mouse_move(win->evas, -1000000, -1000000, 0, NULL);
902 
903    evas_object_event_callback_add(win->ewin, EVAS_CALLBACK_DEL, _evry_cb_win_delete, win);
904 
905    return win;
906 }
907 
908 #if 0
909 static void
910 _evry_cb_drag_finished(E_Drag *drag, int dropped)
911 {
912    E_FREE(drag->data);
913 }
914 
915 #endif
916 
917 static Eina_Bool
_evry_cb_desklock(Evry_Window * win,int type EINA_UNUSED,E_Event_Desklock * ev)918 _evry_cb_desklock(Evry_Window *win, int type EINA_UNUSED, E_Event_Desklock *ev)
919 {
920    if (ev->on) evry_hide(win, 0);
921    return ECORE_CALLBACK_RENEW;
922 }
923 
924 static Eina_Bool
_evry_cb_mouse(void * data,int type,void * event)925 _evry_cb_mouse(void *data, int type, void *event)
926 {
927    Ecore_Event_Mouse_Button *ev;
928    Evry_Window *win = data;
929    Evas_Object *ewin;
930    int x, y, w, h;
931 
932    ev = event;
933 
934    if (!win->grab)
935      return ECORE_CALLBACK_PASS_ON;
936 
937    if ((ev->event_window != ecore_evas_window_get(e_comp->ee)) &&
938        (ev->event_window != elm_win_window_id_get(win->ewin)))
939      return ECORE_CALLBACK_PASS_ON;
940 
941    ewin = win->ewin;
942 
943 #if 0
944    if (type == ECORE_EVENT_MOUSE_MOVE)
945      {
946         Ecore_Event_Mouse_Move *ev = event;
947         Evry_State *s;
948 
949         if ((win->mouse_button == 3) &&
950             (s = (CUR_SEL)->state) && (s->cur_item) &&
951             (CHECK_TYPE(s->cur_item, EVRY_TYPE_FILE)) &&
952             (!E_INSIDE(ev->x, ev->y,
953                        win->zone->x,
954                        win->zone->y,
955                        ewin->w, ewin->h)))
956           {
957              const char *drag_types[] = { "text/uri-list" };
958              E_Drag *d;
959              Evas_Object *o;
960              const char *uri;
961              int s_len, sel_length = 0;
962              char *tmp, *sel = NULL;
963 
964              GET_FILE(file, s->cur_item);
965 
966              if (!(uri = evry_file_url_get(file)))
967                return ECORE_CALLBACK_PASS_ON;
968 
969              s_len = strlen(uri);
970              if (!(tmp = realloc(sel, sel_length + s_len + 2 + 1)))
971                return ECORE_CALLBACK_PASS_ON;
972              sel = tmp;
973              memcpy(sel + sel_length, uri, s_len);
974              memcpy(sel + sel_length + s_len, "\r\n", 2);
975              sel_length += s_len + 2;
976 
977              d = e_drag_new(e_comp),
978                             ev->x, ev->y,
979                             drag_types, 1, sel, sel_length, NULL,
980                             _evry_cb_drag_finished);
981              e_drag_resize(d, 128, 128);
982              o = evry_util_icon_get(s->cur_item, e_drag_evas_get(d));
983              e_drag_object_set(d, o);
984              e_drag_xdnd_start(d, ev->x, ev->y);
985 
986              evry_hide(win, 0);
987              return ECORE_CALLBACK_PASS_ON;
988           }
989      }
990    else if (type == ECORE_EVENT_MOUSE_WHEEL)
991      {
992         Ecore_Event_Mouse_Wheel *ev = event;
993      }
994    else
995 #endif
996    evas_object_geometry_get(ewin, &x, &y, &w, &h);
997    if (type == ECORE_EVENT_MOUSE_BUTTON_DOWN)
998      {
999         win->mouse_out = 0;
1000 
1001         if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1002           {
1003              if (ev->event_window == ecore_evas_window_get(e_comp->ee))
1004                {
1005                   if (!E_INSIDE(e_comp_canvas_x_root_adjust(ev->root.x),
1006                       e_comp_canvas_y_root_adjust(ev->root.y), x, y, w, h))
1007                     win->mouse_out = 1;
1008                }
1009           }
1010         else if (!E_INSIDE(e_comp_canvas_x_root_adjust(ev->root.x),
1011                  e_comp_canvas_y_root_adjust(ev->root.y), x, y, w, h))
1012           win->mouse_out = 1;
1013         if (win->mouse_out)
1014           return ECORE_CALLBACK_PASS_ON;
1015 
1016         win->mouse_button = ev->buttons;
1017      }
1018    else if (type == ECORE_EVENT_MOUSE_BUTTON_UP)
1019      {
1020         win->mouse_button = 0;
1021 
1022         if (win->mouse_out)
1023           {
1024              evry_hide(win, 0);
1025              return ECORE_CALLBACK_PASS_ON;
1026           }
1027      }
1028 
1029    return ECORE_CALLBACK_PASS_ON;
1030 }
1031 
1032 static void
_evry_window_free(Evry_Window * win)1033 _evry_window_free(Evry_Window *win)
1034 {
1035    evas_event_freeze(win->evas);
1036    evas_object_event_callback_del(e_win_client_get(win->ewin)->frame,
1037      EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_evry_cb_show);
1038    evas_object_del(win->ewin);
1039    free(win);
1040 }
1041 
1042 static void
_evry_selector_cb_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1043 _evry_selector_cb_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1044 {
1045    Evas_Event_Mouse_Down *ev = event_info;
1046    Evry_Selector *sel = data;
1047 
1048    if (ev->button == 1)
1049      {
1050         if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1051           evry_plugin_action(sel->win, 1);
1052      }
1053 }
1054 
1055 static void
_evry_selector_cb_wheel(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1056 _evry_selector_cb_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1057 {
1058    Evas_Event_Mouse_Wheel *ev = event_info;
1059    Evry_Selector *sel = data;
1060    Evry_Window *win = sel->win;
1061 
1062    if (ev->z > 0)
1063      {
1064         /* FIXME dont loose selector 2 state until state 0 changed: */
1065         if (CUR_SEL != OBJ_SEL)
1066           _evry_selectors_switch(sel->win, 1);
1067      }
1068    else if (ev->z < 0)
1069      {
1070         _evry_selectors_switch(sel->win, -1);
1071      }
1072 }
1073 
1074 static void
_evry_selector_cb_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1075 _evry_selector_cb_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1076 {
1077    Evas_Event_Mouse_Up *ev = event_info;
1078    Evry_Selector *sel = data;
1079    Evry_Window *win = sel->win;
1080 
1081    if (sel == CUR_SEL)
1082      return;
1083 
1084    if (ev->button == 3)
1085      {
1086         evry_plugin_action(win, 0);
1087      }
1088    else if (ev->button == 1)
1089      {
1090         if (sel == SUBJ_SEL)
1091           {
1092              if (CUR_SEL == ACTN_SEL)
1093                _evry_selectors_switch(win, -1);
1094              else
1095                _evry_selectors_switch(win, 1);
1096           }
1097         else if (sel == ACTN_SEL)
1098           {
1099              if (CUR_SEL == SUBJ_SEL)
1100                _evry_selectors_switch(win, 1);
1101              else
1102                _evry_selectors_switch(win, -1);
1103           }
1104         else if (sel == OBJ_SEL)
1105           {
1106              if (CUR_SEL == ACTN_SEL)
1107                _evry_selectors_switch(win, 1);
1108           }
1109      }
1110 }
1111 
1112 static Evry_Selector *
_evry_selector_new(Evry_Window * win,int type)1113 _evry_selector_new(Evry_Window *win, int type)
1114 {
1115    Plugin_Config *pc;
1116    Eina_List *l, *pcs = NULL;
1117    Evry_Selector *sel = E_NEW(Evry_Selector, 1);
1118    const Evas_Object *o = NULL;
1119 
1120    sel->aggregator = evry_aggregator_new(type);
1121 
1122    if (type == EVRY_PLUGIN_SUBJECT)
1123      {
1124         pcs = evry_conf->conf_subjects;
1125         sel->edje_part = "subject_selector";
1126      }
1127    else if (type == EVRY_PLUGIN_ACTION)
1128      {
1129         pcs = evry_conf->conf_actions;
1130         sel->edje_part = "action_selector";
1131      }
1132    else if (type == EVRY_PLUGIN_OBJECT)
1133      {
1134         pcs = evry_conf->conf_objects;
1135         sel->edje_part = "object_selector";
1136      }
1137 
1138    if ((o = edje_object_part_object_get(win->o_main, sel->edje_part)))
1139      {
1140         sel->event_object = o;
1141         evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_DOWN,
1142                                        _evry_selector_cb_down, sel);
1143         evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_UP,
1144                                        _evry_selector_cb_up, sel);
1145         evas_object_event_callback_add((Evas_Object*) o, EVAS_CALLBACK_MOUSE_WHEEL,
1146                                        _evry_selector_cb_wheel, sel);
1147      }
1148 
1149    EINA_LIST_FOREACH (pcs, l, pc)
1150      {
1151         if (!pc->plugin) continue;
1152         if (pc->plugin == sel->aggregator) continue;
1153         sel->plugins = eina_list_append(sel->plugins, pc->plugin);
1154      }
1155 
1156    win->selectors[type] = sel;
1157    sel->win = win;
1158 
1159    return sel;
1160 }
1161 
1162 static void
_evry_selector_free(Evry_Selector * sel)1163 _evry_selector_free(Evry_Selector *sel)
1164 {
1165    Evry_Window *win = sel->win;
1166 
1167    if (sel->event_object)
1168      {
1169         evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_DOWN,
1170                                        _evry_selector_cb_down, sel);
1171         evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_UP,
1172                                        _evry_selector_cb_up, sel);
1173         evas_object_event_callback_del_full((Evas_Object*)sel->event_object, EVAS_CALLBACK_MOUSE_WHEEL,
1174                                        _evry_selector_cb_wheel, sel);
1175      }
1176 
1177    _evry_selector_item_clear(sel);
1178 
1179    if (win->visible && (sel == CUR_SEL))
1180      _evry_view_clear(sel->state);
1181 
1182    while (sel->states)
1183      _evry_state_pop(sel, 1);
1184 
1185    EVRY_PLUGIN_FREE(sel->aggregator);
1186 
1187    if (sel->plugins) eina_list_free(sel->plugins);
1188 
1189    if (sel->update_timer)
1190      ecore_timer_del(sel->update_timer);
1191 
1192    if (sel->action_timer)
1193      ecore_timer_del(sel->action_timer);
1194 
1195    E_FREE(sel);
1196 }
1197 
1198 static void
_evry_selector_signal_emit(Evry_Selector * sel,const char * msg)1199 _evry_selector_signal_emit(Evry_Selector *sel, const char *msg)
1200 {
1201    Evry_Window *win = sel->win;
1202    char buf[128];
1203    snprintf(buf, sizeof(buf), "%s:%s", sel->edje_part, msg);
1204    edje_object_signal_emit(win->o_main, buf, "e");
1205 }
1206 
1207 static void
_evry_selector_label_set(Evry_Selector * sel,const char * part,const char * label)1208 _evry_selector_label_set(Evry_Selector *sel, const char *part, const char *label)
1209 {
1210    Evry_Window *win = sel->win;
1211    char buf[128];
1212    snprintf(buf, sizeof(buf), "%s:%s", sel->edje_part, part);
1213    edje_object_part_text_set(win->o_main, buf, label);
1214 }
1215 
1216 static void
_evry_selector_activate(Evry_Selector * sel,int slide)1217 _evry_selector_activate(Evry_Selector *sel, int slide)
1218 {
1219    Evry_Window *win;
1220    Evry_State *s;
1221 
1222    if (!sel)
1223      {
1224         ERR("selector == NULL");
1225         return;
1226      }
1227 
1228    win = sel->win;
1229 
1230    if (CUR_SEL)
1231      {
1232         Evry_Selector *cur = CUR_SEL;
1233         _evry_selector_signal_emit(cur, "e,state,unselected");
1234 
1235         if (cur->state && cur->state->view)
1236           _evry_view_hide(win, cur->state->view, slide);
1237 
1238         if (!slide && evry_conf->hide_list)
1239           _evry_list_win_hide(win);
1240      }
1241 
1242    CUR_SEL = sel;
1243 
1244    _evry_selector_signal_emit(sel, "e,state,selected");
1245 
1246    /* do delayed actions fetch now */
1247    if (sel->action_timer)
1248      _evry_selector_update_actions_do(sel);
1249 
1250    if ((s = sel->state))
1251      {
1252         _evry_update_text_label(s);
1253 
1254         if (s->cur_item)
1255           _evry_selector_label_set(sel, "e.text.plugin",
1256                                    EVRY_ITEM(s->cur_item->plugin)->label);
1257 
1258         if (_evry_view_create(s))
1259           {
1260              _evry_view_show(win, s->view, slide);
1261              s->view->update(s->view);
1262           }
1263      }
1264 }
1265 
1266 static void
_evry_selector_thumb_gen(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1267 _evry_selector_thumb_gen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1268 {
1269    Evas_Coord w, h;
1270    Evry_Selector *sel = data;
1271    Evry_Window *win = sel->win;
1272    char buf[64];
1273 
1274    if (sel->o_icon)
1275      {
1276         evas_object_del(sel->o_icon);
1277         sel->o_icon = NULL;
1278      }
1279 
1280    e_icon_size_get(sel->o_thumb, &w, &h);
1281    evas_object_size_hint_aspect_set(sel->o_thumb, EVAS_ASPECT_CONTROL_BOTH, w, h);
1282 
1283    snprintf(buf, sizeof(buf), "%s:e.swallow.thumb", sel->edje_part);
1284    edje_object_part_swallow(win->o_main, buf, sel->o_thumb);
1285 
1286    evas_object_show(sel->o_thumb);
1287    _evry_selector_signal_emit(sel, "e,action,thumb,show");
1288    /* edje_object_signal_emit(sel->o_main, "e,action,thumb,show", "e"); */
1289    sel->do_thumb = EINA_FALSE;
1290 }
1291 
1292 static int
_evry_selector_thumb(Evry_Selector * sel,const Evry_Item * it)1293 _evry_selector_thumb(Evry_Selector *sel, const Evry_Item *it)
1294 {
1295    Evry_Window *win = sel->win;
1296    char *suffix = NULL;
1297 
1298    if (sel->do_thumb)
1299      e_thumb_icon_end(sel->o_thumb);
1300 
1301    if (sel->o_thumb)
1302      evas_object_del(sel->o_thumb);
1303    sel->o_thumb = NULL;
1304 
1305    if (it->type != EVRY_TYPE_FILE)
1306      return 0;
1307 
1308    GET_FILE(file, it);
1309 
1310    if (!file->mime)
1311      return 0;
1312 
1313    if (!(evry_file_path_get(file)))
1314      return 0;
1315 
1316    if ((!strncmp(file->mime, "image/", 6)) ||
1317        ((suffix = strrchr(file->path, '.')) && (!strncmp(suffix, ".edj", 4))))
1318      {
1319         sel->o_thumb = e_thumb_icon_add(win->evas);
1320         e_thumb_icon_size_set(sel->o_thumb, 128, 128);
1321         evas_object_smart_callback_add(sel->o_thumb, "e_thumb_gen",
1322                                        _evry_selector_thumb_gen, sel);
1323         if (suffix)
1324           {
1325              e_thumb_icon_file_set(sel->o_thumb, file->path, "e/desktop/background");
1326              e_thumb_icon_size_set(sel->o_thumb, 128, 80);
1327           }
1328         else
1329           e_thumb_icon_file_set(sel->o_thumb, file->path, NULL);
1330 
1331         e_thumb_icon_begin(sel->o_thumb);
1332         sel->do_thumb = EINA_TRUE;
1333         return 1;
1334      }
1335 
1336    return 0;
1337 }
1338 
1339 static void
_evry_selector_item_clear(Evry_Selector * sel)1340 _evry_selector_item_clear(Evry_Selector *sel)
1341 {
1342    if (sel->o_icon)
1343      {
1344         evas_object_del(sel->o_icon);
1345         sel->o_icon = NULL;
1346      }
1347 
1348    if (sel->o_thumb)
1349      {
1350         if (sel->do_thumb)
1351           e_thumb_icon_end(sel->o_thumb);
1352 
1353         evas_object_del(sel->o_thumb);
1354         sel->o_thumb = NULL;
1355      }
1356 }
1357 
1358 static void
_evry_selector_item_update(Evry_Selector * sel)1359 _evry_selector_item_update(Evry_Selector *sel)
1360 {
1361    Evry_State *s = sel->state;
1362    Evry_Item *it = NULL;
1363    Evas_Object *o = NULL;
1364    Evry_Window *win = sel->win;
1365 
1366    _evry_selector_item_clear(sel);
1367 
1368    if ((!s) || !(s->cur_item))
1369      {
1370         /* no items for this state - clear selector */
1371         _evry_selector_label_set(sel, "e.text.label", "");
1372 
1373         if (sel == CUR_SEL && s && s->plugin)
1374           _evry_selector_label_set(sel, "e.text.plugin",
1375                                    EVRY_ITEM(s->plugin)->label);
1376         else
1377           _evry_selector_label_set(sel, "e.text.plugin", "");
1378 
1379         if (!s) return;
1380      }
1381 
1382    if ((it = s->cur_item))
1383      {
1384         _evry_selector_label_set(sel, "e.text.label", it->label);
1385         _evry_selector_label_set(sel, "e.text.plugin",
1386                                  EVRY_ITEM(it->plugin)->label);
1387 
1388         if (!_evry_selector_thumb(sel, it))
1389           {
1390              o = evry_util_icon_get(it, win->evas);
1391 
1392              if ((!o) && it->plugin)
1393                o = evry_util_icon_get(EVRY_ITEM(it->plugin), win->evas);
1394           }
1395      }
1396 
1397    if ((!o) && (s->plugin && (EVRY_ITEM(s->plugin)->icon)))
1398      {
1399         o = evry_icon_theme_get(EVRY_ITEM(s->plugin)->icon, win->evas);
1400      }
1401 
1402    if (o)
1403      {
1404         char buf[64];
1405         snprintf(buf, sizeof(buf), "%s:e.swallow.icons", sel->edje_part);
1406         edje_object_part_swallow(win->o_main, buf, o);
1407         evas_object_show(o);
1408         sel->o_icon = o;
1409      }
1410 }
1411 
1412 static void
_evry_selector_update(Evry_Selector * sel)1413 _evry_selector_update(Evry_Selector *sel)
1414 {
1415    Evry_State *s = sel->state;
1416    Evry_Item *it = NULL;
1417    Eina_Bool item_changed = EINA_FALSE;
1418    Evry_Window *win = sel->win;
1419 
1420    DBG("%p", sel);
1421 
1422    if (!s)
1423      {
1424         _evry_selector_item_update(sel);
1425         return;
1426      }
1427 
1428    if ((it = s->cur_item))
1429      {
1430         if (!s->plugin || !eina_list_data_find_list(s->plugin->items, it))
1431           {
1432              _evry_item_desel(s);
1433              item_changed = EINA_TRUE;
1434           }
1435      }
1436 
1437    /* get first item */
1438    if (s->plugin && ((!s->cur_item) || s->item_auto_selected))
1439      {
1440         it = eina_list_data_get(s->plugin->items);
1441         s->item_auto_selected = EINA_TRUE;
1442         if (!s->cur_plugins || (it != s->cur_item))
1443           item_changed = EINA_TRUE;
1444 
1445         _evry_item_sel(s, it);
1446      }
1447 
1448    _evry_selector_item_update(sel);
1449 
1450    if ((sel == SUBJ_SEL) && (item_changed))
1451      _evry_selector_update_actions(ACTN_SEL);
1452 }
1453 
1454 static void
_evry_list_win_update(Evry_State * s)1455 _evry_list_win_update(Evry_State *s)
1456 {
1457    Evry_Window *win = s->selector->win;
1458 
1459    if (s != (CUR_SEL)->state) return;
1460    if (!win->visible) return;
1461 
1462    if (_evry_view_update(win, s))
1463      _evry_view_show(win, s->view, 0);
1464 }
1465 
1466 static int
_evry_selector_plugins_get(Evry_Selector * sel,Evry_Item * it,const char * plugin_name)1467 _evry_selector_plugins_get(Evry_Selector *sel, Evry_Item *it, const char *plugin_name)
1468 {
1469    Eina_List *l, *plugins = NULL;
1470    Evry_Plugin *p, *pp;
1471    Evry_Window *win = sel->win;
1472    Evry_Action *act = NULL;
1473 
1474    while (sel->state)
1475      _evry_state_pop(sel, 1);
1476 
1477    if ((sel != SUBJ_SEL) && (!it))
1478      return 0;
1479 
1480    if (it && CHECK_TYPE(it, EVRY_TYPE_ACTION))
1481      act = (Evry_Action *)it;
1482 
1483    EINA_LIST_FOREACH (sel->plugins, l, p)
1484      {
1485         if (!p->config->enabled && !win->plugin_dedicated)
1486           continue;
1487 
1488         if (plugin_name && strcmp(plugin_name, p->name))
1489           continue;
1490 
1491         if (act && (!CHECK_SUBTYPE(p, act->it2.type)))
1492           continue;
1493 
1494         if (p->begin && (pp = p->begin(p, it)))
1495           plugins = eina_list_append(plugins, pp);
1496      }
1497 
1498    _evry_state_new(sel, plugins);
1499 
1500    if (plugins)
1501      _evry_matches_update(sel, 1);
1502 
1503    return 1;
1504 }
1505 
1506 static Evry_State *
_evry_state_new(Evry_Selector * sel,Eina_List * plugins)1507 _evry_state_new(Evry_Selector *sel, Eina_List *plugins)
1508 {
1509    Evry_State *s = E_NEW(Evry_State, 1);
1510    Eina_List *l;
1511    Evry_Plugin *p;
1512 
1513    if (!s) return NULL;
1514 
1515    s->inp = calloc(1, INPUTLEN);
1516    s->inp[0] = 0;
1517    s->input = s->inp;
1518    s->plugins = plugins;
1519    s->selector = sel;
1520 
1521    sel->states = eina_list_prepend(sel->states, s);
1522    sel->state = s;
1523 
1524    p = sel->aggregator->begin(sel->aggregator, NULL);
1525    s->plugins = eina_list_append(s->plugins, p);
1526    s->aggregator = p;
1527 
1528    EINA_LIST_FOREACH (s->plugins, l, p)
1529      p->state = s;
1530 
1531    return s;
1532 }
1533 
1534 static void
_evry_state_pop(Evry_Selector * sel,int immediate)1535 _evry_state_pop(Evry_Selector *sel, int immediate)
1536 {
1537    Evry_Plugin *p;
1538    Evry_State *prev;
1539    Evry_Window *win = sel->win;
1540    Evry_State *s = sel->state;
1541 
1542    _evry_item_desel(s);
1543 
1544    if (sel->update_timer)
1545      {
1546         ecore_timer_del(sel->update_timer);
1547         sel->update_timer = NULL;
1548      }
1549 
1550    if (sel->action_timer)
1551      {
1552         ecore_timer_del(sel->action_timer);
1553         sel->action_timer = NULL;
1554      }
1555 
1556    if (s->view)
1557      {
1558         if (immediate)
1559           {
1560              s->view->destroy(s->view);
1561           }
1562         else
1563           {
1564              _evry_view_hide(win, s->view, SLIDE_RIGHT);
1565              /* XXX delay free state? is it possible that
1566                 view can receive events here? */
1567              s->delete_me = EINA_TRUE;
1568           }
1569      }
1570 
1571    if (s->sel_items)
1572      eina_list_free(s->sel_items);
1573 
1574    if (s->cur_plugins)
1575      eina_list_free(s->cur_plugins);
1576 
1577    sel->states = eina_list_remove_list(sel->states, sel->states);
1578    prev = eina_list_data_get(sel->states);
1579 
1580    EINA_LIST_FREE (s->plugins, p)
1581      {
1582         /* skip non top-level plugins */
1583         if (prev && eina_list_data_find(prev->plugins, p))
1584           {
1585              p->state = prev;
1586              continue;
1587           }
1588         EVRY_ITEM_FREE(p);
1589      }
1590 
1591    if (!s->delete_me)
1592      {
1593         if (win->state_clearing == s)
1594           win->state_clearing = NULL;
1595         ecore_timer_del(s->clear_timer);
1596         E_FREE(s->inp);
1597         E_FREE(s);
1598      }
1599 
1600    sel->state = prev;
1601 }
1602 
1603 int
evry_state_push(Evry_Selector * sel,Eina_List * plugins)1604 evry_state_push(Evry_Selector *sel, Eina_List *plugins)
1605 {
1606    Evry_State *s, *new_state;
1607    Eina_List *l;
1608    Evry_Plugin *p;
1609    Evry_View *view = NULL;
1610    Evry_Window *win = sel->win;
1611 
1612    s = sel->state;
1613 
1614    if (!(new_state = _evry_state_new(sel, plugins)))
1615      {
1616         DBG("no new state");
1617         return 0;
1618      }
1619 
1620    EINA_LIST_FOREACH (plugins, l, p)
1621      p->state = new_state;
1622 
1623    if (s && s->view)
1624      {
1625         _evry_view_hide(win, s->view, SLIDE_LEFT);
1626         view = s->view;
1627      }
1628 
1629    _evry_matches_update(sel, 1);
1630    s = new_state;
1631 
1632    _evry_selector_update(sel);
1633 
1634    if (view && win->visible)
1635      {
1636         s->view = view->create(view, s, win->o_main);
1637         if (s->view)
1638           {
1639              s->view->state = s;
1640              _evry_view_show(win, s->view, SLIDE_LEFT);
1641              s->view->update(s->view);
1642           }
1643      }
1644 
1645    _evry_update_text_label(sel->state);
1646 
1647    return 1;
1648 }
1649 
1650 int
evry_browse_item(Evry_Item * it)1651 evry_browse_item(Evry_Item *it)
1652 {
1653    Evry_State *s, *new_state;
1654    Evry_Selector *sel;
1655    Eina_List *l, *plugins = NULL;
1656    Evry_Plugin *p, *pp, *pref = NULL;
1657    Evry_View *view = NULL;
1658    int browse_aggregator = 0;
1659    Evry_Window *win;
1660 
1661    if (!(it) || !(it->plugin) || !(it->browseable))
1662      {
1663         DBG("no item");
1664         return 0;
1665      }
1666 
1667    if (!(s = it->plugin->state))
1668      {
1669         DBG("no state");
1670         return 0;
1671      }
1672 
1673    sel = s->selector;
1674    win = sel->win;
1675 
1676    /* aggregator */
1677    if (CHECK_TYPE(it, EVRY_TYPE_PLUGIN))
1678      {
1679         browse_aggregator = 1;
1680         plugins = eina_list_append(plugins, it);
1681      }
1682    else
1683      {
1684         if ((it->plugin->browse) && (pp = it->plugin->browse(it->plugin, it)))
1685           {
1686              plugins = eina_list_append(plugins, pp);
1687              pref = pp;
1688           }
1689 
1690         /* items of type NONE can only be browsed by their own plugin */
1691         if (!CHECK_TYPE(it, EVRY_TYPE_NONE))
1692           {
1693              EINA_LIST_FOREACH (sel->plugins, l, p)
1694                {
1695                   if (!p->browse)
1696                     continue;
1697 
1698                   if ((pref) && (!strcmp(p->name, pref->name)))
1699                     continue;
1700 
1701                   if ((pp = p->browse(p, it)))
1702                     plugins = eina_list_append(plugins, pp);
1703                }
1704           }
1705      }
1706 
1707    if (!(plugins))
1708      {
1709         DBG("no plugins");
1710         return 0;
1711      }
1712 
1713    if (!(new_state = _evry_state_new(sel, plugins)))
1714      {
1715         DBG("no new state");
1716         return 0;
1717      }
1718 
1719    if (s->view)
1720      {
1721         _evry_view_hide(win, s->view, SLIDE_LEFT);
1722         view = s->view;
1723      }
1724 
1725    if (browse_aggregator)
1726      {
1727         it->hi = NULL;
1728 
1729         if (!EVRY_PLUGIN(it)->items)
1730           {
1731              evry_history_item_add(it, NULL, s->input);
1732              s = new_state;
1733              EVRY_PLUGIN(it)->state = s;
1734              _evry_matches_update(sel, 1);
1735           }
1736         else
1737           {
1738              evry_history_item_add(it, NULL, NULL);
1739              strncpy(new_state->input, s->input, INPUTLEN);
1740              s = new_state;
1741              EVRY_PLUGIN(it)->state = s;
1742              s->cur_plugins = eina_list_append(s->cur_plugins, it);
1743           }
1744 
1745         _evry_plugin_select(s, EVRY_PLUGIN(it));
1746      }
1747    else
1748      {
1749         if (it->plugin->history)
1750           evry_history_item_add(it, NULL, s->input);
1751 
1752         _evry_matches_update(sel, 1);
1753         s = new_state;
1754         _evry_plugin_select(s, pref);
1755      }
1756 
1757    _evry_selector_update(sel);
1758 
1759    if (view && win->visible)
1760      {
1761         s->view = view->create(view, s, win->o_main);
1762         if (s->view)
1763           {
1764              s->view->state = s;
1765              s->view->update(s->view);
1766              _evry_view_show(win, s->view, SLIDE_LEFT);
1767           }
1768      }
1769 
1770    _evry_update_text_label(sel->state);
1771 
1772    return 1;
1773 }
1774 
1775 int
evry_browse_back(Evry_Selector * sel)1776 evry_browse_back(Evry_Selector *sel)
1777 {
1778    Evry_Window *win;
1779 
1780    if (!sel) return 0;
1781 
1782    if ((!sel) || !(win = sel->win))
1783      return 0;
1784 
1785    if ((!sel->state) || (!sel->states->next))
1786      return 0;
1787 
1788    _evry_state_pop(sel, 0);
1789 
1790    _evry_selector_update(sel);
1791    _evry_update_text_label(sel->state);
1792 
1793    if (sel == SUBJ_SEL)
1794      _evry_selector_update_actions(ACTN_SEL);
1795 
1796    if (sel->state->view)
1797      {
1798         _evry_view_show(win, sel->state->view, SLIDE_RIGHT);
1799         sel->state->view->update(sel->state->view);
1800      }
1801 
1802    return 1;
1803 }
1804 
1805 int
evry_selectors_switch(Evry_Window * win,int dir,int slide)1806 evry_selectors_switch(Evry_Window *win, int dir, int slide)
1807 {
1808    Evry_State *s = (CUR_SEL)->state;
1809 
1810    if ((CUR_SEL)->update_timer)
1811      {
1812         if ((CUR_SEL == SUBJ_SEL) || (CUR_SEL == ACTN_SEL))
1813           {
1814              _evry_matches_update(CUR_SEL, 0);
1815              _evry_selector_update(CUR_SEL);
1816           }
1817      }
1818 
1819    if (CUR_SEL != SUBJ_SEL && dir == 0)
1820      {
1821         edje_object_signal_emit(win->o_main, "e,state,object_selector_hide", "e");
1822         _evry_selector_activate(SUBJ_SEL, (slide * SLIDE_RIGHT));
1823         return 1;
1824      }
1825    if (CUR_SEL == SUBJ_SEL && dir > 0)
1826      {
1827         if (s->cur_item)
1828           {
1829              _evry_selector_activate(ACTN_SEL, slide * SLIDE_LEFT);
1830              return 1;
1831           }
1832      }
1833    else if (CUR_SEL == ACTN_SEL && dir > 0)
1834      {
1835         Evry_Item *it;
1836 
1837         if (!s || !(it = s->cur_item) || !(CHECK_TYPE(it, EVRY_TYPE_ACTION)))
1838           return 0;
1839 
1840         GET_ACTION(act, it);
1841         if (!act->it2.type)
1842           return 0;
1843 
1844         _evry_selector_plugins_get(OBJ_SEL, it, NULL);
1845         _evry_selector_update(OBJ_SEL);
1846         edje_object_signal_emit(win->o_main, "e,state,object_selector_show", "e");
1847 
1848         _evry_selector_activate(OBJ_SEL, (slide * SLIDE_LEFT));
1849         return 1;
1850      }
1851    else if (CUR_SEL == ACTN_SEL && dir < 0)
1852      {
1853         _evry_selector_activate(SUBJ_SEL, (slide * SLIDE_RIGHT));
1854         edje_object_signal_emit(win->o_main, "e,state,object_selector_hide", "e");
1855         return 1;
1856      }
1857    else if (CUR_SEL == OBJ_SEL && dir < 0)
1858      {
1859         _evry_selector_activate(ACTN_SEL, (slide * SLIDE_RIGHT));
1860         return 1;
1861      }
1862    return 0;
1863 }
1864 
1865 static int
_evry_selectors_switch(Evry_Window * win,int dir)1866 _evry_selectors_switch(Evry_Window *win, int dir)
1867 {
1868    return evry_selectors_switch(win, dir, 0);
1869 }
1870 
1871 static int
_evry_input_complete(Evry_State * s)1872 _evry_input_complete(Evry_State *s)
1873 {
1874    int action = 0;
1875    char *input = NULL;
1876    Evry_Item *it = s->cur_item;
1877    Evry_Window *win = s->selector->win;
1878 
1879    if (!it) return 0;
1880 
1881    evry_item_ref(it);
1882 
1883    s->item_auto_selected = EINA_FALSE;
1884 
1885    if (it->plugin->complete)
1886      action = it->plugin->complete(it->plugin, it, &input);
1887    else
1888      evry_browse_item(it);
1889 
1890    if (input && action == EVRY_COMPLETE_INPUT)
1891      {
1892         strncpy(s->input, input, INPUTLEN - 1);
1893         _evry_update_text_label(s);
1894         if (CUR_SEL->update_timer)
1895           {
1896              ecore_timer_del(CUR_SEL->update_timer);
1897              CUR_SEL->update_timer = NULL;
1898           }
1899         _evry_cb_update_timer(CUR_SEL);
1900         evry_item_select(s, it);
1901      }
1902 
1903    evry_item_free(it);
1904    E_FREE(input);
1905 
1906    return 1;
1907 }
1908 
1909 static int
_evry_cheat_history(Evry_State * s,int promote,int delete)1910 _evry_cheat_history(Evry_State *s, int promote, int delete)
1911 {
1912    History_Entry *he;
1913    History_Item *hi;
1914    History_Types *ht;
1915    Eina_List *l, *ll;
1916    Evry_Item *it = s->cur_item;
1917 
1918    if (!it) return 0;
1919 
1920    if (!(ht = evry_history_types_get(it->type)))
1921      return 1;
1922 
1923    if (!(he = eina_hash_find(ht->types, (it->id ? it->id : it->label))))
1924      return 1;
1925 
1926    EINA_LIST_FOREACH_SAFE (he->items, l, ll, hi)
1927      {
1928         if (hi->plugin != it->plugin->name)
1929           continue;
1930 
1931         if (delete)
1932           {
1933              if (hi->input)
1934                eina_stringshare_del(hi->input);
1935              if (hi->plugin)
1936                eina_stringshare_del(hi->plugin);
1937              if (hi->context)
1938                eina_stringshare_del(hi->context);
1939              E_FREE(hi);
1940 
1941              he->items = eina_list_remove_list(he->items, l);
1942           }
1943         else if (promote)
1944           {
1945              hi->count += 5;
1946              hi->last_used = ecore_time_unix_get();
1947           }
1948         else /* demote */
1949           {
1950              hi->count -= 5;
1951              if (hi->count < 0) hi->count = 1;
1952           }
1953      }
1954    if (s->plugin == s->aggregator)
1955      _evry_aggregator_fetch(s);
1956    if (s->view)
1957      s->view->update(s->view);
1958 
1959    return 1;
1960 }
1961 
1962 static Eina_Bool
_evry_cb_key_down(void * data,int type EINA_UNUSED,void * event)1963 _evry_cb_key_down(void *data, int type EINA_UNUSED, void *event)
1964 {
1965    Ecore_Event_Key *ev = event;
1966    Evry_State *s;
1967    Evry_Selector *sel;
1968    Evry_Window *win = data;
1969    const char *old;
1970 
1971    if ((win->grab && (ev->event_window != ecore_evas_window_get(e_comp->ee))) &&
1972        (ev->event_window != elm_win_window_id_get(win->ewin)))
1973      return ECORE_CALLBACK_PASS_ON;
1974 
1975    if (!strcmp(ev->key, "Escape"))
1976      {
1977         evry_hide(win, 0);
1978         return ECORE_CALLBACK_PASS_ON;
1979      }
1980 #ifdef DRAG_OFF_WINDOW
1981    else if (win->grab && !strcmp(ev->key, "F1"))
1982      {
1983         Evas_Object *ewin = win->ewin;
1984         E_Client *ec;
1985 
1986         e_grabinput_release(elm_win_window_id_get(ewin), elm_win_window_id_get(ewin));
1987 
1988         ec = e_win_client_get(ewin);
1989         elm_win_borderless_set(ewin, 0);
1990         ec->override = 0;
1991 #ifndef HAVE_WAYLAND_ONLY
1992         if (e_comp->comp_type == E_PIXMAP_TYPE_X)
1993           ecore_x_netwm_window_type_set(elm_win_window_id_get(ewin),
1994                                         ECORE_X_WINDOW_TYPE_DIALOG);
1995 #endif
1996         evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NORMAL);
1997         EC_CHANGED(ec);
1998         ec->netwm.fetch.type = 1;
1999         ec->netwm.state.skip_taskbar = 0;
2000         ec->netwm.update.state = 1;
2001         ec->internal_no_remember = 1;
2002         e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
2003 
2004         win->grab = 0;
2005         return ECORE_CALLBACK_PASS_ON;
2006      }
2007 #endif
2008    else if ((ev->modifiers) && (!win->delay_hide_action))
2009      {
2010         Eina_List *l;
2011         E_Config_Binding_Key *binding;
2012         E_Binding_Modifier mod;
2013 
2014 	       EINA_LIST_FOREACH(e_bindings->key_bindings, l, binding)
2015           {
2016              if (binding->action && strcmp(binding->action, "everything")) continue;
2017 
2018              mod = 0;
2019 
2020              if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
2021                mod |= E_BINDING_MODIFIER_SHIFT;
2022              if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
2023                mod |= E_BINDING_MODIFIER_CTRL;
2024              if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
2025                mod |= E_BINDING_MODIFIER_ALT;
2026              if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
2027                mod |= E_BINDING_MODIFIER_WIN;
2028 
2029              if (!(binding->key && (!strcmp(binding->key, ev->key)) &&
2030                    (((unsigned int)binding->modifiers == mod) || (binding->any_mod))))
2031                continue;
2032 
2033              if (win->level > 0)
2034                return ECORE_CALLBACK_PASS_ON;
2035 
2036              if (!(binding->params) && (CUR_SEL == OBJ_SEL) &&
2037                  ((CUR_SEL)->state && (CUR_SEL)->state->cur_item))
2038                {
2039                   _evry_selectors_shift(win, 1);
2040                   return ECORE_CALLBACK_PASS_ON;
2041                }
2042 
2043              evry_hide(win, 1);
2044 
2045 #if 0 /* FIXME this causes segv when triggering a plugin keybinding twice */
2046              if (win && CUR_SEL && binding->params)
2047                {
2048                   Eina_List *ll;
2049                   Evry_Plugin *p;
2050 
2051                   EINA_LIST_FOREACH ((SUBJ_SEL)->plugins, ll, p)
2052                     if (!strcmp(binding->params, p->name)) break;
2053 
2054                   if (p)
2055                     {
2056                        _evry_plugin_select((CUR_SEL)->state, p);
2057                        _evry_selector_update(CUR_SEL);
2058                        _evry_view_update(win, (CUR_SEL)->state);
2059                     }
2060                }
2061 #endif
2062              return ECORE_CALLBACK_PASS_ON;
2063           }
2064      }
2065 
2066    old = ev->key;
2067    win->request_selection = EINA_FALSE;
2068 
2069    if (!strcmp(ev->key, "KP_Enter"))
2070      {
2071         ev->key = "Return";
2072      }
2073    else if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
2074      {
2075         if (!strcmp(ev->key, "Tab"))
2076           {
2077              ev->key = "Down";
2078           }
2079         else if (!strcmp(ev->key, "ISO_Left_Tab") || (!strcmp(ev->key, "Tab") &&
2080                                                       (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)))
2081           {
2082              ev->key = "Up";
2083              ev->modifiers = 0;
2084           }
2085         else if (!strcmp(ev->key, "q"))
2086           {
2087              evry_hide(win, 0);
2088              return 1;
2089           }
2090         else if (!strcmp(ev->key, "w"))
2091           {
2092              ev->key = "Return";
2093              ev->modifiers = 0;
2094           }
2095         else if (evry_conf->quick_nav == 1)
2096           {
2097              if (!strcmp(ev->key, "k") || (!strcmp(ev->key, "K")))
2098                ev->key = "Up";
2099              else if (!strcmp(ev->key, "j") || (!strcmp(ev->key, "J")))
2100                ev->key = "Down";
2101              else if (!strcmp(ev->key, "n") || (!strcmp(ev->key, "N")))
2102                ev->key = "Next";
2103              else if (!strcmp(ev->key, "p") || (!strcmp(ev->key, "P")))
2104                ev->key = "Prior";
2105              else if (!strcmp(ev->key, "l") || (!strcmp(ev->key, "L")))
2106                ev->key = "Right";
2107              else if (!strcmp(ev->key, "h") || (!strcmp(ev->key, "H")))
2108                ev->key = "Left";
2109              else if (!strcmp(ev->key, "i") || (!strcmp(ev->key, "I")))
2110                ev->key = "Tab";
2111              else if (!strcmp(ev->key, "m") || (!strcmp(ev->key, "M")))
2112                ev->key = "Return";
2113           }
2114         else if (evry_conf->quick_nav == 3)
2115           {
2116              if (!strcmp(ev->key, "p") || (!strcmp(ev->key, "P")))
2117                ev->key = "Up";
2118              else if (!strcmp(ev->key, "n") || (!strcmp(ev->key, "N")))
2119                ev->key = "Down";
2120              else if (!strcmp(ev->key, "f") || (!strcmp(ev->key, "F")))
2121                ev->key = "Right";
2122              else if (!strcmp(ev->key, "b") || (!strcmp(ev->key, "B")))
2123                ev->key = "Left";
2124              else if (!strcmp(ev->key, "i") || (!strcmp(ev->key, "I")))
2125                ev->key = "Tab";
2126              else if (!strcmp(ev->key, "m") || (!strcmp(ev->key, "M")))
2127                ev->key = "Return";
2128           }
2129      }
2130 
2131    if (!(sel = CUR_SEL))
2132      goto end;
2133 
2134    if (!strcmp(ev->key, "Tab") &&
2135        !((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) ||
2136          (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)))
2137      {
2138         if (!_evry_selectors_switch(win, 1))
2139           _evry_selectors_switch(win, 0);
2140         goto end;
2141      }
2142 
2143    if (!(s = sel->state))
2144      goto end;
2145 
2146    if (!win->visible && (!strcmp(ev->key, "Down")))
2147      {
2148         _evry_list_win_show(win);
2149         goto end;
2150      }
2151    else if ((!strcmp(ev->key, "ISO_Left_Tab") ||
2152              (((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) ||
2153                (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)) &&
2154               (!strcmp(ev->key, "Tab")))))
2155      {
2156         _evry_input_complete(s);
2157         goto end;
2158      }
2159    else if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
2160             (!strcmp(ev->key, "Delete") || !strcmp(ev->key, "Insert")))
2161      {
2162         int delete = (!strcmp(ev->key, "Delete") &&
2163                       (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT));
2164         int promote = (!strcmp(ev->key, "Insert"));
2165 
2166         _evry_cheat_history(s, promote, delete);
2167         goto end;
2168      }
2169    else if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
2170      {
2171         if (!strcmp(ev->key, "u"))
2172           {
2173              if (!_evry_clear(sel))
2174                evry_browse_back(sel);
2175              goto end;
2176           }
2177         else if (!strcmp(ev->key, "1"))
2178           evry_view_toggle(s, NULL);
2179         else if (!strcmp(ev->key, "Return"))
2180           _evry_plugin_action(sel, 0);
2181         else if (!strcmp(ev->key, "v"))
2182           {
2183 #ifndef HAVE_WAYLAND_ONLY
2184              if (e_comp->comp_type == E_PIXMAP_TYPE_X)
2185                {
2186                   win->request_selection = EINA_TRUE;
2187                   ecore_x_selection_primary_request
2188                     (elm_win_window_id_get(win->ewin), ECORE_X_SELECTION_TARGET_UTF8_STRING);
2189                }
2190 #endif
2191           }
2192         else
2193           {
2194              _evry_view_key_press(s, ev);
2195           }
2196         goto end;
2197      }
2198    if ((s->plugin && s->plugin->cb_key_down) &&
2199        (s->plugin->cb_key_down(s->plugin, ev)))
2200      {
2201         /* let plugin intercept keypress */
2202         goto end;
2203      }
2204    else if (_evry_view_key_press(s, ev))
2205      {
2206         /* let view intercept keypress */
2207         goto end;
2208      }
2209    else if (!strcmp(ev->key, "Right"))
2210      {
2211         if (!evry_browse_item(sel->state->cur_item))
2212           evry_selectors_switch(win, 1, EINA_TRUE);
2213      }
2214    else if (!strcmp(ev->key, "Left"))
2215      {
2216         if (!evry_browse_back(sel))
2217           evry_selectors_switch(win, -1, EINA_TRUE);
2218      }
2219    else if (!strcmp(ev->key, "Return"))
2220      {
2221         if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
2222           {
2223              _evry_plugin_action(sel, 0);
2224           }
2225         else if (s->cur_item && s->cur_item->browseable)
2226           {
2227              evry_browse_item(sel->state->cur_item);
2228           }
2229         else
2230           {
2231              _evry_plugin_action(sel, 1);
2232           }
2233      }
2234    else if (!strcmp(ev->key, "BackSpace"))
2235      {
2236         if (!_evry_backspace(sel))
2237           evry_browse_back(sel);
2238      }
2239    else if ((ev->compose && !(ev->modifiers & ECORE_EVENT_MODIFIER_ALT)))
2240      {
2241         unsigned int len = strlen(s->inp);
2242 
2243         if (len == 0 && (evry_view_toggle(s, ev->compose)))
2244           goto end;
2245 
2246         if (len < (INPUTLEN - strlen(ev->compose)))
2247           {
2248              strcat(s->inp, ev->compose);
2249 
2250              _evry_update(sel, 1);
2251           }
2252      }
2253 
2254 end:
2255    ev->key = old;
2256    return ECORE_CALLBACK_PASS_ON;
2257 }
2258 
2259 static int
_evry_backspace(Evry_Selector * sel)2260 _evry_backspace(Evry_Selector *sel)
2261 {
2262    Evry_State *s = sel->state;
2263    int len, val, pos;
2264 
2265    if (!(len = strlen(s->inp)))
2266      return 0;
2267 
2268    pos = evas_string_char_prev_get(s->inp, len, &val);
2269    if ((pos < len) && (pos >= 0))
2270      {
2271         val = *(s->inp + pos);
2272 
2273         s->inp[pos] = 0;
2274 
2275         if (s->trigger_active && s->inp[0] != 0)
2276           s->input = s->inp + 1;
2277         else
2278           s->input = s->inp;
2279 
2280         if (pos == 0)
2281           s->trigger_active = EINA_FALSE;
2282 
2283         if ((pos == 0) || !isspace(val))
2284           _evry_update(sel, 1);
2285 
2286         return 1;
2287      }
2288 
2289    return 0;
2290 }
2291 
2292 static void
_evry_update_text_label(Evry_State * s)2293 _evry_update_text_label(Evry_State *s)
2294 {
2295    Evry_Window *win = s->selector->win;
2296 
2297    if (!win->visible && evry_conf->hide_input)
2298      {
2299         if (strlen(s->inp) > 0)
2300           edje_object_signal_emit(win->o_main, "list:e,state,entry_show", "e");
2301         else
2302           edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
2303      }
2304 
2305    edje_object_part_text_set(win->o_main, "list:e.text.label", s->inp);
2306 }
2307 
2308 static void
_evry_update(Evry_Selector * sel,int fetch)2309 _evry_update(Evry_Selector *sel, int fetch)
2310 {
2311    Evry_State *s = sel->state;
2312    Evry_Window *win = sel->win;
2313 
2314    _evry_update_text_label(s);
2315 
2316    if (fetch)
2317      {
2318         if (sel->update_timer)
2319           ecore_timer_del(sel->update_timer);
2320 
2321         sel->update_timer =
2322           ecore_timer_loop_add(MATCH_LAG, _evry_cb_update_timer, sel);
2323 
2324         edje_object_signal_emit(win->o_main, "list:e,signal,update", "e");
2325      }
2326 }
2327 
2328 static Eina_Bool
_evry_cb_update_timer(void * data)2329 _evry_cb_update_timer(void *data)
2330 {
2331    Evry_Selector *sel = data;
2332 
2333    _evry_matches_update(sel, 1);
2334    _evry_selector_update(sel);
2335    _evry_list_win_update(sel->state);
2336    sel->update_timer = NULL;
2337 
2338    return ECORE_CALLBACK_CANCEL;
2339 }
2340 
2341 static int
_evry_clear(Evry_Selector * sel)2342 _evry_clear(Evry_Selector *sel)
2343 {
2344    Evry_State *s = sel->state;
2345    Evry_Window *win = sel->win;
2346 
2347    if (!(s->inp) || (s->inp[0] == 0))
2348      return 0;
2349 
2350    if (s->trigger_active && s->inp[1] != 0)
2351      {
2352         s->inp[1] = 0;
2353         s->input = s->inp + 1;
2354      }
2355    else
2356      {
2357         s->inp[0] = 0;
2358         s->input = s->inp;
2359         s->trigger_active = EINA_FALSE;
2360      }
2361 
2362    _evry_update(sel, 1);
2363 
2364    if (!win->visible && evry_conf->hide_input)
2365      edje_object_signal_emit(win->o_main, "list:e,state,entry_hide", "e");
2366 
2367    return 1;
2368 }
2369 
2370 static void
_evry_cb_free_action_performed(void * data EINA_UNUSED,void * event)2371 _evry_cb_free_action_performed(void *data EINA_UNUSED, void *event)
2372 {
2373    Evry_Event_Action_Performed *ev = event;
2374 
2375    if (ev->it1)
2376      EVRY_ITEM_FREE(ev->it1);
2377    if (ev->it2)
2378      EVRY_ITEM_FREE(ev->it2);
2379 
2380    IF_RELEASE(ev->action);
2381 
2382    E_FREE(ev);
2383 }
2384 
2385 static int
_evry_action_do(Evry_Action * act)2386 _evry_action_do(Evry_Action *act)
2387 {
2388    Evry_Event_Action_Performed *ev;
2389    int ret;
2390 
2391    if ((ret = act->action(act)))
2392      {
2393         ev = E_NEW(Evry_Event_Action_Performed, 1);
2394         ev->action = eina_stringshare_ref(act->name);
2395         ev->it1 = act->it1.item;
2396         ev->it2 = act->it2.item;
2397 
2398         if (ev->it1)
2399           EVRY_ITEM_REF(ev->it1);
2400         if (ev->it2)
2401           EVRY_ITEM_REF(ev->it2);
2402 
2403         ecore_event_add(_evry_events[EVRY_EVENT_ACTION_PERFORMED], ev,
2404                         _evry_cb_free_action_performed, NULL);
2405         return ret;
2406      }
2407    return 0;
2408 }
2409 
2410 void
evry_plugin_action(Evry_Window * win,int finished)2411 evry_plugin_action(Evry_Window *win, int finished)
2412 {
2413    _evry_plugin_action(CUR_SEL, finished);
2414 }
2415 
2416 static void
_evry_plugin_action(Evry_Selector * sel,int finished)2417 _evry_plugin_action(Evry_Selector *sel, int finished)
2418 {
2419    Evry_State *s_subj, *s_act, *s_obj = NULL;
2420    Evry_Item *it, *it_subj, *it_act, *it_obj = NULL;
2421    Evry_Window *win = sel->win;
2422    Eina_List *l;
2423    int ret = 0;
2424 
2425    if ((SUBJ_SEL)->update_timer)
2426      {
2427         _evry_matches_update(SUBJ_SEL, 0);
2428         _evry_selector_update(SUBJ_SEL);
2429      }
2430 
2431    /* do delayed fetch actions now */
2432    if ((ACTN_SEL)->action_timer)
2433      _evry_selector_update_actions_do(ACTN_SEL);
2434 
2435    if (!(s_subj = (SUBJ_SEL)->state))
2436      return;
2437 
2438    if (!(it_subj = s_subj->cur_item))
2439      return;
2440 
2441    if ((CUR_SEL == SUBJ_SEL) && (ACTN_SEL)->update_timer)
2442      {
2443         /* _evry_selector_actions_get(it_subj); */
2444         _evry_selector_plugins_get(ACTN_SEL, it_subj, NULL);
2445 
2446         if (!(ACTN_SEL)->state)
2447           return;
2448 
2449         _evry_selector_update(ACTN_SEL);
2450      }
2451 
2452    if (!(s_act = (ACTN_SEL)->state))
2453      return;
2454 
2455    if (!(it_act = s_act->cur_item))
2456      return;
2457 
2458    if (CHECK_TYPE(it_act, EVRY_TYPE_ACTION) ||
2459        CHECK_SUBTYPE(it_act, EVRY_TYPE_ACTION))
2460      {
2461         GET_ACTION(act, it_act);
2462 
2463         if (!act->action)
2464           return;
2465 
2466         /* get object item for action, when required */
2467         if (act->it2.type)
2468           {
2469              /* check if object is provided */
2470              if ((s_obj = (OBJ_SEL)->state) && (!s_obj->delete_me))
2471                {
2472                   it_obj = s_obj->cur_item;
2473                }
2474 
2475              if (!it_obj)
2476                {
2477                   if (SUBJ_SEL == CUR_SEL)
2478                     _evry_selectors_switch(win, 1);
2479                   if (ACTN_SEL == CUR_SEL)
2480                     _evry_selectors_switch(win, 1);
2481                   return;
2482                }
2483 
2484              act->it2.item = it_obj;
2485           }
2486 
2487         if (s_obj && s_obj->sel_items && !(act->it2.accept_list))
2488           {
2489              if (!(act->it1.item && CHECK_TYPE(act->it1.item, EVRY_TYPE_PLUGIN)))
2490                act->it1.item = it_subj;
2491 
2492              EINA_LIST_FOREACH (s_obj->sel_items, l, it)
2493                {
2494                   if (it->type != act->it2.type)
2495                     continue;
2496                   act->it2.item = it;
2497 
2498                   _evry_action_do(act);
2499                }
2500           }
2501         else if (s_subj->sel_items && !(act->it1.accept_list))
2502           {
2503              EINA_LIST_FOREACH (s_subj->sel_items, l, it)
2504                {
2505                   if (it->type != act->it1.type)
2506                     continue;
2507                   act->it1.item = it;
2508 
2509                   _evry_action_do(act);
2510                }
2511           }
2512         else
2513           {
2514              if (!(act->it1.item && CHECK_TYPE(act->it1.item, EVRY_TYPE_PLUGIN)))
2515                {
2516                   act->it1.item = it_subj;
2517                   act->it1.items = s_subj->sel_items;
2518                }
2519 
2520              if (s_obj)
2521                act->it2.items = s_obj->sel_items;
2522 
2523              ret = _evry_action_do(act);
2524 
2525              if (ret == EVRY_ACTION_OTHER)
2526                return;
2527           }
2528      }
2529    else return;
2530 
2531    if (s_subj && it_subj && it_subj->plugin->history)
2532      evry_history_item_add(it_subj, NULL, s_subj->input);
2533 
2534    if (s_act && it_act && it_act->plugin->history)
2535      evry_history_item_add(it_act, it_subj->context, s_act->input);
2536 
2537    if (s_obj && it_obj && it_obj->plugin->history)
2538      evry_history_item_add(it_obj, it_act->context, s_obj->input);
2539 
2540    if (ret == EVRY_ACTION_CONTINUE)
2541      return;
2542 
2543    if (ret == EVRY_ACTION_CLEAR)
2544      {
2545         _evry_clear(CUR_SEL);
2546      }
2547    else
2548      {
2549         win->func.hide(win, finished);
2550      }
2551 }
2552 
2553 static void
_evry_view_list_swallow_set(Evas_Object * obj,const char * part,Evas_Object * swallow)2554 _evry_view_list_swallow_set(Evas_Object *obj, const char *part, Evas_Object *swallow)
2555 {
2556    Evas_Object *o;
2557 
2558    o = edje_object_part_swallow_get(obj, part);
2559    if (o != swallow)
2560      {
2561         evas_object_hide(o);
2562         edje_object_part_unswallow(obj, o);
2563 
2564         edje_object_part_unswallow(obj, swallow);
2565         edje_object_part_swallow(obj, part, swallow);
2566         evas_object_show(swallow);
2567      }
2568 }
2569 
2570 static void
_evry_view_show(Evry_Window * win,Evry_View * v,int slide)2571 _evry_view_show(Evry_Window *win, Evry_View *v, int slide)
2572 {
2573    if (!v) return;
2574 
2575    if (v->o_bar)
2576      {
2577         edje_object_part_swallow(win->o_main, "list:e.swallow.bar", v->o_bar);
2578         evas_object_show(v->o_bar);
2579      }
2580 
2581    if (!v->o_list)
2582      return;
2583 
2584    if (slide == SLIDE_LEFT)
2585      {
2586         _evry_view_list_swallow_set(win->o_main, "list:e.swallow.list2", v->o_list);
2587 
2588         edje_object_signal_emit(win->o_main, "list:e,action,slide,left", "e");
2589         edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
2590      }
2591    else if (slide == SLIDE_RIGHT)
2592      {
2593         _evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
2594 
2595         edje_object_signal_emit(win->o_main, "list:e,action,slide,right", "e");
2596         edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
2597      }
2598    else
2599      {
2600         _evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
2601 
2602         edje_object_signal_emit(win->o_main, "list:e,action,slide,default", "e");
2603         edje_object_signal_emit(v->o_list, "e,action,show,list", "e");
2604      }
2605 }
2606 
2607 static Eina_Bool
_clear_timer(void * data)2608 _clear_timer(void *data)
2609 {
2610    _evry_state_clear(data);
2611 
2612    return ECORE_CALLBACK_CANCEL;
2613 }
2614 
2615 static void
_evry_state_clear(Evry_Window * win)2616 _evry_state_clear(Evry_Window *win)
2617 {
2618    Evry_State *s;
2619    Evry_View *v;
2620 
2621    if (!win->state_clearing)
2622      return;
2623 
2624    s = win->state_clearing;
2625    win->state_clearing = NULL;
2626 
2627    ecore_timer_del(s->clear_timer);
2628    s->clear_timer = NULL;
2629 
2630    if (s->delete_me)
2631      {
2632         if (s->view) s->view->destroy(s->view);
2633         s->clear_timer = NULL;
2634         E_FREE(s->inp);
2635         E_FREE(s);
2636      }
2637    else if ((v = s->view))
2638      {
2639         v->clear(v);
2640 
2641         if (v->o_list)
2642           {
2643              evas_object_hide(v->o_list);
2644              edje_object_part_unswallow(win->o_main, v->o_list);
2645           }
2646      }
2647 
2648    /* replay mouse down to allow direct sliding back */
2649    if (win->mouse_button)
2650      evas_event_feed_mouse_down(win->evas, win->mouse_button, 0, 0, NULL);
2651 }
2652 
2653 static void
_evry_view_hide(Evry_Window * win,Evry_View * v,int slide)2654 _evry_view_hide(Evry_Window *win, Evry_View *v, int slide)
2655 {
2656    _evry_state_clear(win);
2657 
2658    if (!v || v->state->delete_me) return;
2659 
2660    if (slide && v->o_list)
2661      {
2662         win->state_clearing = v->state;
2663 
2664         if (slide == SLIDE_RIGHT)
2665           {
2666              _evry_view_list_swallow_set(win->o_main, "list:e.swallow.list2", v->o_list);
2667           }
2668         else /* if (slide == SLIDE_LEFT) */
2669           {
2670              _evry_view_list_swallow_set(win->o_main, "list:e.swallow.list", v->o_list);
2671           }
2672 
2673         edje_object_signal_emit(v->o_list, "e,action,hide,list", "e");
2674 
2675         /* FIXME get signal from theme when anim finished */
2676         v->state->clear_timer = ecore_timer_loop_add(1.5, _clear_timer, win);
2677 
2678         if (v->o_bar)
2679           {
2680              evas_object_hide(v->o_bar);
2681              edje_object_part_unswallow(win->o_main, v->o_bar);
2682           }
2683 
2684         return;
2685      }
2686 
2687    v->clear(v);
2688 
2689    if (v->o_list)
2690      {
2691         evas_object_hide(v->o_list);
2692         edje_object_part_unswallow(win->o_main, v->o_list);
2693      }
2694 
2695    if (v->o_bar)
2696      {
2697         evas_object_hide(v->o_bar);
2698         edje_object_part_unswallow(win->o_main, v->o_bar);
2699      }
2700 }
2701 
2702 static int
_evry_view_create(Evry_State * s)2703 _evry_view_create(Evry_State *s)
2704 {
2705    Evry_View *view;
2706 
2707    if (s->view)
2708      return 1;
2709 
2710    if (s->plugin && s->plugin->view)
2711      view = s->plugin->view;
2712    else
2713      view = eina_list_data_get(evry_conf->views);
2714 
2715    s->view = view->create(view, s, s->selector->win->o_main);
2716 
2717    if (s->view)
2718      {
2719         s->view->state = s;
2720         return 1;
2721      }
2722 
2723    return 0;
2724 }
2725 
2726 static int
_evry_view_update(Evry_Window * win,Evry_State * s)2727 _evry_view_update(Evry_Window *win, Evry_State *s)
2728 {
2729    if (!win->visible) return 0;
2730    /* TODO check this again !!!!*/
2731    if (s->view)
2732      {
2733         s->view->update(s->view);
2734         return 0;
2735      }
2736 
2737    if (_evry_view_create(s))
2738      {
2739         s->view->update(s->view);
2740         return 1;
2741      }
2742 
2743    return 0;
2744 }
2745 
2746 static void
_evry_view_clear(Evry_State * s)2747 _evry_view_clear(Evry_State *s)
2748 {
2749    if (!s || !s->view) return;
2750 
2751    s->view->clear(s->view);
2752 }
2753 
2754 static int
_evry_view_key_press(Evry_State * s,Ecore_Event_Key * ev)2755 _evry_view_key_press(Evry_State *s, Ecore_Event_Key *ev)
2756 {
2757    if (!s || !s->view || !s->view->cb_key_down) return 0;
2758 
2759    return s->view->cb_key_down(s->view, ev);
2760 }
2761 
2762 int
evry_view_toggle(Evry_State * s,const char * trigger)2763 evry_view_toggle(Evry_State *s, const char *trigger)
2764 {
2765    Evry_View *view, *v = NULL;
2766    Eina_List *l, *ll;
2767    Eina_Bool triggered = EINA_FALSE;
2768    Evry_Window *win = s->selector->win;
2769 
2770    if (trigger)
2771      {
2772         EINA_LIST_FOREACH (evry_conf->views, ll, view)
2773           {
2774              if (view->trigger && !strncmp(trigger, view->trigger, 1) &&
2775                  (!s->view || (view->id != s->view->id)) &&
2776                  (v = view->create(view, s, win->o_main)))
2777                {
2778                   triggered = EINA_TRUE;
2779                   goto found;
2780                }
2781           }
2782      }
2783    else
2784      {
2785         if (s->view)
2786           l = eina_list_data_find_list(evry_conf->views, s->view->id);
2787         else
2788           {
2789              view = evry_conf->views->data;
2790              v = view->create(view, s, win->o_main);
2791              goto found;
2792           }
2793 
2794         if (l && l->next)
2795           l = l->next;
2796         else
2797           l = evry_conf->views;
2798 
2799         EINA_LIST_FOREACH (l, ll, view)
2800           {
2801              if ((!view->trigger) &&
2802                  ((!s->view || (view->id != s->view->id)) &&
2803                   (v = view->create(view, s, win->o_main))))
2804                goto found;
2805           }
2806      }
2807 
2808 found:
2809    if (!v) return 0;
2810 
2811    _evry_list_win_show(win);
2812 
2813    if (s->view)
2814      {
2815         _evry_view_hide(win, s->view, 0);
2816         s->view->destroy(s->view);
2817      }
2818 
2819    s->view = v;
2820    s->view->state = s;
2821    _evry_view_show(win, s->view, 0);
2822    view->update(s->view);
2823 
2824    return triggered;
2825 }
2826 
2827 static void
_evry_matches_update(Evry_Selector * sel,int async)2828 _evry_matches_update(Evry_Selector *sel, int async)
2829 {
2830    Evry_State *s = sel->state;
2831    Evry_Plugin *p;
2832    Eina_List *l;
2833    Evry_Item *it;
2834    Evry_Window *win = sel->win;
2835    const char *input = NULL;
2836    size_t len_inp = 0;
2837 
2838    s->changed = 1;
2839    s->request++;
2840 
2841 #ifdef CHECK_TIME
2842    DBG("matches update %f", ecore_time_get() - _evry_time);
2843 #endif
2844 
2845    if (sel->update_timer)
2846      {
2847         ecore_timer_del(sel->update_timer);
2848         sel->update_timer = NULL;
2849      }
2850 
2851    if (s->sel_items)
2852      {
2853         eina_list_free(s->sel_items);
2854         s->sel_items = NULL;
2855      }
2856 
2857    if (s->inp[0])
2858      {
2859         len_inp = strlen(s->inp);
2860         input = s->inp;
2861      }
2862 
2863    /* use current plugins */
2864    if (s->trigger_active)
2865      {
2866         s->plugin_auto_selected = EINA_FALSE;
2867 
2868         EINA_LIST_FOREACH (s->cur_plugins, l, p)
2869           {
2870              p->request = s->request;
2871              p->fetch(p, s->input);
2872           }
2873         goto found;
2874      }
2875 
2876    EINA_LIST_FREE (s->cur_plugins, p) ;
2877 
2878    /* check if input matches plugin trigger */
2879    if (input)
2880      {
2881         size_t len_trigger = 0;
2882 
2883         EINA_LIST_FOREACH (s->plugins, l, p)
2884           {
2885              size_t len;
2886 
2887              if (!p->config->trigger) continue;
2888              len = strlen(p->config->trigger);
2889 
2890              if (len_trigger && len != len_trigger)
2891                continue;
2892 
2893              if ((len_inp >= len) &&
2894                  (!strncmp(s->inp, p->config->trigger, len)))
2895                {
2896                   len_trigger = len;
2897                   s->cur_plugins = eina_list_append(s->cur_plugins, p);
2898                   p->request = s->request;
2899                   if (len_inp == len)
2900                     p->fetch(p, NULL);
2901                   else
2902                     p->fetch(p, s->input + len);
2903                }
2904           }
2905         if (s->cur_plugins)
2906           {
2907              s->trigger_active = EINA_TRUE;
2908              /* replace trigger with indicator */
2909              if (len_trigger > 1)
2910                {
2911                   s->inp[0] = ':';
2912 
2913                   if (s->inp[len_trigger])
2914                     strcpy(s->inp + 1, s->inp + len_trigger);
2915                   else
2916                     s->inp[1] = 0;
2917                }
2918              s->input = s->inp + 1;
2919              _evry_update_text_label(s);
2920 
2921              goto found;
2922           }
2923      }
2924 
2925    /* query all other plugins for this state */
2926    EINA_LIST_FOREACH (s->plugins, l, p)
2927      {
2928         p->request = s->request;
2929 
2930         if (p == s->aggregator)
2931           goto next;
2932 
2933         /* dont wait for async plugin. use their current items */
2934         if (!async && p->async_fetch && p->items)
2935           {
2936              s->cur_plugins = eina_list_append(s->cur_plugins, p);
2937              goto next;
2938           }
2939 
2940         if (!((sel->states->next) ||
2941               ((CUR_SEL == SUBJ_SEL) &&
2942                (win->plugin_dedicated))))
2943           {
2944              /* skip plugins in toplevel which trigger-only */
2945              if ((sel == SUBJ_SEL) &&
2946                  (p->config->top_level) &&
2947                  (p->config->trigger_only))
2948                goto next;
2949 
2950              /* skip non-toplevel plugins when input < min_query */
2951              if ((!p->config->top_level) &&
2952                  ((size_t) p->config->min_query > len_inp))
2953                goto next;
2954           }
2955 
2956         if (p->fetch(p, input))
2957           {
2958 #ifdef CHECK_TIME
2959              DBG("fetch %s %f", p->name, ecore_time_get() - _evry_time);
2960 #endif
2961              s->cur_plugins = eina_list_append(s->cur_plugins, p);
2962              continue;
2963           }
2964 
2965 next:
2966         if (s->plugin == p)
2967           s->plugin = NULL;
2968      }
2969 
2970 found:
2971    _evry_aggregator_fetch(s);
2972 
2973    if (s->plugin_auto_selected)
2974      s->plugin = NULL;
2975 
2976    _evry_plugin_select(s, s->plugin);
2977 
2978    if (!s->plugin)
2979      return;
2980 
2981    EINA_LIST_FOREACH (s->plugin->items, l, it)
2982      if (it->marked)
2983        s->sel_items = eina_list_append(s->sel_items, it);
2984 }
2985 
2986 static void
_evry_item_desel(Evry_State * s)2987 _evry_item_desel(Evry_State *s)
2988 {
2989    Evry_Item *it = s->cur_item;
2990 
2991    if (it)
2992      {
2993         it->selected = EINA_FALSE;
2994         evry_item_free(it);
2995      }
2996 
2997    s->cur_item = NULL;
2998 }
2999 
3000 static void
_evry_item_sel(Evry_State * s,Evry_Item * it)3001 _evry_item_sel(Evry_State *s, Evry_Item *it)
3002 {
3003    if (s->cur_item == it) return;
3004 
3005    _evry_item_desel(s);
3006 
3007    evry_item_ref(it);
3008    it->selected = EINA_TRUE;
3009 
3010    s->cur_item = it;
3011 }
3012 
3013 static void
_evry_plugin_select(Evry_State * s,Evry_Plugin * p)3014 _evry_plugin_select(Evry_State *s, Evry_Plugin *p)
3015 {
3016    if (!s) return;
3017 
3018    if (p)
3019      {
3020         s->plugin_auto_selected = EINA_FALSE;
3021      }
3022    else
3023      {
3024         p = eina_list_data_get(s->cur_plugins);
3025         s->plugin_auto_selected = EINA_TRUE;
3026      }
3027 
3028    s->plugin = p;
3029 
3030    if ((s->view && s->plugin && s->plugin->view) &&
3031        (s->view->name != s->plugin->view->name))
3032      {
3033         s->view->destroy(s->view);
3034         s->view = NULL;
3035         if (_evry_view_create(s))
3036           {
3037              _evry_view_show(s->selector->win, s->view, 0);
3038              s->view->update(s->view);
3039           }
3040      }
3041 }
3042 
3043 static void
_evry_cb_free_plugin_selected(void * data EINA_UNUSED,void * event)3044 _evry_cb_free_plugin_selected(void *data EINA_UNUSED, void *event)
3045 {
3046    Evry_Event_Item_Selected *ev = event;
3047 
3048    evry_item_free(ev->item);
3049    E_FREE(ev);
3050 }
3051 
3052 void
evry_plugin_select(Evry_Plugin * p)3053 evry_plugin_select(Evry_Plugin *p)
3054 {
3055    Evry_Event_Item_Selected *ev;
3056 
3057    if (!p) return;
3058 
3059    if (!p->state)
3060      {
3061         ERR("no state!");
3062         return;
3063      }
3064 
3065    _evry_plugin_select(p->state, p);
3066    _evry_selector_update(p->state->selector);
3067 
3068    ev = E_NEW(Evry_Event_Item_Selected, 1);
3069    ev->item = EVRY_ITEM(p);
3070    EVRY_ITEM_REF(p);
3071    ecore_event_add(_evry_events[EVRY_EVENT_PLUGIN_SELECTED], ev,
3072                    _evry_cb_free_plugin_selected, NULL);
3073 }
3074 
3075 static void
_evry_plugin_list_insert(Evry_State * s,Evry_Plugin * p)3076 _evry_plugin_list_insert(Evry_State *s, Evry_Plugin *p)
3077 {
3078    Eina_List *l;
3079    Evry_Plugin *p2;
3080 
3081    EINA_LIST_FOREACH (s->cur_plugins, l, p2)
3082      {
3083         if (p == p2)
3084           return;
3085 
3086         if (p->config->priority < p2->config->priority)
3087           break;
3088      }
3089 
3090    if (l)
3091      s->cur_plugins = eina_list_prepend_relative_list(s->cur_plugins, p, l);
3092    else
3093      s->cur_plugins = eina_list_append(s->cur_plugins, p);
3094 }
3095 
3096 static void
_evry_cb_show(Evry_Window * win,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3097 _evry_cb_show(Evry_Window *win, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3098 {
3099    if (win->grab)
3100      e_grabinput_get(elm_win_window_id_get(win->ewin), 0, elm_win_window_id_get(win->ewin));
3101 }
3102 
3103 #ifndef HAVE_WAYLAND_ONLY
3104 static Eina_Bool
_evry_cb_selection_notify(void * data,int type EINA_UNUSED,void * event)3105 _evry_cb_selection_notify(void *data, int type EINA_UNUSED, void *event)
3106 {
3107    Ecore_X_Event_Selection_Notify *ev;
3108    Evry_Window *win = data;
3109    Evry_State *s = (CUR_SEL)->state;
3110 
3111    if (!s || (data != win)) return ECORE_CALLBACK_PASS_ON;
3112    if (!win->request_selection) return ECORE_CALLBACK_PASS_ON;
3113 
3114    win->request_selection = EINA_FALSE;
3115 
3116    ev = event;
3117    if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
3118        (ev->selection == ECORE_X_SELECTION_PRIMARY))
3119      {
3120         if (strcmp(ev->target, ECORE_X_SELECTION_TARGET_UTF8_STRING) == 0)
3121           {
3122              Ecore_X_Selection_Data_Text *text_data;
3123 
3124              text_data = ev->data;
3125 
3126              strncat(s->input, text_data->text, (INPUTLEN - strlen(s->input)) - 1);
3127              _evry_update(CUR_SEL, 1);
3128           }
3129      }
3130 
3131    return ECORE_CALLBACK_PASS_ON;
3132 }
3133 #endif
3134 
3135 void
evry_item_app_free(Evry_Item_App * app)3136 evry_item_app_free(Evry_Item_App *app)
3137 {
3138    efreet_desktop_free(app->desktop);
3139    eina_stringshare_del(app->file);
3140 
3141    free(app);
3142 }
3143 
3144 void
evry_item_file_free(Evry_Item_File * file)3145 evry_item_file_free(Evry_Item_File *file)
3146 {
3147    eina_stringshare_del(file->url);
3148    eina_stringshare_del(file->path);
3149    eina_stringshare_del(file->mime);
3150 
3151    free(file);
3152 }
3153