diff --git a/ChangeLog b/ChangeLog index 315328f09..6254f41c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2013-02-13 Deon Thomas + * Fixed Menu->Applications now only lists valid .desktop files, if the exec is missing it will not be added to the menu list. + 2013-02-11 Mike Blumenkrantz * fixed bug where pointer warping to new clients would start at a random location diff --git a/NEWS b/NEWS index fa0ba5ee2..088932853 100644 --- a/NEWS +++ b/NEWS @@ -103,6 +103,7 @@ Improvements: * enable image preloading for all e_widget_preview using edje * window remember dialog now allows editing of remembers * container now uses compositor window + * Menu->Applications now only list valid .desktop files Fixes: * IBar menu didn't allow to configure different icon sources, show contents menu even on empty IBar. diff --git a/src/bin/e_config.c b/src/bin/e_config.c index d8c5f2ccf..daafbbbc2 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -44,6 +44,7 @@ static E_Config_DD *_e_config_desklock_bg_edd = NULL; static E_Config_DD *_e_config_desktop_name_edd = NULL; static E_Config_DD *_e_config_desktop_window_profile_edd = NULL; static E_Config_DD *_e_config_remember_edd = NULL; +static E_Config_DD *_e_config_menu_applications_edd = NULL; static E_Config_DD *_e_config_color_class_edd = NULL; static E_Config_DD *_e_config_gadcon_edd = NULL; static E_Config_DD *_e_config_gadcon_client_edd = NULL; @@ -123,6 +124,7 @@ _e_config_edd_shutdown(void) E_CONFIG_DD_FREE(_e_config_desktop_name_edd); E_CONFIG_DD_FREE(_e_config_desktop_window_profile_edd); E_CONFIG_DD_FREE(_e_config_remember_edd); + E_CONFIG_DD_FREE(_e_config_menu_applications_edd); E_CONFIG_DD_FREE(_e_config_gadcon_edd); E_CONFIG_DD_FREE(_e_config_gadcon_client_edd); E_CONFIG_DD_FREE(_e_config_shelf_edd); @@ -284,6 +286,18 @@ _e_config_edd_init(Eina_Bool old) #define D _e_config_font_fallback_edd E_CONFIG_VAL(D, T, name, STR); + _e_config_menu_applications_edd = E_CONFIG_DD_NEW("E_Int_Menu_Applications", + E_Int_Menu_Applications); +#undef T +#undef D +#define T E_Int_Menu_Applications +#define D _e_config_menu_applications_edd + E_CONFIG_VAL(D, T, orig_path, STR); + E_CONFIG_VAL(D, T, try_exec, STR); + E_CONFIG_VAL(D, T, exec, STR); + E_CONFIG_VAL(D, T, load_time, LL); + E_CONFIG_VAL(D, T, exec_valid, INT); + _e_config_remember_edd = E_CONFIG_DD_NEW("E_Remember", E_Remember); #undef T #undef D @@ -621,6 +635,7 @@ _e_config_edd_init(Eina_Bool old) E_CONFIG_VAL(D, T, transition_desk, STR); /**/ E_CONFIG_VAL(D, T, transition_change, STR); /**/ E_CONFIG_LIST(D, T, remembers, _e_config_remember_edd); + E_CONFIG_LIST(D, T, menu_applications, _e_config_menu_applications_edd); E_CONFIG_VAL(D, T, remember_internal_windows, INT); E_CONFIG_VAL(D, T, remember_internal_fm_windows, UCHAR); E_CONFIG_VAL(D, T, remember_internal_fm_windows_globally, UCHAR); @@ -2124,6 +2139,7 @@ _e_config_free(E_Config *ecf) E_Config_Env_Var *evr; E_Config_XKB_Option *op; E_Config_Desktop_Window_Profile *wp; + E_Int_Menu_Applications *ema; if (!ecf) return; @@ -2219,6 +2235,13 @@ _e_config_free(E_Config *ecf) if (rem->prop.command) eina_stringshare_del(rem->prop.command); E_FREE(rem); } + EINA_LIST_FREE(ecf->menu_applications, ema) + { + if (ema->orig_path) eina_stringshare_del(ema->orig_path); + if (ema->try_exec) eina_stringshare_del(ema->try_exec); + if (ema->exec) eina_stringshare_del(ema->exec); + E_FREE(ema); + } EINA_LIST_FREE(ecf->color_classes, cc) { if (cc->name) eina_stringshare_del(cc->name); diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 73ec92bff..c56bcf56f 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -430,6 +430,7 @@ struct _E_Config const char *desklock_layout; } xkb; + Eina_List *menu_applications; unsigned char exe_always_single_instance; // GUI int use_desktop_window_profile; // GUI }; diff --git a/src/bin/e_int_menus.c b/src/bin/e_int_menus.c index 02a45c737..ae20f52f2 100644 --- a/src/bin/e_int_menus.c +++ b/src/bin/e_int_menus.c @@ -644,6 +644,117 @@ _e_int_menus_main_exit(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item if ((a) && (a->func.go)) a->func.go(NULL, NULL); } +/* + * 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; + + if (strchr(exec, '/')) + { + if (ecore_file_exists(exec) && ecore_file_can_exec(exec)) + return EINA_TRUE; + } + + if (!env) + { + ERR("Unable to $PATH, Returning TRUE for every .desktop"); + return EINA_TRUE; + } + + split = eina_str_split(env, ":", 0); + for (i = 0; split[i] != NULL; i++) + { + snprintf(buf, sizeof(buf), "%s/%s", split[i], exec); + + if (ecore_file_exists(buf) && ecore_file_can_exec(buf)) + { + exec_found = EINA_TRUE; + break; + } + } + free(split[0]); + free(split); + + if (!exec_found) + ERR("Unable to find: [%s] I searched $PATH=%s", exec, env); + + return exec_found; +} + +/* + * This function initalises E_Int_Menu_Applications and add + * 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; + + if (!desktop) return EINA_TRUE; + + cma = _e_int_menus_app_config_set(desktop); + EINA_LIST_FOREACH(e_config->menu_applications, l, ma) + { + if ((!strcmp(ma->orig_path, cma->orig_path)) && (ma->load_time == cma->load_time)) + return ma->exec_valid; + + if ((!strcmp(ma->orig_path, cma->orig_path)) && (ma->load_time != cma->load_time)) + { + ERR("Modified: [%s]", cma->orig_path); + e_config->menu_applications = eina_list_remove(e_config->menu_applications, ma); + } + } + + if (cma->try_exec) + { + ERR("Try_Exec: [%s]", cma->try_exec); + cma->exec_valid = _e_int_menus_app_finder(cma->try_exec); + } + else + { + if (!strchr(cma->exec, '\0')) + cma->exec_valid = _e_int_menus_app_finder(cma->exec); + else + { + char **split; + split = eina_str_split(cma->exec, " ", 0); + cma->exec_valid = _e_int_menus_app_finder(split[0]); + free(split[0]); + free(split); + } + } + + 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) { @@ -656,8 +767,11 @@ _e_int_menus_apps_scan(E_Menu *m, Efreet_Menu *menu) EINA_LIST_FOREACH(menu->entries, l, entry) { - mi = e_menu_item_new(m); + 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) diff --git a/src/bin/e_int_menus.h b/src/bin/e_int_menus.h index 047be9ef9..757678c05 100644 --- a/src/bin/e_int_menus.h +++ b/src/bin/e_int_menus.h @@ -1,6 +1,7 @@ #ifdef E_TYPEDEFS typedef struct _E_Int_Menu_Augmentation E_Int_Menu_Augmentation; +typedef struct _E_Int_Menu_Applications E_Int_Menu_Applications; #else #ifndef E_INT_MENUS_H @@ -38,6 +39,15 @@ typedef enum #define E_CLIENTLIST_MAX_CAPTION_LEN 256 +struct _E_Int_Menu_Applications +{ + const char *orig_path; + const char *try_exec; + const char *exec; + long long load_time; + int exec_valid; +}; + struct _E_Int_Menu_Augmentation { const char *sort_key;