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