diff --git a/src/bin/e_exec.c b/src/bin/e_exec.c index 40cd0f344..13ae1ed3b 100644 --- a/src/bin/e_exec.c +++ b/src/bin/e_exec.c @@ -12,6 +12,7 @@ typedef struct _E_Exec_Launch E_Exec_Launch; typedef struct _E_Exec_Search E_Exec_Search; typedef struct _E_Exec_Watch E_Exec_Watch; +typedef struct _E_Exec_Recent E_Exec_Recent; struct _E_Exec_Launch { @@ -46,6 +47,11 @@ struct _E_Config_Dialog_Data char *label, *exit, *signal; }; +struct _E_Exec_Recent +{ + Eina_List *files; +}; + /* local subsystem functions */ static E_Exec_Instance *_e_exec_cb_exec(void *data, Efreet_Desktop *desktop, char *exec, int remaining); static Eina_Bool _e_exec_cb_expire_timer(void *data); @@ -82,6 +88,94 @@ E_API int E_EVENT_EXEC_NEW = -1; E_API int E_EVENT_EXEC_NEW_CLIENT = -1; E_API int E_EVENT_EXEC_DEL = -1; +static E_Exec_Recent * _e_exec_recent = NULL; +static Ecore_Idler *_e_exec_recent_idler = NULL; + +static Eina_Bool +_e_exec_cb_recent_idler(void *data EINA_UNUSED) +{ + char buf[4096]; + FILE *f; + Eina_List *l; + E_Exec_Recent_File *fl; + + e_user_dir_snprintf(buf, sizeof(buf), "recent-files.txt"); + if ((_e_exec_recent) && (_e_exec_recent->files)) + { + f = fopen(buf, "w"); + if (f) + { + EINA_LIST_FOREACH(_e_exec_recent->files, l, fl) + { + fprintf(f, "%1.0f %s\n", fl->timestamp * 100.0, fl->file); + } + fclose(f); + } + } + _e_exec_recent_idler = NULL; + return EINA_FALSE; +} + +static void +_e_exec_recent_file_append(const char *file, double tim) +{ + Eina_List *l; + E_Exec_Recent_File *fl = calloc(1, sizeof(E_Exec_Recent_File)); + E_Exec_Recent_File *fl2; + + if (!fl) return; + if (!_e_exec_recent) + _e_exec_recent = calloc(1, sizeof(E_Exec_Recent)); + if (!_e_exec_recent) + { + free(fl); + return; + } + fl->file = eina_stringshare_add(file); + fl->timestamp = tim; + EINA_LIST_FOREACH(_e_exec_recent->files, l, fl2) + { + if (!strcmp(fl2->file, fl->file)) + { + _e_exec_recent->files = eina_list_remove_list(_e_exec_recent->files, l); + eina_stringshare_del(fl2->file); + free(fl2); + break; + } + } + _e_exec_recent->files = eina_list_prepend(_e_exec_recent->files, fl); + if (eina_list_count(_e_exec_recent->files) > 30) + { + l = eina_list_last(_e_exec_recent->files); + if (l) + { + fl = l->data; + _e_exec_recent->files = eina_list_remove_list(_e_exec_recent->files, l); + eina_stringshare_del(fl->file); + free(fl); + } + } + if (!_e_exec_recent_idler) + _e_exec_recent_idler = ecore_idler_add(_e_exec_cb_recent_idler, NULL); +} + +static void +_e_exec_recent_clean(void) +{ + E_Exec_Recent_File *fl; + + if (!_e_exec_recent) return; + EINA_LIST_FREE(_e_exec_recent->files, fl) + { + eina_stringshare_del(fl->file); + free(fl); + } + free(_e_exec_recent); + _e_exec_recent = NULL; + if (_e_exec_recent_idler) ecore_idler_del(_e_exec_recent_idler); + _e_exec_recent_idler = NULL; +} + /* externally accessible functions */ EINTERN int e_exec_init(void) @@ -102,6 +196,7 @@ e_exec_init(void) EINTERN int e_exec_shutdown(void) { + _e_exec_recent_clean(); if (_e_exec_exit_handler) ecore_event_handler_del(_e_exec_exit_handler); if (_e_exec_desktop_update_handler) ecore_event_handler_del(_e_exec_desktop_update_handler); @@ -117,6 +212,43 @@ e_exec_executor_set(E_Exec_Instance *(*func)(void *data, E_Zone * zone, Efreet_D _e_exec_executor_data = (void *)data; } +E_API const Eina_List * +e_exec_recent_files_get(void) +{ + if (!_e_exec_recent) + { + FILE *f; + char buf[4096]; + + e_user_dir_snprintf(buf, sizeof(buf), "recent-files.txt"); + f = fopen(buf, "r"); + if (f) + { + long long timi; + + while (fscanf(f, "%lli %4095[^\n]\n", &timi, buf) == 2) + { + E_Exec_Recent_File *fl = calloc(1, sizeof(E_Exec_Recent_File)); + + if (!fl) free(fl); + if (!_e_exec_recent) + _e_exec_recent = calloc(1, sizeof(E_Exec_Recent)); + if (!_e_exec_recent) + { + free(fl); + break; + } + fl->file = eina_stringshare_add(buf); + fl->timestamp = (double)timi / 100.0; + _e_exec_recent->files = eina_list_prepend(_e_exec_recent->files, fl); + } + fclose(f); + } + } + if (!_e_exec_recent) return NULL; + return _e_exec_recent->files; +} + E_API E_Exec_Instance * e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec, Eina_List *files, const char *launch_method) @@ -126,6 +258,28 @@ e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec, if ((!desktop) && (!exec)) return NULL; + if (files) + { + const char *s; + Eina_List *l; + char buf[4096], buf2[8192+128]; + double tim; + + if (getcwd(buf, sizeof(buf))) + { + tim = ecore_time_unix_get(); + EINA_LIST_FOREACH(files, l, s) + { + if (s[0] == '/') + _e_exec_recent_file_append(s, tim); + else + { + snprintf(buf2, sizeof(buf2), "%s/%s", buf, s); + _e_exec_recent_file_append(buf2, tim); + } + } + } + } if (_e_exec_executor_func) return _e_exec_executor_func(_e_exec_executor_data, zone, desktop, exec, files, launch_method); diff --git a/src/bin/e_exec.h b/src/bin/e_exec.h index c6de54c5e..905216f20 100644 --- a/src/bin/e_exec.h +++ b/src/bin/e_exec.h @@ -1,6 +1,7 @@ #ifdef E_TYPEDEFS typedef struct _E_Exec_Instance E_Exec_Instance; +typedef struct _E_Exec_Recent_File E_Exec_Recent_File; #else #ifndef E_EXEC_H @@ -24,6 +25,12 @@ struct _E_Exec_Instance Eina_Bool deleted E_BITFIELD; }; +struct _E_Exec_Recent_File +{ + const char *file; + double timestamp; +}; + typedef enum { E_EXEC_WATCH_STARTED, @@ -44,6 +51,7 @@ E_API void e_exec_instance_found(E_Exec_Instance *inst); E_API void e_exec_instance_watcher_add(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data); E_API void e_exec_instance_watcher_del(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data); E_API const Eina_List *e_exec_desktop_instances_find(const Efreet_Desktop *desktop); +E_API const Eina_List *e_exec_recent_files_get(void); E_API const Eina_Hash *e_exec_instances_get(void); E_API void e_exec_instance_client_add(E_Exec_Instance *inst, E_Client *ec); diff --git a/src/modules/fileman/e_fwin.c b/src/modules/fileman/e_fwin.c index c991879b5..0df9c8b59 100644 --- a/src/modules/fileman/e_fwin.c +++ b/src/modules/fileman/e_fwin.c @@ -1275,8 +1275,8 @@ _e_fwin_defaults_apps_get(const char *mime, const char *path) return apps; } -static Eina_List * -_e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default) +Eina_List * +e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default) { char path[PATH_MAX]; Eina_List *order, *l; @@ -1359,7 +1359,7 @@ _e_fwin_suggested_apps_list_get(Eina_List *files, if (mime_list) *mime_list = eina_list_append(*mime_list, mime); - desktops = _e_fwin_suggested_apps_list_sort(mime, desktops, &hd); + desktops = e_fwin_suggested_apps_list_sort(mime, desktops, &hd); if ((hd) && (has_default)) *has_default = EINA_TRUE; diff --git a/src/modules/fileman/e_mod_main.h b/src/modules/fileman/e_mod_main.h index 7b01e2f42..f5d930dd0 100644 --- a/src/modules/fileman/e_mod_main.h +++ b/src/modules/fileman/e_mod_main.h @@ -131,6 +131,8 @@ Eina_Bool e_fwin_show (const char *dev, const char *path); Eina_Bool e_fwin_nav_init(void); Eina_Bool e_fwin_nav_shutdown(void); +Eina_List *e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default); + /** * @addtogroup Optional_Fileman * @{ diff --git a/src/modules/fileman/e_mod_menu.c b/src/modules/fileman/e_mod_menu.c index e4446b375..6b2af064a 100644 --- a/src/modules/fileman/e_mod_menu.c +++ b/src/modules/fileman/e_mod_menu.c @@ -391,6 +391,125 @@ _e_mod_fileman_parse_gtk_bookmarks(E_Menu *m, } } +static void +_e_mod_menu_populate_cleanup_cb(void *obj) +{ + eina_stringshare_del(e_object_data_get(E_OBJECT(obj))); +} + +static void +_e_mod_menu_recent_cb(void *data EINA_UNUSED, + E_Menu *m, + E_Menu_Item *mi) +{ + const char *file = e_object_data_get(E_OBJECT(mi)); + + if (file) + { + const char *mime = efreet_mime_type_get(file); + + if (mime) + { + // XXX: need to share logic with _e_fileman_dbus_daemon_open_file_cb() + // and _e_fwin_file_open_dialog + Eina_List *handlers = efreet_util_desktop_mime_list(mime); + if (handlers) + { + Efreet_Desktop *desktop; + Eina_Bool hd = EINA_FALSE; + + handlers = e_fwin_suggested_apps_list_sort(mime, handlers, &hd); + desktop = handlers->data; + if (desktop) + { + Eina_List *files = NULL; + + files = eina_list_append(files, file); + e_exec(m->zone, desktop, NULL, files, "fwin"); + files = eina_list_free(files); + } + EINA_LIST_FREE(handlers, desktop) + { + efreet_desktop_free(desktop); + } + } + } + } +} + + +static void +_e_mod_menu_populate_recent_cb(void *data EINA_UNUSED, + E_Menu *m EINA_UNUSED, + E_Menu_Item *mi EINA_UNUSED) +{ + Eina_List *l; + Eina_List *files = (Eina_List *)e_exec_recent_files_get(); + E_Exec_Recent_File *fl; + E_Menu *subm; + E_Menu_Item *mi2; + + subm = e_menu_new(); + e_menu_item_submenu_set(mi, subm); + e_menu_freeze(subm); + EINA_LIST_FOREACH(files, l, fl) + { + const char *fname; + + fname = ecore_file_file_get(fl->file); + if (fname) + { + const char *mime = efreet_mime_type_get(fl->file); + + mi2 = e_menu_item_new(subm); + e_menu_item_label_set(mi2, fname); + e_object_data_set(E_OBJECT(mi2), eina_stringshare_add(fl->file)); + e_object_free_attach_func_set(E_OBJECT(mi2), + _e_mod_menu_populate_cleanup_cb); + e_menu_item_callback_set(mi2, _e_mod_menu_recent_cb, NULL); + if (mime) + { + char buf[1024]; + const char *icon_file, *edje_file; + + snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", mime); + edje_file = e_theme_edje_file_get("base/theme/icons", buf); + if (edje_file) + { + e_menu_item_icon_edje_set(mi2, edje_file, buf); + } + else + { + icon_file = efreet_mime_type_icon_get(mime, e_config->icon_theme, 48); + e_menu_item_icon_file_set(mi2, icon_file); + } + } + } + } + e_menu_thaw(subm); +} + + +static void +_e_mod_fileman_add_recent(E_Menu *m, + Eina_Bool need_separator) +{ + E_Menu_Item *mi; + const Eina_List *files = e_exec_recent_files_get(); + + if (!files) return; + + if (need_separator) + { + 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, _("Recent")); + e_util_menu_item_theme_icon_set(mi, "folder"); + e_menu_item_submenu_pre_callback_set(mi, _e_mod_menu_populate_recent_cb, NULL); +} + static void _e_mod_menu_free(void *data) { @@ -528,6 +647,7 @@ _e_mod_menu_generate(void *data, E_Menu *m) } _e_mod_fileman_parse_gtk_bookmarks(m, need_separator || volumes_visible > 0); + _e_mod_fileman_add_recent(m, need_separator || volumes_visible > 0); e_menu_pre_activate_callback_set(m, NULL, NULL); } diff --git a/src/modules/mixer/lib/backends/pulseaudio/pulse.c b/src/modules/mixer/lib/backends/pulseaudio/pulse.c index 7ac3be0de..327a58f46 100644 --- a/src/modules/mixer/lib/backends/pulseaudio/pulse.c +++ b/src/modules/mixer/lib/backends/pulseaudio/pulse.c @@ -1491,7 +1491,9 @@ _pulse_connect(void *data) { pa_proplist *proplist; Context *c = data; + Eina_Bool ret = ECORE_CALLBACK_DONE; + printf("PULSE CONN...\n"); proplist = pa_proplist_new(); pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "Efl Volume Control"); pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, @@ -1512,7 +1514,10 @@ _pulse_connect(void *data) { pa_context_set_state_callback(c->context, _pulse_pa_state_cb, c); if (pa_context_connect(c->context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) - ERR("Could not connect to pulse"); + { + ret = EINA_TRUE; + ERR("Could not connect to pulse"); + } } #if !defined(EMIXER_BUILD) && defined(HAVE_WAYLAND) && !defined(HAVE_WAYLAND_ONLY) if (e_comp->comp_type != E_PIXMAP_TYPE_X) @@ -1526,7 +1531,7 @@ _pulse_connect(void *data) #endif pa_proplist_free(proplist); - return ECORE_CALLBACK_DONE; + return ret; } static Eina_Bool pulse_started;