1 #include "luncher.h"
2 static Eina_List *handlers;
3 static Eina_Bool _bar_icon_preview_show(void *data);
4 static Eina_Bool _bar_icon_preview_hide(void *data);
5 static void      _bar_icon_del(Instance *inst, Icon *ic);
6 static void _bar_exec_new_show(void *data, Evas *e, Evas_Object *obj, void *event_data);
7 static void _bar_icon_preview_menu_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED);
8 
9 static void
_bar_aspect(Instance * inst)10 _bar_aspect(Instance *inst)
11 {
12    Evas_Coord w, h;
13 
14    switch (e_gadget_site_orient_get(e_gadget_site_get(inst->o_main)))
15      {
16       case E_GADGET_SITE_ORIENT_VERTICAL:
17         h = eina_list_count(inst->icons);
18         w = 1;
19         break;
20       default:
21         w = eina_list_count(inst->icons);
22         h = 1;
23      }
24    evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, w, h);
25 }
26 
27 static Eina_Bool
_bar_check_for_duplicates(Icon * ic,E_Client * dupe)28 _bar_check_for_duplicates(Icon *ic, E_Client *dupe)
29 {
30    Eina_List *l;
31    E_Exec_Instance *ex;
32 
33    EINA_LIST_FOREACH(ic->execs, l, ex)
34      if (eina_list_data_find(ex->clients, dupe)) return EINA_TRUE;
35    return !!eina_list_data_find(ic->clients, dupe);
36 }
37 
38 static Eina_Bool
_bar_check_modifiers(Evas_Modifier * modifiers)39 _bar_check_modifiers(Evas_Modifier *modifiers)
40 {
41    if ((evas_key_modifier_is_set(modifiers, "Alt")) ||
42        (evas_key_modifier_is_set(modifiers, "Control")) ||
43        (evas_key_modifier_is_set(modifiers, "Shift")))
44      return EINA_TRUE;
45    return EINA_FALSE;
46 }
47 
48 static Evas_Object *
_bar_gadget_configure(Evas_Object * g)49 _bar_gadget_configure(Evas_Object *g)
50 {
51    if (!luncher_config) return NULL;
52    if (luncher_config->config_dialog) return NULL;
53    Instance *inst = evas_object_data_get(g, "instance");
54    return config_luncher(e_zone_current_get(), inst, EINA_TRUE);
55 }
56 
57 static void
_bar_popup_dismissed(void * data EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)58 _bar_popup_dismissed(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
59 {
60    E_FREE_FUNC(obj, evas_object_del);
61 }
62 
63 static const char *
_bar_location_get(Instance * inst)64 _bar_location_get(Instance *inst)
65 {
66    const char *s = "float";
67 
68    E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main));
69    E_Gadget_Site_Anchor anchor = e_gadget_site_anchor_get(e_gadget_site_get(inst->o_main));
70 
71    if (anchor & E_GADGET_SITE_ANCHOR_LEFT)
72      {
73         if (anchor & E_GADGET_SITE_ANCHOR_TOP)
74           {
75              switch (orient)
76                {
77                 case E_GADGET_SITE_ORIENT_HORIZONTAL:
78                   s = "top";
79                   break;
80                 case E_GADGET_SITE_ORIENT_VERTICAL:
81                   s = "left";
82                   break;
83                 case E_GADGET_SITE_ORIENT_NONE:
84                   s = "left";
85                   break;
86                }
87           }
88         else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
89           {
90              switch (orient)
91                {
92                 case E_GADGET_SITE_ORIENT_HORIZONTAL:
93                   s = "bottom";
94                   break;
95                 case E_GADGET_SITE_ORIENT_VERTICAL:
96                   s = "left";
97                   break;
98                 case E_GADGET_SITE_ORIENT_NONE:
99                   s = "left";
100                   break;
101                }
102           }
103         else
104           s = "left";
105      }
106    else if (anchor & E_GADGET_SITE_ANCHOR_RIGHT)
107      {
108         if (anchor & E_GADGET_SITE_ANCHOR_TOP)
109           {
110              switch (orient)
111                {
112                 case E_GADGET_SITE_ORIENT_HORIZONTAL:
113                   s = "top";
114                   break;
115                 case E_GADGET_SITE_ORIENT_VERTICAL:
116                   s = "right";
117                   break;
118                 case E_GADGET_SITE_ORIENT_NONE:
119                   s = "right";
120                   break;
121                }
122           }
123         else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
124           {
125              switch (orient)
126                {
127                 case E_GADGET_SITE_ORIENT_HORIZONTAL:
128                   s = "bottom";
129                   break;
130                 case E_GADGET_SITE_ORIENT_VERTICAL:
131                   s = "right";
132                   break;
133                 case E_GADGET_SITE_ORIENT_NONE:
134                   s = "right";
135                   break;
136                }
137           }
138         else
139           s = "right";
140      }
141    else if (anchor & E_GADGET_SITE_ANCHOR_TOP)
142      s = "top";
143    else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM)
144      s = "bottom";
145    else
146      {
147         switch (orient)
148           {
149            case E_GADGET_SITE_ORIENT_HORIZONTAL:
150              s = "bottom";
151              break;
152            case E_GADGET_SITE_ORIENT_VERTICAL:
153              s = "left";
154              break;
155            default:
156              s = "bottom";
157              break;
158           }
159      }
160    return s;
161 }
162 
163 static Icon *
_bar_icon_match(Instance * inst,E_Client * ec)164 _bar_icon_match(Instance *inst, E_Client *ec)
165 {
166    Icon *ic = NULL, *ic2 = NULL;
167    Eina_Bool has_desktop = EINA_FALSE;
168    char ori[32];
169 
170    if (ec->exe_inst)
171      {
172         if (ec->exe_inst->desktop)
173           has_desktop = EINA_TRUE;
174      }
175    if (has_desktop)
176      {
177         ic = eina_hash_find(inst->icons_desktop_hash, ec->exe_inst->desktop->orig_path);
178         if ((ic) && (ic2 = eina_hash_find(inst->icons_clients_hash, &ec)))
179           {
180              ic2->execs = eina_list_remove(ic2->execs, ec->exe_inst);
181              ic2->clients = eina_list_remove(ic2->clients, ec);
182              if (ic2->client_cbs)
183                {
184                   ic2->client_cbs = eina_list_remove(ic2->client_cbs, ec);
185                   evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic2);
186                }
187              if (!eina_list_count(ic2->execs) && !eina_list_count(ic2->clients))
188                {
189                   eina_hash_del(inst->icons_clients_hash, ec, ic2);
190                   snprintf(ori, sizeof(ori), "e,state,off,%s", _bar_location_get(inst));
191                   elm_layout_signal_emit(ic2->o_layout, ori, "e");
192                   if (!ic2->in_order)
193                     _bar_icon_del(inst, ic2);
194                }
195           }
196      }
197    if (has_desktop && !ic)
198      ic = eina_hash_find(inst->icons_clients_hash, &ec);
199    if (!ic)
200      ic = eina_hash_find(inst->icons_clients_hash, &ec);
201 
202    return ic;
203 }
204 
205 static void
_bar_instance_watch(void * data,E_Exec_Instance * ex,E_Exec_Watch_Type type)206 _bar_instance_watch(void *data, E_Exec_Instance *ex, E_Exec_Watch_Type type)
207 {
208    Icon *ic = data;
209    char ori[32];
210 
211    switch (type)
212      {
213       case E_EXEC_WATCH_STARTED:
214         if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
215         ic->starting = EINA_FALSE;
216         if (!ic->execs && ic->inst->cfg->type != E_LUNCHER_MODULE_LAUNCH_ONLY)
217           {
218              snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(ic->inst));
219              elm_layout_signal_emit(ic->o_layout, ori, "e");
220           }
221         if (!eina_list_data_find(ic->execs, ex) && ic->inst->cfg->type != E_LUNCHER_MODULE_LAUNCH_ONLY)
222           ic->execs = eina_list_append(ic->execs, ex);
223         break;
224       case E_EXEC_WATCH_TIMEOUT:
225       case E_EXEC_WATCH_STOPPED:
226         ic->exec = NULL;
227         break;
228       default:
229         break;
230      }
231 }
232 
233 static void
_bar_icon_del(Instance * inst,Icon * ic)234 _bar_icon_del(Instance *inst, Icon *ic)
235 {
236    E_Client *ec;
237 
238    inst->icons = eina_list_remove(inst->icons, ic);
239    if (ic->client_menu)
240      evas_object_event_callback_del_full(ic->client_menu, EVAS_CALLBACK_HIDE, _bar_icon_preview_menu_hide, ic);
241    if (ic->preview)
242      _bar_icon_preview_hide(ic);
243    if (!inst->main_del)
244      _bar_aspect(inst);
245    evas_object_del(ic->o_icon);
246    evas_object_del(ic->o_layout);
247    eina_hash_del_by_data(inst->icons_desktop_hash, ic);
248    eina_hash_del_by_data(inst->icons_clients_hash, ic);
249    if (ic->desktop)
250      efreet_desktop_unref(ic->desktop);
251    eina_list_free(ic->execs);
252    eina_list_free(ic->clients);
253    EINA_LIST_FREE(ic->client_cbs, ec)
254      evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic);
255    eina_stringshare_del(ic->icon);
256    eina_stringshare_del(ic->key);
257    if (ic->exec)
258      e_exec_instance_watcher_del(ic->exec, _bar_instance_watch, ic);
259    ic->exec = NULL;
260    E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
261    E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
262    E_FREE(ic);
263 }
264 
265 #if 0
266 static void
267 _bar_icon_menu_icon_mouse_out(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
268 {
269    elm_layout_signal_emit(obj, "e,state,unfocused", "e");
270 }
271 
272 static void
273 _bar_icon_menu_icon_mouse_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
274 {
275    Evas_Event_Mouse_In *ev = event_data;
276 
277    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
278    if (_bar_check_modifiers(ev->modifiers)) return;
279 
280    elm_layout_signal_emit(obj, "e,state,focused", "e");
281 }
282 
283 static Evas_Object *
284 _bar_icon_menu_item_new(Icon *ic, Evas_Object *popup, Evas_Object *parent, const char *name, const char *icon)
285 {
286    const char *path = NULL, *k = NULL;
287    char buf[4096];
288    int len = 0;
289    Evas_Object *layout, *label, *img;
290 
291    layout = elm_layout_add(parent);
292    e_theme_edje_object_set(layout, "e/gadget/luncher/preview",
293        "e/gadget/luncher/preview");
294    evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
295    evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_IN, _bar_icon_menu_icon_mouse_in, NULL);
296    evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_OUT, _bar_icon_menu_icon_mouse_out, NULL);
297    elm_layout_signal_emit(layout, "e,state,icon,menu", "e");
298    elm_box_pack_end(parent, layout);
299    evas_object_data_set(layout, "popup", popup);
300    evas_object_data_set(layout, "content", parent);
301    evas_object_show(layout);
302 
303    label = elm_label_add(layout);
304    elm_object_style_set(label, "luncher_preview");
305    elm_label_ellipsis_set(label, EINA_TRUE);
306    elm_object_text_set(label, name);
307    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
308    elm_layout_content_set(layout, "e.swallow.title", label);
309    evas_object_show(label);
310 
311    img = elm_icon_add(layout);
312    evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
313    if (!icon)
314      path = NULL;
315    else if (strncmp(icon, "/", 1) && !ecore_file_exists(icon))
316      {
317         path = efreet_icon_path_find(e_config->icon_theme, icon, ic->inst->size);
318         if (!path)
319           {
320              if (e_util_strcmp(e_config->icon_theme, "hicolor"))
321              path = efreet_icon_path_find("hicolor", icon, ic->inst->size);
322           }
323      }
324    else if (ecore_file_exists(icon))
325      {
326         path = icon;
327      }
328    if (!path && icon)
329      {
330         snprintf(buf, sizeof(buf), "e/icons/%s", icon);
331         if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf)))
332           {
333              path = e_theme_edje_file_get("base/theme/icons", buf);
334              k = buf;
335           }
336         else
337           {
338              path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
339              k =  "e/icons/unknown";
340           }
341      }
342    else if (!path && !icon)
343      {
344         path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
345         k =  "e/icons/unknown";
346      }
347    if (path && icon)
348      {
349         len = strlen(icon);
350         if ((len > 4) && (!strcasecmp(icon + len - 4, ".edj")))
351         k = "icon";
352      }
353    elm_image_file_set(img, path, k);
354    elm_layout_content_set(layout, "e.swallow.icon", img);
355    evas_object_show(img);
356 
357    elm_layout_sizing_eval(layout);
358 
359    return layout;
360 }
361 #endif
362 
363 static void
_bar_icon_drag_done(E_Drag * drag,int dropped)364 _bar_icon_drag_done(E_Drag *drag, int dropped)
365 {
366    Instance *inst = e_object_data_get(E_OBJECT(drag));
367 
368    efreet_desktop_unref(drag->data);
369    if (!inst) return;
370    evas_object_smart_callback_call(e_gadget_site_get(inst->o_main), "gadget_site_unlocked", NULL);
371    if (!dropped)
372      bar_recalculate(inst);
373 }
374 
375 static Eina_Bool
_bar_icon_preview_hide(void * data)376 _bar_icon_preview_hide(void *data)
377 {
378    Icon *ic = data;
379 
380    if (!ic) return EINA_FALSE;
381 
382    ic->mouse_out_timer = NULL;
383 
384    if (!ic->preview || ic->preview_dismissed)
385      {
386         ic->active = EINA_FALSE;
387         return EINA_FALSE;
388      }
389    E_FREE_FUNC(ic->preview_box, evas_object_del);
390    E_FREE_FUNC(ic->preview_scroller, evas_object_del);
391    elm_ctxpopup_dismiss(ic->preview);
392    ic->preview_dismissed = EINA_TRUE;
393    ic->inst->current_preview = NULL;
394    ic->inst->current_preview_menu = EINA_FALSE;
395    ic->active = EINA_FALSE;
396 
397    return EINA_FALSE;
398 }
399 
400 static void
_bar_icon_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)401 _bar_icon_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
402 {
403    Icon *ic = data;
404 
405    elm_layout_signal_emit(ic->o_layout, "e,state,default", "e");
406    elm_layout_signal_emit(ic->o_layout, "e,state,unfocused", "e");
407    ic->active = EINA_FALSE;
408    if (!ic->inst->cfg->hide_tooltips)
409      elm_object_tooltip_hide(obj);
410    E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
411    E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
412    ic->mouse_out_timer = ecore_timer_loop_add(.25, _bar_icon_preview_hide, ic);
413 }
414 
415 static void
_bar_icon_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)416 _bar_icon_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
417 {
418    Icon *ic = data;
419    Evas_Event_Mouse_Move *ev = event_data;
420    int dx, dy;
421 
422    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
423    if (_bar_check_modifiers(ev->modifiers)) return;
424 
425    if (!ic->drag.start)
426      return;
427 
428    dx = ev->cur.output.x - ic->drag.x;
429    dy = ev->cur.output.y - ic->drag.y;
430    if (((dx * dx) + (dy * dy)) >
431        (e_config->drag_resist * e_config->drag_resist))
432      {
433         E_Drag *d;
434         Evas_Object *o;
435         Evas_Coord x, y, w, h;
436         unsigned int size;
437         const char *drag_types[] = { "enlightenment/desktop" };
438 
439         _bar_icon_preview_hide(ic);
440         ic->drag.dnd = 1;
441         ic->drag.start = 0;
442 
443         evas_object_geometry_get(ic->o_icon, &x, &y, &w, &h);
444         d = e_drag_new(x, y, drag_types, 1,
445                        ic->desktop, -1, NULL, _bar_icon_drag_done);
446         d->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
447         efreet_desktop_ref(ic->desktop);
448         size = MAX(w, h);
449         o = e_util_desktop_icon_add(ic->desktop, size, e_drag_evas_get(d));
450         e_drag_object_set(d, o);
451 
452         e_drag_resize(d, w, h);
453         e_drag_start(d, ic->drag.x, ic->drag.y);
454         e_object_data_set(E_OBJECT(d), ic->inst);
455         if (ic->in_order)
456           e_order_remove(ic->inst->order, ic->desktop);
457      }
458 }
459 
460 static Eina_Bool
_bar_drag_timer(void * data)461 _bar_drag_timer(void *data)
462 {
463    Icon *ic = data;
464 
465    ic->drag_timer = NULL;
466    ic->drag.start = 1;
467    evas_object_smart_callback_call(e_gadget_site_get(ic->inst->o_main), "gadget_site_locked", NULL);
468    return EINA_FALSE;
469 }
470 
471 static void
_bar_icon_menu_action_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)472 _bar_icon_menu_action_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
473 {
474    Efreet_Desktop_Action *action = (Efreet_Desktop_Action*)data;
475 
476    e_exec(e_zone_current_get(), NULL, action->exec, NULL, "luncher");
477 }
478 
479 static void
_bar_icon_menu_add_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)480 _bar_icon_menu_add_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
481 {
482    Icon *ic = data;
483 
484    if (ic->desktop)
485      e_order_append(ic->inst->order, ic->desktop);
486 }
487 
488 static void
_bar_icon_menu_remove_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)489 _bar_icon_menu_remove_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
490 {
491    Icon *ic = data;
492 
493    if (ic->desktop)
494      e_order_remove(ic->inst->order, ic->desktop);
495 }
496 
497 static void
_bar_icon_menu_properties_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)498 _bar_icon_menu_properties_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
499 {
500    Icon *ic = data;
501 
502    if (ic->desktop)
503      e_desktop_edit(ic->desktop);
504 }
505 
506 static void
_bar_gadget_menu_populate(Evas_Object * g,E_Menu * m)507 _bar_gadget_menu_populate(Evas_Object *g, E_Menu *m)
508 {
509    Instance *inst = evas_object_data_get(g, "instance");
510    Evas *e = evas_object_evas_get(g);
511    Eina_List *l;
512    Icon *ic = NULL;
513    Evas_Coord px, py;
514    E_Menu_Item *mi;
515    Efreet_Desktop_Action *action;
516 
517    evas_pointer_canvas_xy_get(e, &px, &py);
518    EINA_LIST_FOREACH(inst->icons, l, ic)
519      {
520         Evas_Coord x, y, w, h;
521 
522         evas_object_geometry_get(ic->o_icon, &x, &y, &w, &h);
523         if (E_INSIDE(px, py, x, y, w, h)) break;
524         ic = NULL;
525      }
526    if (!ic) return;
527 
528    mi = e_menu_item_new(m);
529    e_menu_item_separator_set(mi, 1);
530 
531    if (ic->desktop)
532      {
533         if (ic->desktop->actions)
534           {
535              EINA_LIST_FOREACH(ic->desktop->actions, l, action)
536                {
537                   mi = e_menu_item_new(m);
538                   e_menu_item_label_set(mi, action->name);
539                   e_util_menu_item_theme_icon_set(mi, action->icon);
540                   e_menu_item_callback_set(mi, _bar_icon_menu_action_cb, action);
541                }
542              mi = e_menu_item_new(m);
543              e_menu_item_separator_set(mi, 1);
544           }
545      }
546    if (ic->desktop)
547      {
548         mi = e_menu_item_new(m);
549         e_menu_item_label_set(mi, _("Icon Properties"));
550         e_util_menu_item_theme_icon_set(mi, "preferences-applications");
551         e_menu_item_callback_set(mi, _bar_icon_menu_properties_cb, ic);
552      }
553    if (ic->in_order)
554      {
555         mi = e_menu_item_new(m);
556         e_menu_item_label_set(mi, _("Remove Icon"));
557         e_util_menu_item_theme_icon_set(mi, "list-remove");
558         e_menu_item_callback_set(mi, _bar_icon_menu_remove_cb, ic);
559      }
560    else if ((!ic->in_order) && (ic->desktop))
561      {
562         mi = e_menu_item_new(m);
563         e_menu_item_label_set(mi, _("Add Icon"));
564         e_util_menu_item_theme_icon_set(mi, "list-add");
565         e_menu_item_callback_set(mi, _bar_icon_menu_add_cb, ic);
566      }
567 }
568 
569 static void
_bar_icon_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)570 _bar_icon_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
571 {
572    Icon *ic = data;
573    Evas_Event_Mouse_Up *ev = event_data;
574 
575    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
576    if (_bar_check_modifiers(ev->modifiers)) return;
577 
578    if (ev->button == 1)
579      {
580         E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
581         E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
582         ic->drag.x = ev->output.x;
583         ic->drag.y = ev->output.y;
584         E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
585         ic->drag_timer = ecore_timer_loop_add(0.35, _bar_drag_timer, ic);
586      }
587 }
588 
589 static void
_bar_icon_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)590 _bar_icon_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
591 {
592    Icon *ic = data;
593    Evas_Event_Mouse_Up *ev = event_data;
594 
595    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
596      {
597         if (ev->button == 1)
598           {
599              ic->drag.start = 0;
600              ic->drag.dnd = 0;
601              E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
602              E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
603              E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
604           }
605         return;
606      }
607    if (_bar_check_modifiers(ev->modifiers)) return;
608 
609    if (ev->button == 1)
610      {
611         E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
612         if (ic->drag.dnd)
613           {
614              ic->drag.start = 0;
615              ic->drag.dnd = 0;
616              return;
617           }
618      }
619    if (ev->button == 1 && ic->desktop)
620      {
621         if (ic->desktop->type == EFREET_DESKTOP_TYPE_APPLICATION)
622           {
623              E_Exec_Instance *ex;
624 
625              ex = e_exec(e_zone_current_get(), ic->desktop, NULL, NULL, "luncher");
626              ic->exec = ex;
627              e_exec_instance_watcher_add(ex, _bar_instance_watch, ic);
628              if (!ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,starting", "e");
629              ic->starting = EINA_TRUE;
630           }
631         else if (ic->desktop->type == EFREET_DESKTOP_TYPE_LINK)
632           {
633              if (!strncasecmp(ic->desktop->url, "file:", 5))
634                {
635                   E_Action *act;
636 
637                   act = e_action_find("fileman");
638                   if (act)
639                     act->func.go(NULL, ic->desktop->url + 5);
640                }
641           }
642      }
643    else if (ev->button == 1 && !ic->in_order)
644      {
645         _bar_icon_preview_show(ic);
646      }
647 }
648 
649 static void
_bar_icon_preview_item_mouse_out(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)650 _bar_icon_preview_item_mouse_out(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
651 {
652    elm_layout_signal_emit(obj, "e,state,unfocused", "e");
653 }
654 
655 static void
_bar_icon_preview_item_mouse_in(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data)656 _bar_icon_preview_item_mouse_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
657 {
658    Evas_Event_Mouse_In *ev = event_data;
659 
660    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
661    if (_bar_check_modifiers(ev->modifiers)) return;
662 
663    elm_layout_signal_emit(obj, "e,state,focused", "e");
664 }
665 
666 static void
_bar_icon_preview_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)667 _bar_icon_preview_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
668 {
669    Icon *ic = data;
670 
671    if (ic->inst->current_preview_menu)
672      return;
673    E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
674    ic->mouse_out_timer = ecore_timer_loop_add(0.25, _bar_icon_preview_hide, ic);
675 }
676 
677 static void
_bar_icon_preview_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)678 _bar_icon_preview_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
679 {
680    Icon *ic = data;
681    Evas_Event_Mouse_In *ev = event_data;
682 
683    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
684    if (_bar_check_modifiers(ev->modifiers)) return;
685 
686    E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
687 }
688 
689 static void
_bar_icon_preview_menu_hide(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)690 _bar_icon_preview_menu_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
691 {
692    Icon *ic = data;
693 
694    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _bar_icon_preview_menu_hide, ic);
695    ic->client_menu = NULL;
696    if (ic->preview)
697      {
698         ic->inst->current_preview_menu = EINA_FALSE;
699         _bar_icon_preview_mouse_out(ic, NULL, NULL, NULL);
700      }
701 }
702 
703 static void
_bar_icon_preview_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data)704 _bar_icon_preview_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
705 {
706    E_Client *ec = data;
707    Evas_Event_Mouse_Up *ev = event_data;
708    Icon *ic = evas_object_data_get(obj, "icon");
709 
710    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
711    if (_bar_check_modifiers(ev->modifiers)) return;
712 
713    if (ev->button == 3)
714      {
715         e_int_client_menu_show(ec, ev->canvas.x, ev->canvas.y, 0, ev->timestamp);
716         evas_object_event_callback_add(ec->border_menu->comp_object, EVAS_CALLBACK_HIDE,
717             _bar_icon_preview_menu_hide, ic);
718         ic->client_menu = ec->border_menu->comp_object;
719         ic->inst->current_preview_menu = EINA_TRUE;
720         return;
721      }
722    e_client_activate(ec, 1);
723    _bar_icon_preview_hide(ic);
724 }
725 
726 static void
_bar_icon_preview_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)727 _bar_icon_preview_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
728 {
729    Evas_Object *img = data;
730 
731    evas_object_del(img);
732 }
733 
734 static void
_bar_icon_preview_client_add(Icon * ic,E_Client * ec)735 _bar_icon_preview_client_add(Icon *ic, E_Client *ec)
736 {
737    Evas_Object *layout, *label, *img;
738 
739    layout = elm_layout_add(ic->preview_box);
740    edje_object_update_hints_set(elm_layout_edje_get(layout), EINA_TRUE);
741    evas_object_data_set(layout, "icon", ic);
742    e_theme_edje_object_set(layout, "e/gadget/luncher/preview",
743        "e/gadget/luncher/preview");
744    evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
745    evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
746    evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_IN,
747        _bar_icon_preview_item_mouse_in, ic);
748    evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_OUT,
749        _bar_icon_preview_item_mouse_out, ic);
750    elm_box_pack_end(ic->preview_box, layout);
751    evas_object_show(layout);
752 
753    label = elm_label_add(layout);
754    elm_object_style_set(label, "luncher_preview");
755    elm_label_ellipsis_set(label, EINA_TRUE);
756    elm_object_text_set(label, e_client_util_name_get(ec));
757    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
758    elm_layout_content_set(layout, "e.swallow.title", label);
759    evas_object_show(label);
760 
761    img = e_comp_object_util_mirror_add(ec->frame);
762    evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, ec->client.w, ec->client.h);
763    evas_object_size_hint_min_set(img, ic->inst->cfg->preview_size, ic->inst->cfg->preview_size);
764    elm_layout_content_set(layout, "e.swallow.icon", img);
765    if (evas_object_image_alpha_get(img))
766      elm_layout_signal_emit(layout, "e,state,icon,alpha", "e");
767    evas_object_show(img);
768 
769    if (!(ec->desk->visible) || (ec->iconic))
770      elm_layout_signal_emit(layout, "e,state,invisible", "e");
771 
772    evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_UP,
773        _bar_icon_preview_mouse_up, ec);
774    evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL,
775        _bar_icon_preview_del, img);
776    elm_layout_sizing_eval(layout);
777 }
778 
779 static Eina_Bool
_bar_icon_preview_show(void * data)780 _bar_icon_preview_show(void *data)
781 {
782    Icon *ic = data;
783    Eina_List *l, *ll;
784    E_Client *ec;
785    E_Exec_Instance *ex;
786    Eina_List *clients = NULL;
787    E_Gadget_Site_Orient orient;
788    E_Zone *zone = e_zone_current_get();
789    int count = 0;
790 
791    if (!ic)
792      return EINA_FALSE;
793    ic->mouse_in_timer = NULL;
794    if (ic->drag.dnd)
795      return EINA_FALSE;
796    if (!ic->inst)
797      return EINA_FALSE;
798    if (!ic->inst->o_icon_con)
799      return EINA_FALSE;
800 
801    orient = e_gadget_site_orient_get(e_gadget_site_get(ic->inst->o_main));
802 
803    if (ic->inst->current_preview && (ic->inst->current_preview != ic->preview))
804      _bar_icon_preview_hide(evas_object_data_get(ic->inst->current_preview, "icon"));
805    if (ic->preview && !ic->preview_dismissed)
806      _bar_icon_preview_hide(ic);
807    ic->preview_dismissed = EINA_FALSE;
808    if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients))
809      return EINA_FALSE;
810 
811    ic->preview = elm_ctxpopup_add(e_comp->elm);
812    elm_object_style_set(ic->preview, "noblock");
813    evas_object_smart_callback_add(ic->preview, "dismissed", _bar_popup_dismissed, ic);
814    evas_object_event_callback_add(ic->preview, EVAS_CALLBACK_MOUSE_IN,
815        _bar_icon_preview_mouse_in, ic);
816    evas_object_event_callback_add(ic->preview, EVAS_CALLBACK_MOUSE_OUT,
817        _bar_icon_preview_mouse_out, ic);
818 
819    ic->preview_scroller = elm_scroller_add(ic->preview);
820    elm_scroller_content_min_limit(ic->preview_scroller, EINA_TRUE, EINA_TRUE);
821    evas_object_size_hint_max_set(ic->preview_scroller, zone->w - 15, zone->h - 15);
822    elm_object_style_set(ic->preview_scroller, "no_inset_shadow");
823    E_EXPAND(ic->preview_scroller);
824 
825    ic->preview_box = elm_box_add(ic->preview);
826    evas_object_size_hint_align_set(ic->preview_box, 0, 0);
827    switch (orient)
828      {
829         case E_GADGET_SITE_ORIENT_HORIZONTAL:
830           elm_box_horizontal_set(ic->preview_box, EINA_TRUE);
831           elm_box_padding_set(ic->preview_box, 2, 0);
832 	  break;
833         case E_GADGET_SITE_ORIENT_VERTICAL:
834           elm_box_horizontal_set(ic->preview_box, EINA_FALSE);
835           elm_box_padding_set(ic->preview_box, 0, 2);
836 	  break;
837         default:
838           elm_box_horizontal_set(ic->preview_box, EINA_TRUE);
839           elm_box_padding_set(ic->preview_box, 2, 0);
840      }
841    EINA_LIST_FOREACH(ic->execs, l, ex)
842      {
843         EINA_LIST_FOREACH(ex->clients, ll, ec)
844           clients = eina_list_append(clients, ec);
845      }
846    EINA_LIST_FOREACH(ic->clients, l, ec)
847      clients = eina_list_append(clients, ec);
848 
849    EINA_LIST_FREE(clients, ec)
850      {
851         if (ec && !ec->netwm.state.skip_taskbar && !e_client_util_ignored_get(ec))
852           {
853              if (!e_client_util_is_popup(ec))
854                {
855                   _bar_icon_preview_client_add(ic, ec);
856                   count++;
857                }
858           }
859      }
860 
861    if (!count)
862      {
863         _bar_icon_preview_hide(ic);
864         return EINA_FALSE;
865      }
866    elm_object_content_set(ic->preview_scroller, ic->preview_box);
867    elm_object_content_set(ic->preview, ic->preview_scroller);
868    evas_object_show(ic->preview_box);
869 
870    e_gadget_util_ctxpopup_place(ic->inst->o_main, ic->preview, ic->o_icon);
871    evas_object_layer_set(ic->preview, E_LAYER_POPUP);
872 
873    evas_object_data_del(ic->preview, "icon");
874    evas_object_data_set(ic->preview, "icon", ic);
875    evas_object_show(ic->preview);
876    ic->inst->current_preview = ic->preview;
877 
878    return EINA_FALSE;
879 }
880 
881 static void
_bar_icon_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data)882 _bar_icon_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
883 {
884    Icon *ic = data;
885    Eina_Bool clients = EINA_FALSE;
886    Evas_Event_Mouse_In *ev = event_data;
887 
888    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
889    if (_bar_check_modifiers(ev->modifiers)) return;
890 
891    if (!ic->active)
892      {
893         if (!ic->inst->cfg->hide_tooltips)
894           elm_object_tooltip_show(obj);
895         ic->active = EINA_TRUE;
896         elm_layout_signal_emit(ic->o_layout, "e,state,focused", "e");
897      }
898    E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
899    E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
900    if (ic->inst->current_preview && (ic->preview == ic->inst->current_preview)) return;
901    if (eina_list_count(ic->execs) || eina_list_count(ic->clients))
902      clients = EINA_TRUE;
903    if (clients && ic->inst->current_preview && !ic->inst->current_preview_menu)
904      ic->mouse_in_timer = ecore_timer_loop_add(0.2, _bar_icon_preview_show, ic);
905    else if (clients && !ic->inst->current_preview)
906      ic->mouse_in_timer = ecore_timer_loop_add(0.3, _bar_icon_preview_show, ic);
907 }
908 
909 static void
_bar_exec_new_show(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)910 _bar_exec_new_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
911 {
912    Icon *ic = data;
913    E_Client *ec = e_comp_object_client_get(obj);
914 
915    if (ic->preview && (ic->inst->current_preview == ic->preview))
916      {
917         _bar_icon_preview_client_add(ic, ec);
918      }
919    else
920      {
921         if (ic->active)
922           {
923              E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
924              E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
925              if (ic->inst->current_preview && !ic->inst->current_preview_menu)
926                _bar_icon_preview_show(ic);
927              else if (!ic->inst->current_preview)
928                ic->mouse_in_timer = ecore_timer_loop_add(0.3, _bar_icon_preview_show, ic);
929           }
930      }
931    ic->client_cbs = eina_list_remove(ic->client_cbs, ec);
932    evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic);
933 }
934 
935 static void
_bar_icon_file_set(Icon * ic,Efreet_Desktop * desktop,E_Client * non_desktop_client)936 _bar_icon_file_set(Icon *ic, Efreet_Desktop *desktop, E_Client *non_desktop_client)
937 {
938    const char *path = NULL, *k = NULL;
939    char buf[4096];
940    int len = 0, clamp = 0;
941    if (desktop)
942      {
943         if (!desktop->icon)
944           path = NULL;
945         else if (strncmp(desktop->icon, "/", 1) && !ecore_file_exists(desktop->icon))
946           {
947              clamp = MAX((4 * round((double)ic->inst->size/4)), 8);
948              path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, clamp);
949              if (!path)
950                {
951                   if (e_util_strcmp(e_config->icon_theme, "hicolor"))
952                     path = efreet_icon_path_find("hicolor", desktop->icon, clamp);
953                }
954           }
955         else if (ecore_file_exists(desktop->icon))
956           {
957              path = desktop->icon;
958           }
959         if (!path && desktop->icon)
960           {
961              snprintf(buf, sizeof(buf), "e/icons/%s", desktop->icon);
962              if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf)))
963                {
964                   path = e_theme_edje_file_get("base/theme/icons", buf);
965                   k = buf;
966                }
967              else
968                {
969                   path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
970                   k =  "e/icons/unknown";
971                }
972           }
973         else if (!path && !desktop->icon)
974           {
975              path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
976              k = "e/icons/unknown";
977           }
978         if (path && desktop->icon && !k)
979           {
980              len = strlen(desktop->icon);
981              if ((len > 4) && (!strcasecmp(desktop->icon + len - 4, ".edj")))
982                k = "icon";
983           }
984      }
985    else if (non_desktop_client)
986      {
987         Evas_Object *tmp;
988         const char *file, *group;
989         Eina_Bool ret = EINA_FALSE;
990 
991         tmp = e_client_icon_add(non_desktop_client, evas_object_evas_get(ic->o_layout));
992         if (isedje(tmp))
993           {
994              edje_object_file_get(tmp, &file, &group);
995              if (file && group)
996                ret = EINA_TRUE;
997           }
998         else
999           ret = e_icon_file_get(tmp, &file, &group);
1000         if (ret)
1001           {
1002              eina_stringshare_replace(&ic->icon, file);
1003              eina_stringshare_replace(&ic->key, group);
1004              path = ic->icon;
1005              k = ic->key;
1006           }
1007         evas_object_del(tmp);
1008      }
1009    else if (ic->icon)
1010      {
1011         if (strncmp(ic->icon, "/", 1) && !ecore_file_exists(ic->icon))
1012           {
1013              clamp = (4 * round((double)ic->inst->size/4));
1014              path = efreet_icon_path_find(e_config->icon_theme, ic->icon, clamp);
1015              if (!path)
1016                {
1017                   if (e_util_strcmp(e_config->icon_theme, "hicolor"))
1018                     path = efreet_icon_path_find("hicolor", ic->icon, clamp);
1019                }
1020           }
1021         else if (ecore_file_exists(ic->icon))
1022           {
1023              path = ic->icon;
1024              k = ic->key;
1025           }
1026         if (!path)
1027           {
1028              path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
1029              k = "e/icons/unknown";
1030           }
1031      }
1032    else
1033      {
1034         path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
1035         k = "e/icons/unknown";
1036      }
1037    elm_image_file_set(ic->o_icon, path, k);
1038 }
1039 
1040 static void
_bar_resized_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1041 _bar_resized_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1042 {
1043    Instance *inst = data;
1044 
1045    _bar_aspect(inst);
1046 }
1047 
1048 static Icon *
_bar_icon_add(Instance * inst,Efreet_Desktop * desktop,E_Client * non_desktop_client)1049 _bar_icon_add(Instance *inst, Efreet_Desktop *desktop, E_Client *non_desktop_client)
1050 {
1051    char ori[32];
1052    Icon *ic;
1053    const Eina_List *l;
1054 
1055    ic = E_NEW(Icon, 1);
1056    if (desktop)
1057      efreet_desktop_ref(desktop);
1058    ic->desktop = desktop;
1059    ic->inst = inst;
1060    ic->preview = NULL;
1061    ic->preview_box = NULL;
1062    ic->preview_scroller = NULL;
1063    ic->client_menu = NULL;
1064    ic->mouse_in_timer = NULL;
1065    ic->mouse_out_timer = NULL;
1066    ic->active = EINA_FALSE;
1067    ic->starting = EINA_FALSE;
1068    ic->preview_dismissed = EINA_FALSE;
1069    ic->exec = NULL;
1070 
1071    ic->o_layout = elm_layout_add(inst->o_icon_con);
1072    edje_object_update_hints_set(elm_layout_edje_get(ic->o_layout), EINA_TRUE);
1073    e_theme_edje_object_set(ic->o_layout, "e/gadget/luncher/icon",
1074        "e/gadget/luncher/icon");
1075    E_EXPAND(ic->o_layout);
1076    E_FILL(ic->o_layout);
1077    edje_object_signal_callback_add(elm_layout_edje_get(ic->o_layout), "e,state,resized", "e", _bar_resized_cb, inst);
1078    elm_box_pack_end(inst->o_icon_con, ic->o_layout);
1079    evas_object_show(ic->o_layout);
1080 
1081    snprintf(ori, sizeof(ori), "e,state,off,%s", _bar_location_get(inst));
1082    elm_layout_signal_emit(ic->o_layout, ori, "e");
1083 
1084    ic->o_icon = elm_icon_add(ic->o_layout);
1085    E_EXPAND(ic->o_icon);
1086 
1087 
1088    _bar_icon_file_set(ic, desktop, non_desktop_client);
1089 
1090    if (!inst->cfg->hide_tooltips)
1091      {
1092         if (desktop)
1093           elm_object_tooltip_text_set(ic->o_icon, desktop->name);
1094         else if (non_desktop_client && non_desktop_client->icccm.class)
1095           elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.class);
1096         else if (non_desktop_client && non_desktop_client->icccm.name)
1097           elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.name);
1098         else if (non_desktop_client && non_desktop_client->icccm.title)
1099           elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.title);
1100         else if (non_desktop_client && non_desktop_client->netwm.name)
1101           elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->netwm.name);
1102         else
1103           elm_object_tooltip_text_set(ic->o_icon, _("Unknown"));
1104         elm_object_tooltip_orient_set(ic->o_icon, ELM_TOOLTIP_ORIENT_CENTER);
1105         elm_object_tooltip_style_set(ic->o_icon, "luncher");
1106      }
1107    evas_object_size_hint_aspect_set(ic->o_icon, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
1108    elm_layout_content_set(ic->o_layout, "e.swallow.icon", ic->o_icon);
1109    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_UP,
1110        _bar_icon_mouse_up, ic);
1111    evas_object_event_callback_priority_add(ic->o_icon, EVAS_CALLBACK_MOUSE_DOWN, 0,
1112        _bar_icon_mouse_down, ic);
1113    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_MOVE,
1114        _bar_icon_mouse_move, ic);
1115    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_IN,
1116        _bar_icon_mouse_in, ic);
1117    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_OUT,
1118        _bar_icon_mouse_out, ic);
1119    evas_object_show(ic->o_icon);
1120 
1121    if (desktop)
1122      eina_hash_add(inst->icons_desktop_hash, eina_stringshare_add(desktop->orig_path), ic);
1123    else
1124      eina_hash_add(inst->icons_clients_hash, &non_desktop_client, ic);
1125 
1126    if (desktop)
1127      {
1128         if (inst->cfg->type != E_LUNCHER_MODULE_LAUNCH_ONLY)
1129           {
1130              l = e_exec_desktop_instances_find(desktop);
1131              if (l)
1132                {
1133                   snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1134                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1135                   ic->execs = eina_list_clone(l);
1136                }
1137           }
1138      }
1139    else
1140      {
1141         if (!_bar_check_for_duplicates(ic, non_desktop_client))
1142           ic->clients = eina_list_append(ic->clients, non_desktop_client);
1143      }
1144    elm_layout_sizing_eval(ic->o_layout);
1145    _bar_aspect(inst);
1146    return ic;
1147 }
1148 
1149 static Eina_Bool
_bar_cb_desk_switch(void * data EINA_UNUSED,int type EINA_UNUSED,E_Event_Client * ev EINA_UNUSED)1150 _bar_cb_desk_switch(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client *ev EINA_UNUSED)
1151 {
1152    Instance *inst = NULL;
1153    Icon *ic = NULL;
1154    Eina_List *l = NULL, *ll = NULL;
1155 
1156 
1157    EINA_LIST_FOREACH(luncher_instances, l, inst)
1158      {
1159         if (inst->current_preview)
1160           {
1161              EINA_LIST_FOREACH(inst->icons, ll, ic)
1162                {
1163                   if (inst->current_preview && (inst->current_preview == ic->preview))
1164                     {
1165                        _bar_icon_preview_show(ic);
1166                        return ECORE_CALLBACK_RENEW;
1167                     }
1168                }
1169           }
1170      }
1171    return ECORE_CALLBACK_RENEW;
1172 }
1173 
1174 static Eina_Bool
_bar_cb_client_remove(void * data EINA_UNUSED,int type EINA_UNUSED,E_Event_Client * ev)1175 _bar_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client *ev)
1176 {
1177    Instance *inst = NULL;
1178    Eina_List *l = NULL;
1179    char ori[32];
1180 
1181    EINA_LIST_FOREACH(luncher_instances, l, inst)
1182      {
1183         Icon *ic = NULL;
1184 
1185         if (!inst->bar) continue;
1186         if (inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY) continue;
1187         ic = _bar_icon_match(inst, ev->ec);
1188         if (ic)
1189           {
1190              if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
1191              ic->starting = EINA_FALSE;
1192              ic->clients = eina_list_remove(ic->clients, ev->ec);
1193              if (ic->client_cbs)
1194                {
1195                   ic->client_cbs = eina_list_remove(ic->client_cbs, ev->ec);
1196                   evas_object_event_callback_del_full(ev->ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic);
1197                }
1198              if (ev->ec->exe_inst)
1199                ic->execs = eina_list_remove(ic->execs, ev->ec->exe_inst);
1200              if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients))
1201                {
1202                   snprintf(ori, sizeof(ori), "e,state,off,%s", _bar_location_get(inst));
1203                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1204                   if (ic->preview)
1205                     _bar_icon_preview_hide(ic);
1206                   if (!ic->in_order)
1207                     _bar_icon_del(inst, ic);
1208                }
1209              else if (ic->preview && (inst->current_preview == ic->preview))
1210                {
1211                   _bar_icon_preview_show(ic);
1212                }
1213           }
1214      }
1215    return ECORE_CALLBACK_RENEW;
1216 }
1217 
1218 static Eina_Bool
_bar_cb_exec_del(void * data EINA_UNUSED,int type EINA_UNUSED,E_Exec_Instance * ex)1219 _bar_cb_exec_del(void *data EINA_UNUSED, int type EINA_UNUSED, E_Exec_Instance *ex)
1220 {
1221    Instance *inst = NULL;
1222    Eina_List *l = NULL;
1223    E_Client *ec = NULL;
1224    char ori[32];
1225 
1226    EINA_LIST_FOREACH(ex->clients, l, ec)
1227      {
1228         if (!ec->netwm.state.skip_taskbar && !e_client_util_is_popup(ec))
1229           {
1230              break;
1231           }
1232      }
1233 
1234    EINA_LIST_FOREACH(luncher_instances, l, inst)
1235      {
1236         Icon *ic = NULL;
1237 
1238         if (!inst->bar) continue;
1239         if (inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY) continue;
1240 	       if (ex->desktop)
1241           {
1242              ic = eina_hash_find(inst->icons_desktop_hash, ex->desktop->orig_path);
1243           }
1244         if (ic)
1245           {
1246              if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
1247              ic->starting = EINA_FALSE;
1248              ic->execs = eina_list_remove(ic->execs, ex);
1249              if (ec) ic->clients = eina_list_remove(ic->clients, ec);
1250              if (ec && ic->client_cbs)
1251                {
1252                   ic->client_cbs = eina_list_remove(ic->client_cbs, ec);
1253                   evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic);
1254                }
1255              if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients))
1256                {
1257                   snprintf(ori, sizeof(ori), "e,state,off,%s", _bar_location_get(inst));
1258                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1259                   if (ic->preview)
1260                     _bar_icon_preview_hide(ic);
1261                   if (!ic->in_order)
1262                     _bar_icon_del(inst, ic);
1263                }
1264              else if (ic->preview && (inst->current_preview == ic->preview))
1265                {
1266                   _bar_icon_preview_show(ic);
1267                }
1268           }
1269      }
1270    return ECORE_CALLBACK_RENEW;
1271 }
1272 
1273 static Eina_Bool
_bar_cb_exec_client_prop(void * data EINA_UNUSED,int type EINA_UNUSED,E_Event_Client_Property * ev)1274 _bar_cb_exec_client_prop(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client_Property *ev)
1275 {
1276    Instance *inst = NULL;
1277    E_Client *ec = NULL;
1278    Eina_List *l = NULL;
1279    Eina_Bool skip;
1280    Eina_Bool has_desktop = EINA_TRUE;
1281 
1282    if (e_client_util_ignored_get(ev->ec))
1283      return ECORE_CALLBACK_RENEW;
1284    if ((!(ev->property & E_CLIENT_PROPERTY_NETWM_STATE)) && (!(ev->property & E_CLIENT_PROPERTY_ICON))
1285        && (!(ev->property & E_CLIENT_PROPERTY_URGENCY)))
1286      return ECORE_CALLBACK_RENEW;
1287 
1288    if (!ev->ec->exe_inst)
1289      has_desktop = EINA_FALSE;
1290    if (ev->ec->exe_inst)
1291      {
1292         if (!ev->ec->exe_inst->desktop)
1293           has_desktop = EINA_FALSE;
1294      }
1295    if (has_desktop)
1296      {
1297         skip = EINA_TRUE;
1298         EINA_LIST_FOREACH(ev->ec->exe_inst->clients, l, ec)
1299           {
1300              if (!ec->netwm.state.skip_taskbar && !e_client_util_is_popup(ec))
1301                {
1302                   skip = EINA_FALSE;
1303                   break;
1304                }
1305           }
1306      }
1307    else
1308      {
1309         if (ev->ec->netwm.state.skip_taskbar || e_client_util_is_popup(ev->ec))
1310           skip = EINA_TRUE;
1311         else
1312           skip = EINA_FALSE;
1313      }
1314    EINA_LIST_FOREACH(luncher_instances, l, inst)
1315      {
1316         Icon *ic = NULL;
1317         char ori[32];
1318 
1319         if (!inst->bar) continue;
1320         if (inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY) continue;
1321 	ic = _bar_icon_match(inst, ev->ec);
1322         if (skip && !ic) continue;
1323         if (!skip)
1324           {
1325              if (ic)
1326                {
1327                   if ((ev->property & E_CLIENT_PROPERTY_URGENCY))
1328                     {
1329                        if (ev->ec->urgent)
1330                          elm_layout_signal_emit(ic->o_layout, "e,state,urgent", "e");
1331                        else
1332                          elm_layout_signal_emit(ic->o_layout, "e,state,normal", "e");
1333                        return ECORE_CALLBACK_RENEW;
1334                     }
1335                   if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
1336                   ic->starting = EINA_FALSE;
1337                   snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1338                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1339                   if (has_desktop)
1340                     {
1341                        if (!(_bar_check_for_duplicates(ic, ev->ec)))
1342                          ic->execs = eina_list_append(ic->execs, ev->ec->exe_inst);
1343                     }
1344                   else
1345                     {
1346                        if (!(_bar_check_for_duplicates(ic, ev->ec)))
1347                          ic->clients = eina_list_append(ic->clients, ev->ec);
1348                     }
1349                }
1350              else
1351                {
1352                   if (has_desktop && !ev->ec->internal_elm_win)
1353                     ic = _bar_icon_add(inst, ev->ec->exe_inst->desktop, NULL);
1354                   else
1355                     ic = _bar_icon_add(inst, NULL, ev->ec);
1356                   snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1357                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1358                   ic->in_order = EINA_FALSE;
1359                   inst->icons = eina_list_append(inst->icons, ic);
1360                   _bar_aspect(inst);
1361                }
1362           }
1363         else
1364           {
1365              if (has_desktop)
1366                ic->execs = eina_list_remove(ic->execs, ev->ec->exe_inst);
1367              else
1368                ic->clients = eina_list_remove(ic->clients, ev->ec);
1369              if (ic->client_cbs)
1370                {
1371                   ic->client_cbs = eina_list_remove(ic->client_cbs, ev->ec);
1372                   evas_object_event_callback_del_full(ev->ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic);
1373                }
1374              if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients))
1375                {
1376                   if (ic->preview)
1377                     _bar_icon_preview_hide(ic);
1378                   if (!ic->in_order)
1379                     _bar_icon_del(inst, ic);
1380                   else
1381                     {
1382                        snprintf(ori, sizeof(ori), "e,state,off,%s", _bar_location_get(inst));
1383                        elm_layout_signal_emit(ic->o_layout, ori, "e");
1384                     }
1385                }
1386              else if (ic->preview && (inst->current_preview == ic->preview))
1387                {
1388                   _bar_icon_preview_show(ic);
1389                }
1390           }
1391      }
1392    return ECORE_CALLBACK_RENEW;
1393 }
1394 
1395 static Eina_Bool
_bar_cb_exec_new(void * data EINA_UNUSED,int type,E_Exec_Instance * ex)1396 _bar_cb_exec_new(void *data EINA_UNUSED, int type, E_Exec_Instance *ex)
1397 {
1398    Instance *inst = NULL;
1399    E_Client *ec = NULL;
1400    Eina_List *l = NULL;
1401    Eina_Bool skip;
1402 
1403    if (type == E_EVENT_EXEC_NEW_CLIENT)
1404      {
1405         ec = eina_list_last_data_get(ex->clients);
1406         if (ec->netwm.state.skip_taskbar || e_client_util_is_popup(ec))
1407           skip = EINA_TRUE;
1408         else
1409           skip = EINA_FALSE;
1410      }
1411    else
1412      {
1413         skip = EINA_TRUE;
1414         EINA_LIST_FOREACH(ex->clients, l, ec)
1415           {
1416              if (!ec->netwm.state.skip_taskbar && !e_client_util_is_popup(ec))
1417                {
1418                   skip = EINA_FALSE;
1419                   break;
1420                }
1421           }
1422      }
1423    EINA_LIST_FOREACH(luncher_instances, l, inst)
1424      {
1425         Icon *ic = NULL;
1426         char ori[32];
1427 
1428         if (!inst->bar) continue;
1429         if (inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY) continue;
1430         if (ec) ic = _bar_icon_match(inst, ec);
1431         if (ic)
1432           {
1433              if (skip) continue;
1434              if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
1435              ic->starting = EINA_FALSE;
1436              snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1437              elm_layout_signal_emit(ic->o_layout, ori, "e");
1438              if (!(_bar_check_for_duplicates(ic, ec)))
1439                {
1440                   if (ex->desktop)
1441                     ic->execs = eina_list_append(ic->execs, ex);
1442                   else
1443                     ic->clients = eina_list_append(ic->clients, ec);
1444                }
1445              if (evas_object_visible_get(ec->frame))
1446                _bar_exec_new_show(ic, NULL, ec->frame, NULL);
1447              else
1448                {
1449                   ic->client_cbs = eina_list_append(ic->client_cbs, ec);
1450                   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,
1451                     _bar_exec_new_show, ic);
1452                }
1453           }
1454         else
1455           {
1456              if (skip) continue;
1457              if (ex->desktop && !ec->internal_elm_win)
1458                ic = _bar_icon_add(inst, ex->desktop, NULL);
1459              else
1460                ic = _bar_icon_add(inst, NULL, ec);
1461              snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1462              elm_layout_signal_emit(ic->o_layout, ori, "e");
1463              ic->in_order = EINA_FALSE;
1464              inst->icons = eina_list_append(inst->icons, ic);
1465              _bar_aspect(inst);
1466           }
1467      }
1468    return ECORE_CALLBACK_RENEW;
1469 }
1470 
1471 static void
_bar_empty(Instance * inst)1472 _bar_empty(Instance *inst)
1473 {
1474    if (inst->icons)
1475      {
1476         elm_box_clear(inst->o_icon_con);
1477         while (inst->icons)
1478           _bar_icon_del(inst, eina_list_data_get(inst->icons));
1479         inst->icons = NULL;
1480      }
1481 }
1482 
1483 static void
_bar_fill(Instance * inst)1484 _bar_fill(Instance *inst)
1485 {
1486    const Eina_Hash *execs = e_exec_instances_get();
1487    Eina_Iterator *it;
1488    Eina_List *l, *ll, *lll;
1489    E_Exec_Instance *ex;
1490    E_Client *ec;
1491    Icon *ic;
1492    char ori[32];
1493 
1494    if (inst->order && inst->cfg->type != E_LUNCHER_MODULE_TASKS_ONLY)
1495      {
1496         Efreet_Desktop *desktop;
1497         Eina_List *list;
1498 
1499         EINA_LIST_FOREACH(inst->order->desktops, list, desktop)
1500           {
1501              ic = _bar_icon_add(inst, desktop, NULL);
1502              ic->in_order = EINA_TRUE;
1503              inst->icons = eina_list_append(inst->icons, ic);
1504           }
1505      }
1506    if (inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY)
1507      {
1508         _bar_aspect(inst);
1509         return;
1510      }
1511    it = eina_hash_iterator_data_new(execs);
1512    EINA_ITERATOR_FOREACH(it, l)
1513      {
1514         EINA_LIST_FOREACH(l, ll, ex)
1515           {
1516              Eina_Bool skip = EINA_TRUE;
1517 
1518              EINA_LIST_FOREACH(ex->clients, lll, ec)
1519                {
1520                   if (!ec->netwm.state.skip_taskbar && !e_client_util_is_popup(ec))
1521                     {
1522                        skip = EINA_FALSE;
1523                     }
1524                   if (skip) continue;
1525                   ic = _bar_icon_match(inst, ec);
1526                   if (ic)
1527                     {
1528                        if (!(_bar_check_for_duplicates(ic, ec)))
1529                          ic->execs = eina_list_append(ic->execs, ex);
1530                        continue;
1531                     }
1532                   if (!ec->internal_elm_win)
1533                     ic = _bar_icon_add(inst, ex->desktop, NULL);
1534                   else
1535                     ic = _bar_icon_add(inst, NULL, ec);
1536                   snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1537                   elm_layout_signal_emit(ic->o_layout, ori, "e");
1538                   ic->in_order = EINA_FALSE;
1539                   inst->icons = eina_list_append(inst->icons, ic);
1540                }
1541           }
1542      }
1543    eina_iterator_free(it);
1544    E_CLIENT_FOREACH(ec)
1545      {
1546         if (e_client_util_ignored_get(ec)) continue;
1547         if (ec->netwm.state.skip_taskbar) continue;
1548         if (e_client_util_is_popup(ec)) continue;
1549         ic = _bar_icon_match(inst, ec);
1550         if (!ic)
1551           {
1552              if (ec->exe_inst && ec->exe_inst->desktop && !ec->internal_elm_win)
1553                ic = _bar_icon_add(inst, ec->exe_inst->desktop, NULL);
1554              else
1555                ic = _bar_icon_add(inst, NULL, ec);
1556              snprintf(ori, sizeof(ori), "e,state,on,%s", _bar_location_get(inst));
1557              elm_layout_signal_emit(ic->o_layout, ori, "e");
1558              ic->in_order = EINA_FALSE;
1559              inst->icons = eina_list_append(inst->icons, ic);
1560           }
1561      }
1562    _bar_aspect(inst);
1563 }
1564 
1565 static void
_bar_resize_job(void * data)1566 _bar_resize_job(void *data)
1567 {
1568    Instance *inst = data;
1569    Eina_List *l;
1570    Icon *ic;
1571    E_Gadget_Site_Orient orient;
1572    Evas_Coord x, y, w, h, size;
1573 
1574    if (inst)
1575      {
1576         orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main));
1577         elm_layout_sizing_eval(inst->o_main);
1578         evas_object_geometry_get(inst->o_main, &x, &y, &w, &h);
1579         switch (orient)
1580           {
1581              case E_GADGET_SITE_ORIENT_HORIZONTAL:
1582                size = h;
1583                break;
1584              case E_GADGET_SITE_ORIENT_VERTICAL:
1585                size = w;
1586                break;
1587              default:
1588                size = h;
1589           }
1590         if (inst->size == size)
1591           {
1592              inst->resize_job = NULL;
1593              return;
1594           }
1595         inst->size = size;
1596         EINA_LIST_FOREACH(inst->icons, l, ic)
1597           _bar_icon_file_set(ic, ic->desktop, NULL);
1598         inst->resize_job = NULL;
1599      }
1600 }
1601 
1602 static Eina_Bool
_bar_cb_update_icons(EINA_UNUSED void * data,EINA_UNUSED int ev_type,EINA_UNUSED void * ev)1603 _bar_cb_update_icons(EINA_UNUSED void *data, EINA_UNUSED int ev_type, EINA_UNUSED void *ev)
1604 {
1605    Instance *inst = NULL;
1606    Eina_List *l, *ll;
1607    Icon *ic;
1608 
1609    EINA_LIST_FOREACH(luncher_instances, l, inst)
1610      {
1611         if (!inst->bar) continue;
1612         EINA_LIST_FOREACH(inst->icons, ll, ic)
1613           _bar_icon_file_set(ic, ic->desktop, eina_list_data_get(ic->clients));
1614      }
1615    return ECORE_CALLBACK_PASS_ON;
1616 }
1617 
1618 static void
_bar_resize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)1619 _bar_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
1620 {
1621    Instance *inst = data;
1622 
1623    if (inst->resize_job) return;
1624    inst->resize_job = ecore_job_add(_bar_resize_job, inst);
1625 }
1626 
1627 static void
_bar_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)1628 _bar_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
1629 {
1630    Instance *inst = data;
1631    Evas_Coord px, py, x, y, w, h;
1632    Eina_List *l = NULL;
1633    Icon *ic = NULL;
1634 
1635    evas_pointer_canvas_xy_get(evas_object_evas_get(inst->o_main), &px, &py);
1636    evas_object_geometry_get(inst->o_main, &x, &y, &w, &h);
1637 
1638    if (E_INSIDE(px, py, x, y, w, h)) return;
1639 
1640    EINA_LIST_FOREACH(inst->icons, l, ic)
1641      {
1642         elm_layout_signal_emit(ic->o_layout, "e,state,default", "e");
1643         elm_layout_signal_emit(ic->o_layout, "e,state,unfocused", "e");
1644         _bar_icon_mouse_out(ic, NULL, ic->o_icon, NULL);
1645      }
1646    _bar_aspect(inst);
1647 }
1648 
1649 static void
_bar_removed_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_data)1650 _bar_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
1651 {
1652    Instance *inst = data;
1653    char buf[4096];
1654 
1655    if (inst->o_main != event_data) return;
1656    if (e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", inst->cfg->dir) >= sizeof(buf))
1657      return;
1658 
1659    luncher_config->items = eina_list_remove(luncher_config->items, inst->cfg);
1660    eina_stringshare_del(inst->cfg->dir);
1661    E_FREE(inst->cfg);
1662 }
1663 
1664 static void
_bar_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)1665 _bar_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
1666 {
1667    Instance *inst = data;
1668    Ecore_Event_Handler *handler;
1669 
1670    evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_removed", _bar_removed_cb, inst);
1671    E_FREE_FUNC(inst->iconify_provider, e_comp_object_effect_mover_del);
1672    inst->main_del = EINA_TRUE;
1673    _bar_empty(inst);
1674    e_object_del(E_OBJECT(inst->order));
1675    E_FREE_FUNC(inst->drop_handler, evas_object_del);
1676    eina_hash_free(inst->icons_desktop_hash);
1677    eina_hash_free(inst->icons_clients_hash);
1678    luncher_instances = eina_list_remove(luncher_instances, inst);
1679    free(inst);
1680    if (!eina_list_count(luncher_instances))
1681      {
1682         EINA_LIST_FREE(handlers, handler)
1683           E_FREE_FUNC(handler, ecore_event_handler_del);
1684      }
1685 }
1686 
1687 static void
_bar_drop_drop(void * data,const char * type,void * event_data)1688 _bar_drop_drop(void *data, const char *type, void *event_data)
1689 {
1690    Instance *inst = data;
1691    E_Event_Dnd_Drop *ev = event_data;
1692    Efreet_Desktop *desktop = NULL;
1693    Eina_List *l = NULL;
1694    Icon *ic = NULL;
1695 
1696    evas_object_del(inst->place_holder);
1697    inst->place_holder = NULL;
1698    if (!strcmp(type, "enlightenment/desktop"))
1699      desktop = ev->data;
1700    else if (!strcmp(type, "enlightenment/border"))
1701      {
1702         E_Client *ec;
1703 
1704         ec = ev->data;
1705         desktop = ec->desktop;
1706         if (!desktop)
1707           {
1708              desktop = e_desktop_client_create(ec);
1709              efreet_desktop_save(desktop);
1710              e_desktop_edit(desktop);
1711           }
1712      }
1713    else if (!strcmp(type, "text/uri-list"))
1714      l = ev->data;
1715 
1716    ic = inst->drop_before;
1717    if (ic)
1718      {
1719         if (desktop)
1720           e_order_prepend_relative(inst->order, desktop, ic->desktop);
1721         else
1722           e_order_files_prepend_relative(inst->order, l, ic->desktop);
1723      }
1724    else
1725      {
1726         if (desktop)
1727           e_order_append(inst->order, desktop);
1728         else
1729           e_order_files_append(inst->order, l);
1730      }
1731 }
1732 
1733 static void
_bar_drop_leave(void * data,const char * type EINA_UNUSED,void * event_data EINA_UNUSED)1734 _bar_drop_leave(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
1735 {
1736    Instance *inst = data;
1737 
1738    inst->inside = EINA_FALSE;
1739    evas_object_del(inst->place_holder);
1740    inst->place_holder = NULL;
1741 }
1742 
1743 static void
_bar_drop_move(void * data,const char * type EINA_UNUSED,void * event_data)1744 _bar_drop_move(void *data, const char *type EINA_UNUSED, void *event_data)
1745 {
1746    Instance *inst = data;
1747    E_Event_Dnd_Move *ev = event_data;
1748    Evas_Coord x = ev->x, y = ev->y;
1749    Eina_List *l;
1750    Icon *ic;
1751 
1752    if (!inst->inside)
1753      return;
1754 
1755    EINA_LIST_FOREACH(inst->icons, l, ic)
1756      {
1757         Evas_Coord dx, dy, dw, dh;
1758 
1759         if (!ic->in_order) continue;
1760         evas_object_geometry_get(ic->o_layout, &dx, &dy, &dw, &dh);
1761         if (E_INSIDE(x, y, dx, dy, dw, dh))
1762           inst->drop_before = ic;
1763      }
1764    elm_box_unpack(inst->o_icon_con, inst->place_holder);
1765    if (inst->drop_before)
1766      elm_box_pack_before(inst->o_icon_con, inst->place_holder, inst->drop_before->o_layout);
1767 }
1768 
1769 static void
_bar_drop_enter(void * data,const char * type EINA_UNUSED,void * event_data EINA_UNUSED)1770 _bar_drop_enter(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
1771 {
1772    Instance *inst = data;
1773 
1774    inst->inside = EINA_TRUE;
1775    inst->place_holder = evas_object_rectangle_add(evas_object_evas_get(inst->o_icon_con));
1776    evas_object_color_set(inst->place_holder, 0, 0, 0, 0);
1777    evas_object_size_hint_min_set(inst->place_holder, inst->size, inst->size);
1778    evas_object_size_hint_max_set(inst->place_holder, inst->size, inst->size);
1779    evas_object_show(inst->place_holder);
1780 }
1781 
1782 static void
_bar_iconify_end(void * data,Evas_Object * obj EINA_UNUSED,const char * sig EINA_UNUSED,const char * src EINA_UNUSED)1783 _bar_iconify_end(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
1784 {
1785    E_Client *ec = data;
1786 
1787    evas_object_layer_set(ec->frame, ec->layer);
1788    ec->layer_block = 0;
1789    if (ec->iconic)
1790      evas_object_hide(ec->frame);
1791 }
1792 
1793 static Eina_Bool
_bar_iconify_start(void * data,Evas_Object * obj,const char * signal EINA_UNUSED)1794 _bar_iconify_start(void *data, Evas_Object *obj, const char *signal EINA_UNUSED)
1795 {
1796    Instance *inst = data;
1797    Icon *ic = NULL;
1798    E_Client *ec;
1799    int ox, oy, ow, oh;
1800 
1801    ec = e_comp_object_client_get(obj);
1802 
1803    if (ec)
1804      ic = _bar_icon_match(inst, ec);
1805 
1806    if (!ic) return EINA_FALSE;
1807 
1808    ec->layer_block = 1;
1809    evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
1810    evas_object_geometry_get(ic->o_layout, &ox, &oy, &ow, &oh);
1811    e_comp_object_effect_set(ec->frame, "iconify/luncher");
1812    e_comp_object_effect_params_set(ec->frame, 1, (int[]){ec->x, ec->y, ec->w, ec->h, ox, oy, ow, oh}, 8);
1813    e_comp_object_effect_params_set(ec->frame, 0, (int[]){!!strcmp(signal, "e,action,iconify")}, 1);
1814    e_comp_object_effect_start(ec->frame, _bar_iconify_end, ec);
1815    return EINA_TRUE;
1816 }
1817 
1818 static void
_bar_anchor_changed_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1819 _bar_anchor_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1820 {
1821    Instance *inst = data;
1822 
1823    if (inst && inst->o_icon_con)
1824      {
1825         bar_recalculate(inst);
1826      }
1827 }
1828 
1829 static void
_bar_order_update(void * data,E_Order * eo EINA_UNUSED)1830 _bar_order_update(void *data, E_Order *eo EINA_UNUSED)
1831 {
1832    Instance *inst = data;
1833 
1834    if (inst && inst->o_icon_con)
1835      {
1836         bar_recalculate(inst);
1837      }
1838 }
1839 
1840 static void
_bar_created_cb(void * data,Evas_Object * obj,void * event_data EINA_UNUSED)1841 _bar_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
1842 {
1843    Instance *inst = data;
1844    char buf[4096];
1845    const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" };
1846    E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main));
1847 
1848    inst->o_icon_con = elm_box_add(inst->o_main);
1849    E_EXPAND(inst->o_icon_con);
1850    switch (orient)
1851      {
1852         case E_GADGET_SITE_ORIENT_HORIZONTAL:
1853            elm_box_horizontal_set(inst->o_icon_con, EINA_TRUE);
1854            break;
1855         case E_GADGET_SITE_ORIENT_VERTICAL:
1856            elm_box_horizontal_set(inst->o_icon_con, EINA_FALSE);
1857            break;
1858          default:
1859            elm_box_horizontal_set(inst->o_icon_con, EINA_TRUE);
1860      }
1861    elm_layout_content_set(inst->o_main, "e.swallow.bar", inst->o_icon_con);
1862    evas_object_show(inst->o_icon_con);
1863 
1864    evas_object_data_set(inst->o_main, "instance", inst);
1865    evas_object_data_set(inst->o_icon_con, "instance", inst);
1866 
1867    e_gadget_configure_cb_set(inst->o_main, _bar_gadget_configure);
1868    e_gadget_menu_populate_cb_set(inst->o_main, _bar_gadget_menu_populate);
1869    evas_object_smart_callback_del_full(obj, "gadget_created", _bar_created_cb, data);
1870 
1871    if (!inst->cfg->dir)
1872      inst->cfg->dir = eina_stringshare_add("default");
1873    if (inst->cfg->dir[0] != '/')
1874      e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
1875                          inst->cfg->dir);
1876    else
1877      eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));
1878 
1879    inst->order = e_order_new(buf);
1880    e_order_update_callback_set(inst->order, _bar_order_update, inst);
1881 
1882    if (inst->cfg->type != E_LUNCHER_MODULE_LAUNCH_ONLY)
1883      {
1884         if (inst->cfg->id != -1)
1885           inst->iconify_provider = e_comp_object_effect_mover_add(80, "e,action,*iconify",
1886               _bar_iconify_start, inst);
1887      }
1888    _bar_fill(inst);
1889 
1890    if (inst->cfg->type != E_LUNCHER_MODULE_TASKS_ONLY)
1891      {
1892         inst->drop_handler =
1893           e_gadget_drop_handler_add(inst->o_main, inst,
1894                              _bar_drop_enter, _bar_drop_move,
1895                              _bar_drop_leave, _bar_drop_drop,
1896                              drop, 3);
1897         elm_layout_content_set(inst->o_main, "e.swallow.drop", inst->drop_handler);
1898         evas_object_show(inst->drop_handler);
1899      }
1900    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_RESIZE, _bar_resize, inst);
1901 }
1902 
1903 static Config_Item *
_conf_item_get(int * id)1904 _conf_item_get(int *id)
1905 {
1906    Config_Item *ci;
1907    Eina_List *l;
1908 
1909    if (*id > 0)
1910      {
1911         EINA_LIST_FOREACH(luncher_config->items, l, ci)
1912           if (*id == ci->id) return ci;
1913      }
1914 
1915    ci = E_NEW(Config_Item, 1);
1916 
1917    if (*id != -1)
1918      ci->id = eina_list_count(luncher_config->items)+1;
1919    else
1920      ci->id = -1;
1921    ci->preview_size = 64;
1922    ci->dir = eina_stringshare_add("default");
1923    ci->type = E_LUNCHER_MODULE_FULL;
1924    luncher_config->items = eina_list_append(luncher_config->items, ci);
1925 
1926    return ci;
1927 }
1928 
1929 static void
_bar_recalculate_job(void * data)1930 _bar_recalculate_job(void *data)
1931 {
1932    Instance *inst = data;
1933 
1934    if (inst)
1935      {
1936         if (inst->o_icon_con)
1937           {
1938              _bar_empty(inst);
1939              _bar_fill(inst);
1940           }
1941         inst->recalc_job = NULL;
1942      }
1943 }
1944 
1945 EINTERN void
bar_recalculate(Instance * inst)1946 bar_recalculate(Instance *inst)
1947 {
1948    E_FREE_FUNC(inst->recalc_job, ecore_job_del);
1949    inst->recalc_job = ecore_job_add(_bar_recalculate_job, inst);
1950 }
1951 
1952 EINTERN void
bar_reorder(Instance * inst)1953 bar_reorder(Instance *inst)
1954 {
1955    char buf[4096];
1956 
1957    if (inst)
1958      {
1959         E_FREE_FUNC(inst->recalc_job, ecore_job_del);
1960         _bar_empty(inst);
1961         if (!inst->cfg->dir)
1962           inst->cfg->dir = eina_stringshare_add("default");
1963         if (inst->cfg->dir[0] != '/')
1964           e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
1965                               inst->cfg->dir);
1966         else
1967           eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));
1968         e_object_del(E_OBJECT(inst->order));
1969         inst->order = e_order_new(buf);
1970         e_order_update_callback_set(inst->order, _bar_order_update, inst);
1971         _bar_fill(inst);
1972      }
1973 }
1974 
1975 EINTERN void
bar_config_updated(Instance * inst)1976 bar_config_updated(Instance *inst)
1977 {
1978    const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" };
1979 
1980    if (!inst->iconify_provider && inst->cfg->type != E_LUNCHER_MODULE_LAUNCH_ONLY)
1981      {
1982         inst->iconify_provider = e_comp_object_effect_mover_add(80, "e,action,*iconify",
1983             _bar_iconify_start, inst);
1984      }
1985    else if (inst->iconify_provider && inst->cfg->type == E_LUNCHER_MODULE_LAUNCH_ONLY)
1986      {
1987         E_FREE_FUNC(inst->iconify_provider, e_comp_object_effect_mover_del);
1988      }
1989 
1990    bar_reorder(inst);
1991 
1992    if (!inst->drop_handler && inst->cfg->type != E_LUNCHER_MODULE_TASKS_ONLY)
1993      {
1994         inst->drop_handler =
1995           e_gadget_drop_handler_add(inst->o_main, inst,
1996                              _bar_drop_enter, _bar_drop_move,
1997                              _bar_drop_leave, _bar_drop_drop,
1998                              drop, 3);
1999         elm_layout_content_set(inst->o_main, "e.swallow.drop", inst->drop_handler);
2000         evas_object_show(inst->drop_handler);
2001      }
2002    else if (inst->drop_handler && inst->cfg->type == E_LUNCHER_MODULE_TASKS_ONLY)
2003      {
2004         E_FREE_FUNC(inst->drop_handler, evas_object_del);
2005      }
2006 }
2007 
2008 EINTERN Evas_Object *
bar_create(Evas_Object * parent,int * id,E_Gadget_Site_Orient orient EINA_UNUSED)2009 bar_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
2010 {
2011    Instance *inst;
2012 
2013    if (e_gadget_site_is_desklock(parent)) return NULL;
2014    inst = E_NEW(Instance, 1);
2015    inst->size = 0;
2016    inst->resize_job = NULL;
2017    inst->cfg = _conf_item_get(id);
2018    *id = inst->cfg->id;
2019    inst->inside = EINA_FALSE;
2020    inst->bar = EINA_TRUE;
2021    inst->main_del = EINA_FALSE;
2022    inst->icons_desktop_hash = eina_hash_string_superfast_new(NULL);
2023    inst->icons_clients_hash = eina_hash_pointer_new(NULL);
2024 
2025    if (!inst->cfg->preview_size)
2026      inst->cfg->preview_size = 64;
2027 
2028    inst->o_main = elm_layout_add(parent);
2029    e_theme_edje_object_set(inst->o_main, "e/gadget/luncher/bar",
2030        "e/gadget/luncher/bar");
2031    edje_object_update_hints_set(elm_layout_edje_get(inst->o_main), EINA_TRUE);
2032    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_MOUSE_OUT, _bar_mouse_out, inst);
2033    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, _bar_del, inst);
2034    evas_object_smart_callback_add(parent, "gadget_created", _bar_created_cb, inst);
2035    evas_object_smart_callback_add(parent, "gadget_site_anchor", _bar_anchor_changed_cb, inst);
2036    evas_object_smart_callback_add(parent, "gadget_removed", _bar_removed_cb, inst);
2037    evas_object_show(inst->o_main);
2038 
2039    if (!eina_list_count(handlers))
2040      {
2041         E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_ICON_THEME,
2042                               _bar_cb_update_icons, NULL);
2043         E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_ICON_CACHE_UPDATE,
2044                               _bar_cb_update_icons, NULL);
2045         E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_NEW,
2046                               _bar_cb_exec_new, NULL);
2047         E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_NEW_CLIENT,
2048                               _bar_cb_exec_new, NULL);
2049         E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,
2050                               _bar_cb_exec_client_prop, NULL);
2051         E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_DEL,
2052                               _bar_cb_exec_del, NULL);
2053         E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE,
2054                               _bar_cb_client_remove, NULL);
2055         E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW,
2056                               _bar_cb_desk_switch, NULL);
2057      }
2058    if (inst->cfg->id < 0) return inst->o_main;
2059    luncher_instances = eina_list_append(luncher_instances, inst);
2060 
2061    inst->current_preview = NULL;
2062    inst->current_preview_menu = EINA_FALSE;
2063 
2064    return inst->o_main;
2065 }
2066 
2067