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