#include "e_mod_main.h" /* FIXME: fwin - the fm2 filemanager wrapped with a window and scrollframe. * primitive BUT enough to test generic dnd and fm stuff more easily. don't * play with this unless u want to help with it. NOT COMPLETE! BEWARE! */ /* FIXME: multiple selected files across different fwins - you can only dnd the * ones in the 1 window src - not all selected ones. also selecting a new file * in a new fwin doesn't deseclect other selections in other fwin's (unless * multi-selecting) */ #define DEFAULT_WIDTH 600 #define DEFAULT_HEIGHT 350 #define MINIMUM_WIDTH 360 #define MINIMUM_HEIGHT 250 typedef struct _E_Fwin E_Fwin; typedef struct _E_Fwin_Page E_Fwin_Page; typedef struct _E_Fwin_Apps_Dialog E_Fwin_Apps_Dialog; #define E_FWIN_TYPE 0xE0b0101f struct _E_Fwin { E_Object e_obj_inherit; Evas_Object *win; E_Zone *zone; Fileman_Path *path; /* not freed with fwin, actually attached to config */ Evas_Object *bg_obj; E_Fwin_Apps_Dialog *fad; E_Fwin_Page *cur_page; Evas_Object *under_obj; Evas_Object *over_obj; const char *wallpaper_file; Eina_Bool wallpaper_is_edj E_BITFIELD; const char *overlay_file; const char *scrollframe_file; const char *theme_file; const char *over_file; Ecore_Timer *popup_timer; Ecore_Job *popup_del_job; Ecore_Job *object_del_job; Eina_List *popup_handlers; Evas_Object *popup; Ecore_Timer *spring_timer; Ecore_Timer *spring_close_timer; E_Fwin *spring_parent; E_Fwin *spring_child; Ecore_Event_Handler *zone_handler; Ecore_Event_Handler *zone_del_handler; }; struct _E_Fwin_Page { E_Fwin *fwin; Ecore_Event_Handler *fm_op_entry_add_handler; Evas_Object *flist; Evas_Object *flist_frame; Evas_Object *scrollframe_obj; Evas_Object *scr; Evas_Object *fm_obj; E_Toolbar *tbar; struct { Evas_Coord x, y, max_x, max_y, w, h; } fm_pan, fm_pan_last; int index; Eina_Bool setting E_BITFIELD; }; struct _E_Fwin_Apps_Dialog { E_Dialog *dia; E_Fwin *fwin; const char *app2; Evas_Object *o_filepreview; Evas_Object *o_all; Evas_Object *o_entry; char *exec_cmd; }; typedef enum { E_FWIN_EXEC_NONE, E_FWIN_EXEC_DIRECT, E_FWIN_EXEC_SH, E_FWIN_EXEC_TERMINAL_DIRECT, E_FWIN_EXEC_TERMINAL_SH, E_FWIN_EXEC_DESKTOP } E_Fwin_Exec_Type; typedef enum { E_FWIN_WIN_AUTO, E_FWIN_WIN_FORCE_INLINE, E_FWIN_WIN_FORCE_WIN } E_Fwin_Win_Mode; /* local subsystem prototypes */ static int _e_fwin_cb_dir_handler_test(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *path); static void _e_fwin_cb_dir_handler(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *path); static void _e_fwin_page_favorites_add(E_Fwin_Page *page); static void _e_fwin_icon_mouse_out(void *data, Evas_Object *obj EINA_UNUSED, void *event_info); static void _e_fwin_icon_mouse_in(void *data, Evas_Object *obj EINA_UNUSED, void *event_info); static E_Fwin *_e_fwin_open(E_Fwin_Page *page, E_Fm2_Icon_Info *ici, E_Fwin_Win_Mode win_mode, int *need_dia); static E_Fwin *_e_fwin_new(const char *dev, const char *path); static void _e_fwin_free(E_Fwin *fwin); static E_Fwin_Page *_e_fwin_page_create(E_Fwin *fwin); static void _e_fwin_page_free(E_Fwin_Page *page); static void _e_fwin_cb_delete(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_fwin_cb_resize(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_fwin_deleted(void *data, Evas_Object *obj, void *event_info); static const char *_e_fwin_custom_file_path_eval(E_Fwin *fwin, Efreet_Desktop *ef, const char *prev_path, const char *key); static void _e_fwin_desktop_run(Efreet_Desktop *desktop, E_Fwin_Page *page, Eina_Bool skip_history); static Eina_List *_e_fwin_suggested_apps_list_get(Eina_List *files, Eina_List **mime_list, Eina_Bool *has_default); static void _e_fwin_changed(void *data, Evas_Object *obj, void *event_info); static void _e_fwin_favorite_selected(void *data, Evas_Object *obj, void *event_info); static void _e_fwin_selected(void *data, Evas_Object *obj, void *event_info); static void _e_fwin_selection_change(void *data, Evas_Object *obj, void *event_info); static void _e_fwin_cb_menu_extend_open_with(void *data, E_Menu *m); static void _e_fwin_cb_menu_open_fast(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_fwin_parent(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_fwin_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_fwin_cb_menu_extend_start(void *data, Evas_Object *obj, E_Menu *m, E_Fm2_Icon_Info *info); static void _e_fwin_cb_menu_open(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_fwin_cb_menu_open_with(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_fwin_cb_all_change(void *data, Evas_Object *obj); static void _e_fwin_cb_exec_cmd_changed(void *data, void *data2); static void _e_fwin_cb_open(void *data, E_Dialog *dia); static void _e_fwin_cb_close(void *data, E_Dialog *dia); static void _e_fwin_cb_dialog_free(void *obj); static E_Fwin_Exec_Type _e_fwin_file_is_exec(E_Fm2_Icon_Info *ici); static void _e_fwin_file_exec(E_Fwin_Page *page, E_Fm2_Icon_Info *ici, E_Fwin_Exec_Type ext); static void _e_fwin_file_open_dialog(E_Fwin_Page *page, Eina_List *files, int always); static void _e_fwin_file_open_dialog_preview_set(void *data1, void *data2); static void _e_fwin_file_open_dialog_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_fwin_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y); static void _e_fwin_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y); static void _e_fwin_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y); static void _e_fwin_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h); static void _e_fwin_pan_scroll_update(E_Fwin_Page *page); static void _e_fwin_cb_page_obj_del(void *data, Evas *evas, Evas_Object *obj, void *event_info); static void _e_fwin_zone_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info); static Eina_Bool _e_fwin_zone_move_resize(void *data, int type, void *event); static Eina_Bool _e_fwin_zone_del(void *data, int type, void *event); static void _e_fwin_config_set(E_Fwin_Page *page); static void _e_fwin_window_title_set(E_Fwin_Page *page); static void _e_fwin_toolbar_resize(E_Fwin_Page *page); static int _e_fwin_dlg_cb_desk_sort(const void *p1, const void *p2); static int _e_fwin_dlg_cb_desk_list_sort(const void *data1, const void *data2); static void _e_fwin_op_registry_listener_cb(void *data, const E_Fm2_Op_Registry_Entry *ere); static Eina_Bool _e_fwin_op_registry_entry_add_cb(void *data, int type, void *event); static void _e_fwin_op_registry_entry_iter(E_Fwin_Page *page); static void _e_fwin_op_registry_abort_cb(void *data, Evas_Object *obj, const char *emission, const char *source); static E_Fwin *drag_fwin = NULL; static E_Client_Hook *focus_out_hook = NULL; /* local subsystem globals */ static Eina_List *fwins = NULL; static E_Fm2_Mime_Handler *dir_handler = NULL; static Efreet_Desktop *tdesktop = NULL; static Eina_Stringshare *fwin_class = NULL; static void _e_fwin_client_hook_focus_unset(void *d EINA_UNUSED, E_Client *ec) { E_Fwin *fwin; /* if there is no new focused, set focus to zone fwin */ if (e_client_focused_get() || (!e_client_util_ignored_get(e_desk_client_top_visible_get(e_desk_current_get(ec->zone))))) return; if (e_comp_util_kbd_grabbed()) return; fwin = e_fwin_zone_find(ec->zone); if (fwin) evas_object_focus_set(fwin->cur_page->fm_obj, 1); } typedef struct _E_Fwin_Mime_Handler { const char *mime; Efreet_Desktop *desktop; E_Fm2_Mime_Handler *handler; } E_Fwin_Mime_Handler; static Ecore_Event_Handler *_e_fwin_efreet_desktop_update_handler = NULL; static Eina_List *_e_fwin_mime_all_handlers_list = NULL; static int _e_fwin_cb_dir_mime_handler_test(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *path) { if (ecore_file_is_dir(path)) return 1; if (e_fm2_real_path_get(obj)) { evas_object_data_set(obj, "fileman_terminal_realpath", (void*)1); return 1; } return 0; } static void _e_fwin_cb_dir_mime_handler(void *data, Evas_Object *obj EINA_UNUSED, const char *path) { E_Fwin_Mime_Handler *h = data; Eina_Stringshare *rp; Eina_List *files = NULL; rp = e_fm2_real_path_get(obj); if (rp && (rp != path) && (evas_object_data_del(obj, "fileman_terminal_realpath"))) //icon menu; use rp path = rp; files = eina_list_append(files, path); e_exec(e_zone_current_get(), h->desktop, NULL, files, "fileman"); eina_list_free(files); } static void _e_fwin_mime_all_handlers_fill(void) { E_Fwin_Mime_Handler *h; Eina_List *desktops; Efreet_Desktop *desktop; desktops = efreet_util_desktop_name_glob_list("*"); EINA_LIST_FREE(desktops, desktop) { const char *mime = eina_hash_find (desktop->x, "X-Enlightenment-Action-Mime"); if (!mime) continue; h = calloc(1, sizeof(E_Fwin_Mime_Handler)); if (!h) continue; h->mime = eina_stringshare_add(mime); h->desktop = desktop; efreet_desktop_ref(desktop); h->handler = e_fm2_mime_handler_new (desktop->name, desktop->icon, _e_fwin_cb_dir_mime_handler, h, _e_fwin_cb_dir_mime_handler_test, h); e_fm2_mime_handler_mime_add(h->handler, h->mime); _e_fwin_mime_all_handlers_list = eina_list_append(_e_fwin_mime_all_handlers_list, h); } } static void _e_fwin_mime_all_handlers_clear(void) { E_Fwin_Mime_Handler *h; EINA_LIST_FREE(_e_fwin_mime_all_handlers_list, h) { efreet_desktop_free(h->desktop); e_fm2_mime_handler_mime_del(h->handler, h->mime); e_fm2_mime_handler_free(h->handler); eina_stringshare_del(h->mime); free(h); } } static Eina_Bool _e_fwin_cb_efreet_cache_update(void *data EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED) { _e_fwin_mime_all_handlers_clear(); _e_fwin_mime_all_handlers_fill(); return ECORE_CALLBACK_RENEW; } static void _e_fwin_mime_all_handlers_init(void) { _e_fwin_efreet_desktop_update_handler = ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_fwin_cb_efreet_cache_update, NULL); _e_fwin_mime_all_handlers_fill(); } static void _e_fwin_mime_all_handlers_shutdown(void) { _e_fwin_mime_all_handlers_clear(); ecore_event_handler_del(_e_fwin_efreet_desktop_update_handler); } /* externally accessible functions */ int e_fwin_init(void) { focus_out_hook = e_client_hook_add(E_CLIENT_HOOK_FOCUS_UNSET, _e_fwin_client_hook_focus_unset, NULL); fwin_class = eina_stringshare_add("e_fwin"); _e_fwin_mime_all_handlers_init(); tdesktop = e_util_terminal_desktop_get(); if (!tdesktop) return 1; dir_handler = e_fm2_mime_handler_new(_("Open Terminal here"), tdesktop->icon, _e_fwin_cb_dir_handler, NULL, _e_fwin_cb_dir_handler_test, NULL); e_fm2_mime_handler_mime_add(dir_handler, "inode/directory"); return 1; } int e_fwin_shutdown(void) { E_Fwin *fwin; EINA_LIST_FREE(fwins, fwin) e_object_del(E_OBJECT(fwin)); if (dir_handler) { e_fm2_mime_handler_mime_del(dir_handler, "inode/directory"); e_fm2_mime_handler_free(dir_handler); dir_handler = NULL; } if (tdesktop) { efreet_desktop_free(tdesktop); tdesktop = NULL; } _e_fwin_mime_all_handlers_shutdown(); eina_stringshare_replace(&fwin_class, NULL); if (focus_out_hook) { e_client_hook_del(focus_out_hook); focus_out_hook = NULL; } return 1; } /* FIXME: this opens a new window - we need a way to inherit a zone as the * "fwin" window */ void e_fwin_new(const char *dev, const char *path) { _e_fwin_new(dev, path); } static Eina_Bool _e_fwin_spring_cb(E_Fwin *fwin) { E_Fm2_Icon_Info *ici; E_Fwin *f; if (fwin->spring_child) _e_fwin_free(fwin->spring_child); ici = e_fm2_drop_icon_get(fwin->cur_page->fm_obj); if (!ici) ici = e_fm2_drop_icon_get(fwin->cur_page->flist); while (ici) { /* FIXME: could use an animation here */ f = _e_fwin_open(fwin->cur_page, ici, E_FWIN_WIN_FORCE_WIN, NULL); if (!f) break; f->spring_parent = fwin; fwin->spring_child = f; break; } if (fwin->spring_timer) ecore_timer_del(fwin->spring_timer); fwin->spring_timer = NULL; return EINA_FALSE; } /* called on the drop source */ static void _e_fwin_dnd_end_cb(E_Fwin *fwin, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { if (fwin->spring_timer) ecore_timer_del(fwin->spring_timer); fwin->spring_timer = NULL; if (!drag_fwin) return; if (drag_fwin->spring_timer) ecore_timer_del(drag_fwin->spring_timer); drag_fwin->spring_timer = NULL; /* NOTE: closing the drop target window here WILL break things */ fwin = drag_fwin->spring_parent; if (!fwin) { if (!drag_fwin->zone) return; //dragging from desktop, we'll never have a parent here if (drag_fwin->spring_child) _e_fwin_free(drag_fwin->spring_child); return; } fwin->spring_child->spring_parent = NULL; fwin->spring_child = NULL; while (fwin->spring_parent) { /* FIXME: needs closing animation? */ fwin = fwin->spring_parent; _e_fwin_free(fwin->spring_child); } drag_fwin = NULL; } static void _e_fwin_dnd_change_cb(E_Fwin *fwin, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { drag_fwin = fwin; if (fwin->spring_timer) ecore_timer_loop_reset(fwin->spring_timer); else fwin->spring_timer = ecore_timer_loop_add(fileman_config->view.spring_delay, (Ecore_Task_Cb)_e_fwin_spring_cb, fwin); } static void _e_fwin_dnd_enter_cb(E_Fwin *fwin, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { if (drag_fwin == fwin) return; if (fwin->spring_timer) ecore_timer_del(fwin->spring_timer); fwin->spring_timer = NULL; if (fwin->spring_child && (drag_fwin == fwin->spring_child)) _e_fwin_free(fwin->spring_child); drag_fwin = fwin; if (fwin->spring_close_timer) ecore_timer_del(fwin->spring_close_timer); fwin->spring_close_timer = NULL; } static Eina_Bool _e_fwin_dnd_close_cb(E_Fwin *fwin) { _e_fwin_free(fwin); return EINA_FALSE; } static void _e_fwin_dnd_leave_cb(E_Fwin *fwin, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { if (fwin->spring_timer) ecore_timer_del(fwin->spring_timer); fwin->spring_timer = NULL; if (fwin->spring_parent && (!fwin->spring_child)) { if (!fwin->spring_close_timer) fwin->spring_close_timer = ecore_timer_loop_add(0.01, (Ecore_Task_Cb)_e_fwin_dnd_close_cb, fwin); } drag_fwin = NULL; } static void _e_fwin_dnd_begin_cb(E_Fwin *fwin EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { drag_fwin = NULL; } static void _e_fwin_zone_shutdown(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { E_Fwin *fwin = data; const char *dev, *path; fwin->path->desktop_mode = e_fm2_view_mode_get(obj); e_fm2_path_get(obj, &dev, &path); eina_stringshare_replace(&fwin->path->dev, dev); eina_stringshare_replace(&fwin->path->path, path); e_object_del(E_OBJECT(fwin)); } void e_fwin_zone_new(E_Zone *zone, void *p) { E_Fwin *fwin; Fileman_Path *path = p; E_Fwin_Page *page; Evas_Object *o; int x, y, w, h; fwin = E_OBJECT_ALLOC(E_Fwin, E_FWIN_TYPE, _e_fwin_free); if (!fwin) return; fwin->zone = zone; page = E_NEW(E_Fwin_Page, 1); page->fwin = fwin; fwin->path = path; /* Add Event Handler for zone move/resize & del */ fwin->zone_handler = ecore_event_handler_add(E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGED, _e_fwin_zone_move_resize, fwin); fwin->zone_del_handler = ecore_event_handler_add(E_EVENT_ZONE_DEL, _e_fwin_zone_del, fwin); /* Trap the mouse_down on zone so we can unselect */ evas_object_event_callback_add(zone->bg_event_object, EVAS_CALLBACK_MOUSE_DOWN, _e_fwin_zone_cb_mouse_down, fwin); fwins = eina_list_append(fwins, fwin); o = e_fm2_add(e_comp->evas); evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_fwin_zone_shutdown, fwin); page->fm_obj = o; _e_fwin_config_set(page); e_fm2_custom_theme_content_set(o, "desktop"); evas_object_smart_callback_add(o, "changed", _e_fwin_icon_mouse_out, fwin); evas_object_smart_callback_add(o, "dir_changed", _e_fwin_changed, page); evas_object_smart_callback_add(o, "dir_deleted", _e_fwin_deleted, page); evas_object_smart_callback_add(o, "selected", _e_fwin_selected, page); evas_object_smart_callback_add(o, "selection_change", _e_fwin_selection_change, page); evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_fwin_cb_page_obj_del, page); evas_object_smart_callback_add(o, "dnd_enter", (Evas_Smart_Cb)_e_fwin_dnd_enter_cb, fwin); evas_object_smart_callback_add(o, "dnd_leave", (Evas_Smart_Cb)_e_fwin_dnd_leave_cb, fwin); evas_object_smart_callback_add(o, "dnd_changed", (Evas_Smart_Cb)_e_fwin_dnd_change_cb, fwin); evas_object_smart_callback_add(o, "dnd_begin", (Evas_Smart_Cb)_e_fwin_dnd_begin_cb, fwin); evas_object_smart_callback_add(o, "dnd_end", (Evas_Smart_Cb)_e_fwin_dnd_end_cb, fwin); evas_object_smart_callback_add(o, "icon_mouse_in", (Evas_Smart_Cb)_e_fwin_icon_mouse_in, fwin); evas_object_smart_callback_add(o, "icon_mouse_out", (Evas_Smart_Cb)_e_fwin_icon_mouse_out, fwin); e_fm2_icon_menu_start_extend_callback_set(o, _e_fwin_cb_menu_extend_start, page); e_fm2_underlay_hide(o); evas_object_focus_set(o, !e_client_focused_get()); evas_object_show(o); o = e_scrollframe_add(e_comp->evas); e_scrollframe_custom_theme_set(o, "base/theme/fileman", "e/fileman/desktop/scrollframe"); /* FIXME: this theme object will have more versions and options later * for things like swallowing widgets/buttons ot providing them - a * gadcon for starters for fm widgets. need to register the owning * e_object of the gadcon so gadcon clients can get it and thus do * things like find out what dirs/path the fwin is for etc. this will * probably be how you add optional gadgets to fwin views like empty/full * meters for disk usage, and other dir info/stats or controls. also it * might be possible that we can have custom frames per dir later so need * a way to set an edje file directly */ /* FIXME: allow specialised scrollframe obj per dir - get from e config, * then look in the dir itself for a magic dot-file, if not - use theme. * same as currently done for bg & overlay. also add to fm2 the ability * to specify the .edj files to get the list and icon theme stuff from */ evas_object_data_set(page->fm_obj, "fm_page", page); evas_object_data_set(page->fm_obj, "page_is_zone", page); e_scrollframe_extern_pan_set(o, page->fm_obj, _e_fwin_pan_set, _e_fwin_pan_get, _e_fwin_pan_max_get, _e_fwin_pan_child_size_get); evas_object_propagate_events_set(page->fm_obj, 0); e_widget_can_focus_set(o, 0); evas_object_name_set(o, "zone_fwin"); e_zone_useful_geometry_get(zone, &x, &y, &w, &h); evas_object_move(o, x, y); evas_object_resize(o, w, h); evas_object_show(o); evas_object_layer_set(o, E_LAYER_DESKTOP); evas_object_lower(o); page->scrollframe_obj = page->scr = o; e_fm2_window_object_set(page->fm_obj, E_OBJECT(fwin->zone)); e_fm2_path_set(page->fm_obj, path->dev, path->path); fwin->cur_page = page; } void e_fwin_all_unsel(void *data) { E_Fwin *fwin; fwin = data; E_OBJECT_CHECK(fwin); E_OBJECT_TYPE_CHECK(fwin, E_FWIN_TYPE); e_fm2_all_unsel(fwin->cur_page->fm_obj); } void e_fwin_zone_shutdown(E_Zone *zone) { Eina_List *f, *fn; E_Fwin *fwin; EINA_LIST_FOREACH_SAFE(fwins, f, fn, fwin) { if (fwin->zone != zone) continue; _e_fwin_zone_shutdown(fwin, NULL, fwin->cur_page->fm_obj, NULL); fwin = NULL; } } static void _e_fwin_cb_toolbar_del(void *obj) { E_Fwin_Page *page = e_object_data_get(obj); page->tbar = NULL; } void e_fwin_reload_all(void) { const Eina_List *l, *ll; E_Fwin *fwin; E_Zone *zone; /* Reload/recreate zones cause of property changes */ EINA_LIST_FOREACH_SAFE(fwins, l, ll, fwin) { if (!fwin) continue; //safety if (fwin->zone) e_fwin_zone_shutdown(fwin->zone); else { _e_fwin_config_set(fwin->cur_page); if (fileman_config->view.show_toolbar) { if (!fwin->cur_page->tbar) { fwin->cur_page->tbar = e_toolbar_new (evas_object_evas_get(fwin->win), "toolbar", fwin->win, fwin->cur_page->fm_obj); e_toolbar_orient(fwin->cur_page->tbar, fileman_config->view.toolbar_orient); e_object_data_set(E_OBJECT(fwin->cur_page->tbar), fwin->cur_page); E_OBJECT_DEL_SET(fwin->cur_page->tbar, _e_fwin_cb_toolbar_del); } } else { if (fwin->cur_page->tbar) { fileman_config->view.toolbar_orient = fwin->cur_page->tbar->gadcon->orient; e_object_del(E_OBJECT(fwin->cur_page->tbar)); fwin->cur_page->tbar = NULL; } } if (fileman_config->view.show_sidebar) { if (!fwin->cur_page->flist_frame) { _e_fwin_page_favorites_add(fwin->cur_page); edje_object_signal_emit(fwin->bg_obj, "e,favorites,enabled", "e"); edje_object_message_signal_process(fwin->bg_obj); } } else { if (fwin->cur_page->flist_frame) { evas_object_del(fwin->cur_page->flist_frame); fwin->cur_page->flist_frame = fwin->cur_page->flist = NULL; edje_object_signal_emit(fwin->bg_obj, "e,favorites,disabled", "e"); edje_object_message_signal_process(fwin->bg_obj); } } _e_fwin_window_title_set(fwin->cur_page); _e_fwin_cb_resize(fwin, NULL, NULL, NULL); _e_fwin_toolbar_resize(fwin->cur_page); e_fm2_refresh(fwin->cur_page->fm_obj); } } /* Hook into zones */ EINA_LIST_FOREACH(e_comp->zones, l, zone) { if (e_fwin_zone_find(zone)) continue; if (e_config->show_desktop_icons) e_fwin_zone_new(zone, e_mod_fileman_path_find(zone)); } } void * e_fwin_zone_find(E_Zone *zone) { Eina_List *f; E_Fwin *fwin; EINA_LIST_FOREACH(fwins, f, fwin) if (fwin->zone == zone) return fwin; return NULL; } Eina_Bool e_fwin_show(const char *dev, const char *path) { Eina_List *f; E_Fwin *fwin; EINA_LIST_FOREACH(fwins, f, fwin) { const char *d, *p; e_fm2_path_get(fwin->cur_page->fm_obj, &d, &p); if ((d) && (!strcmp(dev, d)) && (p) && (!strcmp(path, p))) { elm_win_activate(fwin->win); return EINA_TRUE; } } return EINA_FALSE; } /* local subsystem functions */ static void _e_fwin_bg_mouse_down(E_Fwin *fwin, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { int x, y, w, h, zx, zy, zw, zh, cx, cy, cw, ch; E_Client *ec; ec = e_win_client_get(fwin->win); if (ec->maximized) e_client_unmaximize(ec, ec->maximized); if (ec->fullscreen) e_client_unfullscreen(ec); e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh); x = ec->x, y = ec->y; if (!e_fm2_optimal_size_calc(fwin->cur_page->fm_obj, MINIMUM_WIDTH, zw + zx - x, zh + zy - y, &w, &h)) return; evas_object_geometry_get(fwin->cur_page->fm_obj, &cx, &cy, &cw, &ch); if (x + w > zx + zw) w = zx + zw - x; if (y + h > zy + zh) h = zy + zh - y; w = w + cx; h = h + cy; evas_object_resize(fwin->win, MAX(w, MINIMUM_WIDTH), MAX(h, MINIMUM_HEIGHT)); } static void _e_fwin_cb_focus(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin *fwin = data; if (!e_fm2_icon_editing_get(fwin->cur_page->fm_obj)) evas_object_focus_set(fwin->cur_page->fm_obj, 1); } static E_Fwin * _e_fwin_new(const char *dev, const char *path) { E_Fwin *fwin; E_Fwin_Page *page; Evas_Object *o; E_Zone *zone; fwin = E_OBJECT_ALLOC(E_Fwin, E_FWIN_TYPE, _e_fwin_free); if (!fwin) return NULL; fwin->win = elm_win_add(NULL, NULL, ELM_WIN_BASIC); if (!fwin->win) { free(fwin); return NULL; } fwins = eina_list_append(fwins, fwin); evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_FOCUS_IN, _e_fwin_cb_focus, fwin); evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_DEL, _e_fwin_cb_delete, fwin); evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_RESIZE, _e_fwin_cb_resize, fwin); o = edje_object_add(evas_object_evas_get(fwin->win)); elm_win_resize_object_add(fwin->win, o); e_theme_edje_object_set(o, "base/theme/fileman", "e/fileman/default/window/main"); evas_object_show(o); fwin->bg_obj = o; page = _e_fwin_page_create(fwin); fwin->cur_page = page; /* o = edje_object_add(evas_object_evas_get(fwin->win)); // o = e_icon_add(evas_object_evas_get(fwin->win)); // e_icon_scale_size_set(o, 0); // e_icon_fill_inside_set(o, 0); edje_object_part_swallow(fwin->bg_obj, "e.swallow.bg", o); evas_object_pass_events_set(o, 1); fwin->under_obj = o; */ o = edje_object_add(evas_object_evas_get(fwin->win)); // o = e_icon_add(evas_object_evas_get(fwin->win)); // e_icon_scale_size_set(o, 0); // e_icon_fill_inside_set(o, 0); edje_object_part_swallow(e_scrollframe_edje_object_get(page->scr), "e.swallow.overlay", o); evas_object_pass_events_set(o, 1); fwin->over_obj = o; e_fm2_path_set(page->fm_obj, dev, path); _e_fwin_window_title_set(page); evas_object_size_hint_min_set(fwin->win, MINIMUM_WIDTH, MINIMUM_HEIGHT); zone = e_zone_current_get(); if ((zone) && (zone->w < DEFAULT_WIDTH)) { int w, h; e_zone_useful_geometry_get(zone, NULL, NULL, &w, &h); evas_object_resize(fwin->win, w, h); } else evas_object_resize(fwin->win, DEFAULT_WIDTH, DEFAULT_HEIGHT); evas_object_show(fwin->win); if (elm_win_window_id_get(fwin->win)) e_drop_xdnd_register_set(elm_win_window_id_get(fwin->win), 1); e_win_client_icon_set(fwin->win, "system-file-manager"); return fwin; } static Eina_Bool _e_fwin_icon_popup_handler(void *data) { E_Fwin *fwin = data; E_FREE_FUNC(fwin->popup_timer, ecore_timer_del); if (fwin->popup) { evas_object_hide(fwin->popup); E_FREE_FUNC(fwin->popup, evas_object_del); } if (fwin->win) { evas_object_event_callback_del(fwin->win, EVAS_CALLBACK_MOUSE_IN, (void *)_e_fwin_icon_popup_handler); evas_object_event_callback_del(fwin->win, EVAS_CALLBACK_MOUSE_OUT, (void *)_e_fwin_icon_popup_handler); } E_FREE_LIST(fwin->popup_handlers, ecore_event_handler_del); if (fwin->over_file) eina_stringshare_del(fwin->over_file); fwin->over_file = NULL; return ECORE_CALLBACK_RENEW; } static void _e_fwin_free(E_Fwin *fwin) { if (!fwin) return; //safety _e_fwin_page_free(fwin->cur_page); if (fwin->zone) evas_object_event_callback_del(fwin->zone->bg_event_object, EVAS_CALLBACK_MOUSE_DOWN, _e_fwin_zone_cb_mouse_down); if (fwin->zone_handler) ecore_event_handler_del(fwin->zone_handler); if (fwin->zone_del_handler) ecore_event_handler_del(fwin->zone_del_handler); if (fwin->spring_timer) ecore_timer_del(fwin->spring_timer); fwin->spring_timer = NULL; if (fwin->spring_close_timer) ecore_timer_del(fwin->spring_close_timer); fwin->spring_close_timer = NULL; fwins = eina_list_remove(fwins, fwin); if (fwin->wallpaper_file) eina_stringshare_del(fwin->wallpaper_file); if (fwin->overlay_file) eina_stringshare_del(fwin->overlay_file); if (fwin->scrollframe_file) eina_stringshare_del(fwin->scrollframe_file); if (fwin->theme_file) eina_stringshare_del(fwin->theme_file); if (fwin->over_file) eina_stringshare_del(fwin->over_file); if (fwin->fad) { e_object_del(E_OBJECT(fwin->fad->dia)); fwin->fad = NULL; } if (fwin->popup_del_job) ecore_job_del(fwin->popup_del_job); if (fwin->popup) { evas_object_hide(fwin->popup); evas_object_del(fwin->popup); fwin->popup = NULL; } if (fwin->object_del_job) ecore_job_del(fwin->object_del_job); fwin->object_del_job = NULL; if (fwin->popup_timer) ecore_timer_del(fwin->popup_timer); fwin->popup_timer = NULL; if (fwin->win) { evas_object_event_callback_del(fwin->win, EVAS_CALLBACK_MOUSE_IN, (void *)_e_fwin_icon_popup_handler); evas_object_event_callback_del(fwin->win, EVAS_CALLBACK_MOUSE_OUT, (void *)_e_fwin_icon_popup_handler); } E_FREE_LIST(fwin->popup_handlers, ecore_event_handler_del); if (fwin->spring_parent) fwin->spring_parent->spring_child = NULL; if (fwin->win) { evas_object_event_callback_del_full(fwin->win, EVAS_CALLBACK_DEL, _e_fwin_cb_delete, fwin); evas_object_del(fwin->win); } free(fwin); } static void _e_fwin_icon_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { int x, y, w, h, mw, mh, fx, fy, px, py; E_Zone *zone; Evas_Object *edje; E_Fwin *fwin = data; E_Fm2_Icon_Info *popup_icon; popup_icon = e_fm2_icon_file_get(fwin->cur_page->fm_obj, fwin->over_file); if (!popup_icon) return; e_fm2_icon_geometry_get(popup_icon->ic, &x, &y, &w, &h); if (fwin->zone) { zone = fwin->zone; evas_object_geometry_get(popup_icon->fm, &fx, &fy, NULL, NULL); fx -= zone->x, fy -= zone->y; } else { E_Client *ec = e_win_client_get(fwin->win); fx = ec->x, fy = ec->y; zone = ec->zone; } edje = evas_object_smart_parent_get(obj); /* failing to unswallow here causes edje to fail its min size calculations */ edje_object_part_unswallow(edje, obj); edje_object_part_swallow(edje, "e.swallow.content", obj); edje_object_size_min_calc(edje, &mw, &mh); /* prefer tooltip left of icon */ px = (fx + x) - mw - 3; /* if it's offscreen, try right of icon */ if (px < zone->x) px = (fx + x + w) + 3; /* fuck this, stick it right on the icon */ if (px + mw + 3 > zone->x + zone->w) px = (x + w / 2) - (mw / 2); /* give up */ if (px < zone->x) px = zone->x; /* prefer tooltip above icon */ py = (fy + y) - mh - 3; /* if it's offscreen, try below icon */ if (py < zone->y) py = (fy + y + h) + 3; /* fuck this, stick it right on the icon */ if (py + mh + 3 > zone->x + zone->h) py = (y + h / 2) - (mh / 2); /* give up */ if (py < zone->y) py = zone->y; evas_object_geometry_set(fwin->popup, px, py, mw, mh); } static void _e_fwin_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { evas_object_event_callback_del(data, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _e_fwin_icon_hints); } static Eina_Bool _e_fwin_icon_popup(void *data) { E_Fwin *fwin = data; Evas_Object *bg, *list, *o; E_Zone *zone; char buf[4096]; int mw, mh; E_Fm2_Icon_Info *popup_icon; struct stat st; fwin->popup_timer = NULL; popup_icon = e_fm2_icon_file_get(fwin->cur_page->fm_obj, fwin->over_file); if (!popup_icon) return EINA_FALSE; snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(fwin->cur_page->fm_obj), popup_icon->file); if (!ecore_file_can_read(buf)) return EINA_FALSE; if (stat(buf, &st) < 0) return EINA_FALSE; if (S_ISFIFO(st.st_mode)) return EINA_FALSE; if (fwin->popup) { evas_object_hide(fwin->popup); evas_object_del(fwin->popup); } zone = fwin->zone ?: e_comp_object_util_zone_get(fwin->win); bg = edje_object_add(e_comp->evas); e_theme_edje_object_set(bg, "base/theme/fileman", "e/fileman/popup/default"); mw = zone->w * fileman_config->tooltip.size / 100.0; mh = zone->h * fileman_config->tooltip.size / 100.0; edje_object_part_text_set(bg, "e.text.title", popup_icon->label ? popup_icon->label : popup_icon->file); list = e_widget_list_add(e_comp->evas, 0, 0); if (fwin->win) evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_DEL, _e_fwin_popup_del, list); o = e_widget_filepreview_add(e_comp->evas, mw, mh, 0); e_widget_filepreview_clamp_video_set(o, fileman_config->tooltip.clamp_size); e_widget_filepreview_path_set(o, buf, popup_icon->mime); e_widget_list_object_append(list, o, 1, 0, 0.5); edje_object_part_swallow(bg, "e.swallow.content", list); _e_fwin_icon_hints(fwin, NULL, list, NULL); evas_object_event_callback_add(list, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _e_fwin_icon_hints, fwin); fwin->popup = e_comp_object_util_add(bg, E_COMP_OBJECT_TYPE_POPUP); evas_object_layer_set(fwin->popup, E_LAYER_POPUP); e_comp_object_util_del_list_append(fwin->popup, list); e_comp_object_util_del_list_append(fwin->popup, o); evas_object_pass_events_set(fwin->popup, 1); #ifndef HAVE_WAYLAND_ONLY if (!fwin->popup_handlers) { evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_MOUSE_IN, (void *)_e_fwin_icon_popup_handler, fwin); evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_MOUSE_OUT, (void *)_e_fwin_icon_popup_handler, fwin); if (e_comp_util_has_x()) E_LIST_HANDLER_APPEND(fwin->popup_handlers, ECORE_X_EVENT_XDND_POSITION, (void *)_e_fwin_icon_popup_handler, fwin); E_LIST_HANDLER_APPEND(fwin->popup_handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, (void *)_e_fwin_icon_popup_handler, fwin); } #endif evas_object_show(fwin->popup); return EINA_FALSE; } static void _e_fwin_icon_popup_del(E_Fwin *fwin) { evas_object_hide(fwin->popup); E_FREE_FUNC(fwin->popup, evas_object_del); fwin->popup_del_job = NULL; } static void _e_fwin_icon_mouse_out(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin *fwin = data; E_FREE_FUNC(fwin->popup_timer, ecore_timer_del); if (!fwin->popup_del_job) fwin->popup_del_job = ecore_job_add((Ecore_Cb)_e_fwin_icon_popup_del, fwin); } static void _e_fwin_icon_mouse_in(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) { E_Fwin *fwin = data; E_Fm2_Icon_Info *ici = event_info; if (fwin->popup_timer) ecore_timer_del(fwin->popup_timer); fwin->popup_timer = NULL; if (!fileman_config->tooltip.enable) return; fwin->popup_timer = ecore_timer_loop_add(fileman_config->tooltip.delay, _e_fwin_icon_popup, fwin); if (fwin->over_file) eina_stringshare_del(fwin->over_file); fwin->over_file = NULL; if (ici->file) fwin->over_file = eina_stringshare_add(ici->file); #ifndef HAVE_WAYLAND_ONLY if (!fwin->popup_handlers) { if (fwin->win) { evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_MOUSE_IN, (void *)_e_fwin_icon_popup_handler, fwin); evas_object_event_callback_add(fwin->win, EVAS_CALLBACK_MOUSE_OUT, (void *)_e_fwin_icon_popup_handler, fwin); } if (e_comp_util_has_x()) E_LIST_HANDLER_APPEND(fwin->popup_handlers, ECORE_X_EVENT_XDND_POSITION, (void *)_e_fwin_icon_popup_handler, fwin); E_LIST_HANDLER_APPEND(fwin->popup_handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, (void *)_e_fwin_icon_popup_handler, fwin); } #endif } static void _e_fwin_page_favorites_add(E_Fwin_Page *page) { E_Fm2_Config fmc; Evas_Object *o; Evas *evas = evas_object_evas_get(page->fwin->bg_obj); o = e_fm2_add(evas); evas_object_data_set(o, "fm_page", page); page->flist = o; memset(&fmc, 0, sizeof(E_Fm2_Config)); fmc.view.mode = E_FM2_VIEW_MODE_LIST; fmc.view.open_dirs_in_place = 1; fmc.view.selector = 1; fmc.view.single_click = 1; fmc.view.no_subdir_jump = 1; fmc.view.link_drop = 1; fmc.icon.list.w = 24; fmc.icon.list.h = 24; fmc.icon.fixed.w = 1; fmc.icon.fixed.h = 1; fmc.icon.extension.show = 0; fmc.icon.key_hint = NULL; fmc.list.sort.no_case = 1; fmc.list.sort.dirs.first = 0; fmc.list.sort.dirs.last = 0; fmc.selection.single = 1; fmc.selection.windows_modifiers = 0; fmc.view.no_click_rename = 1; e_fm2_config_set(o, &fmc); e_fm2_icon_menu_flags_set(o, E_FM2_MENU_NO_NEW | E_FM2_MENU_NO_ACTIVATE_CHANGE | E_FM2_MENU_NO_VIEW_CHANGE); evas_object_smart_callback_add(o, "selected", _e_fwin_favorite_selected, page); evas_object_smart_callback_add(o, "dnd_enter", (Evas_Smart_Cb)_e_fwin_dnd_enter_cb, page->fwin); evas_object_smart_callback_add(o, "dnd_leave", (Evas_Smart_Cb)_e_fwin_dnd_leave_cb, page->fwin); evas_object_smart_callback_add(o, "dnd_changed", (Evas_Smart_Cb)_e_fwin_dnd_change_cb, page->fwin); evas_object_smart_callback_add(o, "dnd_begin", (Evas_Smart_Cb)_e_fwin_dnd_begin_cb, page->fwin); evas_object_smart_callback_add(o, "dnd_end", (Evas_Smart_Cb)_e_fwin_dnd_end_cb, page->fwin); e_fm2_path_set(o, "favorites", "/"); o = e_widget_scrollframe_pan_add(evas, page->flist, e_fm2_pan_set, e_fm2_pan_get, e_fm2_pan_max_get, e_fm2_pan_child_size_get); e_scrollframe_custom_theme_set(e_widget_scrollframe_object_get(o), "base/theme/fileman", "e/fileman/default/scrollframe"); evas_object_propagate_events_set(page->flist, 0); e_widget_can_focus_set(o, EINA_FALSE); e_fm2_window_set(page->flist, page->fwin->win); e_widget_scrollframe_focus_object_set(o, page->flist); page->flist_frame = o; evas_object_size_hint_min_set(o, 128 * e_scale, 0); edje_object_part_swallow(page->fwin->bg_obj, "e.swallow.favorites", o); } static E_Fwin_Page * _e_fwin_page_create(E_Fwin *fwin) { Evas_Object *o; E_Fwin_Page *page; Evas *evas; page = E_NEW(E_Fwin_Page, 1); page->fwin = fwin; evas = evas_object_evas_get(fwin->win); if (fileman_config->view.show_sidebar) { _e_fwin_page_favorites_add(page); edje_object_signal_emit(fwin->bg_obj, "e,favorites,enabled", "e"); edje_object_message_signal_process(fwin->bg_obj); } o = e_fm2_add(evas); page->fm_obj = o; e_fm2_view_flags_set(o, E_FM2_VIEW_DIR_CUSTOM); // low priority to be called last... after e_fm's own cb's evas_object_event_callback_priority_add(o, EVAS_CALLBACK_KEY_DOWN, 1000, _e_fwin_cb_key_down, page); evas_object_smart_callback_add(o, "changed", _e_fwin_icon_mouse_out, fwin); evas_object_smart_callback_add(o, "dir_changed", _e_fwin_changed, page); evas_object_smart_callback_add(o, "dir_deleted", _e_fwin_deleted, page); evas_object_smart_callback_add(o, "selected", _e_fwin_selected, page); evas_object_smart_callback_add(o, "selection_change", _e_fwin_selection_change, page); evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_fwin_cb_page_obj_del, page); evas_object_smart_callback_add(o, "dnd_enter", (Evas_Smart_Cb)_e_fwin_dnd_enter_cb, fwin); evas_object_smart_callback_add(o, "dnd_leave", (Evas_Smart_Cb)_e_fwin_dnd_leave_cb, fwin); evas_object_smart_callback_add(o, "dnd_changed", (Evas_Smart_Cb)_e_fwin_dnd_change_cb, fwin); evas_object_smart_callback_add(o, "dnd_begin", (Evas_Smart_Cb)_e_fwin_dnd_begin_cb, fwin); evas_object_smart_callback_add(o, "dnd_end", (Evas_Smart_Cb)_e_fwin_dnd_end_cb, fwin); evas_object_smart_callback_add(o, "double_clicked", (Evas_Smart_Cb)_e_fwin_bg_mouse_down, fwin); evas_object_smart_callback_add(o, "icon_mouse_in", (Evas_Smart_Cb)_e_fwin_icon_mouse_in, fwin); evas_object_smart_callback_add(o, "icon_mouse_out", (Evas_Smart_Cb)_e_fwin_icon_mouse_out, fwin); e_fm2_icon_menu_start_extend_callback_set(o, _e_fwin_cb_menu_extend_start, page); e_fm2_window_set(o, fwin->win); evas_object_focus_set(o, 1); _e_fwin_config_set(page); /* FIXME: this theme object will have more versions and options later * for things like swallowing widgets/buttons ot providing them - a * gadcon for starters for fm widgets. need to register the owning * e_object of the gadcon so gadcon clients can get it and thus do * things like find out what dirs/path the fwin is for etc. this will * probably be how you add optional gadgets to fwin views like empty/full * meters for disk usage, and other dir info/stats or controls. also it * might be possible that we can have custom frames per dir later so need * a way to set an edje file directly */ /* FIXME: allow specialised scrollframe obj per dir - get from e config, * then look in the dir itself for a magic dot-file, if not - use theme. * same as currently done for bg & overlay. also add to fm2 the ability * to specify the .edj files to get the list and icon theme stuff from */ evas_object_data_set(page->fm_obj, "fm_page", page); evas_object_data_set(page->fm_obj, "page_is_window", page); o = e_widget_scrollframe_pan_add(evas, page->fm_obj, e_fm2_pan_set, e_fm2_pan_get, e_fm2_pan_max_get, e_fm2_pan_child_size_get); evas_object_propagate_events_set(page->fm_obj, 0); e_widget_can_focus_set(o, EINA_FALSE); page->scrollframe_obj = o; page->scr = e_widget_scrollframe_object_get(o); e_scrollframe_key_navigation_set(o, EINA_FALSE); e_scrollframe_custom_theme_set(o, "base/theme/fileman", "e/fileman/default/scrollframe"); edje_object_part_swallow(fwin->bg_obj, "e.swallow.content", o); e_widget_scrollframe_focus_object_set(o, page->fm_obj); if (fileman_config->view.show_toolbar) { page->tbar = e_toolbar_new(evas, "toolbar", fwin->win, page->fm_obj); e_toolbar_orient(page->tbar, fileman_config->view.toolbar_orient); e_object_data_set(E_OBJECT(page->tbar), page); E_OBJECT_DEL_SET(page->tbar, _e_fwin_cb_toolbar_del); } page->fm_op_entry_add_handler = ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_ADD, _e_fwin_op_registry_entry_add_cb, page); _e_fwin_op_registry_entry_iter(page); _e_fwin_toolbar_resize(page); return page; } static void _e_fwin_page_free(E_Fwin_Page *page) { evas_object_del(page->flist); evas_object_del(page->flist_frame); if (page->tbar) { fileman_config->view.toolbar_orient = page->tbar->gadcon->orient; E_OBJECT_DEL_SET(E_OBJECT(page->tbar), NULL); e_object_del(E_OBJECT(page->tbar)); } else evas_object_del(page->scrollframe_obj); if (page->fm_obj) evas_object_del(page->fm_obj); if (page->fm_op_entry_add_handler) ecore_event_handler_del(page->fm_op_entry_add_handler); E_FREE(page); } static const char * _e_fwin_custom_file_path_eval(E_Fwin *fwin, Efreet_Desktop *ef, const char *prev_path, const char *key) { char buf[PATH_MAX]; const char *res, *ret = NULL; /* get a X-something custom stage from the .desktop for the dir */ res = efreet_desktop_x_field_get(ef, key); /* free the old path */ if (prev_path) eina_stringshare_del(prev_path); /* if there was no key found - return NULL */ if (!res) return NULL; /* it's a full path */ if (res[0] == '/') return res; /* relative path to the dir */ snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(fwin->cur_page->fm_obj), res); ret = eina_stringshare_add(buf); eina_stringshare_del(res); return ret; } static Eina_List * _e_fwin_defaults_apps_get(const char *mime, const char *path) { Efreet_Ini *ini; const char *str; Eina_List *apps = NULL; char **array, **itr; if (!ecore_file_exists(path)) return NULL; ini = efreet_ini_new(path); if (!ini) return NULL; efreet_ini_section_set(ini, "Default Applications"); str = efreet_ini_string_get(ini, mime); if (!str) goto end; array = eina_str_split(str, ";", 0); if (!array) goto end; for (itr = array; *itr != NULL; itr++) { const char *name = *itr; Efreet_Desktop *desktop; if (name[0] == '/') desktop = efreet_desktop_new(name); else desktop = efreet_util_desktop_file_id_find(name); if (!desktop) continue; if (!desktop->exec) { efreet_desktop_free(desktop); continue; } apps = eina_list_append(apps, desktop); } free(array[0]); free(array); end: efreet_ini_free(ini); return apps; } 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; Efreet_Desktop *desktop; snprintf(path, sizeof(path), "%s/mimeapps.list", efreet_config_home_get()); order = _e_fwin_defaults_apps_get(mime, path); if (!order) { const Eina_List *n, *dirs = efreet_data_dirs_get(); const char *d; EINA_LIST_FOREACH(dirs, n, d) { snprintf(path, sizeof(path), "%s/applications/defaults.list", d); order = _e_fwin_defaults_apps_get(mime, path); if (order) break; } } if (!order) { if (has_default) *has_default = EINA_FALSE; return desktops; } EINA_LIST_FOREACH(order, l, desktop) { Eina_List *node = eina_list_data_find_list(desktops, desktop); if (!node) continue; desktops = eina_list_remove_list(desktops, node); efreet_desktop_free(desktop); } if (has_default) *has_default = EINA_TRUE; return eina_list_merge(order, desktops); } static Eina_List * _e_fwin_suggested_apps_list_get(Eina_List *files, Eina_List **mime_list, Eina_Bool *has_default) { E_Fm2_Icon_Info *ici; Eina_Hash *set_mimes; Eina_List *apps = NULL, *l; set_mimes = eina_hash_string_small_new(NULL); EINA_LIST_FOREACH(files, l, ici) if (!((ici->link) && (ici->mount))) { if (_e_fwin_file_is_exec(ici) == E_FWIN_EXEC_NONE) { const char *key = ici->mime; if (ici->link) key = efreet_mime_globs_type_get(ici->link); if (!eina_hash_find(set_mimes, key)) eina_hash_direct_add(set_mimes, key, (void *)1); } } if (mime_list) *mime_list = NULL; if (has_default) *has_default = EINA_FALSE; if (eina_hash_population(set_mimes) > 0) { Eina_Hash *set_apps = eina_hash_pointer_new(NULL); Eina_Iterator *itr = eina_hash_iterator_key_new(set_mimes); const char *mime; EINA_ITERATOR_FOREACH(itr, mime) { Eina_List *desktops = efreet_util_desktop_mime_list(mime); Efreet_Desktop *d; Eina_Bool hd = EINA_FALSE; if (mime_list) *mime_list = eina_list_append(*mime_list, mime); desktops = e_fwin_suggested_apps_list_sort(mime, desktops, &hd); if ((hd) && (has_default)) *has_default = EINA_TRUE; EINA_LIST_FREE(desktops, d) { if (eina_hash_find(set_apps, &d)) efreet_desktop_free(d); else { eina_hash_add(set_apps, &d, (void *)1); apps = eina_list_append(apps, d); } } } eina_iterator_free(itr); eina_hash_free(set_apps); } eina_hash_free(set_mimes); return apps; } static void _e_fwin_desktop_run(Efreet_Desktop *desktop, E_Fwin_Page *page, Eina_Bool skip_history) { char pcwd[4096], buf[4096]; Eina_List *selected, *l, *files = NULL; E_Fwin *fwin = page->fwin; E_Fm2_Icon_Info *ici; char *file; skip_history = EINA_FALSE; selected = e_fm2_selected_list_get(page->fm_obj); if (!selected) return; if (!getcwd(pcwd, sizeof(pcwd))) return; if (chdir(e_fm2_real_path_get(page->fm_obj)) < 0) return; EINA_LIST_FOREACH(selected, l, ici) { E_Fwin_Exec_Type ext; /* this snprintf is silly - but it's here in case i really do * need to provide full paths (seems silly since we chdir * into the dir) */ buf[0] = 0; ext = _e_fwin_file_is_exec(ici); if ((ext == E_FWIN_EXEC_NONE) || (desktop)) { if (!((ici->link) && (ici->mount))) eina_strlcpy(buf, ici->file, sizeof(buf)); } else _e_fwin_file_exec(page, ici, ext); if (buf[0] != 0) { if ((ici->mime) && (desktop) && !(skip_history)) e_exehist_mime_desktop_add(ici->mime, desktop); files = eina_list_append(files, strdup(ici->file)); } } if ((fwin->win) && (desktop)) { e_exec(e_comp_object_util_zone_get(fwin->win), desktop, NULL, files, "fwin"); ici = selected->data; if ((ici) && (ici->mime) && (desktop) && !(skip_history)) e_exehist_mime_desktop_add(ici->mime, desktop); } else if (fwin->zone && desktop) e_exec(fwin->zone, desktop, NULL, files, "fwin"); eina_list_free(selected); EINA_LIST_FREE(files, file) free(file); if (chdir(pcwd) < 0) perror("chdir"); } static E_Fwin_Exec_Type _e_fwin_file_is_exec(E_Fm2_Icon_Info *ici) { /* special file or dir - can't exec anyway */ if ((S_ISCHR(ici->statinfo.st_mode)) || (S_ISBLK(ici->statinfo.st_mode)) || (S_ISFIFO(ici->statinfo.st_mode)) || (S_ISSOCK(ici->statinfo.st_mode))) return E_FWIN_EXEC_NONE; /* it is executable */ if ((ici->statinfo.st_mode & S_IXOTH) || ((getgid() == ici->statinfo.st_gid) && (ici->statinfo.st_mode & S_IXGRP)) || ((getuid() == ici->statinfo.st_uid) && (ici->statinfo.st_mode & S_IXUSR))) { /* no mimetype */ if (!ici->mime) return E_FWIN_EXEC_DIRECT; /* mimetype */ else { /* FIXME: - this could be config */ if (!strcmp(ici->mime, "application/x-desktop")) return E_FWIN_EXEC_DESKTOP; else if ((!strcmp(ici->mime, "application/x-sh")) || (!strcmp(ici->mime, "application/x-shellscript")) || (!strcmp(ici->mime, "application/x-csh")) || (!strcmp(ici->mime, "application/x-perl")) || (!strcmp(ici->mime, "application/x-shar")) || (!strcmp(ici->mime, "application/x-executable")) || (!strcmp(ici->mime, "text/x-csh")) || (!strcmp(ici->mime, "text/x-python")) || (!strcmp(ici->mime, "text/x-sh")) ) { return E_FWIN_EXEC_DIRECT; } } } else { /* mimetype */ if (ici->mime) { /* FIXME: - this could be config */ if (!strcmp(ici->mime, "application/x-desktop")) return E_FWIN_EXEC_DESKTOP; else if ((!strcmp(ici->mime, "application/x-sh")) || (!strcmp(ici->mime, "application/x-shellscript")) || (!strcmp(ici->mime, "text/x-sh")) ) { return E_FWIN_EXEC_TERMINAL_SH; } } else if ((e_util_glob_match(ici->file, "*.desktop")) || (e_util_glob_match(ici->file, "*.kdelink")) ) { return E_FWIN_EXEC_DESKTOP; } else if (e_util_glob_match(ici->file, "*.run")) return E_FWIN_EXEC_TERMINAL_SH; } return E_FWIN_EXEC_NONE; } static void _e_fwin_file_exec(E_Fwin_Page *page, E_Fm2_Icon_Info *ici, E_Fwin_Exec_Type ext) { E_Fwin *fwin = page->fwin; char buf[4096]; Efreet_Desktop *desktop; /* FIXME: execute file ici with either a terminal, the shell, or directly * or open the .desktop and exec it */ switch (ext) { case E_FWIN_EXEC_NONE: break; case E_FWIN_EXEC_DIRECT: snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(fwin->cur_page->fm_obj), ici->file); // XXX: exec verify buf if (fwin->win) e_exec(e_comp_object_util_zone_get(fwin->win), NULL, buf, NULL, "fwin"); else if (fwin->zone) e_exec(fwin->zone, NULL, buf, NULL, "fwin"); break; case E_FWIN_EXEC_SH: snprintf(buf, sizeof(buf), "/bin/sh %s", e_util_filename_escape(ici->file)); // XXX: exec verify buf if (fwin->win) e_exec(e_comp_object_util_zone_get(fwin->win), NULL, buf, NULL, "fwin"); else if (fwin->zone) e_exec(fwin->zone, NULL, buf, NULL, "fwin"); break; case E_FWIN_EXEC_TERMINAL_DIRECT: snprintf(buf, sizeof(buf), "%s %s", e_config->exebuf_term_cmd, e_util_filename_escape(ici->file)); // XXX: exec verify buf if (fwin->win) e_exec(e_comp_object_util_zone_get(fwin->win), NULL, buf, NULL, "fwin"); else if (fwin->zone) e_exec(fwin->zone, NULL, buf, NULL, "fwin"); break; case E_FWIN_EXEC_TERMINAL_SH: snprintf(buf, sizeof(buf), "%s /bin/sh %s", e_config->exebuf_term_cmd, e_util_filename_escape(ici->file)); // XXX: exec verify buf if (fwin->win) e_exec(e_comp_object_util_zone_get(fwin->win), NULL, buf, NULL, "fwin"); else if (fwin->zone) e_exec(fwin->zone, NULL, buf, NULL, "fwin"); break; case E_FWIN_EXEC_DESKTOP: snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); // XXX: exec verify buf desktop = efreet_desktop_new(buf); if (desktop) { if (fwin->win) e_exec(e_comp_object_util_zone_get(fwin->win), desktop, NULL, NULL, "fwin"); else if (fwin->zone) e_exec(fwin->zone, desktop, NULL, NULL, "fwin"); efreet_desktop_free(desktop); } break; default: break; } } static void _e_fwin_config_set(E_Fwin_Page *page) { E_Fm2_Config fmc; memset(&fmc, 0, sizeof(E_Fm2_Config)); if (!page->fwin->zone) { #if 0 fmc.view.mode = E_FM2_VIEW_MODE_LIST; fmc.icon.list.w = 24 * e_scale; fmc.icon.list.h = 24 * e_scale; fmc.icon.fixed.w = 1; fmc.icon.fixed.h = 1; #else fmc.view.mode = fileman_config->view.mode; fmc.icon.icon.w = fileman_config->icon.icon.w * e_scale; fmc.icon.icon.h = fileman_config->icon.icon.h * e_scale; fmc.icon.fixed.w = 0; fmc.icon.fixed.h = 0; #endif fmc.view.open_dirs_in_place = fileman_config->view.open_dirs_in_place; } else { #if 0 fmc.view.mode = E_FM2_VIEW_MODE_LIST; fmc.icon.list.w = 24 * e_scale; fmc.icon.list.h = 24 * e_scale; fmc.icon.fixed.w = 1; fmc.icon.fixed.h = 1; #else fmc.view.mode = page->fwin->path->desktop_mode; fmc.icon.icon.w = fileman_config->icon.icon.w * e_scale; fmc.icon.icon.h = fileman_config->icon.icon.h * e_scale; fmc.icon.fixed.w = 0; fmc.icon.fixed.h = 0; #endif fmc.view.no_typebuf_set = !fileman_config->view.desktop_navigation; fmc.view.open_dirs_in_place = 0; fmc.view.fit_custom_pos = 1; } fmc.view.selector = 0; fmc.view.single_click = fileman_config->view.single_click; fmc.view.no_subdir_jump = 0; fmc.icon.max_thumb_size = fileman_config->icon.max_thumb_size; fmc.icon.extension.show = fileman_config->icon.extension.show; fmc.list.sort.no_case = fileman_config->list.sort.no_case; fmc.list.sort.extension = fileman_config->list.sort.extension; fmc.list.sort.mtime = fileman_config->list.sort.mtime; fmc.list.sort.size = fileman_config->list.sort.size; fmc.list.sort.dirs.first = fileman_config->list.sort.dirs.first; fmc.list.sort.dirs.last = fileman_config->list.sort.dirs.last; fmc.selection.single = fileman_config->selection.single; fmc.selection.windows_modifiers = fileman_config->selection.windows_modifiers; e_fm2_config_set(page->fm_obj, &fmc); } static void _e_fwin_window_title_set(E_Fwin_Page *page) { char buf[PATH_MAX + sizeof("e_fwin::")]; const char *file; if (!page) return; if (page->fwin->zone) return; //safety if (fileman_config->view.show_full_path) file = e_fm2_real_path_get(page->fm_obj); else file = ecore_file_file_get(e_fm2_real_path_get(page->fm_obj)); if (file) elm_win_title_set(page->fwin->win, file); if (e_config->remember_internal_fm_windows_globally) ecore_evas_name_class_set(e_win_ee_get(page->fwin->win), "E", fwin_class); else { snprintf(buf, sizeof(buf), "e_fwin::%s", e_fm2_real_path_get(page->fm_obj)); ecore_evas_name_class_set(e_win_ee_get(page->fwin->win), "E", buf); } } static void _e_fwin_toolbar_resize(E_Fwin_Page *page) { if (!page->tbar) { edje_object_signal_emit(page->fwin->bg_obj, "e,toolbar,disabled", "e"); return; } switch (page->tbar->gadcon->orient) { case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_TOP: evas_object_size_hint_min_set(page->tbar->o_base, 0, page->tbar->minh); edje_object_part_swallow(page->fwin->bg_obj, "e.swallow.toolbar", page->tbar->o_base); edje_object_signal_emit(page->fwin->bg_obj, "e,toolbar,top", "e"); break; case E_GADCON_ORIENT_BOTTOM: evas_object_size_hint_min_set(page->tbar->o_base, 0, page->tbar->minh); edje_object_part_swallow(page->fwin->bg_obj, "e.swallow.toolbar", page->tbar->o_base); edje_object_signal_emit(page->fwin->bg_obj, "e,toolbar,bottom", "e"); break; case E_GADCON_ORIENT_VERT: case E_GADCON_ORIENT_LEFT: evas_object_size_hint_min_set(page->tbar->o_base, page->tbar->minw, 0); edje_object_part_swallow(page->fwin->bg_obj, "e.swallow.toolbar", page->tbar->o_base); edje_object_signal_emit(page->fwin->bg_obj, "e,toolbar,left", "e"); break; case E_GADCON_ORIENT_RIGHT: evas_object_size_hint_min_set(page->tbar->o_base, page->tbar->minw, 0); edje_object_part_swallow(page->fwin->bg_obj, "e.swallow.toolbar", page->tbar->o_base); edje_object_signal_emit(page->fwin->bg_obj, "e,toolbar,right", "e"); break; default: break; } edje_object_message_signal_process(page->fwin->bg_obj); } /* fwin callbacks */ static void _e_fwin_cb_delete(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { e_object_del(data); } /* static void * _e_fwin_geom_save(E_Fwin *fwin) * { * char buf[PATH_MAX]; * E_Fm2_Custom_File *cf; * * if (!fwin->geom_save_ready) return; * snprintf(buf, sizeof(buf), "dir::%s", e_fm2_real_path_get(fwin->cur_page->fm_obj)); * cf = e_fm2_custom_file_get(buf); * if (!cf) * { * cf = alloca(sizeof(E_Fm2_Custom_File)); * memset(cf, 0, sizeof(E_Fm2_Custom_File)); * } * cf->geom.x = fwin->win->x; * cf->geom.y = fwin->win->y; * cf->geom.w = fwin->win->w; * cf->geom.h = fwin->win->h; * cf->geom.valid = 1; * e_fm2_custom_file_set(buf, cf); * } */ static void _e_fwin_cb_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin *fwin = data; if (fwin->bg_obj) { if (fwin->zone) evas_object_resize(fwin->bg_obj, fwin->zone->w, fwin->zone->h); } _e_fwin_toolbar_resize(fwin->cur_page); if (fwin->zone) evas_object_resize(fwin->cur_page->scrollframe_obj, fwin->zone->w, fwin->zone->h); /* _e_fwin_geom_save(fwin); */ } static void _e_fwin_deleted(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin_Page *page; page = data; e_object_del(E_OBJECT(page->fwin)); } static void _e_fwin_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { E_Fwin *fwin; E_Fwin_Page *page; E_Fm2_Config *cfg; Efreet_Desktop *ef; const char *dev, *path; char buf[PATH_MAX]; Eina_Bool need_free = EINA_TRUE; page = data; fwin = page->fwin; if (!fwin) return; //safety _e_fwin_icon_mouse_out(fwin, NULL, NULL); cfg = e_fm2_config_get(page->fm_obj); e_fm2_path_get(page->fm_obj, &dev, NULL); e_user_dir_concat_static(buf, "fileman/favorites"); path = e_fm2_real_path_get(page->fm_obj); if ((dev && (!strcmp(dev, "favorites"))) || (path && (!strcmp(buf, path)))) cfg->view.link_drop = 1; else cfg->view.link_drop = 0; /* FIXME: first look in E config for a special override for this dir's bg * or overlay */ ef = e_fm2_desktop_get(page->fm_obj); if (ef) need_free = EINA_FALSE; else { snprintf(buf, sizeof(buf), "%s/.directory.desktop", e_fm2_real_path_get(page->fm_obj)); ef = efreet_desktop_new(buf); } //printf("EF=%p for %s\n", ef, buf); if (ef) { fwin->wallpaper_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->wallpaper_file, "X-Enlightenment-Directory-Wallpaper"); fwin->overlay_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->overlay_file, "X-Enlightenment-Directory-Overlay"); fwin->scrollframe_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->scrollframe_file, "X-Enlightenment-Directory-Scrollframe"); fwin->theme_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->theme_file, "X-Enlightenment-Directory-Theme"); //printf("fwin->wallpaper_file = %s\n", fwin->wallpaper_file); if (need_free) efreet_desktop_free(ef); } else { eina_stringshare_replace(&fwin->wallpaper_file, NULL); eina_stringshare_replace(&fwin->overlay_file, NULL); eina_stringshare_replace(&fwin->scrollframe_file, NULL); eina_stringshare_replace(&fwin->theme_file, NULL); } if (page->scrollframe_obj) { if ((fwin->scrollframe_file) && (e_util_edje_collection_exists(fwin->scrollframe_file, "e/fileman/default/scrollframe"))) e_scrollframe_custom_edje_file_set(page->scr, (char *)fwin->scrollframe_file, "e/fileman/default/scrollframe"); else { if (fwin->zone) e_scrollframe_custom_theme_set(page->scr, "base/theme/fileman", "e/fileman/desktop/scrollframe"); else e_scrollframe_custom_theme_set(page->scr, "base/theme/fileman", "e/fileman/default/scrollframe"); } e_scrollframe_child_pos_set(page->scr, 0, 0); } if ((fwin->theme_file) && (ecore_file_exists(fwin->theme_file))) e_fm2_custom_theme_set(obj, fwin->theme_file); else e_fm2_custom_theme_set(obj, NULL); if (fwin->wallpaper_file) { if (eina_str_has_extension(fwin->wallpaper_file, "edj")) { if (!fwin->wallpaper_is_edj) { if (fwin->under_obj) evas_object_del(fwin->under_obj); fwin->under_obj = edje_object_add(evas_object_evas_get(fwin->win)); fwin->wallpaper_is_edj = EINA_TRUE; } edje_object_file_set(fwin->under_obj, fwin->wallpaper_file, "e/desktop/background"); } else { if (fwin->wallpaper_is_edj) evas_object_del(fwin->under_obj); fwin->wallpaper_is_edj = EINA_FALSE; fwin->under_obj = e_icon_add(evas_object_evas_get(fwin->win)); e_icon_scale_size_set(fwin->under_obj, 0); e_icon_fill_inside_set(fwin->under_obj, 0); e_icon_file_set(fwin->under_obj, fwin->wallpaper_file); } if (fwin->under_obj) { edje_object_part_swallow(e_scrollframe_edje_object_get(page->scr), "e.swallow.bg", fwin->under_obj); evas_object_pass_events_set(fwin->under_obj, 1); evas_object_show(fwin->under_obj); } } else { edje_object_part_swallow(e_scrollframe_edje_object_get(page->scr), "e.swallow.bg", NULL); if (fwin->under_obj) evas_object_hide(fwin->under_obj); } if (fwin->over_obj) { //printf("over obj\n"); evas_object_hide(fwin->over_obj); if (fwin->overlay_file) { edje_object_file_set(fwin->over_obj, fwin->overlay_file, "e/desktop/background"); // ext = strrchr(fwin->overlay_file, '.'); // if (ext && !strcasecmp(ext, ".edj")) // e_icon_file_edje_set(fwin->over_obj, fwin->overlay_file, "e/desktop/background"); // else // e_icon_file_set(fwin->over_obj, fwin->overlay_file); } // else // e_icon_file_edje_set(fwin->over_obj, NULL, NULL); evas_object_show(fwin->over_obj); } _e_fwin_icon_mouse_out(fwin, NULL, NULL); if (fwin->zone) { e_fm2_path_get(page->fm_obj, &dev, &path); eina_stringshare_replace(&fwin->path->dev, dev); eina_stringshare_replace(&fwin->path->path, path); return; } _e_fwin_window_title_set(page); if (page->setting) return; if (page->flist) e_fm2_deselect_all(page->flist); } static void _e_fwin_favorite_selected(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin_Page *page; Eina_List *selected; page = data; selected = e_fm2_selected_list_get(page->flist); if (!selected) return; page->setting = 1; _e_fwin_file_open_dialog(page, selected, -1); eina_list_free(selected); page->setting = 0; } static void _e_fwin_selected(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin_Page *page; Eina_List *selected; page = data; selected = e_fm2_selected_list_get(page->fm_obj); if (!selected) return; _e_fwin_file_open_dialog(page, selected, 0); eina_list_free(selected); } static void _e_fwin_selection_change(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Eina_List *l; E_Fwin_Page *page; page = data; for (l = fwins; l; l = l->next) { if (l->data != page->fwin) e_fwin_all_unsel(l->data); } evas_object_focus_set(obj, 1); } static void _e_fwin_cb_all_change(void *data, Evas_Object *obj EINA_UNUSED) { E_Fwin_Apps_Dialog *fad; Efreet_Desktop *desktop = NULL; fad = data; desktop = efreet_util_desktop_file_id_find(fad->app2); if ((desktop) && (desktop->exec)) e_widget_entry_text_set(fad->o_entry, desktop->exec); if (desktop) efreet_desktop_free(desktop); else e_widget_entry_text_set(fad->o_entry, fad->app2); } static void _e_fwin_cb_delay_del_job(void *data) { E_Fwin *fwin = data; fwin->object_del_job = NULL; e_object_del(E_OBJECT(fwin)); } static void _e_fwin_cb_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Key_Down *ev; E_Fwin *fwin; E_Fwin_Page *page; page = data; fwin = page->fwin; ev = event_info; if (evas_key_modifier_is_set(ev->modifiers, "Control")) { if (!strcmp(ev->key, "n")) { const char *dev, *path; e_fm2_path_get(page->fm_obj, &dev, &path); e_fwin_new(dev, path); } else if (!strcmp(ev->key, "a")) { e_fm2_all_sel(page->fm_obj); } else if (!strcmp(ev->key, "w")) { if (fwin->object_del_job) ecore_job_del(fwin->object_del_job); fwin->object_del_job = ecore_job_add(_e_fwin_cb_delay_del_job, fwin); } } } static void _e_fwin_cb_page_obj_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { evas_object_smart_callback_del(obj, "dir_changed", _e_fwin_changed); evas_object_smart_callback_del(obj, "dir_deleted", _e_fwin_deleted); evas_object_smart_callback_del(obj, "selected", _e_fwin_selected); evas_object_smart_callback_del(obj, "selection_change", _e_fwin_selection_change); evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_fwin_cb_page_obj_del); } /* fwin zone callbacks */ static void _e_fwin_zone_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Fwin *fwin; fwin = data; if (!fwin) return; e_fwin_all_unsel(fwin); e_fm2_typebuf_clear(fwin->cur_page->fm_obj); } static Eina_Bool _e_fwin_zone_move_resize(void *data, int type EINA_UNUSED, void *event) { E_Event_Zone_Move_Resize *ev = event; E_Fwin *fwin = data; int x, y, w, h, sx, sy, sw, sh; if (!fwin) return ECORE_CALLBACK_PASS_ON; if (fwin->zone != ev->zone) return ECORE_CALLBACK_PASS_ON; if (!fwin->cur_page->scrollframe_obj) return ECORE_CALLBACK_RENEW; e_zone_useful_geometry_get(ev->zone, &x, &y, &w, &h); evas_object_geometry_get(fwin->cur_page->scrollframe_obj, &sx, &sy, &sw, &sh); /* if same, do nothing */ if ((sx == x) && (sy == y) && (sw == w) && (sh == h)) return ECORE_CALLBACK_RENEW; evas_object_geometry_set(fwin->cur_page->scrollframe_obj, x, y, w, h); e_fm2_refresh(fwin->cur_page->fm_obj); return ECORE_CALLBACK_RENEW; } static Eina_Bool _e_fwin_zone_del(void *data, int type, void *event) { E_Event_Zone_Del *ev; E_Fwin *fwin; if (type != E_EVENT_ZONE_DEL) return ECORE_CALLBACK_PASS_ON; fwin = data; ev = event; if (!fwin) return ECORE_CALLBACK_PASS_ON; if (fwin->zone != ev->zone) return ECORE_CALLBACK_PASS_ON; e_object_del(E_OBJECT(fwin)); return ECORE_CALLBACK_PASS_ON; } static int _e_fwin_cb_dir_handler_test(void *data EINA_UNUSED, Evas_Object *obj, const char *path) { if (ecore_file_is_dir(path)) return 1; if (e_fm2_real_path_get(obj)) { evas_object_data_set(obj, "fileman_terminal_realpath", (void*)1); return 1; } return 0; } static void _e_fwin_cb_dir_handler(void *data EINA_UNUSED, Evas_Object *obj, const char *path) { char buf[PATH_MAX]; Eina_Stringshare *rp; if (!getcwd(buf, sizeof(buf))) return; rp = e_fm2_real_path_get(obj); if (rp && (rp != path) && (evas_object_data_del(obj, "fileman_terminal_realpath"))) //icon menu; use rp path = rp; if (chdir(path) < 0) perror("chdir"); e_exec(e_zone_current_get(), tdesktop, NULL, NULL, "fileman"); if (chdir(buf) < 0) perror("chdir"); /* FIXME: if info != null then check mime type and offer options based * on that */ } static void _e_fwin_parent(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { e_fm2_parent_go(data); } static void _e_fwin_cb_menu_open_fast(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi) { E_Fwin_Page *page; Efreet_Desktop *desk; page = data; desk = e_object_data_get(E_OBJECT(mi)); if ((page) && (desk)) _e_fwin_desktop_run(desk, page, EINA_TRUE); } static void _e_fwin_cb_menu_extend_open_with(void *data, E_Menu *m) { Eina_List *selected = NULL, *apps = NULL, *l; E_Menu_Item *mi; E_Fwin_Page *page; Efreet_Desktop *desk = NULL; page = data; selected = e_fm2_selected_list_get(page->fm_obj); if (!selected) return; apps = _e_fwin_suggested_apps_list_get(selected, NULL, NULL); EINA_LIST_FOREACH(apps, l, desk) { if (!desk) continue; mi = e_menu_item_new(m); e_menu_item_label_set(mi, desk->name); e_util_desktop_menu_item_icon_add(desk, 24, mi); e_menu_item_callback_set(mi, _e_fwin_cb_menu_open_fast, page); e_object_data_set(E_OBJECT(mi), desk); } if (apps) { 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, _("Other application...")); e_util_menu_item_theme_icon_set(mi, "document-open"); e_menu_item_callback_set(mi, _e_fwin_cb_menu_open_with, page); e_menu_pre_activate_callback_set(m, NULL, NULL); eina_list_free(apps); eina_list_free(selected); } static void _e_fwin_path(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { const char *path; E_Fwin_Page *page; Ecore_Window xwin; path = e_fm2_real_path_get(data); page = evas_object_data_get(data, "fm_page"); if (page->fwin->win) xwin = elm_win_window_id_get(page->fwin->win); else xwin = e_comp->ee_win; #ifndef HAVE_WAYLAND_ONLY ecore_x_selection_clipboard_set(xwin, path, strlen(path) + 1); #endif } static void _e_fwin_clone(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Fwin *fwin = data; E_Action *act_fm; /* path of least resistance! */ act_fm = e_action_find("fileman"); if (!act_fm) return; act_fm->func.go(NULL, e_win_client_get(fwin->win)->icccm.class + 8); } static void _e_fwin_cb_menu_extend_start(void *data, Evas_Object *obj, E_Menu *m, E_Fm2_Icon_Info *info) { E_Menu_Item *mi = NULL; E_Fwin_Page *page; E_Menu *subm; Eina_List *selected = NULL; Eina_Bool set = EINA_FALSE; char buf[PATH_MAX] = {0}; page = data; selected = e_fm2_selected_list_get(page->fm_obj); #ifdef ENABLE_FILES if (info && info->file && (info->link || S_ISDIR(info->statinfo.st_mode))) snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), info->file); subm = e_mod_menu_add(m, (buf[0]) ? buf : e_fm2_real_path_get(page->fm_obj)); if (((!page->fwin->zone) || fileman_config->view.desktop_navigation) && e_fm2_has_parent_get(obj)) { mi = e_menu_item_new_relative(subm, NULL); e_menu_item_label_set(mi, _("Go To Parent Directory")); e_menu_item_icon_edje_set(mi, e_theme_edje_file_get("base/theme/fileman", "e/fileman/default/button/parent"), "e/fileman/default/button/parent"); e_menu_item_callback_set(mi, _e_fwin_parent, obj); } if (!page->fwin->zone) { mi = e_menu_item_new_relative(subm, mi); e_menu_item_label_set(mi, _("Clone Window")); e_util_menu_item_theme_icon_set(mi, "window-duplicate"); e_menu_item_callback_set(mi, _e_fwin_clone, page->fwin); } mi = e_menu_item_new_relative(subm, mi); e_menu_item_label_set(mi, _("Copy Path")); e_util_menu_item_theme_icon_set(mi, "edit-copy"); e_menu_item_callback_set(mi, _e_fwin_path, obj); mi = e_menu_item_new_relative(subm, mi); e_menu_item_separator_set(mi, EINA_TRUE); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, EINA_TRUE); #endif if (!selected) return; mi = e_menu_item_new(m); while (eina_list_count(selected) == 1) { if (_e_fwin_file_is_exec(eina_list_data_get(selected)) == E_FWIN_EXEC_NONE) break; e_menu_item_label_set(mi, _("Run")); e_util_menu_item_theme_icon_set(mi, "system-run"); set = EINA_TRUE; break; } if (!set) { e_menu_item_label_set(mi, _("Open")); e_util_menu_item_theme_icon_set(mi, "document-open"); } e_menu_item_callback_set(mi, _e_fwin_cb_menu_open, page); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Open with...")); e_util_menu_item_theme_icon_set(mi, "document-open"); subm = e_menu_new(); e_menu_item_submenu_set(mi, subm); e_menu_pre_activate_callback_set(subm, _e_fwin_cb_menu_extend_open_with, page); mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); eina_list_free(selected); } static void _e_fwin_cb_menu_open(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Fwin_Page *page; Eina_List *selected; page = data; selected = e_fm2_selected_list_get(page->fm_obj); if (!selected) return; _e_fwin_file_open_dialog(page, selected, 0); eina_list_free(selected); } static void _e_fwin_cb_menu_open_with(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Fwin_Page *page; Eina_List *selected = NULL; page = data; selected = e_fm2_selected_list_get(page->fm_obj); if (!selected) return; _e_fwin_file_open_dialog(page, selected, 1); eina_list_free(selected); } static void _e_fwin_border_set(E_Fwin_Page *page, E_Fwin *fwin, E_Fm2_Icon_Info *ici) { Evas_Object *oic; const char *itype = NULL; int ix, iy, iw, ih, nx, ny, found = 0; E_Remember *rem = NULL; Eina_List *ll; const char *file = NULL, *group = NULL, *class; int w, h, zw, zh; E_Client *ec; /* E_Fm2_Custom_File *cf; */ if (ici->label) elm_win_title_set(fwin->win, ici->label); else if (ici->file) elm_win_title_set(fwin->win, ici->file); oic = e_fm2_icon_get(evas_object_evas_get(ici->fm), ici->ic, NULL, NULL, 0, &itype); if (!oic) return; ec = e_win_client_get(fwin->win); eina_stringshare_replace(&ec->internal_icon, NULL); eina_stringshare_replace(&ec->internal_icon_key, NULL); if (!strcmp(evas_object_type_get(oic), "edje")) { edje_object_file_get(oic, &file, &group); ec->internal_icon = eina_stringshare_ref(file); ec->internal_icon_key = eina_stringshare_ref(group); } else { e_icon_file_get(oic, &file, &group); ec->internal_icon = eina_stringshare_ref(file); ec->internal_icon_key = eina_stringshare_ref(group); } evas_object_del(oic); if (ec->placed) return; if (e_config->remember_internal_fm_windows_globally) class = fwin_class; else class = eina_stringshare_printf("e_fwin::%s", e_fm2_real_path_get(fwin->cur_page->fm_obj)); e_zone_useful_geometry_get(e_comp_object_util_zone_get(fwin->win), NULL, NULL, &zw, &zh); EINA_LIST_FOREACH(e_config->remembers, ll, rem) if (rem->class == class) { found = 1; rem->prop.w = E_CLAMP(rem->prop.w, DEFAULT_WIDTH, zw); rem->prop.h = E_CLAMP(rem->prop.h, DEFAULT_HEIGHT, zh); rem->prop.pos_x = E_CLAMP(rem->prop.pos_x, 0, zw - rem->prop.w); rem->prop.pos_y = E_CLAMP(rem->prop.pos_y, 0, zh - rem->prop.h); break; } if (!e_config->remember_internal_fm_windows_globally) eina_stringshare_del(class); if (found) return; /* No custom info, so just put window near icon */ e_fm2_icon_geometry_get(ici->ic, &ix, &iy, &iw, &ih); nx = (ix + (iw / 2)); ny = (iy + (ih / 2)); if (page->fwin->win) { nx += ec->x; ny += ec->y; } /* checking width and height */ /* TODO add config for preffered initial size? */ w = DEFAULT_WIDTH; if (w > zw) w = zw; h = DEFAULT_HEIGHT; if (h > zh) h = zh; /* iff going out of zone - adjust to be in */ if ((ec->zone->x + ec->zone->w) < (w + nx)) nx -= w; if ((ec->zone->y + ec->zone->h) < (h + ny)) ny -= h; evas_object_geometry_set(fwin->win, nx, ny, w, h); ec->placed = 1; } static E_Fwin * _e_fwin_open(E_Fwin_Page *page, E_Fm2_Icon_Info *ici, E_Fwin_Win_Mode win_mode, int *need_dia) { E_Fwin *fwin = NULL; char buf[PATH_MAX + sizeof("removable:")]; Eina_Bool new_fwin; new_fwin = ((win_mode == E_FWIN_WIN_FORCE_WIN) || ((!fileman_config->view.open_dirs_in_place || page->fwin->zone))) && (win_mode != E_FWIN_WIN_FORCE_INLINE); if ((ici->link) && (ici->mount)) { if (new_fwin) { if (page->fwin->win) fwin = _e_fwin_new(ici->link, "/"); else if (page->fwin->zone) fwin = _e_fwin_new(ici->link, "/"); } else { _e_fwin_border_set(page, page->fwin, ici); e_fm2_path_set(page->fm_obj, ici->link, "/"); return page->fwin; } } else if ((ici->link) && (ici->removable)) { snprintf(buf, sizeof(buf), "removable:%s", ici->link); if (new_fwin) { if (page->fwin->win) fwin = _e_fwin_new(buf, "/"); else if (page->fwin->zone) fwin = _e_fwin_new(buf, "/"); } else { _e_fwin_border_set(page, page->fwin, ici); e_fm2_path_set(page->fm_obj, buf, "/"); return page->fwin; } } else if (ici->real_link) { if (S_ISDIR(ici->statinfo.st_mode)) { if (new_fwin) { if (page->fwin->win) fwin = _e_fwin_new(NULL, ici->real_link); else if (page->fwin->zone) fwin = _e_fwin_new(NULL, ici->real_link); } else { _e_fwin_border_set(page, page->fwin, ici); e_fm2_path_set(page->fm_obj, NULL, ici->real_link); return page->fwin; } } else { if (need_dia) *need_dia = 1; } } else { snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); if (S_ISDIR(ici->statinfo.st_mode)) { if (new_fwin) { if (page->fwin->win) fwin = _e_fwin_new(NULL, ici->link ?: buf); else if (page->fwin->zone) fwin = _e_fwin_new(NULL, ici->link ?: buf); } else { _e_fwin_border_set(page, page->fwin, ici); e_fm2_path_set(page->fm_obj, NULL, ici->link ?: buf); return page->fwin; } } else { if (need_dia) *need_dia = 1; } } if (!fwin) return NULL; if ((!fwin->win) || (!e_win_client_get(fwin->win))) { _e_fwin_free(fwin); return NULL; } _e_fwin_border_set(page, fwin, ici); return fwin; } /* 'open with' dialog*/ static void _e_fwin_file_open_dialog(E_Fwin_Page *page, Eina_List *files, int always) { E_Fwin *fwin = page->fwin; E_Dialog *dia; Evas_Coord mw, mh; Evas_Object *o, *of, *ol, *ot; Evas *evas; Eina_List *l = NULL, *ll, *apps = NULL, *mlist = NULL; Eina_List *cats = NULL; Efreet_Desktop *desk = NULL; E_Fwin_Apps_Dialog *fad; E_Fm2_Icon_Info *ici; char buf[PATH_MAX + sizeof("removable:")]; Eina_Bool has_default = EINA_FALSE; int need_dia = 0, n = 0;; n = eina_list_count(files); if (fwin->fad) { e_object_del(E_OBJECT(fwin->fad->dia)); fwin->fad = NULL; } if ((!always) || (always == -1)) { if (((fileman_config->view.open_dirs_in_place) && (!page->fwin->zone)) || (always == -1)) { _e_fwin_open(page, eina_list_data_get(files), (always == -1) ? E_FWIN_WIN_FORCE_INLINE : E_FWIN_WIN_AUTO, &need_dia); } else { EINA_LIST_FOREACH(files, l, ici) _e_fwin_open(page, ici, E_FWIN_WIN_AUTO, &need_dia); } if (!need_dia) return; } apps = _e_fwin_suggested_apps_list_get(files, &mlist, &has_default); // fprintf(stderr, "GOGOGOGOOGOGOG\n"); if (!always) { /* FIXME: well this is simplisitic - if only 1 mime type is being * opened then look for the previously used app for that mimetype and * if found, use that. * * we could get more sophisitcated. * 1. find apps for each mimetype in mlist. if all prev used apps are * the same, then use previously used app. * OR if this fails * 2. find all apps for each mimetype. find the one used the most. * if that app can handle all mimetypes in the list - use that. if not * find the next most often listed app - if that can handle all apps, * use it, if not fall back again - and so on - if all apps listed do * not contain 1 that handles all the mime types - fall back to dialog */ if ((has_default) || (eina_list_count(mlist) <= 1)) { char *file; char pcwd[4096]; Eina_List *files_list = NULL; need_dia = 1; //fprintf(stderr, "XXXXX %i %p\n", has_default, apps); if ((has_default) && (apps)) desk = apps->data; else if (mlist) desk = e_exehist_mime_desktop_get(mlist->data); //fprintf(stderr, "mlist = %p\n", mlist); if (!getcwd(pcwd, sizeof(pcwd))) perror("getcwd"); if (chdir(e_fm2_real_path_get(page->fm_obj)) < 0) perror("chdir"); files_list = NULL; EINA_LIST_FOREACH(files, l, ici) if (_e_fwin_file_is_exec(ici) == E_FWIN_EXEC_NONE) files_list = eina_list_append(files_list, strdup(ici->file)); EINA_LIST_FOREACH(files, l, ici) { E_Fwin_Exec_Type ext; ext = _e_fwin_file_is_exec(ici); if (ext != E_FWIN_EXEC_NONE) { _e_fwin_file_exec(page, ici, ext); need_dia = 0; } } if (desk) { if (fwin->win) { if (e_exec(e_comp_object_util_zone_get(fwin->win), desk, NULL, files_list, "fwin")) need_dia = 0; } else if (fwin->zone) { if (e_exec(fwin->zone, desk, NULL, files_list, "fwin")) need_dia = 0; } if (!need_dia) { if (mlist) e_exehist_mime_desktop_add(mlist->data, desk); } } EINA_LIST_FREE(files_list, file) free(file); if (chdir(pcwd) < 0) perror("chdir"); if (!need_dia) { EINA_LIST_FREE(apps, desk) efreet_desktop_free(desk); mlist = eina_list_free(mlist); return; } } } if (fwin->win) dia = e_dialog_new(NULL, "E", "_fwin_open_apps"); else if (fwin->zone) dia = e_dialog_new(NULL, "E", "_fwin_open_apps"); else return; /* make clang happy */ e_dialog_resizable_set(dia, 1); fad = E_NEW(E_Fwin_Apps_Dialog, 1); e_dialog_title_set(dia, _("Open with...")); e_dialog_button_add(dia, _("Open"), "document-open", _e_fwin_cb_open, fad); e_dialog_button_add(dia, _("Close"), "window-close", _e_fwin_cb_close, fad); fad->dia = dia; fad->fwin = fwin; fwin->fad = fad; dia->data = fad; e_object_free_attach_func_set(E_OBJECT(dia), _e_fwin_cb_dialog_free); evas = evas_object_evas_get(dia->win); ol = e_widget_list_add(evas, 0, 0); l = eina_list_free(l); #if 1 o = e_widget_filepreview_add(evas, 96 * e_scale, 96 * e_scale, 1); fad->o_filepreview = o; if (n == 1) { ici = eina_list_data_get(files); of = e_widget_framelist_add(evas, ici->file, 0); snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); e_widget_filepreview_path_set(o, buf, ici->mime); } else { snprintf(buf, sizeof(buf), P_("%d file", "%d files", n), n); of = e_widget_framelist_add(evas, buf, 0); ot = e_widget_toolbar_add(evas, 24 * e_scale, 24 * e_scale); e_widget_toolbar_scrollable_set(ot, 1); EINA_LIST_FOREACH(files, l, ici) e_widget_toolbar_item_append(ot, NULL, ici->file, _e_fwin_file_open_dialog_preview_set, page, ici); e_widget_toolbar_item_select(ot, 0); e_widget_framelist_object_append(of, ot); } e_widget_framelist_object_append(of, o); #else // Here each file has its own widget, created at start, resulting on a longish time to show the dialog. // However, this doesn't display artefacts as the previous method, so is kept here for reference. if (n == 1) { ici = eina_list_data_get(files); of = e_widget_framelist_add(evas, ici->file, 0); o = e_widget_filepreview_add(evas, 96 * e_scale, 96 * e_scale, 1); snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); e_widget_filepreview_path_set(o, buf, ici->mime); e_widget_framelist_object_append(of, o); } else { snprintf(buf, sizeof(buf), P_("%d file", "%d files", n), n); of = e_widget_framelist_add(evas, buf, 0); ot = e_widget_toolbook_add(evas, 24 * e_scale, 24 * e_scale); EINA_LIST_FOREACH(files, l, ici) { o = e_widget_filepreview_add(evas, 96 * e_scale, 96 * e_scale, 1); snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); e_widget_filepreview_path_set(o, buf, ici->mime); e_widget_toolbook_page_append(ot, NULL, ici->file, o, 1, 1, 1, 1, .5, .5); } e_widget_toolbook_page_show(ot, 0); e_widget_framelist_object_append(of, ot); } #endif e_widget_list_object_append(ol, of, 1, 0, 0.5); // Make frame with list of applications of = e_widget_framelist_add(evas, _("Known Applications"), 0); o = e_widget_ilist_add(evas, 24, 24, &(fad->app2)); e_widget_on_change_hook_set(o, _e_fwin_cb_all_change, fad); fad->o_all = o; evas_event_freeze(evas); edje_freeze(); e_widget_ilist_freeze(o); // Adding Specific Applications list into widget if (apps) e_widget_ilist_header_append(o, NULL, _("Suggested Applications")); mlist = eina_list_free(mlist); EINA_LIST_FOREACH_SAFE(apps, l, ll, desk) { Evas_Object *icon = NULL; const char *val; if (!desk) continue; icon = e_util_desktop_icon_add(desk, 24, evas); val = efreet_util_path_to_file_id(desk->orig_path); if (!val) val = eina_stringshare_add(desk->exec); if (val) e_widget_ilist_append(o, icon, desk->name, NULL, NULL, val); else { /* not executable, don't keep in list */ apps = eina_list_remove_list(apps, l); efreet_desktop_free(desk); } } // Building All Applications list cats = efreet_util_desktop_name_glob_list("*"); cats = eina_list_sort(cats, 0, _e_fwin_dlg_cb_desk_sort); EINA_LIST_FREE(cats, desk) { if (!eina_list_data_find(l, desk) && !eina_list_data_find(apps, desk)) l = eina_list_append(l, desk); else efreet_desktop_free(desk); } l = eina_list_sort(l, -1, _e_fwin_dlg_cb_desk_list_sort); // Adding All Applications list into widget if (l) e_widget_ilist_header_append(o, NULL, _("All Applications")); EINA_LIST_FREE(l, desk) { Evas_Object *icon = NULL; if (!desk) continue; icon = e_util_desktop_icon_add(desk, 24, evas); e_widget_ilist_append(o, icon, desk->name, NULL, NULL, efreet_util_path_to_file_id(desk->orig_path)); efreet_desktop_free(desk); } EINA_LIST_FREE(apps, desk) efreet_desktop_free(desk); e_widget_ilist_go(o); e_widget_ilist_thaw(o); edje_thaw(); evas_event_thaw(evas); e_widget_size_min_set(o, 160, 160); e_widget_framelist_object_append(of, o); e_widget_list_object_append(ol, of, 1, 1, 0.5); o = e_widget_label_add(evas, _("Custom Command")); e_widget_list_object_append(ol, o, 1, 0, 0.5); fad->o_entry = e_widget_entry_add(dia->win, &(fad->exec_cmd), _e_fwin_cb_exec_cmd_changed, fad, NULL); e_widget_list_object_append(ol, fad->o_entry, 1, 0, 0.5); e_widget_size_min_get(ol, &mw, &mh); e_dialog_content_set(dia, ol, mw, mh); evas_object_event_callback_add(ol, EVAS_CALLBACK_KEY_DOWN, _e_fwin_file_open_dialog_cb_key_down, page); e_dialog_show(dia); e_dialog_border_icon_set(dia, "preferences-applications"); e_widget_focus_steal(fad->o_entry); } static void _e_fwin_file_open_dialog_preview_set(void *data1, void *data2) { E_Fwin_Page *page = data1; E_Fm2_Icon_Info *ici = data2; char buf[PATH_MAX]; snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file); e_widget_filepreview_path_set(page->fwin->fad->o_filepreview, buf, ici->mime); } static void _e_fwin_file_open_dialog_cb_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info) { Evas_Event_Key_Down *ev = event_info; E_Fwin_Page *page = data; E_Fwin *fwin = page->fwin; if (!strcmp(ev->key, "Escape")) _e_fwin_cb_close(fwin->fad, fwin->fad->dia); else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter"))) _e_fwin_cb_open(fwin->fad, fwin->fad->dia); } static int _e_fwin_dlg_cb_desk_sort(const void *p1, const void *p2) { Efreet_Desktop *d1, *d2; d1 = (Efreet_Desktop *)p1; d2 = (Efreet_Desktop *)p2; if (!d1->name) return 1; if (!d2->name) return -1; return strcmp(d1->name, d2->name); } static int _e_fwin_dlg_cb_desk_list_sort(const void *data1, const void *data2) { const Efreet_Desktop *d1, *d2; if (!(d1 = data1)) return 1; if (!(d2 = data2)) return -1; return strcmp(d1->name, d2->name); } static void _e_fwin_cb_exec_cmd_changed(void *data, void *data2 EINA_UNUSED) { E_Fwin_Apps_Dialog *fad = NULL; Efreet_Desktop *desktop = NULL; if (!(fad = data)) return; if (fad->app2) desktop = efreet_util_desktop_file_id_find(fad->app2); if (!desktop) return; if (strcmp(desktop->exec, fad->exec_cmd)) { eina_stringshare_del(fad->app2); fad->app2 = NULL; if (fad->o_all) e_widget_ilist_unselect(fad->o_all); } efreet_desktop_free(desktop); } static void _e_fwin_cb_open(void *data, E_Dialog *dia EINA_UNUSED) { E_Fwin_Apps_Dialog *fad; Efreet_Desktop *desktop = NULL; fad = data; if (fad->app2) desktop = efreet_util_desktop_file_id_find(fad->app2); if ((!desktop) && (!fad->exec_cmd)) return; // Create a fake .desktop for custom command. if (!desktop) { desktop = efreet_desktop_empty_new(""); if (strchr(fad->exec_cmd, '%')) { desktop->exec = strdup(fad->exec_cmd); } else { desktop->exec = malloc(strlen(fad->exec_cmd) + 4); if (desktop->exec) snprintf(desktop->exec, strlen(fad->exec_cmd) + 4, "%s %%U", fad->exec_cmd); } } if ((fad->exec_cmd) && (strcmp(fad->exec_cmd, ""))) _e_fwin_desktop_run(desktop, fad->fwin->cur_page, EINA_FALSE); efreet_desktop_free(desktop); e_object_del(E_OBJECT(fad->dia)); } static void _e_fwin_cb_close(void *data, E_Dialog *dia EINA_UNUSED) { E_Fwin_Apps_Dialog *fad; fad = data; e_object_del(E_OBJECT(fad->dia)); } static void _e_fwin_cb_dialog_free(void *obj) { E_Dialog *dia; E_Fwin_Apps_Dialog *fad; dia = (E_Dialog *)obj; fad = dia->data; eina_stringshare_del(fad->app2); E_FREE(fad->exec_cmd); fad->fwin->fad = NULL; E_FREE(fad); } /* scrolling ability */ static void _e_fwin_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { E_Fwin_Page *page; page = evas_object_data_get(obj, "fm_page"); e_fm2_pan_set(obj, x, y); if (x > page->fm_pan.max_x) x = page->fm_pan.max_x; if (y > page->fm_pan.max_y) y = page->fm_pan.max_y; if (x < 0) x = 0; if (y < 0) y = 0; page->fm_pan.x = x; page->fm_pan.y = y; _e_fwin_pan_scroll_update(page); } static void _e_fwin_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { E_Fwin_Page *page; page = evas_object_data_get(obj, "fm_page"); e_fm2_pan_get(obj, x, y); page->fm_pan.x = *x; page->fm_pan.y = *y; } static void _e_fwin_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { E_Fwin_Page *page; page = evas_object_data_get(obj, "fm_page"); e_fm2_pan_max_get(obj, x, y); page->fm_pan.max_x = *x; page->fm_pan.max_y = *y; _e_fwin_pan_scroll_update(page); } static void _e_fwin_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { E_Fwin_Page *page; page = evas_object_data_get(obj, "fm_page"); e_fm2_pan_child_size_get(obj, w, h); page->fm_pan.w = *w; page->fm_pan.h = *h; _e_fwin_pan_scroll_update(page); } static void _e_fwin_pan_scroll_update(E_Fwin_Page *page) { Edje_Message_Int_Set *msg; if ((page->fm_pan.x == page->fm_pan_last.x) && (page->fm_pan.y == page->fm_pan_last.y) && (page->fm_pan.max_x == page->fm_pan_last.max_x) && (page->fm_pan.max_y == page->fm_pan_last.max_y) && (page->fm_pan.w == page->fm_pan_last.w) && (page->fm_pan.h == page->fm_pan_last.h)) return; msg = alloca(sizeof(Edje_Message_Int_Set) - sizeof(int) + (6 * sizeof(int))); msg->count = 6; msg->val[0] = page->fm_pan.x; msg->val[1] = page->fm_pan.y; msg->val[2] = page->fm_pan.max_x; msg->val[3] = page->fm_pan.max_y; msg->val[4] = page->fm_pan.w; msg->val[5] = page->fm_pan.h; // printf("SEND MSG %i %i | %i %i | %ix%i\n", // page->fm_pan.x, page->fm_pan.y, // page->fm_pan.max_x, page->fm_pan.max_y, // page->fm_pan.w, page->fm_pan.h); if (page->fwin->under_obj && page->fwin->wallpaper_is_edj) edje_object_message_send(page->fwin->under_obj, EDJE_MESSAGE_INT_SET, 1, msg); if (page->fwin->over_obj) edje_object_message_send(page->fwin->over_obj, EDJE_MESSAGE_INT_SET, 1, msg); if (page->scr) edje_object_message_send(e_scrollframe_edje_object_get(page->scr), EDJE_MESSAGE_INT_SET, 1, msg); page->fm_pan_last.x = page->fm_pan.x; page->fm_pan_last.y = page->fm_pan.y; page->fm_pan_last.max_x = page->fm_pan.max_x; page->fm_pan_last.max_y = page->fm_pan.max_y; page->fm_pan_last.w = page->fm_pan.w; page->fm_pan_last.h = page->fm_pan.h; } /* e_fm_op_registry */ static void _e_fwin_op_registry_listener_cb(void *data, const E_Fm2_Op_Registry_Entry *ere) { Evas_Object *o = data; char buf[4096]; char *total; int mw, mh; Edje_Message_Float msg; // Don't show if the operation keep less than 1 second if (ere->start_time + 1.0 > ecore_loop_time_get()) return; // Update icon switch (ere->op) { case E_FM_OP_COPY: edje_object_signal_emit(o, "e,action,icon,copy", "e"); break; case E_FM_OP_MOVE: edje_object_signal_emit(o, "e,action,icon,move", "e"); break; case E_FM_OP_REMOVE: edje_object_signal_emit(o, "e,action,icon,delete", "e"); break; case E_FM_OP_SECURE_REMOVE: edje_object_signal_emit(o, "e,action,icon,secure_delete", "e"); break; default: edje_object_signal_emit(o, "e,action,icon,unknown", "e"); } // Update information text switch (ere->status) { case E_FM2_OP_STATUS_ABORTED: switch (ere->op) { case E_FM_OP_COPY: snprintf(buf, sizeof(buf), _("Copying is aborted")); break; case E_FM_OP_MOVE: snprintf(buf, sizeof(buf), _("Moving is aborted")); break; case E_FM_OP_REMOVE: snprintf(buf, sizeof(buf), _("Deleting is aborted")); break; case E_FM_OP_SECURE_REMOVE: snprintf(buf, sizeof(buf), _("Secure deletion is aborted")); break; default: snprintf(buf, sizeof(buf), _("Unknown operation from slave is aborted")); } break; default: total = e_util_size_string_get(ere->total); switch (ere->op) { case E_FM_OP_COPY: if (ere->finished) snprintf(buf, sizeof(buf), _("Copy of %s done"), total); else snprintf(buf, sizeof(buf), _("Copying %s (eta: %s)"), total, e_util_time_str_get(ere->eta)); break; case E_FM_OP_MOVE: if (ere->finished) snprintf(buf, sizeof(buf), _("Move of %s done"), total); else snprintf(buf, sizeof(buf), _("Moving %s (eta: %s)"), total, e_util_time_str_get(ere->eta)); break; case E_FM_OP_REMOVE: if (ere->finished) snprintf(buf, sizeof(buf), _("Delete done")); else snprintf(buf, sizeof(buf), _("Deleting files...")); break; case E_FM_OP_SECURE_REMOVE: if (ere->finished) snprintf(buf, sizeof(buf), _("Secure delete done")); else snprintf(buf, sizeof(buf), _("Securely deleting files...")); break; default: snprintf(buf, sizeof(buf), _("Unknown operation from slave %d"), ere->id); } E_FREE(total); } edje_object_part_text_set(o, "e.text.info", buf); if (ere->needs_attention) edje_object_signal_emit(o, "e,action,set,need_attention", "e"); else edje_object_signal_emit(o, "e,action,set,normal", "e"); if ((ere->finished) || (ere->status == E_FM2_OP_STATUS_ABORTED)) { if (!evas_object_data_get(o, "stopped")) { evas_object_data_set(o, "stopped", o); edje_object_signal_emit(o, "e,state,busy,stop", "e"); } } if (ere->percent > 0) { if (!evas_object_data_get(o, "started")) { evas_object_data_set(o, "started", o); edje_object_signal_emit(o, "e,state,busy,start", "e"); } } // Update element edje_object_part_drag_size_set(o, "e.gauge.bar", ((double)(ere->percent)) / 100.0, 1.0); msg.val = ((double)(ere->percent)) / 100.0; edje_object_message_send(o, EDJE_MESSAGE_FLOAT, 1, &msg); edje_object_size_min_get(o, &mw, &mh); if ((mw == 0) || (mh == 0)) edje_object_size_min_calc(o, &mw, &mh); else { mw *= e_scale; mh *= e_scale; } evas_object_resize(o, mw, mh); evas_object_show(o); } static void _e_fwin_op_registry_free_check(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { Ecore_Timer *t; t = evas_object_data_get(obj, "_e_fwin_op_registry_thingy"); if (!t) return; ecore_timer_del(t); } static Eina_Bool _e_fwin_op_registry_free_data_delayed(void *data) { evas_object_event_callback_del_full(data, EVAS_CALLBACK_FREE, _e_fwin_op_registry_free_check, data); evas_object_del((Evas_Object *)data); return ECORE_CALLBACK_CANCEL; } static void _e_fwin_op_registry_free_data(void *data) { Ecore_Timer *t; t = ecore_timer_loop_add(5.0, _e_fwin_op_registry_free_data_delayed, data); evas_object_data_set(data, "_e_fwin_op_registry_thingy", t); evas_object_event_callback_add(data, EVAS_CALLBACK_FREE, _e_fwin_op_registry_free_check, data); } static Eina_Bool _e_fwin_op_registry_entry_add_cb(void *data, EINA_UNUSED int type, void *event) { E_Fm2_Op_Registry_Entry *ere = (E_Fm2_Op_Registry_Entry *)event; E_Fwin_Page *page = data; Evas_Object *o; Evas_Coord mw, mh; if ((ere->op != E_FM_OP_COPY) && (ere->op != E_FM_OP_MOVE) && (ere->op != E_FM_OP_REMOVE) && (ere->op != E_FM_OP_SECURE_REMOVE)) return ECORE_CALLBACK_RENEW; o = edje_object_add(evas_object_evas_get(page->scrollframe_obj)); e_theme_edje_object_set(o, "base/theme/fileman", "e/fileman/default/progress"); edje_object_size_min_calc(o, &mw, &mh); evas_object_size_hint_min_set(o, mw, mh); // Append the element to the box edje_object_part_box_append(e_scrollframe_edje_object_get(page->scr), "e.box.operations", o); evas_object_size_hint_align_set(o, 1.0, 1.0); //FIXME this should be theme-configurable // add abort button callback with id of operation in registry edje_object_signal_callback_add(o, "e,fm,operation,abort", "", _e_fwin_op_registry_abort_cb, (void *)(long)ere->id); //Listen to progress changes e_fm2_op_registry_entry_listener_add(ere, _e_fwin_op_registry_listener_cb, o, _e_fwin_op_registry_free_data); return ECORE_CALLBACK_RENEW; } static void _e_fwin_op_registry_entry_iter(E_Fwin_Page *page) { Eina_Iterator *itr; E_Fm2_Op_Registry_Entry *ere; itr = e_fm2_op_registry_iterator_new(); EINA_ITERATOR_FOREACH(itr, ere) _e_fwin_op_registry_entry_add_cb(page, 0, ere); eina_iterator_free(itr); } static void _e_fwin_op_registry_abort_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { int id; id = (long)data; if (!id) return; e_fm2_operation_abort(id); }