Tizen 2.1 release
[platform/core/uifw/e17.git] / src / bin / e_int_menus.c
1 #include "e.h"
2
3 /*
4  * TODO: Listen to EFREET_EVENT_DESKTOP_CACHE_UPDATE
5  */
6
7 typedef struct _Main_Data Main_Data;
8
9 struct _Main_Data
10 {
11    E_Menu *menu;
12    E_Menu *apps;
13    E_Menu *all_apps;
14    E_Menu *desktops;
15    E_Menu *clients;
16    E_Menu *enlightenment;
17    E_Menu *config;
18    E_Menu *lost_clients;
19 };
20
21 /* local subsystem functions */
22 static void        _e_int_menus_main_del_hook(void *obj);
23 static void        _e_int_menus_main_about(void *data, E_Menu *m, E_Menu_Item *mi);
24 //static void _e_int_menus_fwin_favorites_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
25 static void        _e_int_menus_apps_scan(E_Menu *m, Efreet_Menu *menu);
26 static void        _e_int_menus_apps_start(void *data, E_Menu *m);
27 static void        _e_int_menus_apps_free_hook(void *obj);
28 static void        _e_int_menus_apps_free_hook2(void *obj);
29 static void        _e_int_menus_apps_run(void *data, E_Menu *m, E_Menu_Item *mi);
30 static void        _e_int_menus_apps_drag(void *data, E_Menu *m, E_Menu_Item *mi);
31 static void        _e_int_menus_config_pre_cb(void *data, E_Menu *m);
32 static void        _e_int_menus_config_free_hook(void *obj);
33 static void        _e_int_menus_clients_pre_cb(void *data, E_Menu *m);
34 static void        _e_int_menus_clients_item_create(E_Border *bd, E_Menu *m);
35 static void        _e_int_menus_clients_free_hook(void *obj);
36 static void        _e_int_menus_clients_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
37 static void        _e_int_menus_clients_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi);
38 static void        _e_int_menus_clients_cleanup_cb(void *data, E_Menu *m, E_Menu_Item *mi);
39 static int         _e_int_menus_clients_group_desk_cb(const void *d1, const void *d2);
40 static int         _e_int_menus_clients_group_class_cb(const void *d1, const void *d2);
41 static int         _e_int_menus_clients_sort_alpha_cb(const void *d1, const void *d2);
42 static int         _e_int_menus_clients_sort_z_order_cb(const void *d1, const void *d2);
43 static void        _e_int_menus_clients_add_by_class(Eina_List *borders, E_Menu *m);
44 static void        _e_int_menus_clients_add_by_desk(E_Desk *curr_desk, Eina_List *borders, E_Menu *m);
45 static void        _e_int_menus_clients_add_by_none(Eina_List *borders, E_Menu *m);
46 static void        _e_int_menus_clients_menu_add_iconified(Eina_List *borders, E_Menu *m);
47 static const char *_e_int_menus_clients_title_abbrv(const char *title);
48 static void        _e_int_menus_virtuals_pre_cb(void *data, E_Menu *m);
49 static void        _e_int_menus_virtuals_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
50 static void        _e_int_menus_virtuals_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi);
51 static void        _e_int_menus_themes_about(void *data, E_Menu *m, E_Menu_Item *mi);
52 static void        _e_int_menus_lost_clients_pre_cb(void *data, E_Menu *m);
53 static void        _e_int_menus_lost_clients_free_hook(void *obj);
54 static void        _e_int_menus_lost_clients_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
55 static void        _e_int_menus_augmentation_add(E_Menu *m, Eina_List *augmentation);
56 static void        _e_int_menus_augmentation_del(E_Menu *m, Eina_List *augmentation);
57 static void        _e_int_menus_shelves_pre_cb(void *data, E_Menu *m);
58 static void        _e_int_menus_shelves_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
59 static void        _e_int_menus_shelves_add_cb(void *data, E_Menu *m, E_Menu_Item *mi);
60 static void        _e_int_menus_shelves_del_cb(void *data, E_Menu *m, E_Menu_Item *mi);
61 static void        _e_int_menus_config_cb(void *data, E_Menu *m, E_Menu_Item *mi);
62 static void        _e_int_menus_main_showhide(void *data, E_Menu *m, E_Menu_Item *mi);
63 static void        _e_int_menus_main_restart(void *data, E_Menu *m, E_Menu_Item *mi);
64 static void        _e_int_menus_main_exit(void *data, E_Menu *m, E_Menu_Item *mi);
65 static void        _e_int_menus_desktops_free_hook(void *obj);
66 static void        _e_int_menus_desk_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
67 static void        _e_int_menus_item_label_set(Efreet_Menu *entry, E_Menu_Item *mi);
68
69 //static void _e_int_menus_apps_drag_finished(E_Drag *drag, int dropped __UNUSED__);
70
71 /* local subsystem globals */
72 static Eina_Hash *_e_int_menus_augmentation = NULL;
73 static Eina_List *_e_int_menus_augmentation_disabled = NULL;
74
75 static Eina_List *
76 _e_int_menus_augmentation_find(const char *key)
77 {
78    Eina_List *l;
79    char *data;
80
81    if ((!_e_int_menus_augmentation) || (!key)) return NULL;
82
83    EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data)
84      if (!strcmp(data, key)) return NULL;
85    return eina_hash_find(_e_int_menus_augmentation, key);
86 }
87
88 /* externally accessible functions */
89 EAPI E_Menu *
90 e_int_menus_main_new(void)
91 {
92    E_Menu *m, *subm;
93    E_Menu_Item *mi;
94    Main_Data *dat;
95    Eina_List *l = NULL;
96    int separator = 0;
97
98    dat = calloc(1, sizeof(Main_Data));
99    m = e_menu_new();
100    e_menu_title_set(m, _("Main"));
101    dat->menu = m;
102    e_object_data_set(E_OBJECT(m), dat);
103    e_object_del_attach_func_set(E_OBJECT(m), _e_int_menus_main_del_hook);
104
105    e_menu_category_set(m, "main");
106
107    l = _e_int_menus_augmentation_find("main/0");
108    if (l) _e_int_menus_augmentation_add(m, l);
109
110    if (e_config->menu_favorites_show)
111      {
112         subm = e_int_menus_favorite_apps_new();
113         if (subm)
114           {
115              dat->apps = subm;
116              mi = e_menu_item_new(m);
117              e_menu_item_label_set(mi, _("Favorite Applications"));
118              e_util_menu_item_theme_icon_set(mi, "user-bookmarks");
119              e_menu_item_submenu_set(mi, subm);
120           }
121      }
122
123    if (e_config->menu_apps_show)
124      {
125         subm = e_int_menus_all_apps_new();
126         dat->all_apps = subm;
127         mi = e_menu_item_new(m);
128         e_menu_item_label_set(mi, _("Applications"));
129         e_util_menu_item_theme_icon_set(mi, "preferences-applications");
130         e_menu_item_submenu_set(mi, subm);
131      }
132
133    l = _e_int_menus_augmentation_find("main/1");
134    if (l) _e_int_menus_augmentation_add(m, l);
135
136    mi = e_menu_item_new(m);
137    e_menu_item_separator_set(mi, 1);
138
139    l = _e_int_menus_augmentation_find("main/2");
140    if (l) _e_int_menus_augmentation_add(m, l);
141
142    subm = e_int_menus_desktops_new();
143    dat->desktops = subm;
144    mi = e_menu_item_new(m);
145    e_menu_item_label_set(mi, _("Desktop"));
146    e_util_menu_item_theme_icon_set(mi, "preferences-desktop");
147    e_menu_item_submenu_set(mi, subm);
148
149    subm = e_int_menus_clients_new();
150    dat->clients = subm;
151    mi = e_menu_item_new(m);
152    e_menu_item_label_set(mi, _("Windows"));
153    e_util_menu_item_theme_icon_set(mi, "preferences-system-windows");
154    e_menu_item_submenu_set(mi, subm);
155    e_object_data_set(E_OBJECT(subm), dat);
156
157 #if 0 // lost windows already handled inside "Windows" from main menu.
158    subm = e_int_menus_lost_clients_new();
159    e_object_data_set(E_OBJECT(subm), dat);
160    dat->lost_clients = subm;
161    mi = e_menu_item_new(m);
162    e_menu_item_label_set(mi, _("Lost Windows"));
163    e_util_menu_item_theme_icon_set(mi, "preferences-windows-lost");
164    e_menu_item_submenu_set(mi, subm);
165 #endif
166
167    l = _e_int_menus_augmentation_find("main/3");
168    if (l) _e_int_menus_augmentation_add(m, l);
169
170    mi = e_menu_item_new(m);
171    e_menu_item_separator_set(mi, 1);
172
173    l = _e_int_menus_augmentation_find("main/4");
174    if (l) _e_int_menus_augmentation_add(m, l);
175
176    subm = e_menu_new();
177    dat->enlightenment = subm;
178
179    l = _e_int_menus_augmentation_find("enlightenment/0");
180    if (l) _e_int_menus_augmentation_add(subm, l);
181
182    mi = e_menu_item_new(m);
183    e_menu_item_label_set(mi, _("Enlightenment"));
184    e_util_menu_item_theme_icon_set(mi, "enlightenment");
185    e_menu_item_submenu_set(mi, subm);
186
187    mi = e_menu_item_new(subm);
188    e_menu_item_label_set(mi, _("About"));
189    e_util_menu_item_theme_icon_set(mi, "help-about");
190    e_menu_item_callback_set(mi, _e_int_menus_main_about, NULL);
191
192    mi = e_menu_item_new(subm);
193    e_menu_item_label_set(mi, _("Theme"));
194    e_util_menu_item_theme_icon_set(mi, "preferences-desktop-theme");
195    e_menu_item_callback_set(mi, _e_int_menus_themes_about, NULL);
196
197    l = _e_int_menus_augmentation_find("enlightenment/1");
198    if (l) _e_int_menus_augmentation_add(subm, l);
199
200    mi = e_menu_item_new(subm);
201    e_menu_item_separator_set(mi, 1);
202
203    l = _e_int_menus_augmentation_find("enlightenment/2");
204    if (l) _e_int_menus_augmentation_add(subm, l);
205
206    mi = e_menu_item_new(subm);
207    e_menu_item_label_set(mi, _("Restart"));
208    e_util_menu_item_theme_icon_set(mi, "system-restart");
209    e_menu_item_callback_set(mi, _e_int_menus_main_restart, NULL);
210
211    mi = e_menu_item_new(subm);
212    e_menu_item_label_set(mi, _("Exit"));
213    e_util_menu_item_theme_icon_set(mi, "application-exit");
214    e_menu_item_callback_set(mi, _e_int_menus_main_exit, NULL);
215
216    l = _e_int_menus_augmentation_find("enlightenment/3");
217    if (l) _e_int_menus_augmentation_add(subm, l);
218
219    l = _e_int_menus_augmentation_find("main/5");
220    if (l) _e_int_menus_augmentation_add(m, l);
221
222    mi = e_menu_item_new(m);
223    e_menu_item_separator_set(mi, 1);
224
225    l = _e_int_menus_augmentation_find("main/6");
226    if (l) _e_int_menus_augmentation_add(m, l);
227
228    subm = e_int_menus_config_new();
229    dat->config = subm;
230    mi = e_menu_item_new(m);
231    e_menu_item_label_set(mi, _("Settings"));
232    e_menu_item_callback_set(mi, _e_int_menus_config_cb, NULL);
233    e_util_menu_item_theme_icon_set(mi, "preferences-system");
234    e_menu_item_submenu_set(mi, subm);
235
236    l = _e_int_menus_augmentation_find("main/7");
237    if (l) _e_int_menus_augmentation_add(m, l);
238
239    l = eina_hash_find(_e_int_menus_augmentation, "main/8");
240    if (l)
241      {
242         separator = 1;
243         mi = e_menu_item_new(m);
244         e_menu_item_separator_set(mi, 1);
245         _e_int_menus_augmentation_add(m, l);
246      }
247
248    l = eina_hash_find(_e_int_menus_augmentation, "main/9");
249    if (l)
250      {
251         if (!separator)
252           {
253              mi = e_menu_item_new(m);
254              e_menu_item_separator_set(mi, 1);
255           }
256         _e_int_menus_augmentation_add(m, l);
257      }
258
259    return m;
260 }
261
262 EAPI E_Menu *
263 e_int_menus_apps_new(const char *dir)
264 {
265    E_Menu *m;
266
267    m = e_menu_new();
268    if (dir) e_object_data_set(E_OBJECT(m), strdup(dir));
269    e_menu_pre_activate_callback_set(m, _e_int_menus_apps_start, NULL);
270    e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_apps_free_hook);
271    return m;
272 }
273
274 EAPI E_Menu *
275 e_int_menus_desktops_new(void)
276 {
277    E_Menu *m, *subm;
278    E_Menu_Item *mi;
279
280    m = e_menu_new();
281
282    subm = e_menu_new();
283    mi = e_menu_item_new(m);
284    e_menu_item_label_set(mi, _("Virtual"));
285    e_util_menu_item_theme_icon_set(mi, "preferences-desktop");
286    e_menu_pre_activate_callback_set(subm, _e_int_menus_virtuals_pre_cb, NULL);
287    e_menu_item_submenu_set(mi, subm);
288
289    subm = e_menu_new();
290    mi = e_menu_item_new(m);
291    e_menu_item_label_set(mi, _("Shelves"));
292    e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf");
293    e_menu_pre_activate_callback_set(subm, _e_int_menus_shelves_pre_cb, NULL);
294    e_menu_item_submenu_set(mi, subm);
295
296    mi = e_menu_item_new(m);
297    e_menu_item_separator_set(mi, 1);
298
299    mi = e_menu_item_new(m);
300    e_menu_item_label_set(mi, _("Show/Hide All Windows"));
301    e_util_menu_item_theme_icon_set(mi, "preferences-system-windows");
302    e_menu_item_callback_set(mi, _e_int_menus_main_showhide, NULL);
303
304    e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_desktops_free_hook);
305    return m;
306 }
307
308 EAPI E_Menu *
309 e_int_menus_favorite_apps_new(void)
310 {
311    E_Menu *m = NULL;
312    char buf[PATH_MAX];
313
314    e_user_dir_concat_static(buf, "applications/menu/favorite.menu");
315    if (ecore_file_exists(buf)) m = e_int_menus_apps_new(buf);
316    return m;
317 }
318
319 EAPI E_Menu *
320 e_int_menus_all_apps_new(void)
321 {
322    E_Menu *m;
323
324    m = e_int_menus_apps_new(NULL);
325    return m;
326 }
327
328 EAPI E_Menu *
329 e_int_menus_config_new(void)
330 {
331    E_Menu *m;
332
333    m = e_menu_new();
334    e_menu_pre_activate_callback_set(m, _e_int_menus_config_pre_cb, NULL);
335    return m;
336 }
337
338 EAPI E_Menu *
339 e_int_menus_clients_new(void)
340 {
341    E_Menu *m;
342
343    m = e_menu_new();
344    e_menu_pre_activate_callback_set(m, _e_int_menus_clients_pre_cb, NULL);
345    return m;
346 }
347
348 EAPI E_Menu *
349 e_int_menus_lost_clients_new(void)
350 {
351    E_Menu *m;
352
353    m = e_menu_new();
354    e_menu_pre_activate_callback_set(m, _e_int_menus_lost_clients_pre_cb, NULL);
355    return m;
356 }
357
358 EAPI E_Int_Menu_Augmentation *
359 e_int_menus_menu_augmentation_add_sorted(const char *menu,
360                                          const char *sort_key,
361                                          void (*func_add)(void *data, E_Menu *m),
362                                          void *data_add,
363                                          void (*func_del)(void *data, E_Menu *m),
364                                          void *data_del)
365 {
366    E_Int_Menu_Augmentation *maug;
367    Eina_List *l;
368    Eina_Bool old = EINA_FALSE;
369
370    maug = E_NEW(E_Int_Menu_Augmentation, 1);
371    if (!maug) return NULL;
372
373    maug->sort_key = eina_stringshare_add(sort_key);
374
375    maug->add.func = func_add;
376    maug->add.data = data_add;
377
378    maug->del.func = func_del;
379    maug->del.data = data_del;
380
381    if (_e_int_menus_augmentation)
382      {
383         if ((l = eina_hash_find(_e_int_menus_augmentation, menu)))
384           old = EINA_TRUE;
385      }
386    else
387      {
388         _e_int_menus_augmentation = eina_hash_string_superfast_new(NULL);
389         l = NULL;
390         old = EINA_FALSE;
391      }
392
393    if ((!l) || (!maug->sort_key))
394      l = eina_list_append(l, maug);
395    else
396      {
397         E_Int_Menu_Augmentation *m2;
398         Eina_List *l2;
399
400         /* keep list sorted, those missing sort_key at the end. */
401         EINA_LIST_FOREACH(l, l2, m2)
402           {
403              if (!m2->sort_key)
404                break;
405              if (strcasecmp(maug->sort_key, m2->sort_key) < 0)
406                break;
407           }
408
409         if (l2)
410           l = eina_list_prepend_relative_list(l, maug, l2);
411         else
412           l = eina_list_append(l, maug);
413      }
414
415    if (old)
416      eina_hash_modify(_e_int_menus_augmentation, menu, l);
417    else
418      eina_hash_add(_e_int_menus_augmentation, menu, l);
419
420    return maug;
421 }
422
423 EAPI E_Int_Menu_Augmentation *
424 e_int_menus_menu_augmentation_add(const char *menu,
425                                   void (*func_add)(void *data, E_Menu *m),
426                                   void *data_add,
427                                   void (*func_del)(void *data, E_Menu *m),
428                                   void *data_del)
429 {
430    return e_int_menus_menu_augmentation_add_sorted
431             (menu, NULL, func_add, data_add, func_del, data_del);
432 }
433
434 EAPI void
435 e_int_menus_menu_augmentation_del(const char *menu, E_Int_Menu_Augmentation *maug)
436 {
437    Eina_List *l;
438
439    if (!_e_int_menus_augmentation)
440      {
441         eina_stringshare_del(maug->sort_key);
442         free(maug);
443         return;
444      }
445
446    l = eina_hash_find(_e_int_menus_augmentation, menu);
447    if (l)
448      {
449         l = eina_list_remove(l, maug);
450
451         if (l)
452           eina_hash_modify(_e_int_menus_augmentation, menu, l);
453         else
454           eina_hash_del_by_key(_e_int_menus_augmentation, menu);
455      }
456    eina_stringshare_del(maug->sort_key);
457    free(maug);
458 }
459
460 EAPI void
461 e_int_menus_menu_augmentation_point_disabled_set(const char *menu, Eina_Bool disabled)
462 {
463    if (!menu) return;
464    if (disabled)
465      {
466         _e_int_menus_augmentation_disabled =
467           eina_list_append(_e_int_menus_augmentation_disabled, menu);
468      }
469    else
470      {
471         _e_int_menus_augmentation_disabled =
472           eina_list_remove(_e_int_menus_augmentation_disabled, menu);
473      }
474 }
475
476 /* local subsystem functions */
477 static void
478 _e_int_menus_main_del_hook(void *obj)
479 {
480    Main_Data *dat;
481    E_Menu *m;
482
483    m = obj;
484    dat = e_object_data_get(E_OBJECT(obj));
485    if (dat->apps) e_object_del(E_OBJECT(dat->apps));
486    if (dat->all_apps) e_object_del(E_OBJECT(dat->all_apps));
487    if (dat->desktops) e_object_del(E_OBJECT(dat->desktops));
488    if (dat->clients) e_object_del(E_OBJECT(dat->clients));
489    if (dat->lost_clients) e_object_del(E_OBJECT(dat->lost_clients));
490    if (dat->enlightenment) e_object_del(E_OBJECT(dat->enlightenment));
491    if (dat->config) e_object_del(E_OBJECT(dat->config));
492    free(dat);
493
494    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/0"));
495    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/1"));
496    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/2"));
497    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/3"));
498    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/4"));
499    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/5"));
500    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/6"));
501    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/7"));
502    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/8"));
503    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/9"));
504    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/10"));
505    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/11"));
506 }
507
508 static void
509 _e_int_menus_main_about(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
510 {
511    E_About *about;
512
513    about = e_about_new(e_container_current_get(e_manager_current_get()));
514    if (about) e_about_show(about);
515 }
516
517 static void
518 _e_int_menus_themes_about(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
519 {
520    E_Theme_About *about;
521
522    about = e_theme_about_new(e_container_current_get(e_manager_current_get()));
523    if (about) e_theme_about_show(about);
524 }
525
526 /*
527    static void
528    _e_int_menus_fwin_favorites_item_cb(void *data, E_Menu *m, E_Menu_Item *mi)
529    {
530    e_fwin_new(m->zone->container, "favorites", "/");
531    }
532  */
533
534 static void
535 _e_int_menus_config_cb(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
536 {
537    E_Action *act;
538
539    act = e_action_find("configuration");
540    if (act) act->func.go(E_OBJECT(m->zone), NULL);
541 }
542
543 static void
544 _e_int_menus_main_showhide(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
545 {
546    E_Action *act;
547
548    act = e_action_find("desk_deskshow_toggle");
549    if (act) act->func.go(E_OBJECT(m->zone), NULL);
550 }
551
552 static void
553 _e_int_menus_main_restart(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
554 {
555    E_Action *a;
556
557    a = e_action_find("restart");
558    if ((a) && (a->func.go)) a->func.go(NULL, NULL);
559 }
560
561 static void
562 _e_int_menus_main_exit(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
563 {
564    E_Action *a;
565
566    a = e_action_find("exit");
567    if ((a) && (a->func.go)) a->func.go(NULL, NULL);
568 }
569
570 static void
571 _e_int_menus_apps_scan(E_Menu *m, Efreet_Menu *menu)
572 {
573    E_Menu_Item *mi;
574    Eina_List *l;
575
576    if (menu->entries)
577      {
578         Efreet_Menu *entry;
579
580         EINA_LIST_FOREACH(menu->entries, l, entry)
581           {
582              mi = e_menu_item_new(m);
583
584              _e_int_menus_item_label_set(entry, mi);
585
586              if (entry->icon)
587                {
588                   if (entry->icon[0] == '/')
589                     e_menu_item_icon_file_set(mi, entry->icon);
590                   else
591                     e_util_menu_item_theme_icon_set(mi, entry->icon);
592                }
593              if (entry->type == EFREET_MENU_ENTRY_SEPARATOR)
594                e_menu_item_separator_set(mi, 1);
595              else if (entry->type == EFREET_MENU_ENTRY_DESKTOP)
596                {
597                   e_menu_item_callback_set(mi, _e_int_menus_apps_run,
598                                            entry->desktop);
599                   e_menu_item_drag_callback_set(mi, _e_int_menus_apps_drag,
600                                                 entry->desktop);
601                }
602              else if (entry->type == EFREET_MENU_ENTRY_MENU)
603                {
604                   E_Menu *subm;
605
606                   subm = e_menu_new();
607                   e_menu_pre_activate_callback_set(subm,
608                                                    _e_int_menus_apps_start,
609                                                    entry);
610                   e_menu_item_submenu_set(mi, subm);
611                   e_object_free_attach_func_set(E_OBJECT(subm),
612                                                 _e_int_menus_apps_free_hook2);
613                }
614              /* TODO: Highlight header
615                 else if (entry->type == EFREET_MENU_ENTRY_HEADER)
616               */
617           }
618      }
619    else
620      {
621         mi = e_menu_item_new(m);
622         e_menu_item_label_set(mi, _("(No Applications)"));
623      }
624 }
625
626 static void
627 _e_int_menus_apps_start(void *data, E_Menu *m)
628 {
629    Efreet_Menu *menu;
630
631    menu = data;
632    if (!menu)
633      {
634         char *dir = NULL;
635
636         dir = e_object_data_get(E_OBJECT(m));
637         if (dir)
638           {
639              menu = efreet_menu_parse(dir);
640              free(dir);
641           }
642         else menu = efreet_menu_get();
643         e_object_data_set(E_OBJECT(m), menu);
644         e_object_free_attach_func_set(E_OBJECT(m),
645                                       _e_int_menus_apps_free_hook2);
646      }
647    if (menu) _e_int_menus_apps_scan(m, menu);
648    e_menu_pre_activate_callback_set(m, NULL, NULL);
649 }
650
651 static void
652 _e_int_menus_apps_free_hook(void *obj)
653 {
654    E_Menu *m;
655    char *dir;
656
657    m = obj;
658    dir = e_object_data_get(E_OBJECT(m));
659    E_FREE(dir);
660 }
661
662 static void
663 _e_int_menus_apps_free_hook2(void *obj)
664 {
665    E_Menu *m;
666    Efreet_Menu *menu;
667    Eina_List *l, *l_next;
668    E_Menu_Item *mi;
669
670    m = obj;
671    // XXX TODO: this should be automatic in e_menu, just get references right!
672    // XXX TODO: fix references and remove me!!!
673    EINA_LIST_FOREACH_SAFE (m->items, l, l_next, mi)
674      {
675         if (mi->submenu)
676           e_object_del(E_OBJECT(mi->submenu));
677      }
678    menu = e_object_data_get(E_OBJECT(m));
679    if (menu) efreet_menu_free(menu);
680 }
681
682 static void
683 _e_int_menus_apps_run(void *data, E_Menu *m, E_Menu_Item *mi __UNUSED__)
684 {
685    Efreet_Desktop *desktop;
686
687    desktop = data;
688    e_exec(m->zone, desktop, NULL, NULL, "menu/apps");
689 }
690
691 /*
692    static void
693    _e_int_menus_apps_drag_finished(E_Drag *drag, int dropped __UNUSED__)
694    {
695    Efreet_Desktop *desktop;
696
697    desktop = drag->data;
698    efreet_desktop_free(desktop);
699    }
700  */
701
702 static void
703 _e_int_menus_apps_drag(void *data, E_Menu *m, E_Menu_Item *mi)
704 {
705    Efreet_Desktop *desktop;
706
707    desktop = data;
708
709    /* start drag! */
710    if (mi->icon_object)
711      {
712         E_Drag *drag;
713         Evas_Object *o = NULL;
714         Evas_Coord x, y, w, h;
715         unsigned int size;
716         const char *drag_types[] = { "enlightenment/desktop" };
717
718         evas_object_geometry_get(mi->icon_object, &x, &y, &w, &h);
719         efreet_desktop_ref(desktop);
720         drag = e_drag_new(m->zone->container, x, y, drag_types, 1, desktop, -1,
721                           NULL, NULL);
722
723         size = MIN(w, h);
724         o = e_util_desktop_icon_add(desktop, size, e_drag_evas_get(drag));
725         e_drag_object_set(drag, o);
726         e_drag_resize(drag, w, h);
727         e_drag_start(drag, mi->drag.x + w, mi->drag.y + h);
728      }
729 }
730
731 static void
732 _e_int_menus_virtuals_pre_cb(void *data __UNUSED__, E_Menu *m)
733 {
734    E_Menu_Item *mi;
735    E_Menu *root;
736
737    e_menu_pre_activate_callback_set(m, NULL, NULL);
738
739    root = e_menu_root_get(m);
740    if ((root) && (root->zone))
741      {
742         E_Zone *zone;
743         int i;
744
745         zone = root->zone;
746         for (i = 0; i < (zone->desk_x_count * zone->desk_y_count); i++)
747           {
748              E_Desk *desk;
749
750              desk = zone->desks[i];
751              mi = e_menu_item_new(m);
752              e_menu_item_radio_group_set(mi, 1);
753              e_menu_item_radio_set(mi, 1);
754              e_menu_item_label_set(mi, desk->name);
755              if (desk == e_desk_current_get(zone))
756                e_menu_item_toggle_set(mi, 1);
757              e_menu_item_callback_set(mi, _e_int_menus_virtuals_item_cb, desk);
758              e_menu_item_realize_callback_set(mi, _e_int_menus_virtuals_icon_cb, desk);
759           }
760      }
761
762    if (e_configure_registry_exists("screen/virtual_desktops"))
763      {
764         mi = e_menu_item_new(m);
765         e_menu_item_separator_set(mi, 1);
766
767         mi = e_menu_item_new(m);
768         e_menu_item_label_set(mi, _("Set Virtual Desktops"));
769         e_util_menu_item_theme_icon_set(mi, "preferences-desktop");
770         e_menu_item_callback_set(mi, _e_int_menus_desk_item_cb, NULL);
771      }
772 }
773
774 static void
775 _e_int_menus_desktops_free_hook(void *obj)
776 {
777    E_Menu *m;
778    Eina_List *l, *l_next;
779    E_Menu_Item *mi;
780
781    m = obj;
782    // XXX TODO: this should be automatic in e_menu, just get references right!
783    // XXX TODO: fix references and remove me!!!
784    EINA_LIST_FOREACH_SAFE (m->items, l, l_next, mi)
785      {
786         if (mi->submenu)
787           e_object_del(E_OBJECT(mi->submenu));
788      }
789 }
790
791 static void
792 _e_int_menus_desk_item_cb(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
793 {
794    e_configure_registry_call("screen/virtual_desktops", m->zone->container, NULL);
795 }
796
797 static void
798 _e_int_menus_virtuals_item_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
799 {
800    E_Desk *desk;
801
802    if (!(desk = data)) return;
803    e_desk_show(desk);
804 }
805
806 static void
807 _e_int_menus_virtuals_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi)
808 {
809    E_Desk *desk;
810    Evas_Object *o;
811    const char *bgfile;
812    int tw, th;
813
814    desk = data;
815    E_OBJECT_CHECK(desk);
816
817    tw = 50;
818    th = (tw * desk->zone->h) / desk->zone->w;
819
820    bgfile = e_bg_file_get(desk->zone->container->num, desk->zone->num, desk->x, desk->y);
821    o = e_thumb_icon_add(m->evas);
822    e_thumb_icon_file_set(o, bgfile, "e/desktop/background");
823    e_thumb_icon_size_set(o, tw, th);
824    e_thumb_icon_begin(o);
825    mi->icon_object = o;
826 }
827
828 static void
829 _e_int_menus_config_pre_cb(void *data __UNUSED__, E_Menu *m)
830 {
831    E_Menu_Item *mi;
832    Eina_List *l = NULL;
833
834    e_menu_pre_activate_callback_set(m, NULL, NULL);
835
836    l = _e_int_menus_augmentation_find("config/0");
837    if (l)
838      {
839         _e_int_menus_augmentation_add(m, l);
840         if (_e_int_menus_augmentation_find("config/1"))
841           {
842              mi = e_menu_item_new(m);
843              e_menu_item_separator_set(mi, 1);
844           }
845      }
846
847    l = _e_int_menus_augmentation_find("config/1");
848    if (l) _e_int_menus_augmentation_add(m, l);
849
850    l = _e_int_menus_augmentation_find("config/2");
851    if (l)
852      {
853         mi = e_menu_item_new(m);
854         e_menu_item_separator_set(mi, 1);
855         _e_int_menus_augmentation_add(m, l);
856      }
857
858    e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_config_free_hook);
859 }
860
861 static void
862 _e_int_menus_config_free_hook(void *obj)
863 {
864    E_Menu *m;
865
866    m = obj;
867    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/0"));
868    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/1"));
869    _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/2"));
870 }
871
872 static int
873 _e_int_menus_clients_group_desk_cb(const void *d1, const void *d2)
874 {
875    const E_Border *bd1;
876    const E_Border *bd2;
877    int j, k;
878
879    if (!d1) return 1;
880    if (!d2) return -1;
881
882    bd1 = d1;
883    bd2 = d2;
884
885    j = bd1->desk->y * 12 + bd1->desk->x;
886    k = bd2->desk->y * 12 + bd2->desk->x;
887
888    if (j > k) return 1;
889    if (j < k) return -1;
890    return -1;   /* Returning '-1' on equal is intentional */
891 }
892
893 static int
894 _e_int_menus_clients_group_class_cb(const void *d1, const void *d2)
895 {
896    const E_Border *bd1, *bd2;
897
898    if (!d1) return 1;
899    if (!d2) return -1;
900
901    bd1 = d1;
902    bd2 = d2;
903
904    if (!bd1->client.icccm.class)
905      return -1;
906    if (!bd2->client.icccm.class)
907      return 1;
908
909    return strcmp(bd1->client.icccm.class, bd2->client.icccm.class) > 0 ? 1 : -1;
910 }
911
912 static int
913 _e_int_menus_clients_sort_alpha_cb(const void *d1, const void *d2)
914 {
915    const E_Border *bd1, *bd2;
916    const char *name1, *name2;
917
918    if (!d1) return 1;
919    if (!d2) return -1;
920
921    bd1 = d1;
922    bd2 = d2;
923    name1 = e_border_name_get(bd1);
924    name2 = e_border_name_get(bd2);
925
926    if (strcasecmp(name1, name2) > 0) return 1;
927    if (strcasecmp(name1, name2) < 0) return -1;
928    return 0;
929 }
930
931 static int
932 _e_int_menus_clients_sort_z_order_cb(const void *d1, const void *d2)
933 {
934    const E_Border *bd1, *bd2;
935
936    if (!d1) return 1;
937    if (!d2) return -1;
938
939    bd1 = d1;
940    bd2 = d2;
941
942    if (bd1->layer < bd2->layer) return 1;
943    if (bd1->layer > bd2->layer) return -1;
944    return 0;
945 }
946
947 static void
948 _e_int_menus_clients_menu_add_iconified(Eina_List *borders, E_Menu *m)
949 {
950    if (eina_list_count(borders) > 0)
951      {
952         Eina_List *l = NULL;
953         E_Border *bd = NULL;
954         E_Menu_Item *mi = NULL;
955
956         mi = e_menu_item_new(m);
957         e_menu_item_separator_set(mi, 1);
958
959         EINA_LIST_FOREACH(borders, l, bd)
960           _e_int_menus_clients_item_create(bd, m);
961      }
962 }
963
964 static void
965 _e_int_menus_clients_add_by_class(Eina_List *borders, E_Menu *m)
966 {
967    Eina_List *l = NULL, *ico = NULL;
968    E_Border *bd;
969    E_Menu *subm = NULL;
970    E_Menu_Item *mi = NULL;
971    char *class = NULL;
972
973    class = strdup("");
974    EINA_LIST_FOREACH(borders, l, bd)
975      {
976         if ((bd->iconic) &&
977             (e_config->clientlist_separate_iconified_apps == E_CLIENTLIST_GROUPICONS_SEP))
978           {
979              ico = eina_list_append(ico, bd);
980              continue;
981           }
982
983         if (((strcmp(class, bd->client.icccm.class) != 0) &&
984              e_config->clientlist_separate_with != E_CLIENTLIST_GROUP_SEP_NONE))
985           {
986              if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
987                {
988                   if ((subm) && (mi)) e_menu_item_submenu_set(mi, subm);
989                   mi = e_menu_item_new(m);
990                   e_menu_item_label_set(mi, bd->client.icccm.class);
991                   e_util_menu_item_theme_icon_set(mi, "preferences-system-windows");
992                   subm = e_menu_new();
993                }
994              else
995                {
996                   mi = e_menu_item_new(m);
997                   e_menu_item_separator_set(mi, 1);
998                }
999              free(class);
1000              class = strdup(bd->client.icccm.class);
1001           }
1002         if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
1003           _e_int_menus_clients_item_create(bd, subm);
1004         else
1005           _e_int_menus_clients_item_create(bd, m);
1006      }
1007
1008    if ((e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
1009        && (subm) && (mi))
1010      e_menu_item_submenu_set(mi, subm);
1011
1012    _e_int_menus_clients_menu_add_iconified(ico, m);
1013
1014    if (class) free(class);
1015 }
1016
1017 static void
1018 _e_int_menus_clients_add_by_desk(E_Desk *curr_desk, Eina_List *borders, E_Menu *m)
1019 {
1020    E_Desk *desk = NULL;
1021    Eina_List *l = NULL, *alt = NULL, *ico = NULL;
1022    E_Border *bd;
1023    E_Menu *subm;
1024    E_Menu_Item *mi = NULL;
1025
1026    /* Deal with present desk first */
1027    EINA_LIST_FOREACH(borders, l, bd)
1028      {
1029         if (bd->iconic && e_config->clientlist_separate_iconified_apps && E_CLIENTLIST_GROUPICONS_SEP)
1030           {
1031              ico = eina_list_append(ico, bd);
1032              continue;
1033           }
1034
1035         if (bd->desk != curr_desk)
1036           {
1037              if ((!bd->iconic) ||
1038                  (bd->iconic && e_config->clientlist_separate_iconified_apps ==
1039                   E_CLIENTLIST_GROUPICONS_OWNER))
1040                {
1041                   alt = eina_list_append(alt, bd);
1042                   continue;
1043                }
1044           }
1045         else
1046           _e_int_menus_clients_item_create(bd, m);
1047      }
1048
1049    desk = NULL;
1050    subm = NULL;
1051    if (eina_list_count(alt) > 0)
1052      {
1053         if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
1054           {
1055              mi = e_menu_item_new(m);
1056              e_menu_item_separator_set(mi, 1);
1057           }
1058
1059         EINA_LIST_FOREACH(alt, l, bd)
1060           {
1061              if ((bd->desk != desk) &&
1062                  (e_config->clientlist_separate_with != E_CLIENTLIST_GROUP_SEP_NONE))
1063                {
1064                   if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
1065                     {
1066                        if (subm && mi) e_menu_item_submenu_set(mi, subm);
1067                        mi = e_menu_item_new(m);
1068                        e_menu_item_label_set(mi, bd->desk->name);
1069                        e_util_menu_item_theme_icon_set(mi, "preferences-desktop");
1070                        subm = e_menu_new();
1071                     }
1072                   else
1073                     {
1074                        mi = e_menu_item_new(m);
1075                        e_menu_item_separator_set(mi, 1);
1076                     }
1077                   desk = bd->desk;
1078                }
1079              if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)
1080                _e_int_menus_clients_item_create(bd, subm);
1081              else
1082                _e_int_menus_clients_item_create(bd, m);
1083           }
1084         if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU
1085             && (subm) && (mi))
1086           e_menu_item_submenu_set(mi, subm);
1087      }
1088
1089    _e_int_menus_clients_menu_add_iconified(ico, m);
1090 }
1091
1092 static void
1093 _e_int_menus_clients_add_by_none(Eina_List *borders, E_Menu *m)
1094 {
1095    Eina_List *l = NULL, *ico = NULL;
1096    E_Border *bd;
1097
1098    EINA_LIST_FOREACH(borders, l, bd)
1099      {
1100         if ((bd->iconic) && (e_config->clientlist_separate_iconified_apps) &&
1101             (E_CLIENTLIST_GROUPICONS_SEP))
1102           {
1103              ico = eina_list_append(ico, bd);
1104              continue;
1105           }
1106         _e_int_menus_clients_item_create(bd, m);
1107      }
1108    _e_int_menus_clients_menu_add_iconified(ico, m);
1109 }
1110
1111 static void
1112 _e_int_menus_clients_pre_cb(void *data __UNUSED__, E_Menu *m)
1113 {
1114    E_Menu *subm;
1115    E_Menu_Item *mi = NULL;
1116    Eina_List *l = NULL, *borders = NULL;
1117    E_Border *border;
1118    E_Zone *zone = NULL;
1119    E_Desk *desk = NULL;
1120    Main_Data *dat;
1121
1122    e_menu_pre_activate_callback_set(m, NULL, NULL);
1123    /* get the current clients */
1124    zone = e_zone_current_get(e_container_current_get(e_manager_current_get()));
1125    desk = e_desk_current_get(zone);
1126
1127    if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_MOST_RECENT)
1128      l = e_border_focus_stack_get();
1129    else
1130      l = e_border_client_list();
1131    EINA_LIST_FOREACH(l, l, border)
1132      {
1133         if (border->user_skip_winlist) continue;
1134         if ((border->zone == zone) || (border->iconic) ||
1135             (border->zone != zone && e_config->clientlist_include_all_zones))
1136           borders = eina_list_append(borders, border);
1137      }
1138
1139    dat = (Main_Data *)e_object_data_get(E_OBJECT(m));
1140    if (!dat) e_menu_title_set(m, _("Windows"));
1141
1142    if (!borders)
1143      {
1144         /* FIXME here we want nothing, but that crashes!!! */
1145         mi = e_menu_item_new(m);
1146         e_menu_item_label_set(mi, _("(No Windows)"));
1147      }
1148
1149    if (borders)
1150      {
1151         /* Sort the borders */
1152         if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_ALPHA)
1153           borders = eina_list_sort(borders, eina_list_count(borders),
1154                                    _e_int_menus_clients_sort_alpha_cb);
1155
1156         if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_ZORDER)
1157           borders = eina_list_sort(borders, eina_list_count(borders),
1158                                    _e_int_menus_clients_sort_z_order_cb);
1159
1160         /* Group the borders */
1161         if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_DESK)
1162           {
1163              borders = eina_list_sort(borders, eina_list_count(borders),
1164                                       _e_int_menus_clients_group_desk_cb);
1165              _e_int_menus_clients_add_by_desk(desk, borders, m);
1166           }
1167         if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_CLASS)
1168           {
1169              borders = eina_list_sort(borders, eina_list_count(borders),
1170                                       _e_int_menus_clients_group_class_cb);
1171              _e_int_menus_clients_add_by_class(borders, m);
1172           }
1173         if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_NONE)
1174           _e_int_menus_clients_add_by_none(borders, m);
1175      }
1176
1177    mi = e_menu_item_new(m);
1178    e_menu_item_separator_set(mi, 1);
1179
1180    mi = e_menu_item_new(m);
1181    e_menu_item_label_set(mi, _("Cleanup Windows"));
1182    e_util_menu_item_theme_icon_set(mi, "preferences-system-windows");
1183    e_menu_item_callback_set(mi, _e_int_menus_clients_cleanup_cb, zone);
1184
1185    if (dat)
1186      {
1187         mi = e_menu_item_new(m);
1188         e_menu_item_separator_set(mi, 1);
1189
1190         subm = e_int_menus_lost_clients_new();
1191         e_object_data_set(E_OBJECT(subm), e_object_data_get(E_OBJECT(m)));
1192         dat->lost_clients = subm;
1193         mi = e_menu_item_new(m);
1194         e_menu_item_label_set(mi, _("Lost Windows"));
1195         e_util_menu_item_theme_icon_set(mi, "preferences-windows-lost");
1196         e_menu_item_submenu_set(mi, subm);
1197      }
1198
1199    e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_clients_free_hook);
1200    e_object_data_set(E_OBJECT(m), borders);
1201 }
1202
1203 static const char *
1204 _e_int_menus_clients_title_abbrv(const char *title)
1205 {
1206    int max_len;
1207
1208    max_len = e_config->clientlist_max_caption_len;
1209    if ((e_config->clientlist_limit_caption_len) && ((int)strlen(title) > max_len))
1210      {
1211         char *abbv;
1212         const char *left, *right;
1213
1214         abbv = calloc(E_CLIENTLIST_MAX_CAPTION_LEN + 4, sizeof(char));
1215         left = title;
1216         right = title + (strlen(title) - (max_len / 2));
1217
1218         strncpy(abbv, left, max_len / 2);
1219         strncat(abbv, "...", 3);
1220         strncat(abbv, right, max_len / 2);
1221
1222         return abbv;
1223      }
1224    else
1225      return title;
1226 }
1227
1228 static void
1229 _e_int_menus_clients_item_create(E_Border *bd, E_Menu *m)
1230 {
1231    E_Menu_Item *mi;
1232    const char *title;
1233
1234    title = _e_int_menus_clients_title_abbrv(e_border_name_get(bd));
1235    mi = e_menu_item_new(m);
1236    e_menu_item_check_set(mi, 1);
1237    if ((title) && (title[0]))
1238      e_menu_item_label_set(mi, title);
1239    else
1240      e_menu_item_label_set(mi, _("No name!!"));
1241    /* ref the border as we implicitly unref it in the callback */
1242    e_object_ref(E_OBJECT(bd));
1243 /*   e_object_breadcrumb_add(E_OBJECT(bd), "clients_menu");*/
1244    e_menu_item_callback_set(mi, _e_int_menus_clients_item_cb, bd);
1245    e_menu_item_realize_callback_set(mi, _e_int_menus_clients_icon_cb, bd);
1246    if (!bd->iconic) e_menu_item_toggle_set(mi, 1);
1247 }
1248
1249 static void
1250 _e_int_menus_clients_free_hook(void *obj)
1251 {
1252    Eina_List *borders;
1253    E_Border *bd;
1254    E_Menu *m;
1255
1256    m = obj;
1257    borders = e_object_data_get(E_OBJECT(m));
1258    EINA_LIST_FREE(borders, bd)
1259      e_object_unref(E_OBJECT(bd));
1260 }
1261
1262 static void
1263 _e_int_menus_clients_item_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1264 {
1265    E_Border *bd;
1266
1267    bd = data;
1268    E_OBJECT_CHECK(bd);
1269
1270    if (bd->iconic)
1271      {
1272         if (e_config->clientlist_warp_to_iconified_desktop == 1)
1273           e_desk_show(bd->desk);
1274         if (!bd->lock_user_iconify)
1275           e_border_uniconify(bd);
1276      }
1277
1278    if (!bd->iconic) e_desk_show(bd->desk);
1279    if (!bd->lock_user_stacking) e_border_raise(bd);
1280    if (!bd->lock_focus_out)
1281      {
1282         if (e_config->focus_policy != E_FOCUS_CLICK)
1283           ecore_x_pointer_warp(bd->zone->container->win,
1284                                bd->x + (bd->w / 2), bd->y + (bd->h / 2));
1285         e_border_focus_set(bd, 1, 1);
1286      }
1287 }
1288
1289 static void
1290 _e_int_menus_clients_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi)
1291 {
1292    E_Border *bd;
1293
1294    bd = data;
1295    E_OBJECT_CHECK(bd);
1296    mi->icon_object = e_border_icon_add(bd, m->evas);
1297 }
1298
1299 static void
1300 _e_int_menus_clients_cleanup_cb(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
1301 {
1302    E_Action *act;
1303
1304    act = e_action_find("cleanup_windows");
1305    if (act) act->func.go(E_OBJECT(m->zone), NULL);
1306 }
1307
1308 static void
1309 _e_int_menus_lost_clients_pre_cb(void *data __UNUSED__, E_Menu *m)
1310 {
1311    E_Menu_Item *mi;
1312    Eina_List *l, *borders = NULL;
1313    E_Border *bd;
1314    E_Menu *root;
1315    E_Zone *zone = NULL;
1316
1317    e_menu_pre_activate_callback_set(m, NULL, NULL);
1318    root = e_menu_root_get(m);
1319    /* get the current clients */
1320    if (root) zone = root->zone;
1321    borders = e_border_lost_windows_get(zone);
1322
1323    if (!borders)
1324      {
1325         /* FIXME here we want nothing, but that crashes!!! */
1326         mi = e_menu_item_new(m);
1327         e_menu_item_label_set(mi, _("(No Windows)"));
1328         return;
1329      }
1330    EINA_LIST_FOREACH(borders, l, bd)
1331      {
1332         const char *title = "";
1333
1334         title = e_border_name_get(bd);
1335         mi = e_menu_item_new(m);
1336         if ((title) && (title[0]))
1337           e_menu_item_label_set(mi, title);
1338         else
1339           e_menu_item_label_set(mi, _("No name!!"));
1340         /* ref the border as we implicitly unref it in the callback */
1341         e_object_ref(E_OBJECT(bd));
1342         e_menu_item_callback_set(mi, _e_int_menus_lost_clients_item_cb, bd);
1343         if (bd->desktop)
1344           e_util_desktop_menu_item_icon_add(bd->desktop, 24, mi);
1345      }
1346    e_object_free_attach_func_set(E_OBJECT(m),
1347                                  _e_int_menus_lost_clients_free_hook);
1348    e_object_data_set(E_OBJECT(m), borders);
1349 }
1350
1351 static void
1352 _e_int_menus_lost_clients_free_hook(void *obj)
1353 {
1354    Eina_List *borders;
1355    E_Border *bd;
1356    E_Menu *m;
1357
1358    m = obj;
1359    borders = e_object_data_get(E_OBJECT(m));
1360    EINA_LIST_FREE(borders, bd)
1361      e_object_unref(E_OBJECT(bd));
1362 }
1363
1364 static void
1365 _e_int_menus_lost_clients_item_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1366 {
1367    E_Border *bd = data;
1368
1369    E_OBJECT_CHECK(bd);
1370    if (bd->iconic) e_border_uniconify(bd);
1371    if (bd->desk) e_desk_show(bd->desk);
1372    e_border_center(bd);
1373    e_border_raise(bd);
1374    if (!bd->lock_focus_out)
1375      e_border_focus_set(bd, 1, 1);
1376 }
1377
1378 static void
1379 _e_int_menus_augmentation_add(E_Menu *m, Eina_List *augmentation)
1380 {
1381    E_Int_Menu_Augmentation *aug;
1382    Eina_List *l;
1383    char *data;
1384
1385    if ((!augmentation) || (!m)) return;
1386    EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data)
1387      if (eina_hash_find(_e_int_menus_augmentation, data) == augmentation)
1388        return;
1389
1390    EINA_LIST_FOREACH(augmentation, l, aug)
1391      if (aug->add.func) aug->add.func(aug->add.data, m);
1392 }
1393
1394 static void
1395 _e_int_menus_augmentation_del(E_Menu *m, Eina_List *augmentation)
1396 {
1397    E_Int_Menu_Augmentation *aug;
1398    Eina_List *l;
1399    char *data;
1400
1401    if ((!augmentation) || (!m)) return;
1402    EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data)
1403      if (eina_hash_find(_e_int_menus_augmentation, data) == augmentation)
1404        return;
1405
1406    EINA_LIST_FOREACH(augmentation, l, aug)
1407      if (aug->del.func) aug->del.func(aug->del.data, m);
1408 }
1409
1410 static void
1411 _e_int_menus_shelves_pre_cb(void *data __UNUSED__, E_Menu *m)
1412 {
1413    E_Menu_Item *mi;
1414    Eina_List *l, *shelves = NULL;
1415    E_Shelf *es;
1416    E_Container *con;
1417    E_Zone *zone;
1418
1419    e_menu_pre_activate_callback_set(m, NULL, NULL);
1420    con = e_container_current_get(e_manager_current_get());
1421    zone = e_zone_current_get(con);
1422
1423    /* get the current clients */
1424    shelves = e_shelf_list();
1425    EINA_LIST_FOREACH(shelves, l, es)
1426      {
1427         const char *name;
1428         char buf[4096];
1429
1430         if (!es) continue;
1431         if (es->zone->num != zone->num) continue;
1432         if (es->cfg->container != (int)con->num) continue;
1433
1434         name = e_shelf_orient_string_get(es);
1435         snprintf(buf, sizeof(buf), "Shelf %s", name);
1436
1437         mi = e_menu_item_new(m);
1438         e_menu_item_label_set(mi, buf);
1439         e_menu_item_callback_set(mi, _e_int_menus_shelves_item_cb, es);
1440         switch (es->cfg->orient)
1441           {
1442            case E_GADCON_ORIENT_LEFT:
1443              e_util_menu_item_theme_icon_set(mi, "preferences-position-left");
1444              break;
1445
1446            case E_GADCON_ORIENT_RIGHT:
1447              e_util_menu_item_theme_icon_set(mi, "preferences-position-right");
1448              break;
1449
1450            case E_GADCON_ORIENT_TOP:
1451              e_util_menu_item_theme_icon_set(mi, "preferences-position-top");
1452              break;
1453
1454            case E_GADCON_ORIENT_BOTTOM:
1455              e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom");
1456              break;
1457
1458            case E_GADCON_ORIENT_CORNER_TL:
1459              e_util_menu_item_theme_icon_set(mi, "preferences-position-top-left");
1460              break;
1461
1462            case E_GADCON_ORIENT_CORNER_TR:
1463              e_util_menu_item_theme_icon_set(mi, "preferences-position-top-right");
1464              break;
1465
1466            case E_GADCON_ORIENT_CORNER_BL:
1467              e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-left");
1468              break;
1469
1470            case E_GADCON_ORIENT_CORNER_BR:
1471              e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-right");
1472              break;
1473
1474            case E_GADCON_ORIENT_CORNER_LT:
1475              e_util_menu_item_theme_icon_set(mi, "preferences-position-left-top");
1476              break;
1477
1478            case E_GADCON_ORIENT_CORNER_RT:
1479              e_util_menu_item_theme_icon_set(mi, "preferences-position-right-top");
1480              break;
1481
1482            case E_GADCON_ORIENT_CORNER_LB:
1483              e_util_menu_item_theme_icon_set(mi, "preferences-position-left-bottom");
1484              break;
1485
1486            case E_GADCON_ORIENT_CORNER_RB:
1487              e_util_menu_item_theme_icon_set(mi, "preferences-position-right-bottom");
1488              break;
1489
1490            default:
1491              e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf");
1492              break;
1493           }
1494      }
1495    if (shelves)
1496      {
1497         mi = e_menu_item_new(m);
1498         e_menu_item_separator_set(mi, 1);
1499      }
1500
1501    mi = e_menu_item_new(m);
1502    e_menu_item_label_set(mi, _("Add a Shelf"));
1503    e_util_menu_item_theme_icon_set(mi, "list-add");
1504    e_menu_item_callback_set(mi, _e_int_menus_shelves_add_cb, NULL);
1505
1506    if (shelves)
1507      {
1508         mi = e_menu_item_new(m);
1509         e_menu_item_label_set(mi, _("Delete a Shelf"));
1510         e_util_menu_item_theme_icon_set(mi, "list-remove");
1511         e_menu_item_callback_set(mi, _e_int_menus_shelves_del_cb, NULL);
1512      }
1513 }
1514
1515 static void
1516 _e_int_menus_shelves_item_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1517 {
1518    E_Shelf *s = data;
1519
1520    E_OBJECT_CHECK(s);
1521    e_int_shelf_config(s);
1522 }
1523
1524 static void
1525 _e_int_menus_shelves_add_cb(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1526 {
1527    E_Zone *zone;
1528
1529    zone = e_util_zone_current_get(e_manager_current_get());
1530    e_shelf_new_dialog(zone);
1531 }
1532
1533 static void
1534 _e_int_menus_shelves_del_cb(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
1535 {
1536    e_configure_registry_call("extensions/shelves", m->zone->container, NULL);
1537 }
1538
1539 static void
1540 _e_int_menus_item_label_set(Efreet_Menu *entry, E_Menu_Item *mi)
1541 {
1542    Efreet_Desktop *desktop;
1543    char label[4096];
1544    int opt = 0;
1545
1546    if ((!entry) || (!mi)) return;
1547
1548    desktop = entry->desktop;
1549    if ((e_config->menu_eap_name_show) && (entry->name)) opt |= 0x4;
1550    if (desktop)
1551      {
1552         if ((e_config->menu_eap_generic_show) && (desktop->generic_name) &&
1553             (desktop->generic_name[0] != 0))
1554           opt |= 0x2;
1555         if ((e_config->menu_eap_comment_show) && (desktop->comment) &&
1556             (desktop->comment[0] != 0))
1557           opt |= 0x1;
1558      }
1559
1560    if (opt == 0x7)
1561      snprintf(label, sizeof(label), "%s (%s) [%s]", entry->name,
1562               desktop->generic_name, desktop->comment);
1563    else if (opt == 0x6)
1564      snprintf(label, sizeof(label), "%s (%s)", entry->name,
1565               desktop->generic_name);
1566    else if (opt == 0x5)
1567      snprintf(label, sizeof(label), "%s [%s]", entry->name, desktop->comment);
1568    else if (opt == 0x4)
1569      snprintf(label, sizeof(label), "%s", entry->name);
1570    else if (opt == 0x3)
1571      snprintf(label, sizeof(label), "%s [%s]", desktop->generic_name,
1572               desktop->comment);
1573    else if (opt == 0x2)
1574      snprintf(label, sizeof(label), "%s", desktop->generic_name);
1575    else if (opt == 0x1)
1576      snprintf(label, sizeof(label), "%s", desktop->comment);
1577    else
1578      snprintf(label, sizeof(label), "%s", entry->name);
1579
1580    e_menu_item_label_set(mi, label);
1581 }
1582