3e8cf67af7c913c6e0de89cac2e3e83956f1273e
[framework/uifw/e17.git] / src / modules / fileman / e_fwin.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 /* FIXME: fwin - the fm2 filemanager wrapped with a window and scrollframe.
5  * primitive BUT enough to test generic dnd and fm stuff more easily. don't
6  * play with this unless u want to help with it. NOT COMPLETE! BEWARE!
7  */
8 /* FIXME: multiple selected files across different fwins - you can only dnd the
9  * ones in the 1 window src - not all selected ones. also selecting a new file
10  * in a new fwin doesn't deseclect other selections in other fwin's (unless
11  * multi-selecting)
12  */
13
14 typedef struct _E_Fwin             E_Fwin;
15 typedef struct _E_Fwin_Page        E_Fwin_Page;
16 typedef struct _E_Fwin_Apps_Dialog E_Fwin_Apps_Dialog;
17
18 #define E_FWIN_TYPE 0xE0b0101f
19
20 struct _E_Fwin
21 {
22    E_Object             e_obj_inherit;
23
24    E_Win               *win;
25    E_Zone              *zone;
26    Evas_Object         *tb_obj;
27    Evas_Object         *bg_obj;
28    E_Fwin_Apps_Dialog  *fad;
29
30    Eina_List           *pages;
31    E_Fwin_Page         *cur_page;
32    int                  page_index;
33
34    Evas_Object         *under_obj;
35    Evas_Object         *over_obj;
36
37    const char          *wallpaper_file;
38    const char          *overlay_file;
39    const char          *scrollframe_file;
40    const char          *theme_file;
41
42    Ecore_Event_Handler *zone_handler;
43    Ecore_Event_Handler *zone_del_handler;
44 };
45
46 struct _E_Fwin_Page
47 {
48    E_Fwin              *fwin;
49    Ecore_Event_Handler *fm_op_entry_add_handler;
50
51    Evas_Object         *scrollframe_obj;
52    Evas_Object         *fm_obj;
53    E_Toolbar           *tbar;
54
55    struct
56    {
57       Evas_Coord x, y, max_x, max_y, w, h;
58    } fm_pan, fm_pan_last;
59
60    int index;
61 };
62
63 struct _E_Fwin_Apps_Dialog
64 {
65    E_Dialog    *dia;
66    E_Fwin      *fwin;
67    const char  *app2;
68    Evas_Object *o_all;
69    Evas_Object *o_entry;
70    char        *exec_cmd;
71 };
72
73 typedef enum
74 {
75    E_FWIN_EXEC_NONE,
76    E_FWIN_EXEC_DIRECT,
77    E_FWIN_EXEC_SH,
78    E_FWIN_EXEC_TERMINAL_DIRECT,
79    E_FWIN_EXEC_TERMINAL_SH,
80    E_FWIN_EXEC_DESKTOP
81 } E_Fwin_Exec_Type;
82
83 /* local subsystem prototypes */
84 static E_Fwin *_e_fwin_new(E_Container *con,
85                            const char  *dev,
86                            const char  *path);
87 static void         _e_fwin_free(E_Fwin *fwin);
88 static E_Fwin_Page *_e_fwin_page_create(E_Fwin *fwin);
89 static void         _e_fwin_page_free(E_Fwin_Page *page);
90 static void         _e_fwin_page_new(E_Fwin *fwin);
91 static void         _e_fwin_cb_page_change(void *data1,
92                                            void *data2);
93 static void         _e_fwin_cb_delete(E_Win *win);
94 static void         _e_fwin_cb_move(E_Win *win);
95 static void         _e_fwin_cb_resize(E_Win *win);
96 static void         _e_fwin_deleted(void        *data,
97                                     Evas_Object *obj,
98                                     void        *event_info);
99 static const char *_e_fwin_custom_file_path_eval(E_Fwin         *fwin,
100                                                  Efreet_Desktop *ef,
101                                                  const char     *prev_path,
102                                                  const char     *key);
103 static void _e_fwin_desktop_run(Efreet_Desktop *desktop,
104                                 E_Fwin_Page    *page,
105                                 Eina_Bool       skip_history);
106 static Eina_List *_e_fwin_suggested_apps_list_get(Eina_List  *files,
107                                                   Eina_List **mime_list);
108 static void       _e_fwin_changed(void        *data,
109                                   Evas_Object *obj,
110                                   void        *event_info);
111 static void _e_fwin_selected(void        *data,
112                              Evas_Object *obj,
113                              void        *event_info);
114 static void _e_fwin_selection_change(void        *data,
115                                      Evas_Object *obj,
116                                      void        *event_info);
117 static void _e_fwin_menu_extend(void            *data,
118                                 Evas_Object     *obj,
119                                 E_Menu          *m,
120                                 E_Fm2_Icon_Info *info);
121 static void _e_fwin_cb_menu_extend_open_with(void   *data,
122                                              E_Menu *m);
123 static void _e_fwin_cb_menu_open_fast(void        *data,
124                                       E_Menu      *m,
125                                       E_Menu_Item *mi);
126 static void _e_fwin_parent(void        *data,
127                            E_Menu      *m,
128                            E_Menu_Item *mi);
129 static void _e_fwin_cb_key_down(void        *data,
130                                 Evas        *e,
131                                 Evas_Object *obj,
132                                 void        *event_info);
133 static void _e_fwin_cb_menu_extend_start(void            *data,
134                                          Evas_Object     *obj,
135                                          E_Menu          *m,
136                                          E_Fm2_Icon_Info *info);
137 static void _e_fwin_cb_menu_open(void        *data,
138                                  E_Menu      *m,
139                                  E_Menu_Item *mi);
140 static void _e_fwin_cb_menu_open_with(void        *data,
141                                       E_Menu      *m,
142                                       E_Menu_Item *mi);
143 static void      _e_fwin_cb_all_change(void        *data,
144                                        Evas_Object *obj);
145 static void      _e_fwin_cb_exec_cmd_changed(void *data,
146                                              void *data2);
147 static void      _e_fwin_cb_open(void     *data,
148                                  E_Dialog *dia);
149 static void      _e_fwin_cb_close(void     *data,
150                                   E_Dialog *dia);
151 static void      _e_fwin_cb_dialog_free(void *obj);
152 static Eina_Bool _e_fwin_cb_hash_foreach(const Eina_Hash *hash __UNUSED__,
153                                          const void           *key,
154                                          void *data            __UNUSED__,
155                                          void                 *fdata);
156 static E_Fwin_Exec_Type _e_fwin_file_is_exec(E_Fm2_Icon_Info *ici);
157 static void             _e_fwin_file_exec(E_Fwin_Page     *page,
158                                           E_Fm2_Icon_Info *ici,
159                                           E_Fwin_Exec_Type ext);
160 static void _e_fwin_file_open_dialog(E_Fwin_Page *page,
161                                      Eina_List   *files,
162                                      int          always);
163 static void _e_fwin_file_open_dialog_cb_key_down(void        *data,
164                                                  Evas        *e,
165                                                  Evas_Object *obj,
166                                                  void        *event_info);
167
168 static void _e_fwin_pan_set(Evas_Object *obj,
169                             Evas_Coord   x,
170                             Evas_Coord   y);
171 static void _e_fwin_pan_get(Evas_Object *obj,
172                             Evas_Coord  *x,
173                             Evas_Coord  *y);
174 static void _e_fwin_pan_max_get(Evas_Object *obj,
175                                 Evas_Coord  *x,
176                                 Evas_Coord  *y);
177 static void _e_fwin_pan_child_size_get(Evas_Object *obj,
178                                        Evas_Coord  *w,
179                                        Evas_Coord  *h);
180 static void _e_fwin_pan_scroll_update(E_Fwin_Page *page);
181 static void _e_fwin_cb_page_obj_del(void *data, Evas *evas,
182                                          Evas_Object *obj, void *event_info);
183 static void _e_fwin_zone_cb_mouse_down(void        *data,
184                                        Evas        *evas,
185                                        Evas_Object *obj,
186                                        void        *event_info);
187 static Eina_Bool _e_fwin_zone_move_resize(void *data,
188                                           int   type,
189                                           void *event);
190 static Eina_Bool _e_fwin_zone_del(void *data,
191                                   int   type,
192                                   void *event);
193 static void _e_fwin_config_set(E_Fwin_Page *page);
194 static void _e_fwin_window_title_set(E_Fwin_Page *page);
195 static void _e_fwin_page_resize(E_Fwin_Page *page);
196 static void _e_fwin_toolbar_resize(E_Fwin_Page *page);
197 static int  _e_fwin_dlg_cb_desk_sort(const void *p1,
198                                      const void *p2);
199 static int  _e_fwin_dlg_cb_desk_list_sort(const void *data1,
200                                           const void *data2);
201
202 static void      _e_fwin_op_registry_listener_cb(void                          *data,
203                                                  const E_Fm2_Op_Registry_Entry *ere);
204 static Eina_Bool _e_fwin_op_registry_entry_add_cb(void *data,
205                                                   int   type,
206                                                   void *event);
207 static void _e_fwin_op_registry_entry_iter(E_Fwin_Page *page);
208 static void _e_fwin_op_registry_abort_cb(void        *data,
209                                          Evas_Object *obj,
210                                          const char  *emission,
211                                          const char  *source);
212
213 /* local subsystem globals */
214 static Eina_List *fwins = NULL;
215
216 /* externally accessible functions */
217 int
218 e_fwin_init(void)
219 {
220    eina_init();
221
222    return 1;
223 }
224
225 int
226 e_fwin_shutdown(void)
227 {
228    E_Fwin *fwin;
229
230    EINA_LIST_FREE(fwins, fwin)
231      e_object_del(E_OBJECT(fwin));
232
233    eina_shutdown();
234
235    return 1;
236 }
237
238 /* FIXME: this opens a new window - we need a way to inherit a zone as the
239  * "fwin" window
240  */
241 void
242 e_fwin_new(E_Container *con,
243            const char  *dev,
244            const char  *path)
245 {
246    _e_fwin_new(con, dev, path);
247 }
248
249 void
250 e_fwin_zone_new(E_Zone     *zone,
251                 const char *dev,
252                 const char *path)
253 {
254    E_Fwin *fwin;
255    E_Fwin_Page *page;
256    Evas_Object *o;
257    int x, y, w, h;
258
259    fwin = E_OBJECT_ALLOC(E_Fwin, E_FWIN_TYPE, _e_fwin_free);
260    if (!fwin) return;
261    fwin->zone = zone;
262
263    page = E_NEW(E_Fwin_Page, 1);
264    page->fwin = fwin;
265
266    /* Add Event Handler for zone move/resize & del */
267    fwin->zone_handler =
268      ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE,
269                              _e_fwin_zone_move_resize, fwin);
270    fwin->zone_del_handler =
271      ecore_event_handler_add(E_EVENT_ZONE_DEL,
272                              _e_fwin_zone_del, fwin);
273
274    /* Trap the mouse_down on zone so we can unselect */
275    evas_object_event_callback_add(zone->bg_event_object,
276                                   EVAS_CALLBACK_MOUSE_DOWN,
277                                   _e_fwin_zone_cb_mouse_down, fwin);
278
279    fwins = eina_list_append(fwins, fwin);
280
281    o = e_fm2_add(zone->container->bg_evas);
282    page->fm_obj = o;
283    _e_fwin_config_set(page);
284
285    e_fm2_custom_theme_content_set(o, "desktop");
286
287    evas_object_smart_callback_add(o, "dir_changed",
288                                   _e_fwin_changed, page);
289    evas_object_smart_callback_add(o, "dir_deleted",
290                                   _e_fwin_deleted, page);
291    evas_object_smart_callback_add(o, "selected",
292                                   _e_fwin_selected, page);
293    evas_object_smart_callback_add(o, "selection_change",
294                                   _e_fwin_selection_change, page);
295    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
296                                   _e_fwin_cb_page_obj_del, page);
297    e_fm2_icon_menu_start_extend_callback_set(o, _e_fwin_cb_menu_extend_start, page);
298    e_fm2_icon_menu_end_extend_callback_set(o, _e_fwin_menu_extend, page);
299    e_fm2_underlay_hide(o);
300    evas_object_show(o);
301
302    o = e_scrollframe_add(zone->container->bg_evas);
303    ecore_x_icccm_state_set(zone->container->bg_win, ECORE_X_WINDOW_STATE_HINT_NORMAL);
304    e_drop_xdnd_register_set(zone->container->event_win, 1);
305    e_scrollframe_custom_theme_set(o, "base/theme/fileman",
306                                   "e/fileman/desktop/scrollframe");
307    /* FIXME: this theme object will have more versions and options later
308     * for things like swallowing widgets/buttons ot providing them - a
309     * gadcon for starters for fm widgets. need to register the owning
310     * e_object of the gadcon so gadcon clients can get it and thus do
311     * things like find out what dirs/path the fwin is for etc. this will
312     * probably be how you add optional gadgets to fwin views like empty/full
313     * meters for disk usage, and other dir info/stats or controls. also it
314     * might be possible that we can have custom frames per dir later so need
315     * a way to set an edje file directly
316     */
317    /* FIXME: allow specialised scrollframe obj per dir - get from e config,
318     * then look in the dir itself for a magic dot-file, if not - use theme.
319     * same as currently done for bg & overlay. also add to fm2 the ability
320     * to specify the .edj files to get the list and icon theme stuff from
321     */
322    evas_object_data_set(page->fm_obj, "fm_page", page);
323    e_scrollframe_extern_pan_set(o, page->fm_obj,
324                                 _e_fwin_pan_set,
325                                 _e_fwin_pan_get,
326                                 _e_fwin_pan_max_get,
327                                 _e_fwin_pan_child_size_get);
328    evas_object_propagate_events_set(page->fm_obj, 0);
329    page->scrollframe_obj = o;
330
331    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
332    evas_object_move(o, x, y);
333    evas_object_resize(o, w, h);
334    evas_object_show(o);
335
336    e_fm2_window_object_set(page->fm_obj, E_OBJECT(fwin->zone));
337
338    evas_object_focus_set(page->fm_obj, 1);
339
340    e_fm2_path_set(page->fm_obj, dev, path);
341
342    fwin->pages = eina_list_append(fwin->pages, page);
343    fwin->cur_page = fwin->pages->data;
344 }
345
346 void
347 e_fwin_all_unsel(void *data)
348 {
349    E_Fwin *fwin;
350
351    fwin = data;
352    E_OBJECT_CHECK(fwin);
353    E_OBJECT_TYPE_CHECK(fwin, E_FWIN_TYPE);
354    e_fm2_all_unsel(fwin->cur_page->fm_obj);
355 }
356
357 void
358 e_fwin_zone_shutdown(E_Zone *zone)
359 {
360    Eina_List *f, *fn;
361    E_Fwin *win;
362
363    EINA_LIST_FOREACH_SAFE(fwins, f, fn, win)
364      {
365         if (win->zone != zone) continue;
366         e_object_del(E_OBJECT(win));
367         win = NULL;
368      }
369 }
370
371 void
372 e_fwin_reload_all(void)
373 {
374    Eina_List *l, *ll, *lll;
375    E_Container *con;
376    E_Manager *man;
377    E_Fwin *fwin;
378    E_Zone *zone;
379
380    /* Reload/recreate zones cause of property changes */
381    EINA_LIST_FOREACH(fwins, l, fwin)
382      {
383         if (!fwin) continue;  //safety
384         if (fwin->zone)
385           e_fwin_zone_shutdown(fwin->zone);
386         else
387           {
388              Eina_List *l2;
389              E_Fwin_Page *page;
390
391              EINA_LIST_FOREACH(fwin->pages, l2, page)
392                {
393                   _e_fwin_config_set(page);
394                   e_fm2_refresh(page->fm_obj);
395                   _e_fwin_window_title_set(page);
396                }
397           }
398      }
399
400    /* Hook into zones */
401    EINA_LIST_FOREACH(e_manager_list(), l, man)
402      EINA_LIST_FOREACH(man->containers, ll, con)
403        EINA_LIST_FOREACH(con->zones, lll, zone)
404          {
405             if (e_fwin_zone_find(zone)) continue;
406             if ((zone->container->num == 0) && (zone->num == 0) &&
407                 (fileman_config->view.show_desktop_icons))
408               e_fwin_zone_new(zone, "desktop", "/");
409             else
410               {
411                  char buf[256];
412
413                  if (fileman_config->view.show_desktop_icons)
414                    {
415                       snprintf(buf, sizeof(buf), "%i",
416                                (zone->container->num + zone->num));
417                       e_fwin_zone_new(zone, "desktop", buf);
418                    }
419               }
420          }
421 }
422
423 int
424 e_fwin_zone_find(E_Zone *zone)
425 {
426    Eina_List *f;
427    E_Fwin *win;
428
429    EINA_LIST_FOREACH(fwins, f, win)
430      if (win->zone == zone) return 1;
431    return 0;
432 }
433
434 /* local subsystem functions */
435 static E_Fwin *
436 _e_fwin_new(E_Container *con,
437             const char  *dev,
438             const char  *path)
439 {
440    E_Fwin *fwin;
441    E_Fwin_Page *page;
442    Evas_Object *o;
443    char buf[PATH_MAX];
444
445    fwin = E_OBJECT_ALLOC(E_Fwin, E_FWIN_TYPE, _e_fwin_free);
446    if (!fwin) return NULL;
447    fwin->win = e_win_new(con);
448    if (!fwin->win)
449      {
450         free(fwin);
451         return NULL;
452      }
453    fwins = eina_list_append(fwins, fwin);
454    e_win_delete_callback_set(fwin->win, _e_fwin_cb_delete);
455    e_win_move_callback_set(fwin->win, _e_fwin_cb_move);
456    e_win_resize_callback_set(fwin->win, _e_fwin_cb_resize);
457    fwin->win->data = fwin;
458
459    o = edje_object_add(e_win_evas_get(fwin->win));
460    e_theme_edje_object_set(o, "base/theme/fileman",
461                            "e/fileman/default/window/main");
462    evas_object_show(o);
463    fwin->bg_obj = o;
464
465    page = _e_fwin_page_create(fwin);
466    fwin->pages = eina_list_append(fwin->pages, page);
467    fwin->cur_page = page;
468
469    o = e_icon_add(e_win_evas_get(fwin->win));
470    e_icon_scale_size_set(o, 0);
471    e_icon_fill_inside_set(o, 0);
472    edje_object_part_swallow(fwin->bg_obj, "e.swallow.bg", o);
473    evas_object_pass_events_set(o, 1);
474    fwin->under_obj = o;
475
476    o = e_icon_add(e_win_evas_get(fwin->win));
477    e_icon_scale_size_set(o, 0);
478    e_icon_fill_inside_set(o, 0);
479    edje_object_part_swallow(e_scrollframe_edje_object_get(page->scrollframe_obj), "e.swallow.overlay", o);
480    evas_object_pass_events_set(o, 1);
481    fwin->over_obj = o;
482
483    e_fm2_path_set(page->fm_obj, dev, path);
484    _e_fwin_window_title_set(page);
485    snprintf(buf, sizeof(buf), "e_fwin::%s", e_fm2_real_path_get(fwin->cur_page->fm_obj));
486    e_win_name_class_set(fwin->win, "E", buf);
487
488    e_win_size_min_set(fwin->win, 24, 24);
489    e_win_resize(fwin->win, 280 * e_scale, 200 * e_scale);
490    e_win_show(fwin->win);
491    if (fwin->win->evas_win)
492      e_drop_xdnd_register_set(fwin->win->evas_win, 1);
493    if (fwin->win->border)
494      {
495         if (fwin->win->border->internal_icon)
496           eina_stringshare_del(fwin->win->border->internal_icon);
497         fwin->win->border->internal_icon =
498           eina_stringshare_add("system-file-manager");
499      }
500
501    return fwin;
502 }
503
504 static void
505 _e_fwin_free(E_Fwin *fwin)
506 {
507    E_Fwin_Page *page;
508
509    if (!fwin) return;  //safety
510
511    EINA_LIST_FREE(fwin->pages, page)
512      _e_fwin_page_free(page);
513
514    if (fwin->zone)
515      {
516         evas_object_event_callback_del(fwin->zone->bg_event_object,
517                                        EVAS_CALLBACK_MOUSE_DOWN,
518                                        _e_fwin_zone_cb_mouse_down);
519      }
520
521    if (fwin->zone_handler)
522      ecore_event_handler_del(fwin->zone_handler);
523    if (fwin->zone_del_handler)
524      ecore_event_handler_del(fwin->zone_del_handler);
525
526    fwins = eina_list_remove(fwins, fwin);
527    if (fwin->wallpaper_file) eina_stringshare_del(fwin->wallpaper_file);
528    if (fwin->overlay_file) eina_stringshare_del(fwin->overlay_file);
529    if (fwin->scrollframe_file) eina_stringshare_del(fwin->scrollframe_file);
530    if (fwin->theme_file) eina_stringshare_del(fwin->theme_file);
531    if (fwin->fad)
532      {
533         e_object_del(E_OBJECT(fwin->fad->dia));
534         fwin->fad = NULL;
535      }
536    if (fwin->win) e_object_del(E_OBJECT(fwin->win));
537    free(fwin);
538 }
539
540 static E_Fwin_Page *
541 _e_fwin_page_create(E_Fwin *fwin)
542 {
543    Evas_Object *o;
544    E_Fwin_Page *page;
545
546    page = E_NEW(E_Fwin_Page, 1);
547    page->fwin = fwin;
548
549    o = e_fm2_add(e_win_evas_get(fwin->win));
550    page->fm_obj = o;
551    e_fm2_view_flags_set(o, E_FM2_VIEW_DIR_CUSTOM);
552    evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, _e_fwin_cb_key_down, page);
553
554    evas_object_smart_callback_add(o, "dir_changed",
555                                   _e_fwin_changed, page);
556    evas_object_smart_callback_add(o, "dir_deleted",
557                                   _e_fwin_deleted, page);
558    evas_object_smart_callback_add(o, "selected",
559                                   _e_fwin_selected, page);
560    evas_object_smart_callback_add(o, "selection_change",
561                                   _e_fwin_selection_change, page);
562    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
563                                   _e_fwin_cb_page_obj_del, page);
564    e_fm2_icon_menu_start_extend_callback_set(o, _e_fwin_cb_menu_extend_start, page);
565    e_fm2_icon_menu_end_extend_callback_set(o, _e_fwin_menu_extend, page);
566    e_fm2_window_object_set(o, E_OBJECT(fwin->win));
567    evas_object_focus_set(o, 1);
568
569    evas_object_show(o);
570
571    o = e_scrollframe_add(e_win_evas_get(fwin->win));
572    /* FIXME: this theme object will have more versions and options later
573     * for things like swallowing widgets/buttons ot providing them - a
574     * gadcon for starters for fm widgets. need to register the owning
575     * e_object of the gadcon so gadcon clients can get it and thus do
576     * things like find out what dirs/path the fwin is for etc. this will
577     * probably be how you add optional gadgets to fwin views like empty/full
578     * meters for disk usage, and other dir info/stats or controls. also it
579     * might be possible that we can have custom frames per dir later so need
580     * a way to set an edje file directly
581     */
582    /* FIXME: allow specialised scrollframe obj per dir - get from e config,
583     * then look in the dir itself for a magic dot-file, if not - use theme.
584     * same as currently done for bg & overlay. also add to fm2 the ability
585     * to specify the .edj files to get the list and icon theme stuff from
586     */
587    e_scrollframe_custom_theme_set(o, "base/theme/fileman",
588                                   "e/fileman/default/scrollframe");
589    evas_object_data_set(page->fm_obj, "fm_page", page);
590    e_scrollframe_extern_pan_set(o, page->fm_obj,
591                                 _e_fwin_pan_set,
592                                 _e_fwin_pan_get,
593                                 _e_fwin_pan_max_get,
594                                 _e_fwin_pan_child_size_get);
595    evas_object_propagate_events_set(page->fm_obj, 0);
596    page->scrollframe_obj = o;
597    evas_object_move(o, 0, 0);
598    evas_object_show(o);
599
600    if (fileman_config->view.show_toolbar)
601      {
602         page->tbar = e_toolbar_new(e_win_evas_get(fwin->win), "toolbar",
603                                    fwin->win, page->fm_obj);
604         e_toolbar_show(page->tbar);
605      }
606
607    page->index = eina_list_count(fwin->pages);
608
609    _e_fwin_config_set(page);
610
611    page->fm_op_entry_add_handler =
612      ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_ADD,
613                              _e_fwin_op_registry_entry_add_cb, page);
614    _e_fwin_op_registry_entry_iter(page);
615    return page;
616 }
617
618 static void
619 _e_fwin_page_free(E_Fwin_Page *page)
620 {
621    if (page->fm_obj) evas_object_del(page->fm_obj);
622    if (page->tbar) e_object_del(E_OBJECT(page->tbar));
623    if (page->scrollframe_obj) evas_object_del(page->scrollframe_obj);
624
625    if (page->fm_op_entry_add_handler)
626      ecore_event_handler_del(page->fm_op_entry_add_handler);
627
628    E_FREE(page);
629 }
630
631 static void
632 _e_fwin_page_new(E_Fwin *fwin)
633 {
634    E_Fwin_Page *page;
635    const char *real;
636    const char *dev, *path;
637
638    if (!fwin->tb_obj)
639      {
640         page = fwin->pages->data;
641
642         /* There is no toolbar yet */
643         fwin->tb_obj = e_widget_toolbar_add(evas_object_evas_get(page->fm_obj),
644                                             48 * e_scale, 48 * e_scale);
645
646         e_widget_toolbar_focus_steal_set(fwin->tb_obj, 0);
647         real = ecore_file_file_get(e_fm2_real_path_get(page->fm_obj));
648         e_widget_toolbar_item_append(fwin->tb_obj, NULL, real,
649                                      _e_fwin_cb_page_change, fwin, page);
650
651         evas_object_move(fwin->tb_obj, 0, 0);
652         evas_object_show(fwin->tb_obj);
653      }
654
655    page = _e_fwin_page_create(fwin);
656    fwin->pages = eina_list_append(fwin->pages, page);
657    real = ecore_file_file_get(e_fm2_real_path_get(fwin->cur_page->fm_obj));
658    e_widget_toolbar_item_append(fwin->tb_obj, NULL, real,
659                                 _e_fwin_cb_page_change, fwin, page);
660    e_fm2_path_get(fwin->cur_page->fm_obj, &dev, &path);
661    e_fm2_path_set(page->fm_obj, dev, path);
662
663    e_widget_toolbar_item_select(fwin->tb_obj, page->index);
664    _e_fwin_cb_resize(fwin->win);
665 }
666
667 static void
668 _e_fwin_cb_page_change(void *data1,
669                        void *data2)
670 {
671    E_Fwin *fwin = data1;
672    E_Fwin_Page *page = data2, *prev;
673
674    if ((!fwin) || (!page)) return;
675    prev = eina_list_nth(fwin->pages, fwin->page_index);
676    fwin->page_index = page->index;
677
678    if (prev)
679      {
680         evas_object_hide(prev->scrollframe_obj);
681         if (prev->tbar)
682           e_toolbar_hide(prev->tbar);
683      }
684
685    evas_object_show(page->scrollframe_obj);
686    if (page->tbar)
687      e_toolbar_show(page->tbar);
688
689    fwin->cur_page = page;
690    evas_object_focus_set(page->fm_obj, 1);
691 }
692
693 static const char *
694 _e_fwin_custom_file_path_eval(E_Fwin         *fwin,
695                               Efreet_Desktop *ef,
696                               const char     *prev_path,
697                               const char     *key)
698 {
699    char buf[PATH_MAX];
700    const char *res, *ret = NULL;
701
702    /* get a X-something custom tage from the .desktop for the dir */
703    res = eina_hash_find(ef->x, key);
704    /* free the old path */
705    if (prev_path) eina_stringshare_del(prev_path);
706    /* if there was no key found - return NULL */
707    if (!res) return NULL;
708
709    /* it's a full path */
710    if (res[0] == '/')
711      ret = eina_stringshare_add(res);
712    /* relative path to the dir */
713    else
714      {
715         snprintf(buf, sizeof(buf), "%s/%s",
716                  e_fm2_real_path_get(fwin->cur_page->fm_obj), res);
717         ret = eina_stringshare_add(buf);
718      }
719    return ret;
720 }
721
722 static Eina_List *
723 _e_fwin_suggested_apps_list_get(Eina_List  *files,
724                                 Eina_List **mime_list)
725 {
726    E_Fm2_Icon_Info *ici;
727    const char *f = NULL;
728    char *mime;
729    Eina_Hash *mimes = NULL;
730    Eina_List *mlist = NULL, *apps = NULL, *ret = NULL, *l;
731    Efreet_Desktop *desk = NULL;
732
733    /* 1. build hash of mimetypes */
734    EINA_LIST_FOREACH(files, l, ici)
735      if (!((ici->link) && (ici->mount)))
736        {
737           if (_e_fwin_file_is_exec(ici) == E_FWIN_EXEC_NONE)
738             {
739                if (ici->link)
740                  f = efreet_mime_globs_type_get(ici->link);
741                if (!mimes)
742                  mimes = eina_hash_string_superfast_new(NULL);
743                eina_hash_del(mimes, ici->link ? f : ici->mime, (void *)1);
744                eina_hash_direct_add(mimes, ici->link ? f : ici->mime, (void *)1);
745             }
746        }
747    if (!mimes) return NULL;
748
749    /* 2. add apps to a list so its a unique app list */
750    eina_hash_foreach(mimes, _e_fwin_cb_hash_foreach, &mlist);
751    eina_hash_free(mimes);
752
753    /* 3. for each mimetype list apps that handle it */
754    EINA_LIST_FOREACH(mlist, l, mime)
755      apps = eina_list_merge(apps, efreet_util_desktop_mime_list(mime));
756
757    /* 4. create a new list without duplicates */
758    EINA_LIST_FREE(apps, desk)
759      {
760         if (!eina_list_data_find(ret, desk))
761           ret = eina_list_append(ret, desk);
762         else
763           efreet_desktop_free(desk);
764      }
765
766    if (mime_list)
767      *mime_list = mlist;
768    else
769    if (mlist)
770      mlist = eina_list_free(mlist);
771
772    return ret;
773 }
774
775 static void
776 _e_fwin_desktop_run(Efreet_Desktop *desktop,
777                     E_Fwin_Page    *page,
778                     Eina_Bool       skip_history)
779 {
780    char pcwd[4096], buf[4096];
781    Eina_List *selected, *l, *files = NULL;
782    E_Fwin *fwin = page->fwin;
783    E_Fm2_Icon_Info *ici;
784    char *file;
785
786    selected = e_fm2_selected_list_get(page->fm_obj);
787    if (!selected) return;
788
789    getcwd(pcwd, sizeof(pcwd));
790    chdir(e_fm2_real_path_get(page->fm_obj));
791
792    EINA_LIST_FOREACH(selected, l, ici)
793      {
794         E_Fwin_Exec_Type ext;
795
796         /* this snprintf is silly - but it's here in case i really do
797          * need to provide full paths (seems silly since we chdir
798          * into the dir)
799          */
800         buf[0] = 0;
801         ext = _e_fwin_file_is_exec(ici);
802         if (ext == E_FWIN_EXEC_NONE)
803           {
804              if (!((ici->link) && (ici->mount)))
805                eina_strlcpy(buf, ici->file, sizeof(buf));
806           }
807         else
808           _e_fwin_file_exec(page, ici, ext);
809         if (buf[0] != 0)
810           {
811              if ((ici->mime) && (desktop) && !(skip_history))
812                e_exehist_mime_desktop_add(ici->mime, desktop);
813              files = eina_list_append(files, strdup(ici->file));
814           }
815      }
816    eina_list_free(selected);
817
818    if ((fwin->win) && (desktop))
819      e_exec(fwin->win->border->zone, desktop, NULL, files, "fwin");
820    else if (fwin->zone && desktop)
821      e_exec(fwin->zone, desktop, NULL, files, "fwin");
822
823    EINA_LIST_FREE(files, file)
824      free(file);
825
826    chdir(pcwd);
827 }
828
829 static Eina_Bool
830 _e_fwin_cb_hash_foreach(const Eina_Hash *hash __UNUSED__,
831                         const void           *key,
832                         void *data            __UNUSED__,
833                         void                 *fdata)
834 {
835    Eina_List **mlist;
836
837    mlist = fdata;
838    *mlist = eina_list_append(*mlist, key);
839    return 1;
840 }
841
842 static E_Fwin_Exec_Type
843 _e_fwin_file_is_exec(E_Fm2_Icon_Info *ici)
844 {
845    /* special file or dir - can't exec anyway */
846     if ((S_ISCHR(ici->statinfo.st_mode)) ||
847         (S_ISBLK(ici->statinfo.st_mode)) ||
848         (S_ISFIFO(ici->statinfo.st_mode)) ||
849         (S_ISSOCK(ici->statinfo.st_mode)))
850       return E_FWIN_EXEC_NONE;
851     /* it is executable */
852     if ((ici->statinfo.st_mode & S_IXOTH) ||
853         ((getgid() == ici->statinfo.st_gid) &&
854          (ici->statinfo.st_mode & S_IXGRP)) ||
855         ((getuid() == ici->statinfo.st_uid) &&
856          (ici->statinfo.st_mode & S_IXUSR)))
857       {
858          /* no mimetype */
859           if (!ici->mime)
860             return E_FWIN_EXEC_DIRECT;
861           /* mimetype */
862           else
863             {
864      /* FIXME: - this could be config */
865                 if (!strcmp(ici->mime, "application/x-desktop"))
866                   return E_FWIN_EXEC_DESKTOP;
867                 else if ((!strcmp(ici->mime, "application/x-sh")) ||
868                          (!strcmp(ici->mime, "application/x-shellscript")) ||
869                          (!strcmp(ici->mime, "application/x-csh")) ||
870                          (!strcmp(ici->mime, "application/x-perl")) ||
871                          (!strcmp(ici->mime, "application/x-shar")) ||
872                          (!strcmp(ici->mime, "text/x-csh")) ||
873                          (!strcmp(ici->mime, "text/x-python")) ||
874                          (!strcmp(ici->mime, "text/x-sh"))
875                          )
876                   {
877                      return E_FWIN_EXEC_DIRECT;
878                   }
879             }
880       }
881     else
882       {
883          /* mimetype */
884           if (ici->mime)
885             {
886      /* FIXME: - this could be config */
887                 if (!strcmp(ici->mime, "application/x-desktop"))
888                   return E_FWIN_EXEC_DESKTOP;
889                 else if ((!strcmp(ici->mime, "application/x-sh")) ||
890                          (!strcmp(ici->mime, "application/x-shellscript")) ||
891                          (!strcmp(ici->mime, "text/x-sh"))
892                          )
893                   {
894                      return E_FWIN_EXEC_TERMINAL_SH;
895                   }
896             }
897           else if ((e_util_glob_match(ici->file, "*.desktop")) ||
898                    (e_util_glob_match(ici->file, "*.kdelink"))
899                    )
900             {
901                return E_FWIN_EXEC_DESKTOP;
902             }
903           else if (e_util_glob_match(ici->file, "*.run"))
904             return E_FWIN_EXEC_TERMINAL_SH;
905       }
906     return E_FWIN_EXEC_NONE;
907 }
908
909 static void
910 _e_fwin_file_exec(E_Fwin_Page     *page,
911                   E_Fm2_Icon_Info *ici,
912                   E_Fwin_Exec_Type ext)
913 {
914    E_Fwin *fwin = page->fwin;
915    char buf[4096];
916    Efreet_Desktop *desktop;
917
918    /* FIXME: execute file ici with either a terminal, the shell, or directly
919     * or open the .desktop and exec it */
920    switch (ext)
921      {
922       case E_FWIN_EXEC_NONE:
923         break;
924
925       case E_FWIN_EXEC_DIRECT:
926         if (fwin->win)
927           e_exec(fwin->win->border->zone, NULL, ici->file, NULL, "fwin");
928         else if (fwin->zone)
929           e_exec(fwin->zone, NULL, ici->file, NULL, "fwin");
930         break;
931
932       case E_FWIN_EXEC_SH:
933         snprintf(buf, sizeof(buf), "/bin/sh %s", e_util_filename_escape(ici->file));
934         if (fwin->win)
935           e_exec(fwin->win->border->zone, NULL, buf, NULL, NULL);
936         else if (fwin->zone)
937           e_exec(fwin->zone, NULL, buf, NULL, NULL);
938         break;
939
940       case E_FWIN_EXEC_TERMINAL_DIRECT:
941         snprintf(buf, sizeof(buf), "%s %s", e_config->exebuf_term_cmd, e_util_filename_escape(ici->file));
942         if (fwin->win)
943           e_exec(fwin->win->border->zone, NULL, buf, NULL, NULL);
944         else if (fwin->zone)
945           e_exec(fwin->zone, NULL, buf, NULL, NULL);
946         break;
947
948       case E_FWIN_EXEC_TERMINAL_SH:
949         snprintf(buf, sizeof(buf), "%s /bin/sh %s", e_config->exebuf_term_cmd, e_util_filename_escape(ici->file));
950         if (fwin->win)
951           e_exec(fwin->win->border->zone, NULL, buf, NULL, NULL);
952         else if (fwin->zone)
953           e_exec(fwin->zone, NULL, buf, NULL, NULL);
954         break;
955
956       case E_FWIN_EXEC_DESKTOP:
957         snprintf(buf, sizeof(buf), "%s/%s", e_fm2_real_path_get(page->fm_obj), ici->file);
958         desktop = efreet_desktop_new(buf);
959         if (desktop)
960           {
961              if (fwin->win)
962                e_exec(fwin->win->border->zone, desktop, NULL, NULL, NULL);
963              else if (fwin->zone)
964                e_exec(fwin->zone, desktop, NULL, NULL, NULL);
965              efreet_desktop_free(desktop);
966           }
967         break;
968
969       default:
970         break;
971      }
972 }
973
974 static void
975 _e_fwin_config_set(E_Fwin_Page *page)
976 {
977    E_Fm2_Config fmc;
978
979    memset(&fmc, 0, sizeof(E_Fm2_Config));
980    if (!page->fwin->zone)
981      {
982 #if 0
983         fmc.view.mode = E_FM2_VIEW_MODE_LIST;
984         fmc.icon.list.w = 24 * e_scale;
985         fmc.icon.list.h = 24 * e_scale;
986         fmc.icon.fixed.w = 1;
987         fmc.icon.fixed.h = 1;
988 #else
989         fmc.view.mode = fileman_config->view.mode;
990         fmc.icon.icon.w = fileman_config->icon.icon.w * e_scale;
991         fmc.icon.icon.h = fileman_config->icon.icon.h * e_scale;
992         fmc.icon.fixed.w = 0;
993         fmc.icon.fixed.h = 0;
994 #endif
995         fmc.view.open_dirs_in_place = fileman_config->view.open_dirs_in_place;
996      }
997    else
998      {
999 #if 0
1000         fmc.view.mode = E_FM2_VIEW_MODE_LIST;
1001         fmc.icon.list.w = 24 * e_scale;
1002         fmc.icon.list.h = 24 * e_scale;
1003         fmc.icon.fixed.w = 1;
1004         fmc.icon.fixed.h = 1;
1005 #else
1006         fmc.view.mode = E_FM2_VIEW_MODE_CUSTOM_ICONS;
1007         fmc.icon.icon.w = fileman_config->icon.icon.w * e_scale;
1008         fmc.icon.icon.h = fileman_config->icon.icon.h * e_scale;
1009         fmc.icon.fixed.w = 0;
1010         fmc.icon.fixed.h = 0;
1011 #endif
1012
1013         fmc.view.open_dirs_in_place = 0;
1014         fmc.view.fit_custom_pos = 1;
1015      }
1016
1017    fmc.view.selector = 0;
1018    fmc.view.single_click = fileman_config->view.single_click;
1019    fmc.view.no_subdir_jump = 0;
1020    fmc.icon.extension.show = fileman_config->icon.extension.show;
1021    fmc.list.sort.no_case = fileman_config->list.sort.no_case;
1022    fmc.list.sort.dirs.first = fileman_config->list.sort.dirs.first;
1023    fmc.list.sort.dirs.last = fileman_config->list.sort.dirs.last;
1024    fmc.selection.single = fileman_config->selection.single;
1025    fmc.selection.windows_modifiers = fileman_config->selection.windows_modifiers;
1026    e_fm2_config_set(page->fm_obj, &fmc);
1027 }
1028
1029 static void
1030 _e_fwin_window_title_set(E_Fwin_Page *page)
1031 {
1032    char buf[4096];
1033    const char *file;
1034
1035    if (!page) return;
1036    if (page->fwin->zone) return;  //safety
1037
1038    if (fileman_config->view.show_full_path)
1039      file = e_fm2_real_path_get(page->fm_obj);
1040    else
1041      file = ecore_file_file_get(e_fm2_real_path_get(page->fm_obj));
1042
1043    if (file)
1044      {
1045         eina_strlcpy(buf, file, sizeof(buf));
1046         e_win_title_set(page->fwin->win, buf);
1047      }
1048 }
1049
1050 static void
1051 _e_fwin_page_resize(E_Fwin_Page *page)
1052 {
1053    if (page->tbar)
1054      _e_fwin_toolbar_resize(page);
1055    else
1056      {
1057         int offset = 0;
1058
1059         if (page->fwin->tb_obj)
1060           evas_object_geometry_get(page->fwin->tb_obj, NULL, NULL, NULL, &offset);
1061         evas_object_move(page->scrollframe_obj, 0, offset);
1062         evas_object_resize(page->scrollframe_obj, page->fwin->win->w, page->fwin->win->h - offset);
1063      }
1064 }
1065
1066 static void
1067 _e_fwin_toolbar_resize(E_Fwin_Page *page)
1068 {
1069    int tx, ty, tw, th, offset = 0;
1070    int x, y, w, h;
1071
1072    if (page->fwin->tb_obj)
1073      evas_object_geometry_get(page->fwin->tb_obj, NULL, NULL, NULL, &offset);
1074    w = page->fwin->win->w;
1075    h = page->fwin->win->h;
1076    switch (page->tbar->gadcon->orient)
1077      {
1078       case E_GADCON_ORIENT_HORIZ:
1079       case E_GADCON_ORIENT_TOP:
1080         tx = 0;
1081         ty = offset;
1082         th = 32;
1083         tw = w;
1084
1085         x = 0;
1086         y = offset + th;
1087         h = (h - offset - th);
1088         break;
1089
1090       case E_GADCON_ORIENT_BOTTOM:
1091         tx = 0;
1092         th = 32;
1093         tw = w;
1094         ty = h - th;
1095
1096         x = 0;
1097         y = offset;
1098         h = (h - offset - th);
1099         break;
1100
1101       case E_GADCON_ORIENT_VERT:
1102       case E_GADCON_ORIENT_LEFT:
1103         tx = 0;
1104         tw = 32;
1105         th = h - offset;
1106         ty = offset;
1107
1108         x = tw;
1109         y = offset;
1110         w = (w - tw);
1111         break;
1112
1113       case E_GADCON_ORIENT_RIGHT:
1114         ty = offset;
1115         tw = 32;
1116         tx = w - tw;
1117         th = h - offset;
1118
1119         x = 0;
1120         y = offset;
1121         w = (w - tw);
1122         break;
1123
1124       default:
1125         return;
1126      }
1127    e_toolbar_move_resize(page->tbar, tx, ty, tw, th);
1128    evas_object_move(page->scrollframe_obj, x, y);
1129    evas_object_resize(page->scrollframe_obj, w, h);
1130 }
1131
1132 /* fwin callbacks */
1133 static void
1134 _e_fwin_cb_delete(E_Win *win)
1135 {
1136    E_Fwin *fwin;
1137
1138    if (!win) return;  //safety
1139    fwin = win->data;
1140    e_object_del(E_OBJECT(fwin));
1141 }
1142
1143 /* static void
1144  * _e_fwin_geom_save(E_Fwin *fwin)
1145  * {
1146  *    char buf[PATH_MAX];
1147  *    E_Fm2_Custom_File *cf;
1148  *
1149  *    if (!fwin->geom_save_ready) return;
1150  *    snprintf(buf, sizeof(buf), "dir::%s", e_fm2_real_path_get(fwin->cur_page->fm_obj));
1151  *    cf = e_fm2_custom_file_get(buf);
1152  *    if (!cf)
1153  *      {
1154  *  cf = alloca(sizeof(E_Fm2_Custom_File));
1155  *  memset(cf, 0, sizeof(E_Fm2_Custom_File));
1156  *      }
1157  *    cf->geom.x = fwin->win->x;
1158  *    cf->geom.y = fwin->win->y;
1159  *    cf->geom.w = fwin->win->w;
1160  *    cf->geom.h = fwin->win->h;
1161  *    cf->geom.valid = 1;
1162  *    e_fm2_custom_file_set(buf, cf);
1163  * } */
1164
1165 static void
1166 _e_fwin_cb_move(E_Win *win)
1167 {
1168    E_Fwin *fwin;
1169
1170    if (!win) return;  //safety
1171    fwin = win->data;
1172    /* _e_fwin_geom_save(fwin); */
1173 }
1174
1175 static void
1176 _e_fwin_cb_resize(E_Win *win)
1177 {
1178    E_Fwin *fwin;
1179
1180    if (!win) return;  //safety
1181    fwin = win->data;
1182    if (fwin->bg_obj)
1183      {
1184         if (fwin->win)
1185           evas_object_resize(fwin->bg_obj, fwin->win->w, fwin->win->h);
1186         else if (fwin->zone)
1187           evas_object_resize(fwin->bg_obj, fwin->zone->w, fwin->zone->h);
1188      }
1189    if (fwin->win)
1190      {
1191         E_Fwin_Page *page;
1192         Eina_List *l;
1193
1194         if (fwin->tb_obj)
1195           {
1196              int height;
1197
1198              e_widget_size_min_get(fwin->tb_obj, NULL, &height);
1199              evas_object_resize(fwin->tb_obj, fwin->win->w, height);
1200           }
1201         EINA_LIST_FOREACH(fwin->pages, l, page)
1202           _e_fwin_page_resize(page);
1203      }
1204    else if (fwin->zone)
1205      evas_object_resize(fwin->cur_page->scrollframe_obj, fwin->zone->w, fwin->zone->h);
1206    /* _e_fwin_geom_save(fwin); */
1207 }
1208
1209 static void
1210 _e_fwin_deleted(void            *data,
1211                 Evas_Object *obj __UNUSED__,
1212                 void *event_info __UNUSED__)
1213 {
1214    E_Fwin_Page *page;
1215
1216    page = data;
1217    e_object_del(E_OBJECT(page->fwin));
1218 }
1219
1220 static void
1221 _e_fwin_changed(void            *data,
1222                 Evas_Object     *obj,
1223                 void *event_info __UNUSED__)
1224 {
1225    E_Fwin *fwin;
1226    E_Fwin_Page *page;
1227    Efreet_Desktop *ef;
1228    char buf[PATH_MAX], *ext;
1229
1230    page = data;
1231    fwin = page->fwin;
1232    if (!fwin) return;  //safety
1233
1234    /* FIXME: first look in E config for a special override for this dir's bg
1235     * or overlay
1236     */
1237    snprintf(buf, sizeof(buf), "%s/.directory.desktop", e_fm2_real_path_get(page->fm_obj));
1238    ef = efreet_desktop_new(buf);
1239    if (ef)
1240      {
1241         fwin->wallpaper_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->wallpaper_file, "X-Enlightenment-Directory-Wallpaper");
1242         fwin->overlay_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->overlay_file, "X-Enlightenment-Directory-Overlay");
1243         fwin->scrollframe_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->scrollframe_file, "X-Enlightenment-Directory-Scrollframe");
1244         fwin->theme_file = _e_fwin_custom_file_path_eval(fwin, ef, fwin->theme_file, "X-Enlightenment-Directory-Theme");
1245         efreet_desktop_free(ef);
1246      }
1247    else
1248      {
1249 #define RELEASE_STR(x) if (x) {eina_stringshare_del(x); (x) = NULL;}
1250         RELEASE_STR(fwin->wallpaper_file);
1251         RELEASE_STR(fwin->overlay_file);
1252         RELEASE_STR(fwin->scrollframe_file);
1253         RELEASE_STR(fwin->theme_file);
1254 #undef RELEASE_STR
1255      }
1256    if (fwin->under_obj)
1257      {
1258         evas_object_hide(fwin->under_obj);
1259         if (fwin->wallpaper_file)
1260           {
1261              ext = strrchr(fwin->wallpaper_file, '.');
1262              if (ext && !strcasecmp(ext, ".edj"))
1263                e_icon_file_edje_set(fwin->under_obj, fwin->wallpaper_file, "e/desktop/background");
1264              else
1265                e_icon_file_set(fwin->under_obj, fwin->wallpaper_file);
1266           }
1267         else
1268           e_icon_file_edje_set(fwin->under_obj, NULL, NULL);
1269         evas_object_show(fwin->under_obj);
1270      }
1271    if (fwin->over_obj)
1272      {
1273         evas_object_hide(fwin->over_obj);
1274         if (fwin->overlay_file)
1275           {
1276              ext = strrchr(fwin->overlay_file, '.');
1277              if (ext && !strcasecmp(ext, ".edj"))
1278                e_icon_file_edje_set(fwin->over_obj, fwin->overlay_file, "e/desktop/background");
1279              else
1280                e_icon_file_set(fwin->over_obj, fwin->overlay_file);
1281           }
1282         else
1283           e_icon_file_edje_set(fwin->over_obj, NULL, NULL);
1284         evas_object_show(fwin->over_obj);
1285      }
1286    if (page->scrollframe_obj)
1287      {
1288         if ((fwin->scrollframe_file) &&
1289             (e_util_edje_collection_exists(fwin->scrollframe_file, "e/fileman/default/scrollframe")))
1290           e_scrollframe_custom_edje_file_set(page->scrollframe_obj,
1291                                              (char *)fwin->scrollframe_file,
1292                                              "e/fileman/default/scrollframe");
1293         else
1294           {
1295              if (fwin->zone)
1296                e_scrollframe_custom_theme_set(page->scrollframe_obj,
1297                                               "base/theme/fileman",
1298                                               "e/fileman/desktop/scrollframe");
1299              else
1300                e_scrollframe_custom_theme_set(page->scrollframe_obj,
1301                                               "base/theme/fileman",
1302                                               "e/fileman/default/scrollframe");
1303           }
1304         e_scrollframe_child_pos_set(page->scrollframe_obj, 0, 0);
1305      }
1306    if (fwin->tb_obj)
1307      {
1308         const char *file;
1309
1310         file = ecore_file_file_get(e_fm2_real_path_get(page->fm_obj));
1311         e_widget_toolbar_item_label_set(fwin->tb_obj, fwin->page_index, file);
1312      }
1313    if ((fwin->theme_file) && (ecore_file_exists(fwin->theme_file)))
1314      e_fm2_custom_theme_set(obj, fwin->theme_file);
1315    else
1316      e_fm2_custom_theme_set(obj, NULL);
1317
1318    if (fwin->zone) return;
1319    _e_fwin_window_title_set(page);
1320 }
1321
1322 static void
1323 _e_fwin_selected(void            *data,
1324                  Evas_Object *obj __UNUSED__,
1325                  void *event_info __UNUSED__)
1326 {
1327    E_Fwin_Page *page;
1328    Eina_List *selected;
1329
1330    page = data;
1331    selected = e_fm2_selected_list_get(page->fm_obj);
1332    if (!selected) return;
1333    _e_fwin_file_open_dialog(page, selected, 0);
1334    eina_list_free(selected);
1335 }
1336
1337 static void
1338 _e_fwin_selection_change(void            *data,
1339                          Evas_Object *obj __UNUSED__,
1340                          void *event_info __UNUSED__)
1341 {
1342    Eina_List *l;
1343    E_Fwin_Page *page;
1344
1345    page = data;
1346    for (l = fwins; l; l = l->next)
1347      {
1348         if (l->data != page->fwin)
1349           e_fwin_all_unsel(l->data);
1350      }
1351 }
1352
1353 static void
1354 _e_fwin_cb_all_change(void            *data,
1355                       Evas_Object *obj __UNUSED__)
1356 {
1357    E_Fwin_Apps_Dialog *fad;
1358    Efreet_Desktop *desktop = NULL;
1359
1360    fad = data;
1361    desktop = efreet_util_desktop_file_id_find(fad->app2);
1362    if ((desktop) && (desktop->exec))
1363      e_widget_entry_text_set(fad->o_entry, desktop->exec);
1364    if (desktop)
1365      efreet_desktop_free(desktop);
1366 }
1367
1368 static void
1369 _e_fwin_cb_key_down(void            *data,
1370                     Evas *e          __UNUSED__,
1371                     Evas_Object *obj __UNUSED__,
1372                     void            *event_info)
1373 {
1374    Evas_Event_Key_Down *ev;
1375    E_Fwin *fwin;
1376    E_Fwin_Page *page;
1377
1378    page = data;
1379    fwin = page->fwin;
1380    ev = event_info;
1381
1382    if (evas_key_modifier_is_set(ev->modifiers, "Control"))
1383      {
1384         if (!strcmp(ev->key, "n"))
1385           {
1386              E_Container *con;
1387              const char *dev, *path;
1388
1389              con = e_container_current_get(e_manager_current_get());
1390              e_fm2_path_get(page->fm_obj, &dev, &path);
1391              e_fwin_new(con, dev, path);
1392              return;
1393           }
1394         if (!strcmp(ev->key, "w"))
1395           {
1396              int count = eina_list_count(fwin->pages);
1397              E_Fwin_Page *page;
1398
1399              if (count > 2)
1400                {
1401                   Eina_List *l;
1402                   int i = 0;
1403
1404                   page = fwin->cur_page;
1405                   if (fwin->page_index > 0)
1406                     {
1407                        if (fwin->tb_obj)
1408                          e_widget_toolbar_item_select(fwin->tb_obj,
1409                                                       fwin->page_index - 1);
1410                     }
1411                   else
1412                     {
1413                        if (fwin->tb_obj)
1414                          e_widget_toolbar_item_select(fwin->tb_obj, 1);
1415                     }
1416                   if (fwin->tb_obj)
1417                     e_widget_toolbar_item_remove(fwin->tb_obj, page->index);
1418                   fwin->pages = eina_list_remove(fwin->pages, page);
1419                   _e_fwin_page_free(page);
1420                   EINA_LIST_FOREACH(fwin->pages, l, page)
1421                     page->index = i++;
1422                }
1423              else if (count > 1)
1424                {
1425                   if (fwin->tb_obj)
1426                     evas_object_del(fwin->tb_obj);
1427                   fwin->tb_obj = NULL;
1428                   fwin->page_index = 0;
1429                   fwin->pages = eina_list_remove(fwin->pages, fwin->cur_page);
1430                   _e_fwin_page_free(fwin->cur_page);
1431                   page = fwin->pages->data;
1432                   page->index = 0;
1433                   _e_fwin_cb_page_change(fwin, page);
1434                   _e_fwin_cb_resize(fwin->win);
1435                }
1436              else
1437                e_object_del(E_OBJECT(fwin));
1438              return;
1439           }
1440         if (!strcmp(ev->key, "a"))
1441           {
1442              e_fm2_all_sel(page->fm_obj);
1443              return;
1444           }
1445         if (!strcmp(ev->key, "t"))
1446           {
1447              _e_fwin_page_new(fwin);
1448              return;
1449           }
1450         if (!strcmp(ev->key, "Tab"))
1451           {
1452              Eina_List *l;
1453
1454              if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1455                {
1456                   l = eina_list_nth_list(fwin->pages, fwin->page_index);
1457                   if (l->prev)
1458                     {
1459                        if (fwin->tb_obj)
1460                          e_widget_toolbar_item_select(fwin->tb_obj,
1461                                                       fwin->page_index - 1);
1462                     }
1463                   else
1464                     {
1465                        if (fwin->tb_obj)
1466                          e_widget_toolbar_item_select(fwin->tb_obj,
1467                                                       eina_list_count(fwin->pages) - 1);
1468                     }
1469                }
1470              else
1471                {
1472                   l = eina_list_nth_list(fwin->pages, fwin->page_index);
1473                   if (l->next)
1474                     {
1475                        if (fwin->tb_obj)
1476                          e_widget_toolbar_item_select(fwin->tb_obj,
1477                                                       fwin->page_index + 1);
1478                     }
1479                   else
1480                     {
1481                        if (fwin->tb_obj)
1482                          e_widget_toolbar_item_select(fwin->tb_obj, 0);
1483                     }
1484                }
1485              return;
1486           }
1487      }
1488 }
1489
1490 static void
1491 _e_fwin_cb_page_obj_del(void            *data,
1492                         Evas *evas       __UNUSED__,
1493                         Evas_Object *obj __UNUSED__,
1494                         void *event_info __UNUSED__)
1495 {
1496    E_Fwin_Page *page;
1497    
1498    page = data;
1499    printf("------ page obj del %p %p\n", page, page->fm_obj);
1500    evas_object_smart_callback_del(page->fm_obj, "dir_changed",
1501                                   _e_fwin_changed);
1502    evas_object_smart_callback_del(page->fm_obj, "dir_deleted",
1503                                   _e_fwin_deleted);
1504    evas_object_smart_callback_del(page->fm_obj, "selected",
1505                                   _e_fwin_selected);
1506    evas_object_smart_callback_del(page->fm_obj, "selection_change",
1507                                   _e_fwin_selection_change);
1508    evas_object_event_callback_del(page->fm_obj, EVAS_CALLBACK_DEL,
1509                                   _e_fwin_cb_page_obj_del);
1510 }
1511
1512 /* fwin zone callbacks */
1513 static void
1514 _e_fwin_zone_cb_mouse_down(void            *data,
1515                            Evas *evas       __UNUSED__,
1516                            Evas_Object *obj __UNUSED__,
1517                            void *event_info __UNUSED__)
1518 {
1519    E_Fwin *fwin;
1520
1521    fwin = data;
1522    if (!fwin) return;
1523    e_fwin_all_unsel(fwin);
1524 }
1525
1526 static Eina_Bool
1527 _e_fwin_zone_move_resize(void *data,
1528                          int   type,
1529                          void *event)
1530 {
1531    E_Event_Zone_Move_Resize *ev;
1532    E_Fwin *fwin;
1533
1534    if (type != E_EVENT_ZONE_MOVE_RESIZE) return ECORE_CALLBACK_PASS_ON;
1535    fwin = data;
1536    ev = event;
1537    if (!fwin) return ECORE_CALLBACK_PASS_ON;
1538    if (fwin->zone != ev->zone) return ECORE_CALLBACK_PASS_ON;
1539    if (fwin->bg_obj)
1540      {
1541         evas_object_move(fwin->bg_obj, ev->zone->x, ev->zone->y);
1542         evas_object_resize(fwin->bg_obj, ev->zone->w, ev->zone->h);
1543      }
1544    if (fwin->cur_page->scrollframe_obj)
1545      {
1546         int x, y, w, h;
1547         e_zone_useful_geometry_get(ev->zone, &x, &y, &w, &h);
1548         evas_object_move(fwin->cur_page->scrollframe_obj, x, y);
1549         evas_object_resize(fwin->cur_page->scrollframe_obj, w, h);
1550      }
1551    return ECORE_CALLBACK_PASS_ON;
1552 }
1553
1554 static Eina_Bool
1555 _e_fwin_zone_del(void *data,
1556                  int   type,
1557                  void *event)
1558 {
1559    E_Event_Zone_Del *ev;
1560    E_Fwin *fwin;
1561
1562    if (type != E_EVENT_ZONE_DEL) return ECORE_CALLBACK_PASS_ON;
1563    fwin = data;
1564    ev = event;
1565    if (!fwin) return ECORE_CALLBACK_PASS_ON;
1566    if (fwin->zone != ev->zone) return ECORE_CALLBACK_PASS_ON;
1567    e_object_del(E_OBJECT(fwin));
1568    return ECORE_CALLBACK_PASS_ON;
1569 }
1570
1571 /* fm menu extend */
1572 static void
1573 _e_fwin_menu_extend(void                 *data,
1574                     Evas_Object          *obj,
1575                     E_Menu               *m,
1576                     E_Fm2_Icon_Info *info __UNUSED__)
1577 {
1578    E_Fwin_Page *page;
1579    E_Menu_Item *mi;
1580
1581    page = data;
1582    if (e_fm2_has_parent_get(obj))
1583      {
1584         mi = e_menu_item_new(m);
1585         e_menu_item_separator_set(mi, 1);
1586
1587         mi = e_menu_item_new(m);
1588         e_menu_item_label_set(mi, _("Go to Parent Directory"));
1589         e_menu_item_icon_edje_set(mi,
1590                                   e_theme_edje_file_get("base/theme/fileman",
1591                                                         "e/fileman/default/button/parent"),
1592                                   "e/fileman/default/button/parent");
1593         e_menu_item_callback_set(mi, _e_fwin_parent, obj);
1594      }
1595    /* FIXME: if info != null then check mime type and offer options based
1596     * on that
1597     */
1598 }
1599
1600 static void
1601 _e_fwin_parent(void           *data,
1602                E_Menu *m       __UNUSED__,
1603                E_Menu_Item *mi __UNUSED__)
1604 {
1605    e_fm2_parent_go(data);
1606 }
1607
1608 static void
1609 _e_fwin_cb_menu_open_fast(void        *data,
1610                           E_Menu *m    __UNUSED__,
1611                           E_Menu_Item *mi)
1612 {
1613    E_Fwin_Page *page;
1614    Efreet_Desktop *desk;
1615
1616    page = data;
1617    desk = e_object_data_get(E_OBJECT(mi));
1618
1619    if ((page) && (desk))
1620      _e_fwin_desktop_run(desk, page, EINA_TRUE);
1621 }
1622
1623 static void
1624 _e_fwin_cb_menu_extend_open_with(void   *data,
1625                                  E_Menu *m)
1626 {
1627    Eina_List *selected = NULL, *apps = NULL, *l;
1628    E_Menu_Item *mi;
1629    E_Fwin_Page *page;
1630    Efreet_Desktop *desk = NULL;
1631
1632    page = data;
1633
1634    selected = e_fm2_selected_list_get(page->fm_obj);
1635    if (!selected) return;
1636
1637    apps = _e_fwin_suggested_apps_list_get(selected, NULL);
1638    EINA_LIST_FOREACH(apps, l, desk)
1639      {
1640         if (!desk) continue;
1641         mi = e_menu_item_new(m);
1642         e_menu_item_label_set(mi, desk->name);
1643         e_util_desktop_menu_item_icon_add(desk, 24, mi);
1644         e_menu_item_callback_set(mi, _e_fwin_cb_menu_open_fast, page);
1645         e_object_data_set(E_OBJECT(mi), desk);
1646      }
1647
1648    if (apps)
1649      {
1650         mi = e_menu_item_new(m);
1651         e_menu_item_separator_set(mi, 1);
1652      }
1653
1654    mi = e_menu_item_new(m);
1655    e_menu_item_label_set(mi, _("Other application..."));
1656    e_util_menu_item_theme_icon_set(mi, "document-open");
1657    e_menu_item_callback_set(mi, _e_fwin_cb_menu_open_with, page);
1658
1659    e_menu_pre_activate_callback_set(m, NULL, NULL);
1660
1661    eina_list_free(apps);
1662    eina_list_free(selected);
1663 }
1664
1665 static void
1666 _e_fwin_cb_menu_extend_start(void                 *data,
1667                              Evas_Object *obj      __UNUSED__,
1668                              E_Menu               *m,
1669                              E_Fm2_Icon_Info *info __UNUSED__)
1670 {
1671    E_Menu_Item *mi;
1672    E_Fwin_Page *page;
1673    E_Menu *subm;
1674
1675    page = data;
1676    mi = e_menu_item_new(m);
1677    e_menu_item_label_set(mi, _("Open"));
1678    e_util_menu_item_theme_icon_set(mi, "document-open");
1679    e_menu_item_callback_set(mi, _e_fwin_cb_menu_open, page);
1680
1681    mi = e_menu_item_new(m);
1682    e_menu_item_label_set(mi, _("Open with..."));
1683    e_util_menu_item_theme_icon_set(mi, "document-open");
1684
1685    subm = e_menu_new();
1686    e_menu_item_submenu_set(mi, subm);
1687    e_menu_pre_activate_callback_set(subm, _e_fwin_cb_menu_extend_open_with, page);
1688 }
1689
1690 static void
1691 _e_fwin_cb_menu_open(void           *data,
1692                      E_Menu *m       __UNUSED__,
1693                      E_Menu_Item *mi __UNUSED__)
1694 {
1695    E_Fwin_Page *page;
1696    Eina_List *selected;
1697
1698    page = data;
1699    selected = e_fm2_selected_list_get(page->fm_obj);
1700    if (!selected) return;
1701    _e_fwin_file_open_dialog(page, selected, 0);
1702    eina_list_free(selected);
1703 }
1704
1705 static void
1706 _e_fwin_cb_menu_open_with(void           *data,
1707                           E_Menu *m       __UNUSED__,
1708                           E_Menu_Item *mi __UNUSED__)
1709 {
1710    E_Fwin_Page *page;
1711    Eina_List *selected = NULL;
1712
1713    page = data;
1714    selected = e_fm2_selected_list_get(page->fm_obj);
1715    if (!selected) return;
1716    _e_fwin_file_open_dialog(page, selected, 1);
1717    eina_list_free(selected);
1718 }
1719
1720 /* 'open with' dialog*/
1721 static void
1722 _e_fwin_file_open_dialog(E_Fwin_Page *page,
1723                          Eina_List   *files,
1724                          int          always)
1725 {
1726    E_Fwin *fwin = page->fwin, *fwin2 = NULL;
1727    E_Dialog *dia;
1728    Evas_Coord mw, mh;
1729    Evas_Object *o, *of, *ot;
1730    Evas *evas;
1731    Eina_List *l = NULL, *apps = NULL, *mlist = NULL;
1732    Eina_List *cats = NULL;
1733    Efreet_Desktop *desk = NULL;
1734    E_Fwin_Apps_Dialog *fad;
1735    E_Fm2_Icon_Info *ici;
1736    char buf[PATH_MAX];
1737    int need_dia = 0;
1738
1739    if (fwin->fad)
1740      {
1741         e_object_del(E_OBJECT(fwin->fad->dia));
1742         fwin->fad = NULL;
1743      }
1744    if (!always)
1745      {
1746         EINA_LIST_FOREACH(files, l, ici)
1747           {
1748              if ((ici->link) && (ici->mount))
1749                {
1750                   if (!fileman_config->view.open_dirs_in_place || fwin->zone)
1751                     {
1752                        if (fwin->win)
1753                          fwin2 = _e_fwin_new(fwin->win->container, ici->link, "/");
1754                        else if (fwin->zone)
1755                          fwin2 = _e_fwin_new(fwin->zone->container, ici->link, "/");
1756                     }
1757                   else
1758                     {
1759                        e_fm2_path_set(page->fm_obj, ici->link, "/");
1760                        _e_fwin_window_title_set(page);
1761                     }
1762                }
1763              else if ((ici->link) && (ici->removable))
1764                {
1765                   snprintf(buf, sizeof(buf), "removable:%s", ici->link);
1766                   if (!fileman_config->view.open_dirs_in_place || fwin->zone)
1767                     {
1768                        if (fwin->win)
1769                          fwin2 = _e_fwin_new(fwin->win->container, buf, "/");
1770                        else if (fwin->zone)
1771                          fwin2 = _e_fwin_new(fwin->zone->container, buf, "/");
1772                     }
1773                   else
1774                     {
1775                        e_fm2_path_set(page->fm_obj, buf, "/");
1776                        _e_fwin_window_title_set(page);
1777                     }
1778                }
1779              else if (ici->real_link)
1780                {
1781                   if (S_ISDIR(ici->statinfo.st_mode))
1782                     {
1783                        if ((!fileman_config->view.open_dirs_in_place) || (fwin->zone))
1784                          {
1785                             if (fwin->win)
1786                               fwin2 = _e_fwin_new(fwin->win->container, NULL, ici->real_link);
1787                             else if (fwin->zone)
1788                               fwin2 = _e_fwin_new(fwin->zone->container, NULL, ici->real_link);
1789                          }
1790                        else
1791                          {
1792                             e_fm2_path_set(page->fm_obj, NULL, ici->real_link);
1793                             _e_fwin_window_title_set(page);
1794                          }
1795                     }
1796                   else
1797                     need_dia = 1;
1798                }
1799              else
1800                {
1801                   snprintf(buf, sizeof(buf), "%s/%s",
1802                            e_fm2_real_path_get(page->fm_obj), ici->file);
1803                   if (S_ISDIR(ici->statinfo.st_mode))
1804                     {
1805                        if ((!fileman_config->view.open_dirs_in_place) || (fwin->zone))
1806                          {
1807                             if (fwin->win)
1808                               fwin2 = _e_fwin_new(fwin->win->container, NULL, buf);
1809                             else if (fwin->zone)
1810                               fwin2 = _e_fwin_new(fwin->zone->container, NULL, buf);
1811                          }
1812                        else
1813                          {
1814                             e_fm2_path_set(page->fm_obj, NULL, buf);
1815                             _e_fwin_window_title_set(page);
1816                          }
1817                     }
1818                   else
1819                     need_dia = 1;
1820                }
1821              if (fwin2)
1822                {
1823                   if ((fwin2->win) && (fwin2->win->border))
1824                     {
1825                        Evas_Object *oic;
1826                        const char *itype = NULL;
1827                        int ix, iy, iw, ih, nx, ny, found = 0;
1828                        E_Remember *rem = NULL;
1829                        Eina_List *ll;
1830
1831                        oic = e_fm2_icon_get(evas_object_evas_get(page->fm_obj),
1832                                             ici->ic, NULL, NULL, 0, &itype);
1833                        if (oic)
1834                          {
1835                             const char *file = NULL, *group = NULL;
1836      /* E_Fm2_Custom_File *cf; */
1837
1838                             if (fwin2->win->border->internal_icon)
1839                               eina_stringshare_del(fwin2->win->border->internal_icon);
1840                             fwin2->win->border->internal_icon = NULL;
1841                             if (fwin2->win->border->internal_icon_key)
1842                               eina_stringshare_del(fwin2->win->border->internal_icon_key);
1843                             fwin2->win->border->internal_icon_key = NULL;
1844
1845                             if (!strcmp(evas_object_type_get(oic), "edje"))
1846                               {
1847                                  edje_object_file_get(oic, &file, &group);
1848                                  if (file)
1849                                    {
1850                                       fwin2->win->border->internal_icon =
1851                                         eina_stringshare_add(file);
1852                                       if (group)
1853                                         fwin2->win->border->internal_icon_key =
1854                                           eina_stringshare_add(group);
1855                                    }
1856                               }
1857                             else
1858                               {
1859                                  file = e_icon_file_get(oic);
1860                                  fwin2->win->border->internal_icon =
1861                                    eina_stringshare_add(file);
1862                               }
1863                             evas_object_del(oic);
1864
1865                             snprintf(buf, sizeof(buf), "e_fwin::%s", e_fm2_real_path_get(fwin2->cur_page->fm_obj));
1866                             EINA_LIST_FOREACH(e_config->remembers, ll, rem)
1867                               if (rem->class && !strcmp(rem->class, buf))
1868                                 {
1869                                    found = 1;
1870                                    break;
1871                                 }
1872
1873                             if (!found)
1874                               {
1875                                  int w, h, zw, zh;
1876
1877                                  e_zone_useful_geometry_get(fwin2->win->border->zone,
1878                                                             NULL, NULL, &zw, &zh);
1879
1880      /* No custom info, so just put window near icon */
1881                                  e_fm2_icon_geometry_get(ici->ic, &ix, &iy, &iw, &ih);
1882                                  nx = (ix + (iw / 2));
1883                                  ny = (iy + (ih / 2));
1884                                  if (fwin->win)
1885                                    {
1886                                       nx += fwin->win->x;
1887                                       ny += fwin->win->y;
1888                                    }
1889
1890      /* checking width and height */
1891                                  /* TODO add config for preffered
1892                                     initial size? */
1893                                  w = 5 * iw * e_scale;
1894                                  if (w > 400)
1895                                    w = 400;
1896                                  if (w > zw)
1897                                    w = zw;
1898
1899                                  h = 4 * ih * e_scale;
1900                                  if (h > 300)
1901                                    h = 300;
1902                                  if (h > zh)
1903                                    h = zh;
1904
1905      /* iff going out of zone - adjust to be in */
1906                                  if ((fwin2->win->border->zone->x + fwin2->win->border->zone->w) < (w + nx))
1907                                    nx -= w;
1908                                  if ((fwin2->win->border->zone->y + fwin2->win->border->zone->h) < (h + ny))
1909                                    ny -= h;
1910
1911                                  e_win_move_resize(fwin2->win, nx, ny, w, h);
1912                                  fwin2->win->border->placed = 1;
1913                               }
1914                          }
1915                        if (ici->label)
1916                          e_win_title_set(fwin2->win, ici->label);
1917                        else if (ici->file)
1918                          e_win_title_set(fwin2->win, ici->file);
1919                     }
1920                   fwin2 = NULL;
1921                }
1922           }
1923         if (!need_dia) return;
1924         need_dia = 0;
1925      }
1926
1927    apps = _e_fwin_suggested_apps_list_get(files, &mlist);
1928
1929    if (!always)
1930      {
1931         /* FIXME: well this is simplisitic - if only 1 mime type is being
1932          * opened then look for the previously used app for that mimetype and
1933          * if found, use that.
1934          *
1935          * we could get more sophisitcated.
1936          * 1. find apps for each mimetype in mlist. if all prev used apps are
1937          * the same, then use previously used app.
1938          * OR if this fails
1939          * 2. find all apps for each mimetype. find the one used the most.
1940          * if that app can handle all mimetypes in the list - use that. if not
1941          * find the next most often listed app - if that can handle all apps,
1942          * use it, if not fall back again - and so on - if all apps listed do
1943          * not contain 1 that handles all the mime types - fall back to dialog
1944          */
1945           if (eina_list_count(mlist) <= 1)
1946             {
1947                char *file;
1948                char pcwd[4096];
1949                Eina_List *files_list = NULL;
1950
1951                need_dia = 1;
1952                if (mlist) desk = e_exehist_mime_desktop_get(mlist->data);
1953                getcwd(pcwd, sizeof(pcwd));
1954                chdir(e_fm2_real_path_get(page->fm_obj));
1955
1956                files_list = NULL;
1957                EINA_LIST_FOREACH(files, l, ici)
1958                  if (_e_fwin_file_is_exec(ici) == E_FWIN_EXEC_NONE)
1959                    files_list = eina_list_append(files_list, strdup(ici->file));
1960                EINA_LIST_FOREACH(files, l, ici)
1961                  {
1962                     E_Fwin_Exec_Type ext;
1963
1964                     ext = _e_fwin_file_is_exec(ici);
1965                     if (ext != E_FWIN_EXEC_NONE)
1966                       {
1967                          _e_fwin_file_exec(page, ici, ext);
1968                          need_dia = 0;
1969                       }
1970                  }
1971                if (desk)
1972                  {
1973                     if (fwin->win)
1974                       {
1975                          if (e_exec(fwin->win->border->zone, desk, NULL, files_list, "fwin"))
1976                            need_dia = 0;
1977                       }
1978                     else if (fwin->zone)
1979                       {
1980                          if (e_exec(fwin->zone, desk, NULL, files_list, "fwin"))
1981                            need_dia = 0;
1982                       }
1983                  }
1984                EINA_LIST_FREE(files_list, file)
1985                  free(file);
1986
1987                chdir(pcwd);
1988                if (!need_dia)
1989                  {
1990                     apps = eina_list_free(apps);
1991                     mlist = eina_list_free(mlist);
1992                     return;
1993                  }
1994             }
1995      }
1996    mlist = eina_list_free(mlist);
1997
1998    fad = E_NEW(E_Fwin_Apps_Dialog, 1);
1999    if (fwin->win)
2000      dia = e_dialog_new(fwin->win->border->zone->container,
2001                         "E", "_fwin_open_apps");
2002    else if (fwin->zone)
2003      dia = e_dialog_new(fwin->zone->container,
2004                         "E", "_fwin_open_apps");
2005    else return;  /* make clang happy */
2006
2007    e_dialog_title_set(dia, _("Open with..."));
2008    e_dialog_resizable_set(dia, 1);
2009    e_dialog_button_add(dia, _("Open"), "document-open",
2010                        _e_fwin_cb_open, fad);
2011    e_dialog_button_add(dia, _("Close"), "window-close",
2012                        _e_fwin_cb_close, fad);
2013
2014    fad->dia = dia;
2015    fad->fwin = fwin;
2016    fwin->fad = fad;
2017    dia->data = fad;
2018    e_object_free_attach_func_set(E_OBJECT(dia), _e_fwin_cb_dialog_free);
2019
2020    evas = e_win_evas_get(dia->win);
2021
2022    ot = e_widget_table_add(evas, 0);
2023
2024    l = eina_list_free(l);
2025
2026    // Make frame with list of applications
2027    of = e_widget_framelist_add(evas, _("Known Applications"), 0);
2028    o = e_widget_ilist_add(evas, 24, 24, &(fad->app2));
2029    e_widget_on_change_hook_set(o, _e_fwin_cb_all_change, fad);
2030    fad->o_all = o;
2031    evas_event_freeze(evas);
2032    edje_freeze();
2033    e_widget_ilist_freeze(o);
2034
2035    // Adding Specific Applications list into widget
2036    if (apps)
2037      e_widget_ilist_header_append(o, NULL, _("Specific Applications"));
2038    EINA_LIST_FOREACH(apps, l, desk)
2039      {
2040         Evas_Object *icon = NULL;
2041
2042         if (!desk) continue;
2043         icon = e_util_desktop_icon_add(desk, 24, evas);
2044         e_widget_ilist_append(o, icon, desk->name, NULL, NULL,
2045                               efreet_util_path_to_file_id(desk->orig_path));
2046      }
2047
2048    // Building All Applications list
2049    cats = efreet_util_desktop_name_glob_list("*");
2050    cats = eina_list_sort(cats, 0, _e_fwin_dlg_cb_desk_sort);
2051    EINA_LIST_FREE(cats, desk)
2052      {
2053         if (!eina_list_data_find(l, desk) && !eina_list_data_find(apps, desk))
2054           l = eina_list_append(l, desk);
2055         else
2056           efreet_desktop_free(desk);
2057      }
2058    l = eina_list_sort(l, -1, _e_fwin_dlg_cb_desk_list_sort);
2059
2060    // Adding All Applications list into widget
2061    if (l)
2062      e_widget_ilist_header_append(o, NULL, _("All Applications"));
2063    EINA_LIST_FREE(l, desk)
2064      {
2065         Evas_Object *icon = NULL;
2066
2067         if (!desk) continue;
2068         icon = e_util_desktop_icon_add(desk, 24, evas);
2069         e_widget_ilist_append(o, icon, desk->name, NULL, NULL,
2070                               efreet_util_path_to_file_id(desk->orig_path));
2071         efreet_desktop_free(desk);
2072      }
2073
2074    EINA_LIST_FREE(apps, desk)
2075      efreet_desktop_free(desk);
2076
2077    e_widget_ilist_go(o);
2078    e_widget_ilist_thaw(o);
2079    edje_thaw();
2080    evas_event_thaw(evas);
2081    e_widget_size_min_set(o, 160, 240);
2082    e_widget_framelist_object_append(of, o);
2083    e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1);
2084
2085    o = e_widget_label_add(evas, _("Custom Command"));
2086    e_widget_table_object_append(ot, o, 0, 1, 1, 1, 1, 1, 1, 0);
2087    fad->o_entry = e_widget_entry_add(evas, &(fad->exec_cmd),
2088                                      _e_fwin_cb_exec_cmd_changed, fad, NULL);
2089    e_widget_table_object_append(ot, fad->o_entry, 0, 2, 1, 1, 1, 1, 1, 0);
2090
2091    e_widget_size_min_get(ot, &mw, &mh);
2092    e_dialog_content_set(dia, ot, mw, mh);
2093    evas_object_event_callback_add(ot, EVAS_CALLBACK_KEY_DOWN, _e_fwin_file_open_dialog_cb_key_down, page);
2094    e_dialog_show(dia);
2095    e_dialog_border_icon_set(dia, "preferences-applications");
2096    e_widget_focus_steal(fad->o_entry);
2097 }
2098
2099 static void
2100 _e_fwin_file_open_dialog_cb_key_down(void          *data,
2101                                      Evas *e        __UNUSED__,
2102                                      Evas_Object *o __UNUSED__,
2103                                      void          *event_info)
2104 {
2105    Evas_Event_Key_Down *ev = event_info;
2106    E_Fwin_Page *page = data;
2107    E_Fwin *fwin = page->fwin;
2108
2109    if (!strcmp(ev->keyname, "Escape"))
2110      _e_fwin_cb_close(fwin->fad, fwin->fad->dia);
2111    else if (!strcmp(ev->keyname, "Return"))
2112      _e_fwin_cb_open(fwin->fad, fwin->fad->dia);
2113 }
2114
2115 static int
2116 _e_fwin_dlg_cb_desk_sort(const void *p1,
2117                          const void *p2)
2118 {
2119    Efreet_Desktop *d1, *d2;
2120
2121    d1 = (Efreet_Desktop *)p1;
2122    d2 = (Efreet_Desktop *)p2;
2123
2124    if (!d1->name) return 1;
2125    if (!d2->name) return -1;
2126    return strcmp(d1->name, d2->name);
2127 }
2128
2129 static int
2130 _e_fwin_dlg_cb_desk_list_sort(const void *data1,
2131                               const void *data2)
2132 {
2133    const Efreet_Desktop *d1, *d2;
2134
2135    if (!(d1 = data1)) return 1;
2136    if (!(d2 = data2)) return -1;
2137    return strcmp(d1->name, d2->name);
2138 }
2139
2140 static void
2141 _e_fwin_cb_exec_cmd_changed(void       *data,
2142                             void *data2 __UNUSED__)
2143 {
2144    E_Fwin_Apps_Dialog *fad = NULL;
2145    Efreet_Desktop *desktop = NULL;
2146
2147    if (!(fad = data)) return;
2148
2149    if (fad->app2)
2150      desktop = efreet_util_desktop_file_id_find(fad->app2);
2151
2152    if (!desktop) return;
2153    if (strcmp(desktop->exec, fad->exec_cmd))
2154      {
2155         eina_stringshare_del(fad->app2);
2156         fad->app2 = NULL;
2157         if (fad->o_all) e_widget_ilist_unselect(fad->o_all);
2158      }
2159    efreet_desktop_free(desktop);
2160 }
2161
2162 static void
2163 _e_fwin_cb_open(void         *data,
2164                 E_Dialog *dia __UNUSED__)
2165 {
2166    E_Fwin_Apps_Dialog *fad;
2167    Efreet_Desktop *desktop = NULL;
2168
2169    fad = data;
2170    if (fad->app2)
2171      desktop = efreet_util_desktop_file_id_find(fad->app2);
2172
2173    if ((!desktop) && (!fad->exec_cmd))
2174      {
2175         if (desktop) efreet_desktop_free(desktop);
2176         return;
2177      }
2178
2179    // Create a fake .desktop for custom command.
2180    if (!desktop)
2181      {
2182         desktop = efreet_desktop_empty_new("");
2183         if (strchr(fad->exec_cmd, '%'))
2184           {
2185              desktop->exec = strdup(fad->exec_cmd);
2186           }
2187         else
2188           {
2189              desktop->exec = malloc(strlen(fad->exec_cmd) + 4);
2190              if (desktop->exec)
2191                snprintf(desktop->exec, strlen(fad->exec_cmd) + 4, "%s %%U", fad->exec_cmd);
2192           }
2193      }
2194
2195    if ((desktop) || (strcmp(fad->exec_cmd, "")))
2196      _e_fwin_desktop_run(desktop, fad->fwin->cur_page, EINA_FALSE);
2197
2198    efreet_desktop_free(desktop);
2199
2200    e_object_del(E_OBJECT(fad->dia));
2201 }
2202
2203 static void
2204 _e_fwin_cb_close(void         *data,
2205                  E_Dialog *dia __UNUSED__)
2206 {
2207    E_Fwin_Apps_Dialog *fad;
2208
2209    fad = data;
2210    e_object_del(E_OBJECT(fad->dia));
2211 }
2212
2213 static void
2214 _e_fwin_cb_dialog_free(void *obj)
2215 {
2216    E_Dialog *dia;
2217    E_Fwin_Apps_Dialog *fad;
2218
2219    dia = (E_Dialog *)obj;
2220    fad = dia->data;
2221    eina_stringshare_del(fad->app2);
2222    E_FREE(fad->exec_cmd);
2223    fad->fwin->fad = NULL;
2224    E_FREE(fad);
2225 }
2226
2227 /* scrolling ability */
2228 static void
2229 _e_fwin_pan_set(Evas_Object *obj,
2230                 Evas_Coord   x,
2231                 Evas_Coord   y)
2232 {
2233    E_Fwin_Page *page;
2234
2235    page = evas_object_data_get(obj, "fm_page");
2236    e_fm2_pan_set(obj, x, y);
2237    if (x > page->fm_pan.max_x) x = page->fm_pan.max_x;
2238    if (y > page->fm_pan.max_y) y = page->fm_pan.max_y;
2239    if (x < 0) x = 0;
2240    if (y < 0) y = 0;
2241    page->fm_pan.x = x;
2242    page->fm_pan.y = y;
2243    _e_fwin_pan_scroll_update(page);
2244 }
2245
2246 static void
2247 _e_fwin_pan_get(Evas_Object *obj,
2248                 Evas_Coord  *x,
2249                 Evas_Coord  *y)
2250 {
2251    E_Fwin_Page *page;
2252
2253    page = evas_object_data_get(obj, "fm_page");
2254    e_fm2_pan_get(obj, x, y);
2255    page->fm_pan.x = *x;
2256    page->fm_pan.y = *y;
2257 }
2258
2259 static void
2260 _e_fwin_pan_max_get(Evas_Object *obj,
2261                     Evas_Coord  *x,
2262                     Evas_Coord  *y)
2263 {
2264    E_Fwin_Page *page;
2265
2266    page = evas_object_data_get(obj, "fm_page");
2267    e_fm2_pan_max_get(obj, x, y);
2268    page->fm_pan.max_x = *x;
2269    page->fm_pan.max_y = *y;
2270    _e_fwin_pan_scroll_update(page);
2271 }
2272
2273 static void
2274 _e_fwin_pan_child_size_get(Evas_Object *obj,
2275                            Evas_Coord  *w,
2276                            Evas_Coord  *h)
2277 {
2278    E_Fwin_Page *page;
2279
2280    page = evas_object_data_get(obj, "fm_page");
2281    e_fm2_pan_child_size_get(obj, w, h);
2282    page->fm_pan.w = *w;
2283    page->fm_pan.h = *h;
2284    _e_fwin_pan_scroll_update(page);
2285 }
2286
2287 static void
2288 _e_fwin_pan_scroll_update(E_Fwin_Page *page)
2289 {
2290    Edje_Message_Int_Set *msg;
2291
2292    if ((page->fm_pan.x == page->fm_pan_last.x) &&
2293        (page->fm_pan.y == page->fm_pan_last.y) &&
2294        (page->fm_pan.max_x == page->fm_pan_last.max_x) &&
2295        (page->fm_pan.max_y == page->fm_pan_last.max_y) &&
2296        (page->fm_pan.w == page->fm_pan_last.w) &&
2297        (page->fm_pan.h == page->fm_pan_last.h)) return;
2298    msg = alloca(sizeof(Edje_Message_Int_Set) -
2299                 sizeof(int) + (6 * sizeof(int)));
2300    msg->count = 6;
2301    msg->val[0] = page->fm_pan.x;
2302    msg->val[1] = page->fm_pan.y;
2303    msg->val[2] = page->fm_pan.max_x;
2304    msg->val[3] = page->fm_pan.max_y;
2305    msg->val[4] = page->fm_pan.w;
2306    msg->val[5] = page->fm_pan.h;
2307 //   printf("SEND MSG %i %i | %i %i | %ix%i\n",
2308 //        page->fm_pan.x, page->fm_pan.y,
2309 //        page->fm_pan.max_x, page->fm_pan.max_y,
2310 //        page->fm_pan.w, page->fm_pan.h);
2311    if (page->fwin->under_obj)
2312      edje_object_message_send(page->fwin->under_obj, EDJE_MESSAGE_INT_SET, 1, msg);
2313    if (page->fwin->over_obj)
2314      edje_object_message_send(page->fwin->over_obj, EDJE_MESSAGE_INT_SET, 1, msg);
2315    if (page->scrollframe_obj)
2316      edje_object_message_send(e_scrollframe_edje_object_get(page->scrollframe_obj), EDJE_MESSAGE_INT_SET, 1, msg);
2317    page->fm_pan_last.x = page->fm_pan.x;
2318    page->fm_pan_last.y = page->fm_pan.y;
2319    page->fm_pan_last.max_x = page->fm_pan.max_x;
2320    page->fm_pan_last.max_y = page->fm_pan.max_y;
2321    page->fm_pan_last.w = page->fm_pan.w;
2322    page->fm_pan_last.h = page->fm_pan.h;
2323 }
2324
2325 /* e_fm_op_registry */
2326 static void
2327 _e_fwin_op_registry_listener_cb(void                          *data,
2328                                 const E_Fm2_Op_Registry_Entry *ere)
2329 {
2330    Evas_Object *o = data;
2331    char buf[PATH_MAX];
2332    char *total;
2333    int mw, mh;
2334
2335    // Don't show if the operation keep less than 1 second
2336    if (ere->start_time + 1.0 > ecore_loop_time_get()) return;
2337
2338    // Update element
2339    edje_object_part_drag_size_set(o, "e.gauge.bar", ((double)(ere->percent)) / 100, 1.0);
2340    edje_object_size_min_get(o, &mw, &mh);
2341    evas_object_resize(o, mw * e_scale, mh * e_scale);
2342    evas_object_show(o);
2343
2344    // Update icon
2345    switch (ere->op)
2346      {
2347       case E_FM_OP_COPY:
2348         edje_object_signal_emit(o, "e,action,icon,copy", "e");
2349         break;
2350
2351       case E_FM_OP_MOVE:
2352         edje_object_signal_emit(o, "e,action,icon,move", "e");
2353         break;
2354
2355       case E_FM_OP_REMOVE:
2356         edje_object_signal_emit(o, "e,action,icon,delete", "e");
2357         break;
2358
2359       default:
2360         edje_object_signal_emit(o, "e,action,icon,unknow", "e");
2361      }
2362
2363    // Update information text
2364    switch (ere->status)
2365      {
2366       case E_FM2_OP_STATUS_ABORTED:
2367         switch (ere->op)
2368           {
2369            case E_FM_OP_COPY:
2370              snprintf(buf, sizeof(buf), _("Copying is aborted"));
2371              break;
2372
2373            case E_FM_OP_MOVE:
2374              snprintf(buf, sizeof(buf), _("Moving is aborted"));
2375              break;
2376
2377            case E_FM_OP_REMOVE:
2378              snprintf(buf, sizeof(buf), _("Deleting is aborted"));
2379              break;
2380
2381            default:
2382              snprintf(buf, sizeof(buf), _("Unknown operation from slave is aborted"));
2383           }
2384         break;
2385
2386       default:
2387         total = e_util_size_string_get(ere->total);
2388         switch (ere->op)
2389           {
2390            case E_FM_OP_COPY:
2391              if (ere->finished)
2392                snprintf(buf, sizeof(buf), _("Copy of %s done"), total);
2393              else
2394                snprintf(buf, sizeof(buf), _("Copying %s (eta: %d sec)"), total, ere->eta);
2395              break;
2396
2397            case E_FM_OP_MOVE:
2398              if (ere->finished)
2399                snprintf(buf, sizeof(buf), _("Move of %s done"), total);
2400              else
2401                snprintf(buf, sizeof(buf), _("Moving %s (eta: %d sec)"), total, ere->eta);
2402              break;
2403
2404            case E_FM_OP_REMOVE:
2405              if (ere->finished)
2406                snprintf(buf, sizeof(buf), _("Delete done"));
2407              else
2408                snprintf(buf, sizeof(buf), _("Deleting files..."));
2409              break;
2410
2411            default:
2412              snprintf(buf, sizeof(buf), _("Unknow operation from slave %d"), ere->id);
2413           }
2414         E_FREE(total);
2415      }
2416    edje_object_part_text_set(o, "e.text.info", buf);
2417
2418    if (ere->needs_attention)
2419      edje_object_signal_emit(o, "e,action,set,need_attention", "e");
2420    else
2421      edje_object_signal_emit(o, "e,action,set,normal", "e");
2422 }
2423
2424 static Eina_Bool
2425 _e_fwin_op_registry_free_data_delayed(void *data)
2426 {
2427    evas_object_del((Evas_Object *)data);
2428    return ECORE_CALLBACK_CANCEL;
2429 }
2430
2431 static void
2432 _e_fwin_op_registry_free_data(void *data)
2433 {
2434    ecore_timer_add(5.0, _e_fwin_op_registry_free_data_delayed, data);
2435 }
2436
2437 static Eina_Bool
2438 _e_fwin_op_registry_entry_add_cb(void          *data,
2439                                  __UNUSED__ int type,
2440                                  void          *event)
2441 {
2442    E_Fm2_Op_Registry_Entry *ere = (E_Fm2_Op_Registry_Entry *)event;
2443    E_Fwin_Page *page = data;
2444    Evas_Object *o;
2445
2446    if (!(ere->op == E_FM_OP_COPY || ere->op == E_FM_OP_MOVE ||
2447          ere->op == E_FM_OP_REMOVE))
2448      return ECORE_CALLBACK_RENEW;
2449
2450    o = edje_object_add(evas_object_evas_get(page->scrollframe_obj));
2451    e_theme_edje_object_set(o, "base/theme/fileman",
2452                            "e/fileman/default/progress");
2453
2454    // Append the element to the box
2455    edje_object_part_box_append(e_scrollframe_edje_object_get(page->scrollframe_obj),
2456                                "e.box.operations", o);
2457    evas_object_size_hint_align_set(o, 1.0, 1.0); //FIXME this should be theme-configurable
2458
2459    // add abort button callback with id of operation in registry
2460    edje_object_signal_callback_add(o, "e,fm,operation,abort", "",
2461                                    _e_fwin_op_registry_abort_cb, (void *)(long)ere->id);
2462
2463    //Listen to progress changes
2464    e_fm2_op_registry_entry_listener_add(ere, _e_fwin_op_registry_listener_cb,
2465                                         o, _e_fwin_op_registry_free_data);
2466
2467    return ECORE_CALLBACK_RENEW;
2468 }
2469
2470 static void
2471 _e_fwin_op_registry_entry_iter(E_Fwin_Page *page)
2472 {
2473    Eina_Iterator *itr;
2474    E_Fm2_Op_Registry_Entry *ere;
2475
2476    itr = e_fm2_op_registry_iterator_new();
2477    EINA_ITERATOR_FOREACH(itr, ere)
2478      _e_fwin_op_registry_entry_add_cb(page, 0, ere);
2479    eina_iterator_free(itr);
2480 }
2481
2482 static void
2483 _e_fwin_op_registry_abort_cb(void                *data,
2484                              Evas_Object *obj     __UNUSED__,
2485                              const char *emission __UNUSED__,
2486                              const char *source   __UNUSED__)
2487 {
2488    int id;
2489
2490    id = (long)data;
2491    if (!id) return;
2492    e_fm2_operation_abort(id);
2493 }
2494