8e96eaee07fb862efea74c3297f65bae289dbb6d
[framework/uifw/e17.git] / src / bin / e_bg.c
1 #include "e.h"
2
3 /* local subsystem functions */
4 static void _e_bg_signal(void *data, Evas_Object *obj, const char *emission, const char *source);
5 static void _e_bg_event_bg_update_free(void *data, void *event);
6 static Eina_Bool  _e_bg_slide_animator(void *data);
7
8 static void _e_bg_image_import_dialog_done(void *data, const char *path, Eina_Bool ok, Eina_Bool external, int quality, E_Image_Import_Mode mode);
9 static void _e_bg_image_import_done(void *data, Eina_Bool ok, const char *image_path, const char *edje_path);
10 static void _e_bg_handler_image_imported(void *data, const char *image_path);
11
12 /* local subsystem globals */
13 EAPI int E_EVENT_BG_UPDATE = 0;
14 static E_Fm2_Mime_Handler *bg_hdl = NULL;
15
16 typedef struct _E_Bg_Anim_Params E_Bg_Anim_Params;
17 struct _E_Bg_Anim_Params
18 {
19    E_Zone *zone;
20    double start_time;
21    int start_x;
22    int start_y;
23    int end_x;
24    int end_y;
25
26    struct {
27       Eina_Bool x, y;
28    } freedom;
29 };
30
31 struct _E_Bg_Image_Import_Handle
32 {
33    struct {
34       void (*func)(void *data, const char *edje_file);
35       void *data;
36    } cb;
37    E_Dialog *dia;
38    E_Util_Image_Import_Handle *importer;
39    Eina_Bool canceled:1;
40 };
41
42 /* externally accessible functions */
43 EINTERN int
44 e_bg_init(void)
45 {
46    Eina_List *l = NULL;
47    E_Config_Desktop_Background *cfbg = NULL;
48
49    /* Register mime handler */
50    bg_hdl = e_fm2_mime_handler_new(_("Set As Background"),
51                                    "preferences-desktop-wallpaper",
52                                    e_bg_handler_set, NULL,
53                                    e_bg_handler_test, NULL);
54    if (bg_hdl)
55      {
56         e_fm2_mime_handler_glob_add(bg_hdl, "*.edj");
57         e_fm2_mime_handler_mime_add(bg_hdl, "image/png");
58         e_fm2_mime_handler_mime_add(bg_hdl, "image/jpeg");
59      }
60
61    /* Register files in use */
62    if (e_config->desktop_default_background)
63      e_filereg_register(e_config->desktop_default_background);
64
65    EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
66      {
67         if (!cfbg) continue;
68         e_filereg_register(cfbg->file);
69      }
70
71    E_EVENT_BG_UPDATE = ecore_event_type_new();
72    return 1;
73 }
74
75 EINTERN int
76 e_bg_shutdown(void)
77 {
78    Eina_List *l = NULL;
79    E_Config_Desktop_Background *cfbg = NULL;
80
81    /* Deregister mime handler */
82    if (bg_hdl)
83      {
84         e_fm2_mime_handler_glob_del(bg_hdl, "*.edj");
85         e_fm2_mime_handler_free(bg_hdl);
86      }
87
88    /* Deregister files in use */
89    if (e_config->desktop_default_background)
90      e_filereg_deregister(e_config->desktop_default_background);
91
92    EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
93      {
94         if (!cfbg) continue;
95         e_filereg_deregister(cfbg->file);
96      }
97
98    return 1;
99 }
100
101 /**
102  * Find the configuration for a given desktop background
103  * Use -1 as a wild card for each parameter.
104  * The most specific match will be returned
105  */
106 EAPI const E_Config_Desktop_Background *
107 e_bg_config_get(int container_num, int zone_num, int desk_x, int desk_y)
108 {
109    Eina_List *l, *ll, *entries;
110    E_Config_Desktop_Background *bg = NULL, *cfbg = NULL;
111    const char *bgfile = "";
112    char *entry;
113    int current_spec = 0; /* how specific the setting is - we want the least general one that applies */
114
115    /* look for desk specific background. */
116    if (container_num >= 0 || zone_num >= 0 || desk_x >= 0 || desk_y >= 0)
117      {
118         EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
119           {
120              int spec;
121
122              if (!cfbg) continue;
123              spec = 0;
124              if (cfbg->container == container_num) spec++;
125              else if (cfbg->container >= 0) continue;
126              if (cfbg->zone == zone_num) spec++;
127              else if (cfbg->zone >= 0) continue;
128              if (cfbg->desk_x == desk_x) spec++;
129              else if (cfbg->desk_x >= 0) continue;
130              if (cfbg->desk_y == desk_y) spec++;
131              else if (cfbg->desk_y >= 0) continue;
132
133              if (spec <= current_spec) continue;
134              bgfile = cfbg->file;
135              if (bgfile)
136                {
137                   if (bgfile[0] != '/')
138                     {
139                        const char *bf;
140
141                        bf = e_path_find(path_backgrounds, bgfile);
142                        if (bf) bgfile = bf;
143                     }
144                }
145              entries = edje_file_collection_list(bgfile);
146              if (entries)
147                {
148                   EINA_LIST_FOREACH(entries, ll, entry)
149                     {
150                        if (!strcmp(entry, "e/desktop/background"))
151                          {
152                             bg = cfbg;
153                             current_spec = spec;
154                          }
155                     }
156                   edje_file_collection_list_free(entries);
157                }
158           }
159      }
160    return bg;
161 }
162
163 EAPI const char *
164 e_bg_file_get(int container_num, int zone_num, int desk_x, int desk_y)
165 {
166    const E_Config_Desktop_Background *cfbg;
167    Eina_List *l, *entries;
168    const char *bgfile = "";
169    char *entry;
170    int ok = 0;
171
172    cfbg = e_bg_config_get(container_num, zone_num, desk_x, desk_y);
173
174    /* fall back to default */
175    if (cfbg)
176      {
177         bgfile = cfbg->file;
178         if (bgfile)
179           {
180              if (bgfile[0] != '/')
181                {
182                   const char *bf;
183
184                   bf = e_path_find(path_backgrounds, bgfile);
185                   if (bf) bgfile = bf;
186                }
187           }
188      }
189    else
190      {
191         bgfile = e_config->desktop_default_background;
192         if (bgfile)
193           {
194              if (bgfile[0] != '/')
195                {
196                   const char *bf;
197
198                   bf = e_path_find(path_backgrounds, bgfile);
199                   if (bf) bgfile = bf;
200                }
201           }
202         entries = edje_file_collection_list(bgfile);
203         if (entries)
204           {
205              EINA_LIST_FOREACH(entries, l, entry)
206                {
207                   if (!strcmp(entry, "e/desktop/background"))
208                     {
209                        ok = 1;
210                        break;
211                     }
212                }
213              edje_file_collection_list_free(entries);
214           }
215         if (!ok)
216           bgfile = e_theme_edje_file_get("base/theme/background",
217                                          "e/desktop/background");
218      }
219
220    return bgfile;
221 }
222
223 EAPI void
224 e_bg_zone_update(E_Zone *zone, E_Bg_Transition transition)
225 {
226    Evas_Object *o;
227    const char *bgfile = "";
228    const char *trans = "";
229    E_Desk *desk;
230
231    if (transition == E_BG_TRANSITION_START) trans = e_config->transition_start;
232    else if (transition == E_BG_TRANSITION_DESK) trans = e_config->transition_desk;
233    else if (transition == E_BG_TRANSITION_CHANGE) trans = e_config->transition_change;
234    if ((!trans) || (!trans[0])) transition = E_BG_TRANSITION_NONE;
235    if (e_config->desk_flip_pan_bg) transition = E_BG_TRANSITION_NONE;
236
237    desk = e_desk_current_get(zone);
238    if (desk)
239      bgfile = e_bg_file_get(zone->container->num, zone->num, desk->x, desk->y);
240    else
241      bgfile = e_bg_file_get(zone->container->num, zone->num, -1, -1);
242
243    if (zone->bg_object)
244      {
245         const char *pfile = "";
246
247         edje_object_file_get(zone->bg_object, &pfile, NULL);
248         if ((!e_util_strcmp(pfile, bgfile)) && !e_config->desk_flip_pan_bg) return;
249      }
250
251    if (transition == E_BG_TRANSITION_NONE)
252      {
253         if (zone->bg_object)
254           {
255              evas_object_del(zone->bg_object);
256              zone->bg_object = NULL;
257           }
258      }
259    else
260      {
261         char buf[4096];
262
263         if (zone->bg_object)
264           {
265              if (zone->prev_bg_object)
266                evas_object_del(zone->prev_bg_object);
267              zone->prev_bg_object = zone->bg_object;
268              if (zone->transition_object)
269                evas_object_del(zone->transition_object);
270              zone->transition_object = NULL;
271              zone->bg_object = NULL;
272           }
273         o = edje_object_add(zone->container->bg_evas);
274         zone->transition_object = o;
275         /* FIXME: segv if zone is deleted while up??? */
276         evas_object_data_set(o, "e_zone", zone);
277         snprintf(buf, sizeof(buf), "e/transitions/%s", trans);
278         e_theme_edje_object_set(o, "base/theme/transitions", buf);
279         edje_object_signal_callback_add(o, "e,state,done", "*", _e_bg_signal, zone);
280         evas_object_move(o, zone->x, zone->y);
281         evas_object_resize(o, zone->w, zone->h);
282         evas_object_layer_set(o, -1);
283         evas_object_clip_set(o, zone->bg_clip_object);
284         evas_object_show(o);
285      }
286    o = edje_object_add(zone->container->bg_evas);
287    zone->bg_object = o;
288    evas_object_data_set(o, "e_zone", zone);
289    edje_object_file_set(o, bgfile, "e/desktop/background");
290    if (transition == E_BG_TRANSITION_NONE)
291      {
292         evas_object_move(o, zone->x, zone->y);
293         evas_object_resize(o, zone->w, zone->h);
294         evas_object_layer_set(o, -1);
295      }
296    evas_object_clip_set(o, zone->bg_clip_object);
297    evas_object_show(o);
298    if (e_config->desk_flip_pan_bg)
299      {
300         int x = 0, y = 0;
301
302         o = zone->bg_scrollframe;
303         if (!o)
304           {
305              o = e_scrollframe_add(zone->container->bg_evas);
306              zone->bg_scrollframe = o;
307              e_scrollframe_custom_theme_set(o, "base/theme/background",
308                                             "e/desktop/background/scrollframe");
309              e_scrollframe_policy_set(o, E_SCROLLFRAME_POLICY_OFF, E_SCROLLFRAME_POLICY_OFF);
310              e_scrollframe_child_pos_set(o, 0, 0);
311              evas_object_show(o);
312           }
313         e_scrollframe_child_set(o, zone->bg_object);
314         if (desk)
315           {
316              x = desk->x;
317              y = desk->y;
318           }
319         e_bg_zone_slide(zone, x, y);
320         return;
321      }
322
323    if (transition != E_BG_TRANSITION_NONE)
324      {
325         edje_extern_object_max_size_set(zone->prev_bg_object, 65536, 65536);
326         edje_extern_object_min_size_set(zone->prev_bg_object, 0, 0);
327         edje_object_part_swallow(zone->transition_object, "e.swallow.bg.old",
328                                  zone->prev_bg_object);
329         edje_extern_object_max_size_set(zone->bg_object, 65536, 65536);
330         edje_extern_object_min_size_set(zone->bg_object, 0, 0);
331         edje_object_part_swallow(zone->transition_object, "e.swallow.bg.new",
332                                  zone->bg_object);
333         edje_object_signal_emit(zone->transition_object, "e,action,start", "e");
334      }
335 }
336
337 EAPI void
338 e_bg_zone_slide(E_Zone *zone, int prev_x, int prev_y)
339 {
340    Evas_Object *o;
341    E_Desk *desk;
342    Evas_Coord w, h, maxw, maxh, step_w, step_h;
343    Ecore_Animator *anim;
344    E_Bg_Anim_Params *params;
345    Evas_Coord vw, vh, px, py;
346    int fx, fy;
347    const void *data;
348
349    desk = e_desk_current_get(zone);
350    edje_object_size_max_get(zone->bg_object, &w, &h);
351    maxw = zone->w * zone->desk_x_count;
352    maxh = zone->h * zone->desk_y_count;
353    if (!w) w = maxw;
354    if (!h) h = maxh;
355    evas_object_resize(zone->bg_object, w, h);
356    if (zone->desk_x_count > 1)
357      step_w = ((double) (w - zone->w)) / (zone->desk_x_count - 1);
358    else step_w = 0;
359    if (zone->desk_y_count > 1)
360      step_h = ((double) (h - zone->h)) / (zone->desk_y_count - 1);
361    else step_h = 0;
362
363    o = zone->bg_scrollframe;
364    evas_object_move(o, zone->x, zone->y);
365    evas_object_resize(o, zone->w, zone->h);
366    evas_object_layer_set(o, -1);
367    evas_object_clip_set(o, zone->bg_clip_object);
368
369    data = edje_object_data_get(zone->bg_object, "directional_freedom");
370    e_scrollframe_child_viewport_size_get(o, &vw, &vh);
371    e_scrollframe_child_pos_get(o, &px, &py);
372    params = evas_object_data_get(zone->bg_object, "switch_animator_params");
373    if (!params)
374      params = E_NEW(E_Bg_Anim_Params, 1);
375    params->zone = zone;
376    params->start_x = px;
377    params->start_y = py;
378    params->end_x = desk->x * step_w * e_config->desk_flip_pan_x_axis_factor;
379    params->end_y = desk->y * step_h * e_config->desk_flip_pan_y_axis_factor;
380    params->start_time = 0.0;
381    if ((data) && (sscanf(data, "%d %d", &fx, &fy) == 2))
382      {
383         if (fx)
384           {
385              params->freedom.x = EINA_TRUE;
386              params->start_x = prev_x * step_w * e_config->desk_flip_pan_x_axis_factor;
387           }
388         if (fy)
389           {
390              params->freedom.y = EINA_TRUE;
391              params->start_y = prev_y * step_h * e_config->desk_flip_pan_y_axis_factor;
392           }
393      }
394
395    anim = evas_object_data_get(zone->bg_object, "switch_animator");
396    if (anim) ecore_animator_del(anim);
397    anim = ecore_animator_add(_e_bg_slide_animator, params);
398    evas_object_data_set(zone->bg_object, "switch_animator", anim);
399    evas_object_data_set(zone->bg_object, "switch_animator_params", params);
400 }
401
402 EAPI void
403 e_bg_default_set(const char *file)
404 {
405    E_Event_Bg_Update *ev;
406    Eina_Bool changed;
407
408    file = eina_stringshare_add(file);
409    changed = file != e_config->desktop_default_background;
410
411    if (!changed)
412      {
413         eina_stringshare_del(file);
414         return;
415      }
416
417    if (e_config->desktop_default_background)
418      {
419         e_filereg_deregister(e_config->desktop_default_background);
420         eina_stringshare_del(e_config->desktop_default_background);
421      }
422
423    if (file)
424      {
425         e_filereg_register(file);
426         e_config->desktop_default_background = file;
427      }
428    else
429      e_config->desktop_default_background = NULL;
430
431    ev = E_NEW(E_Event_Bg_Update, 1);
432    ev->container = -1;
433    ev->zone = -1;
434    ev->desk_x = -1;
435    ev->desk_y = -1;
436    ecore_event_add(E_EVENT_BG_UPDATE, ev, _e_bg_event_bg_update_free, NULL);
437 }
438
439 EAPI void
440 e_bg_add(int container, int zone, int desk_x, int desk_y, const char *file)
441 {
442    const Eina_List *l;
443    E_Config_Desktop_Background *cfbg;
444    E_Event_Bg_Update *ev;
445
446    file = eina_stringshare_add(file);
447
448    EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
449      {
450         if ((cfbg) &&
451             (cfbg->container == container) &&
452             (cfbg->zone == zone) &&
453             (cfbg->desk_x == desk_x) &&
454             (cfbg->desk_y == desk_y) &&
455             (cfbg->file == file))
456           {
457              eina_stringshare_del(file);
458              return;
459           }
460      }
461
462    e_bg_del(container, zone, desk_x, desk_y);
463    cfbg = E_NEW(E_Config_Desktop_Background, 1);
464    cfbg->container = container;
465    cfbg->zone = zone;
466    cfbg->desk_x = desk_x;
467    cfbg->desk_y = desk_y;
468    cfbg->file = file;
469    e_config->desktop_backgrounds = eina_list_append(e_config->desktop_backgrounds, cfbg);
470
471    e_filereg_register(cfbg->file);
472
473    ev = E_NEW(E_Event_Bg_Update, 1);
474    ev->container = container;
475    ev->zone = zone;
476    ev->desk_x = desk_x;
477    ev->desk_y = desk_y;
478    ecore_event_add(E_EVENT_BG_UPDATE, ev, _e_bg_event_bg_update_free, NULL);
479 }
480
481 EAPI void
482 e_bg_del(int container, int zone, int desk_x, int desk_y)
483 {
484    Eina_List *l;
485    E_Config_Desktop_Background *cfbg;
486    E_Event_Bg_Update *ev;
487
488    EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
489      {
490         if (!cfbg) continue;
491         if ((cfbg->container == container) && (cfbg->zone == zone) &&
492             (cfbg->desk_x == desk_x) && (cfbg->desk_y == desk_y))
493           {
494              e_config->desktop_backgrounds = eina_list_remove_list(e_config->desktop_backgrounds, l);
495              e_filereg_deregister(cfbg->file);
496              if (cfbg->file) eina_stringshare_del(cfbg->file);
497              free(cfbg);
498              break;
499           }
500      }
501
502    ev = E_NEW(E_Event_Bg_Update, 1);
503    ev->container = container;
504    ev->zone = zone;
505    ev->desk_x = desk_x;
506    ev->desk_y = desk_y;
507    ecore_event_add(E_EVENT_BG_UPDATE, ev, _e_bg_event_bg_update_free, NULL);
508 }
509
510 EAPI void
511 e_bg_update(void)
512 {
513    Eina_List *l, *ll, *lll;
514    E_Manager *man;
515    E_Container *con;
516    E_Zone *zone;
517
518    EINA_LIST_FOREACH(e_manager_list(), l, man)
519      {
520         EINA_LIST_FOREACH(man->containers, ll, con)
521           {
522              EINA_LIST_FOREACH(con->zones, lll, zone)
523                {
524                   e_zone_bg_reconfigure(zone);
525                }
526           }
527      }
528 }
529
530 static inline Eina_Bool
531 _e_bg_file_edje_check(const char *path)
532 {
533    const char *ext;
534    const size_t extlen = sizeof(".edj") - 1;
535    size_t len;
536
537    if (!path) return EINA_FALSE;
538
539    len = strlen(path);
540    if (len <= extlen) return EINA_FALSE;
541    ext = path + len - extlen;
542    return memcmp(ext, ".edj", extlen) == 0;
543 }
544
545 /**
546  * Go through process of importing an image as E background.
547  *
548  * This will go through process of importing an image as E
549  * background. It will ask fill/tile mode of the image, as well as
550  * quality to use.
551  *
552  * User can cancel operation at any time, and in this case callback is
553  * called with @c NULL as second parameter.
554  *
555  * The operation can be canceled by application/module as well using
556  * e_bg_image_import_cancel(). Even in this case the callback is called so user
557  * can free possibly allocated data.
558  *
559  * @param image_file source file to use, must be supported by Evas.
560  * @param cb callback to call when import process is done. The first
561  *        argument is the given data, while the second is the path to
562  *        the imported background file (edje) that can be used with
563  *        e_bg_add() or e_bg_default_set(). Note that if @a edje_file
564  *        is @c NULL, then the import process was canceled!
565  *        This function is @b always called and after it returns
566  *        E_Bg_Image_Import_Handle is deleted.
567  * @param data pointer to data to be given to callback.
568  *
569  * @return handle to the import process. It will die automatically
570  *         when user cancels the process or when code automatically
571  *         calls e_bg_image_import_cancel().  Before dying, callback
572  *         will always be called.
573  */
574 EAPI E_Bg_Image_Import_Handle *
575 e_bg_image_import(const char *image_file, void (*cb)(void *data, const char *edje_file), const void *data)
576 {
577    E_Bg_Image_Import_Handle *handle;
578
579    if (!image_file) return NULL;
580    if (!cb) return NULL;
581
582    handle = E_NEW(E_Bg_Image_Import_Handle, 1);
583    if (!handle) return NULL;
584    handle->cb.func = cb;
585    handle->cb.data = (void *)data;
586
587    handle->dia = e_util_image_import_settings_new
588      (image_file, _e_bg_image_import_dialog_done, handle);
589    if (!handle->dia)
590      {
591         free(handle);
592         return NULL;
593      }
594    e_dialog_show(handle->dia);
595
596    return handle;
597 }
598
599 /**
600  * Cancels previously started import process.
601  *
602  * Note that his handle will be deleted when process import, so don't
603  * call it after your callback is called!
604  */
605 EAPI void
606 e_bg_image_import_cancel(E_Bg_Image_Import_Handle *handle)
607 {
608    if (!handle) return;
609
610    handle->canceled = EINA_TRUE;
611
612    if (handle->cb.func)
613      {
614         handle->cb.func(handle->cb.data, NULL);
615         handle->cb.func = NULL;
616      }
617    if (handle->dia)
618      {
619         e_object_del(E_OBJECT(handle->dia));
620         handle->dia = NULL;
621      }
622    else if (handle->importer)
623      {
624         e_util_image_import_cancel(handle->importer);
625         handle->importer = NULL;
626      }
627    E_FREE(handle);
628 }
629
630 /**
631  * Set background to image, as required in e_fm2_mime_handler_new()
632  */
633 EAPI void
634 e_bg_handler_set(Evas_Object *obj __UNUSED__, const char *path, void *data __UNUSED__)
635 {
636    if (!path) return;
637
638    if (_e_bg_file_edje_check(path))
639      {
640         char buf[PATH_MAX];
641         int copy = 1;
642
643         E_Container *con = e_container_current_get(e_manager_current_get());
644         E_Zone *zone = e_zone_current_get(con);
645         E_Desk *desk = e_desk_current_get(zone);
646
647         /* if not in system dir or user dir, copy to user dir */
648         e_prefix_data_concat_static(buf, "data/backgrounds");
649         if (!strncmp(buf, path, strlen(buf)))
650            copy = 0;
651         if (copy)
652           {
653              e_user_dir_concat_static(buf, "backgrounds");
654              if (!strncmp(buf, path, strlen(buf)))
655                 copy = 0;
656           }
657         if (copy)
658           {
659              const char *file;
660              char *name;
661
662              file = ecore_file_file_get(path);
663              name = ecore_file_strip_ext(file);
664
665              e_user_dir_snprintf(buf, sizeof(buf), "backgrounds/%s-%f.edj", name, ecore_time_unix_get());
666              free(name);
667
668              if (!ecore_file_exists(buf))
669                {
670                   ecore_file_cp(path, buf);
671                   e_bg_add(con->num, zone->num, desk->x, desk->y, buf);
672                }
673              else
674                 e_bg_add(con->num, zone->num, desk->x, desk->y, path);
675           }
676         else
677            e_bg_add(con->num, zone->num, desk->x, desk->y, path);
678
679         e_bg_update();
680         e_config_save_queue();
681         return;
682      }
683
684    e_bg_image_import(path, _e_bg_handler_image_imported, NULL);
685 }
686
687 /**
688  * Test if possible to set background to file, as required in
689  * e_fm2_mime_handler_new()
690  *
691  * This handler tests for files that would be acceptable for setting
692  * background.
693  *
694  * You should just register it with "*.edj" (glob matching extension)
695  * or "image/" (mimetypes)that are acceptable with Evas loaders.
696  *
697  * Just edje files with "e/desktop/background" group are used.
698  */
699 EAPI int
700 e_bg_handler_test(Evas_Object *obj __UNUSED__, const char *path, void *data __UNUSED__)
701 {
702
703    if (!path) return 0;
704
705    if (_e_bg_file_edje_check(path))
706      {
707         if (edje_file_group_exists(path, "e/desktop/background")) return 1;
708         return 0;
709      }
710
711    /* it's image/png or image/jpeg, we'll import it. */
712    return 1;
713 }
714
715 /* local subsystem functions */
716 static void
717 _e_bg_signal(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
718 {
719    E_Zone *zone = data;
720
721    if (zone->prev_bg_object)
722      {
723         evas_object_del(zone->prev_bg_object);
724         zone->prev_bg_object = NULL;
725      }
726    if (zone->transition_object)
727      {
728         evas_object_del(zone->transition_object);
729         zone->transition_object = NULL;
730      }
731    evas_object_move(zone->bg_object, zone->x, zone->y);
732    evas_object_resize(zone->bg_object, zone->w, zone->h);
733    evas_object_layer_set(zone->bg_object, -1);
734    evas_object_clip_set(zone->bg_object, zone->bg_clip_object);
735    evas_object_show(zone->bg_object);
736 }
737
738 static void
739 _e_bg_event_bg_update_free(void *data __UNUSED__, void *event)
740 {
741    free(event);
742 }
743
744 static Eina_Bool
745 _e_bg_slide_animator(void *data)
746 {
747    E_Bg_Anim_Params *params;
748    E_Zone *zone;
749    Evas_Object *o;
750    double st;
751    double t, dt, spd;
752    Evas_Coord px, py, rx, ry, bw, bh, panw, panh;
753    Edje_Message_Int_Set *msg;
754
755    params = data;
756    zone = params->zone;
757    t = ecore_loop_time_get();
758    spd = e_config->desk_flip_animate_time;
759
760    o = zone->bg_scrollframe;
761    if (!params->start_time)
762      st = params->start_time = t;
763    else
764      st = params->start_time;
765
766    dt = (t - st) / spd;
767    if (dt > 1.0) dt = 1.0;
768    dt = 1.0 - dt;
769    dt *= dt; /* decelerate - could be a better hack */
770
771    if (params->end_x > params->start_x)
772      rx = params->start_x + (params->end_x - params->start_x) * (1.0 - dt);
773    else
774      rx = params->end_x + (params->start_x - params->end_x) * dt;
775    if (params->freedom.x) px = zone->x;
776    else px = rx;
777
778    if (params->end_y > params->start_y)
779      ry = params->start_y + (params->end_y - params->start_y) * (1.0 - dt);
780    else
781      ry = params->end_y + (params->start_y - params->end_y) * dt;
782    if (params->freedom.y) py = zone->y;
783    else py = ry;
784
785    e_scrollframe_child_pos_set(o, px, py);
786
787    evas_object_geometry_get(zone->bg_object, NULL, NULL, &bw, &bh);
788    panw = bw - zone->w;
789    if (panw < 0) panw = 0;
790    panh = bh - zone->h;
791    if (panh < 0) panh = 0;
792    msg = alloca(sizeof(Edje_Message_Int_Set) + (5 * sizeof(int)));
793    msg->count = 6;
794    msg->val[0] = rx;
795    msg->val[1] = ry;
796    msg->val[2] = panw;
797    msg->val[3] = panh;
798    msg->val[4] = bw;
799    msg->val[5] = bh;
800    edje_object_message_send(zone->bg_object, EDJE_MESSAGE_INT_SET, 0, msg);
801
802    if (dt <= 0.0)
803      {
804         evas_object_data_del(zone->bg_object, "switch_animator");
805         evas_object_data_del(zone->bg_object, "switch_animator_params");
806         E_FREE(params);
807         return ECORE_CALLBACK_CANCEL;
808      }
809    return ECORE_CALLBACK_RENEW;
810 }
811
812 static void
813 _e_bg_image_import_dialog_done(void *data, const char *path, Eina_Bool ok, Eina_Bool external, int quality, E_Image_Import_Mode mode)
814 {
815    E_Bg_Image_Import_Handle *handle = data;
816    const char *file;
817    char *name;
818    char buf[PATH_MAX];
819    size_t used, off;
820    unsigned num;
821
822    if (!ok) goto aborted;
823
824    file = ecore_file_file_get(path);
825    if (!file) goto aborted;
826    name = ecore_file_strip_ext(file);
827    if (!name) goto aborted;
828
829    used = e_user_dir_snprintf(buf, sizeof(buf), "backgrounds/%s.edj", name);
830    free(name);
831    if (used >= sizeof(buf)) goto aborted;
832
833    off = used - (sizeof(".edj") - 1);
834
835    for (num = 0; ecore_file_exists(buf); num++)
836      snprintf(buf + off, sizeof(buf) - off, "-%u.edj", num);
837
838    handle->importer = e_util_image_import
839      (path, buf, "e/desktop/background", external, quality, mode,
840       _e_bg_image_import_done, handle);
841    if (!handle->importer) goto aborted;
842
843    return;
844
845  aborted:
846    if (handle->cb.func)
847      {
848         handle->cb.func(handle->cb.data, NULL);
849         handle->cb.func = NULL;
850      }
851    if (!handle->canceled) E_FREE(handle);
852 }
853
854 static void
855 _e_bg_image_import_done(void *data, Eina_Bool ok, const char *image_path __UNUSED__, const char *edje_path)
856 {
857    E_Bg_Image_Import_Handle *handle = data;
858
859    if (!ok) edje_path = NULL;
860
861    if (handle->cb.func)
862      {
863         handle->cb.func(handle->cb.data, edje_path);
864         handle->cb.func = NULL;
865      }
866
867    if (!handle->canceled) E_FREE(handle);
868 }
869
870 static void
871 _e_bg_handler_image_imported(void *data __UNUSED__, const char *image_path)
872 {
873    E_Container *con = e_container_current_get(e_manager_current_get());
874    E_Zone *zone = e_zone_current_get(con);
875    E_Desk *desk = e_desk_current_get(zone);
876
877    if (!image_path) return;
878
879    e_bg_add(con->num, zone->num, desk->x, desk->y, image_path);
880    e_bg_update();
881    e_config_save_queue();
882 }