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