#include "e.h" typedef struct _Main_Data Main_Data; struct _Main_Data { E_Menu *menu; E_Menu *apps; E_Menu *all_apps; E_Menu *desktops; E_Menu *clients; E_Menu *enlightenment; E_Menu *config; E_Menu *lost_clients; }; /* local subsystem functions */ static void _e_int_menus_main_del_hook(void *obj); static void _e_int_menus_main_about(void *data, E_Menu *m, E_Menu_Item *mi); //static void _e_int_menus_fwin_favorites_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_apps_scan(E_Menu *m, Efreet_Menu *menu); static void _e_int_menus_apps_start(void *data, E_Menu *m); static void _e_int_menus_apps_free_hook2(void *obj); static void _e_int_menus_apps_run(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_apps_drag(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_config_pre_cb(void *data, E_Menu *m); static void _e_int_menus_config_free_hook(void *obj); static void _e_int_menus_clients_pre_cb(void *data, E_Menu *m); static void _e_int_menus_clients_item_create(E_Client *ec, E_Menu *m); static void _e_int_menus_clients_free_hook(void *obj); static void _e_int_menus_clients_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_clients_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_clients_cleanup_cb(void *data, E_Menu *m, E_Menu_Item *mi); static int _e_int_menus_clients_group_desk_cb(const void *d1, const void *d2); static int _e_int_menus_clients_group_class_cb(const void *d1, const void *d2); static int _e_int_menus_clients_sort_alpha_cb(const void *d1, const void *d2); static int _e_int_menus_clients_sort_z_order_cb(const void *d1, const void *d2); static void _e_int_menus_clients_add_by_class(Eina_List *clients, E_Menu *m); static void _e_int_menus_clients_add_by_desk(E_Desk *curr_desk, Eina_List *clients, E_Menu *m); static void _e_int_menus_clients_add_by_none(Eina_List *clients, E_Menu *m); static void _e_int_menus_clients_menu_add_iconified(Eina_List *clients, E_Menu *m); static const char *_e_int_menus_clients_title_abbrv(const char *title); static void _e_int_menus_virtuals_pre_cb(void *data, E_Menu *m); static void _e_int_menus_virtuals_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_virtuals_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_themes_about(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_report_bug(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_lost_clients_pre_cb(void *data, E_Menu *m); static void _e_int_menus_lost_clients_free_hook(void *obj); static void _e_int_menus_lost_clients_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_augmentation_add(E_Menu *m, Eina_List *augmentation); static void _e_int_menus_augmentation_del(E_Menu *m, Eina_List *augmentation); static void _e_int_menus_shelves_pre_cb(void *data, E_Menu *m); static void _e_int_menus_shelves_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_shelves_add_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_shelves_del_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_config_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_main_showhide(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_main_restart(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_main_exit(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_desktops_free_hook(void *obj); static void _e_int_menus_desk_item_cb(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_item_label_set(Efreet_Menu *entry, E_Menu_Item *mi); static Efreet_Menu *_e_int_menus_apps_thread_new(E_Menu *m, const char *dir); static Eina_Bool _e_int_menus_efreet_desktop_cache_update(void *d, int type, void *e); //static void _e_int_menus_apps_drag_finished(E_Drag *drag, int dropped EINA_UNUSED); /* local subsystem globals */ static Eina_Hash *_e_int_menus_augmentation = NULL; static Eina_List *_e_int_menus_augmentation_disabled = NULL; static Eina_Hash *_e_int_menus_app_menus = NULL; static Eina_Hash *_e_int_menus_app_menus_waiting = NULL; static Efreet_Menu *_e_int_menus_app_menu_default = NULL; static Ecore_Timer *_e_int_menus_app_cleaner = NULL; static Eina_List *handlers = NULL; static Eina_List * _e_int_menus_augmentation_find(const char *key) { Eina_List *l; char *data; if ((!_e_int_menus_augmentation) || (!key)) return NULL; EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data) if (!strcmp(data, key)) return NULL; return eina_hash_find(_e_int_menus_augmentation, key); } static void _e_int_menus_wallpaper_cb() { e_configure_registry_call("appearance/wallpaper", NULL, NULL); } static void _e_int_menus_bryce_cb() { e_bryce_edit(NULL); } static void _e_int_menus_desktop_gadget_add_cb() { e_gadget_site_desktop_edit(e_comp->canvas->gadget_site); } #ifdef ISCOMFITOR static void _TEST_ADD(void *data, E_Dialog *dia EINA_UNUSED) { char buf[4096]; snprintf(buf, sizeof(buf), "ITEM %d", e_widget_ilist_count(data) + 1); e_widget_ilist_append(data, NULL, buf, NULL, NULL, NULL); } static void _TEST_DEL(void *data, E_Dialog *dia EINA_UNUSED) { e_widget_ilist_remove_num(data, e_widget_ilist_selected_get(data)); } static void _TEST(void *d EINA_UNUSED, E_Menu *m, E_Menu_Item *mi EINA_UNUSED) { E_Dialog *dia; Evas_Object *o_list; Evas *e; dia = e_dialog_normal_win_new(e_comp, "E", "_widget_playground_dialog"); e = evas_object_evas_get(dia->win); o_list = e_widget_ilist_add(e, 32, 32, NULL); e_dialog_button_add(dia, "Add", NULL, _TEST_ADD, o_list); e_dialog_button_add(dia, "Del", NULL, _TEST_DEL, o_list); e_dialog_content_set(dia, o_list, 100, 300); e_dialog_show(dia); } #endif /* externally accessible functions */ E_API E_Menu * e_int_menus_main_new(void) { E_Menu *m, *subm; E_Menu_Item *mi; Main_Data *dat; Eina_List *l = NULL; int separator = 0; dat = calloc(1, sizeof(Main_Data)); m = e_menu_new(); e_menu_title_set(m, _("Main")); dat->menu = m; e_object_data_set(E_OBJECT(m), dat); e_object_del_attach_func_set(E_OBJECT(m), _e_int_menus_main_del_hook); e_menu_category_set(m, "main"); #ifdef ISCOMFITOR mi = e_menu_item_new(m); e_menu_item_label_set(mi, "TEST"); e_menu_item_callback_set(mi, _TEST, NULL); #endif l = _e_int_menus_augmentation_find("main/0"); if (l) _e_int_menus_augmentation_add(m, l); if (e_config->menu_favorites_show) { subm = e_int_menus_favorite_apps_new(); if (subm) { dat->apps = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Favorite Applications")); e_util_menu_item_theme_icon_set(mi, "user-bookmarks"); e_menu_item_submenu_set(mi, subm); } } if (e_config->menu_apps_show) { subm = e_int_menus_all_apps_new(); dat->all_apps = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Applications")); e_util_menu_item_theme_icon_set(mi, "preferences-applications"); e_menu_item_submenu_set(mi, subm); } l = _e_int_menus_augmentation_find("main/1"); if (l) _e_int_menus_augmentation_add(m, l); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); l = _e_int_menus_augmentation_find("main/2"); if (l) _e_int_menus_augmentation_add(m, l); subm = e_int_menus_desktops_new(); dat->desktops = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Desktop")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop"); e_menu_item_submenu_set(mi, subm); subm = e_int_menus_clients_new(); dat->clients = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Windows")); e_util_menu_item_theme_icon_set(mi, "preferences-system-windows"); e_menu_item_submenu_set(mi, subm); e_object_data_set(E_OBJECT(subm), dat); #ifndef HAVE_WAYLAND if (e_comp->comp_type == E_PIXMAP_TYPE_X) { subm = e_int_menus_lost_clients_new(); e_object_data_set(E_OBJECT(subm), dat); dat->lost_clients = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Lost Windows")); e_util_menu_item_theme_icon_set(mi, "preferences-windows-lost"); e_menu_item_submenu_set(mi, subm); } #endif l = _e_int_menus_augmentation_find("main/3"); if (l) _e_int_menus_augmentation_add(m, l); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); l = _e_int_menus_augmentation_find("main/4"); if (l) _e_int_menus_augmentation_add(m, l); subm = e_menu_new(); dat->enlightenment = subm; l = _e_int_menus_augmentation_find("enlightenment/0"); if (l) _e_int_menus_augmentation_add(subm, l); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Enlightenment")); e_util_menu_item_theme_icon_set(mi, "enlightenment"); e_menu_item_submenu_set(mi, subm); mi = e_menu_item_new(subm); e_menu_item_label_set(mi, _("About")); e_util_menu_item_theme_icon_set(mi, "help-about"); e_menu_item_callback_set(mi, _e_int_menus_main_about, NULL); mi = e_menu_item_new(subm); e_menu_item_label_set(mi, _("About Theme")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-theme"); e_menu_item_callback_set(mi, _e_int_menus_themes_about, NULL); mi = e_menu_item_new(subm); e_menu_item_label_set(mi, _("Report Bug")); e_util_menu_item_theme_icon_set(mi, "dialog-error"); e_menu_item_callback_set(mi, _e_int_menus_report_bug, NULL); l = _e_int_menus_augmentation_find("enlightenment/1"); if (l) _e_int_menus_augmentation_add(subm, l); mi = e_menu_item_new(subm); e_menu_item_separator_set(mi, 1); l = _e_int_menus_augmentation_find("enlightenment/2"); if (l) _e_int_menus_augmentation_add(subm, l); mi = e_menu_item_new(subm); e_menu_item_label_set(mi, _("Restart")); e_util_menu_item_theme_icon_set(mi, "system-restart"); e_menu_item_callback_set(mi, _e_int_menus_main_restart, NULL); mi = e_menu_item_new(subm); e_menu_item_label_set(mi, _("Exit")); e_util_menu_item_theme_icon_set(mi, "application-exit"); e_menu_item_callback_set(mi, _e_int_menus_main_exit, NULL); l = _e_int_menus_augmentation_find("enlightenment/3"); if (l) _e_int_menus_augmentation_add(subm, l); l = _e_int_menus_augmentation_find("main/5"); if (l) _e_int_menus_augmentation_add(m, l); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); l = _e_int_menus_augmentation_find("main/6"); if (l) _e_int_menus_augmentation_add(m, l); subm = e_int_menus_config_new(); dat->config = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Settings")); e_menu_item_callback_set(mi, _e_int_menus_config_cb, NULL); e_util_menu_item_theme_icon_set(mi, "preferences-system"); e_menu_item_submenu_set(mi, subm); l = _e_int_menus_augmentation_find("main/7"); if (l) _e_int_menus_augmentation_add(m, l); l = eina_hash_find(_e_int_menus_augmentation, "main/8"); if (l) { separator = 1; mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); _e_int_menus_augmentation_add(m, l); } l = eina_hash_find(_e_int_menus_augmentation, "main/9"); if (l) { if (!separator) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } _e_int_menus_augmentation_add(m, l); } return m; } E_API E_Menu * e_int_menus_apps_new(const char *dir) { E_Menu *m; m = e_menu_new(); if (dir) e_object_data_set(E_OBJECT(m), (void *)eina_stringshare_add(dir)); e_menu_pre_activate_callback_set(m, _e_int_menus_apps_start, NULL); return m; } E_API E_Menu * e_int_menus_desktops_new(void) { E_Menu *m, *subm; E_Menu_Item *mi; m = e_menu_new(); subm = e_menu_new(); e_menu_category_set(m, "desktop"); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Virtual")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop"); e_menu_pre_activate_callback_set(subm, _e_int_menus_virtuals_pre_cb, NULL); e_menu_item_submenu_set(mi, subm); subm = e_menu_new(); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Shelves")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); e_menu_pre_activate_callback_set(subm, _e_int_menus_shelves_pre_cb, NULL); e_menu_item_submenu_set(mi, subm); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Change Wallpaper")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-wallpaper"); e_menu_item_callback_set(mi, _e_int_menus_wallpaper_cb, NULL); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Add Gadget Bar (EXPERIMENTAL)")); e_util_menu_item_theme_icon_set(mi, "list-add"); e_menu_item_callback_set(mi, _e_int_menus_bryce_cb, NULL); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Add Gadgets To Desktop")); e_util_menu_item_theme_icon_set(mi, "list-add"); e_menu_item_callback_set(mi, _e_int_menus_desktop_gadget_add_cb, NULL); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Show/Hide All Windows")); e_util_menu_item_theme_icon_set(mi, "preferences-system-windows"); e_menu_item_callback_set(mi, _e_int_menus_main_showhide, NULL); e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_desktops_free_hook); return m; } E_API E_Menu * e_int_menus_favorite_apps_new(void) { E_Menu *m = NULL; char buf[PATH_MAX]; e_user_dir_concat_static(buf, "applications/menu/favorite.menu"); if (ecore_file_exists(buf)) m = e_int_menus_apps_new(buf); if (m) _e_int_menus_apps_start(NULL, m); return m; } E_API E_Menu * e_int_menus_all_apps_new(void) { E_Menu *m; m = e_int_menus_apps_new(NULL); return m; } E_API E_Menu * e_int_menus_config_new(void) { E_Menu *m; m = e_menu_new(); e_menu_category_set(m, "config"); e_menu_pre_activate_callback_set(m, _e_int_menus_config_pre_cb, NULL); return m; } E_API E_Menu * e_int_menus_clients_new(void) { E_Menu *m; m = e_menu_new(); e_menu_pre_activate_callback_set(m, _e_int_menus_clients_pre_cb, NULL); return m; } E_API E_Menu * e_int_menus_lost_clients_new(void) { E_Menu *m; m = e_menu_new(); e_menu_pre_activate_callback_set(m, _e_int_menus_lost_clients_pre_cb, NULL); return m; } E_API E_Int_Menu_Augmentation * e_int_menus_menu_augmentation_add_sorted(const char *menu, const char *sort_key, void (*func_add)(void *data, E_Menu *m), void *data_add, void (*func_del)(void *data, E_Menu *m), void *data_del) { E_Int_Menu_Augmentation *maug; Eina_List *l; Eina_Bool old = EINA_FALSE; maug = E_NEW(E_Int_Menu_Augmentation, 1); if (!maug) return NULL; maug->sort_key = eina_stringshare_add(sort_key); maug->add.func = func_add; maug->add.data = data_add; maug->del.func = func_del; maug->del.data = data_del; if (_e_int_menus_augmentation) { if ((l = eina_hash_find(_e_int_menus_augmentation, menu))) old = EINA_TRUE; } else { _e_int_menus_augmentation = eina_hash_string_superfast_new(NULL); l = NULL; old = EINA_FALSE; } if ((!l) || (!maug->sort_key)) l = eina_list_append(l, maug); else { E_Int_Menu_Augmentation *m2; Eina_List *l2; /* keep list sorted, those missing sort_key at the end. */ EINA_LIST_FOREACH(l, l2, m2) { if (!m2->sort_key) break; if (strcasecmp(maug->sort_key, m2->sort_key) < 0) break; } if (l2) l = eina_list_prepend_relative_list(l, maug, l2); else l = eina_list_append(l, maug); } if (old) eina_hash_modify(_e_int_menus_augmentation, menu, l); else eina_hash_add(_e_int_menus_augmentation, menu, l); return maug; } E_API E_Int_Menu_Augmentation * e_int_menus_menu_augmentation_add(const char *menu, void (*func_add)(void *data, E_Menu *m), void *data_add, void (*func_del)(void *data, E_Menu *m), void *data_del) { return e_int_menus_menu_augmentation_add_sorted (menu, NULL, func_add, data_add, func_del, data_del); } E_API void e_int_menus_menu_augmentation_del(const char *menu, E_Int_Menu_Augmentation *maug) { Eina_List *l; if (!_e_int_menus_augmentation) { eina_stringshare_del(maug->sort_key); free(maug); return; } l = eina_hash_find(_e_int_menus_augmentation, menu); if (l) { l = eina_list_remove(l, maug); if (l) eina_hash_modify(_e_int_menus_augmentation, menu, l); else eina_hash_del_by_key(_e_int_menus_augmentation, menu); } eina_stringshare_del(maug->sort_key); free(maug); } E_API void e_int_menus_cache_clear(void) { if (_e_int_menus_app_menus) eina_hash_free_buckets(_e_int_menus_app_menus); } E_API void e_int_menus_menu_augmentation_point_disabled_set(const char *menu, Eina_Bool disabled) { if (!menu) return; if (disabled) { _e_int_menus_augmentation_disabled = eina_list_append(_e_int_menus_augmentation_disabled, menu); } else { _e_int_menus_augmentation_disabled = eina_list_remove(_e_int_menus_augmentation_disabled, menu); } } EINTERN void e_int_menus_init(void) { if (!e_config->menu_apps_show) { char buf[PATH_MAX]; e_user_dir_concat_static(buf, "applications/menu/favorite.menu"); _e_int_menus_apps_thread_new(NULL, eina_stringshare_add(buf)); } E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_int_menus_efreet_desktop_cache_update, NULL); E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_DESKTOP_CACHE_BUILD, _e_int_menus_efreet_desktop_cache_update, NULL); } EINTERN void e_int_menus_shutdown(void) { if (_e_int_menus_app_cleaner) ecore_timer_del(_e_int_menus_app_cleaner); _e_int_menus_app_cleaner = NULL; eina_hash_free(_e_int_menus_app_menus_waiting); _e_int_menus_app_menus_waiting = NULL; efreet_menu_free(_e_int_menus_app_menu_default); _e_int_menus_app_menu_default = NULL; E_FREE_LIST(handlers, ecore_event_handler_del); } /* local subsystem functions */ static Eina_Bool _e_int_menus_efreet_desktop_cache_update(void *d EINA_UNUSED, int type EINA_UNUSED, void *e EINA_UNUSED) { e_int_menus_shutdown(); e_int_menus_init(); return ECORE_CALLBACK_RENEW; } static void _e_int_menus_main_del_hook(void *obj) { Main_Data *dat; E_Menu *m; m = obj; dat = e_object_data_get(E_OBJECT(obj)); if (dat->apps) e_object_del(E_OBJECT(dat->apps)); if (dat->all_apps) e_object_del(E_OBJECT(dat->all_apps)); if (dat->desktops) e_object_del(E_OBJECT(dat->desktops)); if (dat->clients) e_object_del(E_OBJECT(dat->clients)); if (dat->lost_clients) e_object_del(E_OBJECT(dat->lost_clients)); if (dat->enlightenment) e_object_del(E_OBJECT(dat->enlightenment)); if (dat->config) e_object_del(E_OBJECT(dat->config)); free(dat); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/0")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/1")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/2")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/3")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/4")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/5")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/6")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/7")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/8")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/9")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/10")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("main/11")); } static void _e_int_menus_main_about(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_About *about; about = e_about_new(); if (about) e_about_show(about); } static void _e_int_menus_themes_about(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Theme_About *about; about = e_theme_about_new(); if (about) e_theme_about_show(about); } static void _e_int_menus_report_bug(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { e_util_open("https://www.enlightenment.org/contrib/report-bug.md", NULL); } /* static void _e_int_menus_fwin_favorites_item_cb(void *data, E_Menu *m, E_Menu_Item *mi) { e_fwin_new("favorites", "/"); } */ static void _e_int_menus_config_cb(void *data EINA_UNUSED, E_Menu *m, E_Menu_Item *mi EINA_UNUSED) { E_Action *act; act = e_action_find("configuration"); if (act) act->func.go(E_OBJECT(m->zone), NULL); } static void _e_int_menus_main_showhide(void *data EINA_UNUSED, E_Menu *m, E_Menu_Item *mi EINA_UNUSED) { E_Action *act; act = e_action_find("desk_deskshow_toggle"); if (act) act->func.go(E_OBJECT(m->zone), NULL); } static void _e_int_menus_main_restart(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Action *a; a = e_action_find("restart"); if ((a) && (a->func.go)) a->func.go(NULL, NULL); } static void _e_int_menus_main_exit(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Action *a; a = e_action_find("exit"); if ((a) && (a->func.go)) a->func.go(NULL, NULL); } static char * _e_int_menus_app_exe_get(const char *exec) { char *real, *d; const char *s; Eina_Bool in_quote_dbl = EINA_FALSE; Eina_Bool in_quote = EINA_FALSE; real = malloc(strlen(exec) + 1); if (!real) return NULL; for (d = real, s = exec; *s; s++) { if (in_quote_dbl) { switch (*s) { case '\"': in_quote_dbl = EINA_FALSE; break; case '\\': s++; EINA_FALLTHROUGH default: *d = *s; d++; break; } } else if (in_quote) { switch (*s) { case '\'': in_quote = EINA_FALSE; break; case '\\': s++; EINA_FALLTHROUGH default: *d = *s; d++; break; } } else { switch (*s) { case ' ': case '\t': case '\r': case '\n': goto done; break; case '\"': in_quote_dbl = EINA_TRUE; break; case '\'': in_quote = EINA_TRUE; break; case '\\': s++; EINA_FALLTHROUGH default: *d = *s; d++; break; } } } done: *d = 0; return real; } /* * This function searches $PATH for try_exec or exec * return true if try_exec or exec is found! */ static Eina_Bool _e_int_menus_app_finder(const char *exec) { const char *env = getenv("PATH"); char **split, buf[PATH_MAX]; Eina_Bool exec_found = EINA_FALSE; int i = 0; char *real = NULL; if (!exec) return EINA_FALSE; real = _e_int_menus_app_exe_get(exec); if (!real) return EINA_FALSE; if (strchr(real, '/')) { if (ecore_file_exists(real) && ecore_file_can_exec(real)) { free(real); return EINA_TRUE; } } if (!env) { WRN("Unable to $PATH, Returning TRUE for every .desktop"); free(real); return EINA_TRUE; } split = eina_str_split(env, ":", 0); for (i = 0; split[i] != NULL; i++) { snprintf(buf, sizeof(buf), "%s/%s", split[i], real); if (ecore_file_exists(buf) && ecore_file_can_exec(buf)) { exec_found = EINA_TRUE; break; } } free(split[0]); free(split); if (!exec_found) WRN("Unable to find: [%s] I searched $PATH=%s", exec, env); free(real); return exec_found; } /* * This function initalises E_Int_Menu_Applications and adds * our data. */ static E_Int_Menu_Applications* _e_int_menus_app_config_set(Efreet_Desktop *desktop) { E_Int_Menu_Applications *ma; ma = E_NEW(E_Int_Menu_Applications, 1); ma->orig_path = eina_stringshare_add(desktop->orig_path); ma->try_exec = eina_stringshare_add(desktop->try_exec); ma->exec = eina_stringshare_add(desktop->exec); ma->load_time = desktop->load_time; ma->exec_valid = 1; //ALL .desktop files are VALID unless proven otherwise :) return ma; } /* * This function adds/updates our E_Int_Menu_Applications config, * returns true if the .desktop file is valid. */ static Eina_Bool _e_int_menus_app_config_append(Efreet_Desktop *desktop) { E_Int_Menu_Applications *ma, *cma; Eina_List *l, *l_next; if (!desktop) return EINA_TRUE; cma = _e_int_menus_app_config_set(desktop); EINA_LIST_FOREACH_SAFE(e_config->menu_applications, l, l_next, ma) { if ((!strcmp(ma->orig_path, cma->orig_path)) && (ma->load_time == cma->load_time)) { eina_stringshare_del(cma->orig_path); eina_stringshare_del(cma->try_exec); eina_stringshare_del(cma->exec); free(cma); return ma->exec_valid; } if ((!strcmp(ma->orig_path, cma->orig_path)) && (ma->load_time != cma->load_time)) { WRN("Modified: [%s]", cma->orig_path); e_config->menu_applications = eina_list_remove(e_config->menu_applications, ma); } } if (cma->try_exec) { WRN("Try_Exec: [%s]", cma->try_exec); cma->exec_valid = _e_int_menus_app_finder(cma->try_exec); } else if (cma->exec) { cma->exec_valid = _e_int_menus_app_finder(cma->exec); } e_config->menu_applications = eina_list_append(e_config->menu_applications, cma); return cma->exec_valid; } static void _e_int_menus_apps_scan(E_Menu *m, Efreet_Menu *menu) { E_Menu_Item *mi; Eina_List *l; if (menu->entries) { Efreet_Menu *entry; EINA_LIST_FOREACH(menu->entries, l, entry) { if ((entry->type == EFREET_MENU_ENTRY_DESKTOP) && (!_e_int_menus_app_config_append(entry->desktop))) continue; mi = e_menu_item_new(m); _e_int_menus_item_label_set(entry, mi); if (entry->icon) { if (entry->icon[0] == '/') e_menu_item_icon_file_set(mi, entry->icon); else e_util_menu_item_theme_icon_set(mi, entry->icon); } if (entry->type == EFREET_MENU_ENTRY_SEPARATOR) e_menu_item_separator_set(mi, 1); else if (entry->type == EFREET_MENU_ENTRY_DESKTOP) { e_menu_item_callback_set(mi, _e_int_menus_apps_run, entry->desktop); e_menu_item_drag_callback_set(mi, _e_int_menus_apps_drag, entry->desktop); } else if (entry->type == EFREET_MENU_ENTRY_MENU) { E_Menu *subm; subm = e_menu_new(); efreet_menu_ref(entry); e_menu_pre_activate_callback_set(subm, _e_int_menus_apps_start, entry); e_menu_item_submenu_set(mi, subm); e_object_free_attach_func_set(E_OBJECT(subm), _e_int_menus_apps_free_hook2); } /* TODO: Highlight header else if (entry->type == EFREET_MENU_ENTRY_HEADER) */ } } else { mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("No applications")); e_menu_item_disabled_set(mi, 1); } } static Eina_Bool _e_int_menus_app_cleaner_cb(void *d EINA_UNUSED) { eina_hash_free_buckets(_e_int_menus_app_menus); return EINA_TRUE; } static void _e_int_menus_apps_menu_del(void *data) { const char *dir; dir = e_object_data_get(data); eina_hash_del_by_key(_e_int_menus_app_menus_waiting, dir); } static Efreet_Menu * _e_int_menus_apps_thread_new(E_Menu *m, const char *dir) { Efreet_Menu *menu = NULL; E_Menu *mn = NULL; char buf[PATH_MAX]; if (dir) { if (_e_int_menus_app_menus) menu = eina_hash_find(_e_int_menus_app_menus, dir); else _e_int_menus_app_menus = eina_hash_string_superfast_new((void *)efreet_menu_free); } else { menu = _e_int_menus_app_menu_default; if (!menu) menu = _e_int_menus_app_menu_default = efreet_menu_get(); } if (menu) return menu; if (dir) { if (_e_int_menus_app_menus_waiting) mn = eina_hash_find(_e_int_menus_app_menus_waiting, dir); else _e_int_menus_app_menus_waiting = eina_hash_string_superfast_new(NULL); } else return NULL; if (mn) return NULL; if (dir && m) eina_hash_add(_e_int_menus_app_menus_waiting, dir, m); menu = efreet_menu_parse(dir); eina_hash_add(_e_int_menus_app_menus, dir, menu); mn = eina_hash_set(_e_int_menus_app_menus_waiting, dir, NULL); if (!mn) goto on_end; e_object_del_attach_func_set(E_OBJECT(mn), NULL); if (_e_int_menus_app_cleaner) ecore_timer_loop_reset(_e_int_menus_app_cleaner); else _e_int_menus_app_cleaner = ecore_timer_loop_add(300, _e_int_menus_app_cleaner_cb, NULL); eina_stringshare_del(dir); if (m) { _e_int_menus_apps_scan(m, menu); e_menu_pre_activate_callback_set(m, NULL, NULL); e_object_data_set(E_OBJECT(m), menu); e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_apps_free_hook2); } if (!e_config->menu_apps_show) goto on_end; e_user_dir_concat_static(buf, "applications/menu/favorite.menu"); dir = eina_stringshare_add(buf); if (eina_hash_find(_e_int_menus_app_menus, dir)) eina_stringshare_del(dir); else _e_int_menus_apps_thread_new(NULL, dir); on_end: if (m) e_object_del_attach_func_set(E_OBJECT(m), _e_int_menus_apps_menu_del); return NULL; } static void _e_int_menus_apps_start(void *data, E_Menu *m) { Efreet_Menu *menu; const char *dir = NULL; if (m->items) return; menu = data; if (!menu) { dir = e_object_data_get(E_OBJECT(m)); menu = _e_int_menus_apps_thread_new(m, dir); } if (!menu) return; if (_e_int_menus_app_cleaner) ecore_timer_loop_reset(_e_int_menus_app_cleaner); eina_stringshare_del(dir); _e_int_menus_apps_scan(m, menu); if (m->pre_activate_cb.func == _e_int_menus_apps_start) { efreet_menu_unref(m->pre_activate_cb.data); m->pre_activate_cb.func = NULL; m->pre_activate_cb.data = NULL; } e_menu_pre_activate_callback_set(m, NULL, NULL); e_object_data_set(E_OBJECT(m), menu); e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_apps_free_hook2); } static void _e_int_menus_apps_free_hook2(void *obj) { E_Menu *m; Eina_List *l, *l_next; E_Menu_Item *mi; m = obj; // unref the e menu we had pointed to in the pre activate cb */ if (m->pre_activate_cb.func == _e_int_menus_apps_start) { efreet_menu_unref(m->pre_activate_cb.data); m->pre_activate_cb.func = NULL; m->pre_activate_cb.data = NULL; } // XXX TODO: this should be automatic in e_menu, just get references right! // XXX TODO: fix references and remove me!!! EINA_LIST_FOREACH_SAFE(m->items, l, l_next, mi) { if (mi->submenu) e_object_del(E_OBJECT(mi->submenu)); } } static void _e_int_menus_apps_run(void *data, E_Menu *m, E_Menu_Item *mi EINA_UNUSED) { Efreet_Desktop *desktop; desktop = data; e_exec(m->zone, desktop, NULL, NULL, "menu/apps"); } /* static void _e_int_menus_apps_drag_finished(E_Drag *drag, int dropped EINA_UNUSED) { Efreet_Desktop *desktop; desktop = drag->data; efreet_desktop_free(desktop); } */ static void _e_int_menus_apps_drag(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi) { Efreet_Desktop *desktop; desktop = data; /* start drag! */ if (mi->icon_object) { E_Drag *drag; Evas_Object *o = NULL; Evas_Coord x, y, w, h; unsigned int size; const char *drag_types[] = { "enlightenment/desktop" }; evas_object_geometry_get(mi->icon_object, &x, &y, &w, &h); efreet_desktop_ref(desktop); drag = e_drag_new(x, y, drag_types, 1, desktop, -1, NULL, NULL); drag->button_mask = evas_pointer_button_down_mask_get(e_comp->evas); size = MIN(w, h); o = e_util_desktop_icon_add(desktop, size, e_drag_evas_get(drag)); e_drag_object_set(drag, o); e_drag_resize(drag, w, h); e_drag_start(drag, mi->drag.x + w, mi->drag.y + h); } } static void _e_int_menus_virtuals_pre_cb(void *data EINA_UNUSED, E_Menu *m) { E_Menu_Item *mi; E_Menu *root; e_menu_pre_activate_callback_set(m, NULL, NULL); root = e_menu_root_get(m); if ((root) && (root->zone)) { E_Zone *zone; int i; zone = root->zone; for (i = 0; i < (zone->desk_x_count * zone->desk_y_count); i++) { E_Desk *desk; desk = zone->desks[i]; mi = e_menu_item_new(m); e_menu_item_radio_group_set(mi, 1); e_menu_item_radio_set(mi, 1); e_menu_item_label_set(mi, desk->name); if (desk == e_desk_current_get(zone)) e_menu_item_toggle_set(mi, 1); e_menu_item_callback_set(mi, _e_int_menus_virtuals_item_cb, desk); e_menu_item_realize_callback_set(mi, _e_int_menus_virtuals_icon_cb, desk); } } if (e_configure_registry_exists("screen/virtual_desktops")) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Set Virtual Desktops")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop"); e_menu_item_callback_set(mi, _e_int_menus_desk_item_cb, NULL); } } static void _e_int_menus_desktops_free_hook(void *obj) { E_Menu *m; Eina_List *l, *l_next; E_Menu_Item *mi; m = obj; // XXX TODO: this should be automatic in e_menu, just get references right! // XXX TODO: fix references and remove me!!! EINA_LIST_FOREACH_SAFE(m->items, l, l_next, mi) { if (mi->submenu) e_object_del(E_OBJECT(mi->submenu)); } } static void _e_int_menus_desk_item_cb(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { e_configure_registry_call("screen/virtual_desktops", NULL, NULL); } static void _e_int_menus_virtuals_item_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Desk *desk; if (!(desk = data)) return; e_desk_show(desk); } static void _e_int_menus_virtuals_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi) { E_Desk *desk; Evas_Object *o; const char *bgfile; int tw, th; desk = data; E_OBJECT_CHECK(desk); tw = 50; th = (tw * desk->zone->h) / desk->zone->w; bgfile = e_bg_file_get(desk->zone->num, desk->x, desk->y); o = e_thumb_icon_add(m->evas); e_thumb_icon_file_set(o, bgfile, "e/desktop/background"); eina_stringshare_del(bgfile); e_thumb_icon_size_set(o, tw, th); e_thumb_icon_begin(o); mi->icon_object = o; } static void _e_e_int_menus_conf_comp_cb(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { e_int_config_comp(NULL, NULL); } static void _e_int_menus_config_pre_cb(void *data EINA_UNUSED, E_Menu *m) { E_Menu_Item *mi; Eina_List *l = NULL; e_menu_pre_activate_callback_set(m, NULL, NULL); l = _e_int_menus_augmentation_find("config/0"); if (l) { _e_int_menus_augmentation_add(m, l); if (_e_int_menus_augmentation_find("config/1")) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } } mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Composite")); e_util_menu_item_theme_icon_set(mi, "preferences-composite"); e_menu_item_callback_set(mi, _e_e_int_menus_conf_comp_cb, NULL); l = _e_int_menus_augmentation_find("config/1"); if (l) _e_int_menus_augmentation_add(m, l); l = _e_int_menus_augmentation_find("config/2"); if (l) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); _e_int_menus_augmentation_add(m, l); } e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_config_free_hook); } static void _e_int_menus_config_free_hook(void *obj) { E_Menu *m; m = obj; _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/0")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/1")); _e_int_menus_augmentation_del(m, _e_int_menus_augmentation_find("config/2")); } static int _e_int_menus_clients_group_desk_cb(const void *d1, const void *d2) { const E_Client *ec1; const E_Client *ec2; int j, k; if (!d1) return 1; if (!d2) return -1; ec1 = d1; ec2 = d2; j = ec1->desk->y * 12 + ec1->desk->x; k = ec2->desk->y * 12 + ec2->desk->x; if (j > k) return 1; if (j < k) return -1; return -1; /* Returning '-1' on equal is intentional */ } static int _e_int_menus_clients_group_class_cb(const void *d1, const void *d2) { const E_Client *ec1, *ec2; if (!d1) return 1; if (!d2) return -1; ec1 = d1; ec2 = d2; if (!ec1->icccm.class) return -1; if (!ec2->icccm.class) return 1; return strcmp(ec1->icccm.class, ec2->icccm.class) > 0 ? 1 : -1; } static int _e_int_menus_clients_sort_alpha_cb(const void *d1, const void *d2) { const E_Client *ec1, *ec2; const char *name1, *name2; if (!d1) return 1; if (!d2) return -1; ec1 = d1; ec2 = d2; name1 = e_client_util_name_get(ec1); name2 = e_client_util_name_get(ec2); if (strcasecmp(name1, name2) > 0) return 1; if (strcasecmp(name1, name2) < 0) return -1; return 0; } static int _e_int_menus_clients_sort_z_order_cb(const void *d1, const void *d2) { const E_Client *ec1, *ec2; if (!d1) return 1; if (!d2) return -1; ec1 = d1; ec2 = d2; if (ec1->layer < ec2->layer) return 1; if (ec1->layer > ec2->layer) return -1; return 0; } static void _e_int_menus_clients_menu_add_iconified(Eina_List *clients, E_Menu *m) { Eina_List *l = NULL; E_Client *ec = NULL; E_Menu_Item *mi = NULL; if (!eina_list_count(clients)) return; mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); EINA_LIST_FOREACH(clients, l, ec) _e_int_menus_clients_item_create(ec, m); } static void _e_int_menus_clients_add_by_class(Eina_List *clients, E_Menu *m) { Eina_List *l = NULL, *ico = NULL; E_Client *ec; E_Menu *subm = NULL; E_Menu_Item *mi = NULL; char *class = NULL; EINA_LIST_FOREACH(clients, l, ec) { if ((ec->iconic) && (e_config->clientlist_separate_iconified_apps == E_CLIENTLIST_GROUPICONS_SEP)) { ico = eina_list_append(ico, ec); continue; } if (((e_util_strcmp(class, ec->icccm.class)) && e_config->clientlist_separate_with != E_CLIENTLIST_GROUP_SEP_NONE)) { if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU) { if ((subm) && (mi)) e_menu_item_submenu_set(mi, subm); mi = e_menu_item_new(m); e_menu_item_label_set(mi, ec->icccm.class); e_util_menu_item_theme_icon_set(mi, "preferences-system-windows"); subm = e_menu_new(); } else { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } free(class); class = strdup(ec->icccm.class); } if (subm && (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)) _e_int_menus_clients_item_create(ec, subm); else _e_int_menus_clients_item_create(ec, m); } if ((e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU) && (subm) && (mi)) e_menu_item_submenu_set(mi, subm); _e_int_menus_clients_menu_add_iconified(ico, m); free(class); } static void _e_int_menus_clients_add_by_desk(E_Desk *curr_desk, Eina_List *clients, E_Menu *m) { E_Desk *desk = NULL; Eina_List *l = NULL, *alt = NULL, *ico = NULL; E_Client *ec; E_Menu *subm; E_Menu_Item *mi = NULL; /* Deal with present desk first */ EINA_LIST_FOREACH(clients, l, ec) { if (ec->iconic && (e_config->clientlist_separate_iconified_apps == E_CLIENTLIST_GROUPICONS_SEP)) { ico = eina_list_append(ico, ec); continue; } if (ec->desk != curr_desk) { if ((!ec->iconic) || (ec->iconic && e_config->clientlist_separate_iconified_apps == E_CLIENTLIST_GROUPICONS_OWNER)) { alt = eina_list_append(alt, ec); continue; } } else _e_int_menus_clients_item_create(ec, m); } desk = NULL; subm = NULL; if (eina_list_count(alt) > 0) { if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } EINA_LIST_FOREACH(alt, l, ec) { if ((ec->desk != desk) && (e_config->clientlist_separate_with != E_CLIENTLIST_GROUP_SEP_NONE)) { if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU) { if (subm && mi) e_menu_item_submenu_set(mi, subm); mi = e_menu_item_new(m); e_menu_item_label_set(mi, ec->desk->name); e_util_menu_item_theme_icon_set(mi, "preferences-desktop"); subm = e_menu_new(); } else { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } desk = ec->desk; } if (subm && (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU)) _e_int_menus_clients_item_create(ec, subm); else _e_int_menus_clients_item_create(ec, m); } if (e_config->clientlist_separate_with == E_CLIENTLIST_GROUP_SEP_MENU && (subm) && (mi)) e_menu_item_submenu_set(mi, subm); } _e_int_menus_clients_menu_add_iconified(ico, m); } static void _e_int_menus_clients_add_by_none(Eina_List *clients, E_Menu *m) { Eina_List *l = NULL, *ico = NULL; E_Client *ec; EINA_LIST_FOREACH(clients, l, ec) { if ((ec->iconic) && (e_config->clientlist_separate_iconified_apps == E_CLIENTLIST_GROUPICONS_SEP)) { ico = eina_list_append(ico, ec); continue; } _e_int_menus_clients_item_create(ec, m); } _e_int_menus_clients_menu_add_iconified(ico, m); } static void _e_int_menus_clients_pre_cb(void *data EINA_UNUSED, E_Menu *m) { E_Menu *subm; E_Menu_Item *mi = NULL; Eina_List *l = NULL, *clients = NULL; E_Client *ec; E_Zone *zone = NULL; E_Desk *desk = NULL; Main_Data *dat; e_menu_pre_activate_callback_set(m, NULL, NULL); /* get the current clients */ zone = e_zone_current_get(); desk = e_desk_current_get(zone); if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_MOST_RECENT) l = e_client_focus_stack_get(); else l = e_comp->clients; EINA_LIST_FOREACH(l, l, ec) { if (ec->user_skip_winlist || e_client_util_ignored_get(ec)) continue; if ((ec->zone == zone) || (ec->iconic) || (ec->zone != zone && e_config->clientlist_include_all_zones)) { if (ec->stack.next == NULL) clients = eina_list_append(clients, ec); } } dat = (Main_Data *)e_object_data_get(E_OBJECT(m)); if (!dat) e_menu_title_set(m, _("Windows")); if (!clients) { /* FIXME here we want nothing, but that crashes!!! */ mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("No windows")); e_menu_item_disabled_set(mi, 1); } if (clients) { /* Sort the clients */ if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_ALPHA) clients = eina_list_sort(clients, eina_list_count(clients), _e_int_menus_clients_sort_alpha_cb); if (e_config->clientlist_sort_by == E_CLIENTLIST_SORT_ZORDER) clients = eina_list_sort(clients, eina_list_count(clients), _e_int_menus_clients_sort_z_order_cb); /* Group the clients */ if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_DESK) { clients = eina_list_sort(clients, eina_list_count(clients), _e_int_menus_clients_group_desk_cb); _e_int_menus_clients_add_by_desk(desk, clients, m); } if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_CLASS) { clients = eina_list_sort(clients, eina_list_count(clients), _e_int_menus_clients_group_class_cb); _e_int_menus_clients_add_by_class(clients, m); } if (e_config->clientlist_group_by == E_CLIENTLIST_GROUP_NONE) _e_int_menus_clients_add_by_none(clients, m); } mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Cleanup Windows")); e_util_menu_item_theme_icon_set(mi, "preferences-system-windows"); e_menu_item_callback_set(mi, _e_int_menus_clients_cleanup_cb, zone); if ((dat) && (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_FULL)) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); subm = e_int_menus_lost_clients_new(); e_object_data_set(E_OBJECT(subm), e_object_data_get(E_OBJECT(m))); dat->lost_clients = subm; mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Lost Windows")); e_util_menu_item_theme_icon_set(mi, "preferences-windows-lost"); e_menu_item_submenu_set(mi, subm); } e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_clients_free_hook); e_object_data_set(E_OBJECT(m), clients); } static const char * _e_int_menus_clients_title_abbrv(const char *title) { static char abbv[E_CLIENTLIST_MAX_CAPTION_LEN + 4]; char *abbvptr = abbv; int str_len, len, len2, max_len; if (!e_config->clientlist_limit_caption_len) return title; max_len = e_config->clientlist_max_caption_len; if (eina_unicode_utf8_get_len(title) <= max_len) return title; memset(&abbv, 0, sizeof(abbv)); /* Advance to the end of the first half of the string. */ len = 0; for (len2 = (max_len / 2); len2; len2--) { Eina_Unicode u = eina_unicode_utf8_next_get(title, &len); if ((!u) || ((u >= 0xdc80) && (u <= 0xdcff))) break; } strncat(abbvptr, title, len); abbvptr += len; /* Append the ellipsis char. */ strcpy(abbvptr, "\xE2\x80\xA6"); abbvptr += 3; /* Advance to the start of the second half of the string */ len = str_len = strlen(title); for (len2 = (max_len / 2); len2; len2--) eina_unicode_utf8_get_prev(title, &len); strncpy(abbvptr, title + len, str_len); abbvptr[str_len] = '\0'; return abbv; } static void _e_int_menus_clients_item_create(E_Client *ec, E_Menu *m) { E_Menu_Item *mi; const char *title; title = _e_int_menus_clients_title_abbrv(e_client_util_name_get(ec)); mi = e_menu_item_new(m); e_menu_item_check_set(mi, 1); if ((title) && (title[0])) e_menu_item_label_set(mi, title); else e_menu_item_label_set(mi, _("Untitled window")); /* ref the client as we implicitly unref it in the callback */ e_object_ref(E_OBJECT(ec)); /* e_object_breadcrumb_add(E_OBJECT(ec), "clients_menu");*/ e_menu_item_callback_set(mi, _e_int_menus_clients_item_cb, ec); e_menu_item_realize_callback_set(mi, _e_int_menus_clients_icon_cb, ec); if (!ec->iconic) e_menu_item_toggle_set(mi, 1); } static void _e_int_menus_clients_free_hook(void *obj) { Eina_List *clients; E_Client *ec; E_Menu *m; m = obj; clients = e_object_data_get(E_OBJECT(m)); EINA_LIST_FREE(clients, ec) e_object_unref(E_OBJECT(ec)); } static void _e_int_menus_clients_item_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Client *ec; ec = data; E_OBJECT_CHECK(ec); if (ec->iconic) { if (e_config->clientlist_warp_to_iconified_desktop == 1) e_desk_show(ec->desk); if (!ec->lock_user_iconify) e_client_uniconify(ec); } if (!ec->iconic) e_desk_show(ec->desk); if (!ec->lock_user_stacking) evas_object_raise(ec->frame); e_client_focus_set_with_pointer(ec); } static void _e_int_menus_clients_icon_cb(void *data, E_Menu *m, E_Menu_Item *mi) { E_Client *ec; ec = data; E_OBJECT_CHECK(ec); mi->icon_object = e_client_icon_add(ec, m->evas); } static void _e_int_menus_clients_cleanup_cb(void *data EINA_UNUSED, E_Menu *m, E_Menu_Item *mi EINA_UNUSED) { E_Action *act; act = e_action_find("cleanup_windows"); if (act) act->func.go(E_OBJECT(m->zone), NULL); } static void _e_int_menus_lost_clients_pre_cb(void *data EINA_UNUSED, E_Menu *m) { E_Menu_Item *mi; Eina_List *l, *clients = NULL; E_Client *ec; E_Menu *root; E_Zone *zone = NULL; e_menu_pre_activate_callback_set(m, NULL, NULL); root = e_menu_root_get(m); /* get the current clients */ if (root) zone = root->zone; clients = e_client_lost_windows_get(zone); if (!clients) { /* FIXME here we want nothing, but that crashes!!! */ mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("No windows")); e_menu_item_disabled_set(mi, 1); return; } EINA_LIST_FOREACH(clients, l, ec) { const char *title = ""; title = e_client_util_name_get(ec); mi = e_menu_item_new(m); if ((title) && (title[0])) e_menu_item_label_set(mi, title); else e_menu_item_label_set(mi, _("Untitled window")); /* ref the client as we implicitly unref it in the callback */ e_object_ref(E_OBJECT(ec)); e_menu_item_callback_set(mi, _e_int_menus_lost_clients_item_cb, ec); if (ec->desktop) e_util_desktop_menu_item_icon_add(ec->desktop, 24, mi); } e_object_free_attach_func_set(E_OBJECT(m), _e_int_menus_lost_clients_free_hook); e_object_data_set(E_OBJECT(m), clients); } static void _e_int_menus_lost_clients_free_hook(void *obj) { Eina_List *clients; E_Client *ec; E_Menu *m; m = obj; clients = e_object_data_get(E_OBJECT(m)); EINA_LIST_FREE(clients, ec) e_object_unref(E_OBJECT(ec)); } static void _e_int_menus_lost_clients_item_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Client *ec = data; E_OBJECT_CHECK(ec); if (ec->iconic) e_client_uniconify(ec); if (ec->desk) e_desk_show(ec->desk); e_comp_object_util_center(ec->frame); evas_object_raise(ec->frame); if (!ec->lock_focus_out) evas_object_focus_set(ec->frame, 1); } static void _e_int_menus_augmentation_add(E_Menu *m, Eina_List *augmentation) { E_Int_Menu_Augmentation *aug; Eina_List *l; char *data; if ((!augmentation) || (!m)) return; EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data) if (eina_hash_find(_e_int_menus_augmentation, data) == augmentation) return; EINA_LIST_FOREACH(augmentation, l, aug) if (aug->add.func) aug->add.func(aug->add.data, m); } static void _e_int_menus_augmentation_del(E_Menu *m, Eina_List *augmentation) { E_Int_Menu_Augmentation *aug; Eina_List *l; char *data; if ((!augmentation) || (!m)) return; EINA_LIST_FOREACH(_e_int_menus_augmentation_disabled, l, data) if (eina_hash_find(_e_int_menus_augmentation, data) == augmentation) return; EINA_LIST_FOREACH(augmentation, l, aug) if (aug->del.func) aug->del.func(aug->del.data, m); } static void _e_int_menus_shelves_pre_cb(void *data EINA_UNUSED, E_Menu *m) { E_Menu_Item *mi; Eina_List *l, *shelves = NULL; E_Shelf *es; E_Zone *zone; e_menu_pre_activate_callback_set(m, NULL, NULL); zone = e_zone_current_get(); /* get the current clients */ shelves = e_shelf_list(); EINA_LIST_FOREACH(shelves, l, es) { char buf[1024]; const char *name; if (!es) continue; if (es->zone->num != zone->num) continue; if (es->name) name = es->name; else { name = buf; snprintf(buf, sizeof(buf), _("Shelf %s"), e_shelf_orient_string_get(es)); } mi = e_menu_item_new(m); e_menu_item_label_set(mi, name); e_menu_item_callback_set(mi, _e_int_menus_shelves_item_cb, es); switch (es->cfg->orient) { case E_GADCON_ORIENT_LEFT: e_util_menu_item_theme_icon_set(mi, "preferences-position-left"); break; case E_GADCON_ORIENT_RIGHT: e_util_menu_item_theme_icon_set(mi, "preferences-position-right"); break; case E_GADCON_ORIENT_TOP: e_util_menu_item_theme_icon_set(mi, "preferences-position-top"); break; case E_GADCON_ORIENT_BOTTOM: e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom"); break; case E_GADCON_ORIENT_CORNER_TL: e_util_menu_item_theme_icon_set(mi, "preferences-position-top-left"); break; case E_GADCON_ORIENT_CORNER_TR: e_util_menu_item_theme_icon_set(mi, "preferences-position-top-right"); break; case E_GADCON_ORIENT_CORNER_BL: e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-left"); break; case E_GADCON_ORIENT_CORNER_BR: e_util_menu_item_theme_icon_set(mi, "preferences-position-bottom-right"); break; case E_GADCON_ORIENT_CORNER_LT: e_util_menu_item_theme_icon_set(mi, "preferences-position-left-top"); break; case E_GADCON_ORIENT_CORNER_RT: e_util_menu_item_theme_icon_set(mi, "preferences-position-right-top"); break; case E_GADCON_ORIENT_CORNER_LB: e_util_menu_item_theme_icon_set(mi, "preferences-position-left-bottom"); break; case E_GADCON_ORIENT_CORNER_RB: e_util_menu_item_theme_icon_set(mi, "preferences-position-right-bottom"); break; default: e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); break; } } if (shelves) { mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); } mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Add a Shelf")); e_util_menu_item_theme_icon_set(mi, "list-add"); e_menu_item_callback_set(mi, _e_int_menus_shelves_add_cb, NULL); if (shelves) { mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Delete a Shelf")); e_util_menu_item_theme_icon_set(mi, "list-remove"); e_menu_item_callback_set(mi, _e_int_menus_shelves_del_cb, NULL); } } static void _e_int_menus_shelves_item_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *s = data; E_OBJECT_CHECK(s); e_int_shelf_config(s); } static void _e_int_menus_shelves_add_cb(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Zone *zone; zone = e_zone_current_get(); e_shelf_new_dialog(zone); } static void _e_int_menus_shelves_del_cb(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { e_configure_registry_call("extensions/shelves", NULL, NULL); } static void _e_int_menus_item_label_set(Efreet_Menu *entry, E_Menu_Item *mi) { Efreet_Desktop *desktop; char label[4096]; int opt = 0; if ((!entry) || (!mi)) return; desktop = entry->desktop; if ((e_config->menu_eap_name_show) && (entry->name)) opt |= 0x4; if (desktop) { if ((e_config->menu_eap_generic_show) && (desktop->generic_name) && (desktop->generic_name[0] != 0)) opt |= 0x2; if ((e_config->menu_eap_comment_show) && (desktop->comment) && (desktop->comment[0] != 0)) opt |= 0x1; } if (opt == 0x7) snprintf(label, sizeof(label), "%s (%s) [%s]", entry->name, desktop->generic_name, desktop->comment); else if (opt == 0x6) snprintf(label, sizeof(label), "%s (%s)", entry->name, desktop->generic_name); else if (opt == 0x5) snprintf(label, sizeof(label), "%s [%s]", entry->name, desktop->comment); else if (opt == 0x4) snprintf(label, sizeof(label), "%s", entry->name); else if (opt == 0x3) snprintf(label, sizeof(label), "%s [%s]", desktop->generic_name, desktop->comment); else if (opt == 0x2) snprintf(label, sizeof(label), "%s", desktop->generic_name); else if (opt == 0x1) snprintf(label, sizeof(label), "%s", desktop->comment); else snprintf(label, sizeof(label), "%s", entry->name); e_menu_item_label_set(mi, label); }