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