f180e842daa533d71f4c933bcd1680ab6868d09d
[framework/uifw/e17.git] / src / bin / e_desk.c
1 #include "e.h"
2
3 /* E_Desk is a child object of E_Zone. A desk is essentially a background
4  * and an associated set of client windows. Each zone can have an arbitrary
5  * number of desktops.
6  */
7
8 static void _e_desk_free(E_Desk *desk);
9 static void _e_desk_event_desk_show_free(void *data, void *ev);
10 static void _e_desk_event_desk_before_show_free(void *data, void *ev);
11 static void _e_desk_event_desk_after_show_free(void *data, void *ev);
12 static void _e_desk_event_desk_deskshow_free(void *data, void *ev);
13 static void _e_desk_event_desk_name_change_free(void *data, void *ev);
14 static void _e_desk_show_begin(E_Desk *desk, int mode, int dx, int dy);
15 static void _e_desk_show_end(E_Desk *desk);
16 static Eina_Bool _e_desk_show_animator(void *data);
17 static void _e_desk_hide_begin(E_Desk *desk, int mode, int dx, int dy);
18 static void _e_desk_hide_end(E_Desk *desk);
19 static Eina_Bool _e_desk_hide_animator(void *data);
20
21 EAPI int E_EVENT_DESK_SHOW = 0;
22 EAPI int E_EVENT_DESK_BEFORE_SHOW = 0;
23 EAPI int E_EVENT_DESK_AFTER_SHOW = 0;
24 EAPI int E_EVENT_DESK_DESKSHOW = 0;
25 EAPI int E_EVENT_DESK_NAME_CHANGE = 0;
26
27 EINTERN int
28 e_desk_init(void)
29 {
30    E_EVENT_DESK_SHOW = ecore_event_type_new();
31    E_EVENT_DESK_BEFORE_SHOW = ecore_event_type_new();
32    E_EVENT_DESK_AFTER_SHOW = ecore_event_type_new();
33    E_EVENT_DESK_DESKSHOW = ecore_event_type_new();
34    E_EVENT_DESK_NAME_CHANGE = ecore_event_type_new();
35    return 1;
36 }
37
38 EINTERN int
39 e_desk_shutdown(void)
40 {
41    return 1;
42 }
43
44 EAPI E_Desk *
45 e_desk_new(E_Zone *zone, int x, int y)
46 {
47    E_Desk *desk;
48    Eina_List *l;
49    E_Config_Desktop_Name *cfname;
50    char name[40];
51    int ok;
52
53    E_OBJECT_CHECK_RETURN(zone, NULL);
54    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
55
56    desk = E_OBJECT_ALLOC(E_Desk, E_DESK_TYPE, _e_desk_free);
57    if (!desk) return NULL;
58
59    desk->zone = zone;
60    desk->x = x;
61    desk->y = y;
62
63    /* Get current desktop's name */
64    ok = 0;
65    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
66      {
67         if ((cfname->container >= 0) &&
68             ((int) zone->container->num != cfname->container)) continue;
69         if ((cfname->zone >= 0) &&
70             ((int) zone->num != cfname->zone)) continue;
71         if ((cfname->desk_x != desk->x) || (cfname->desk_y != desk->y)) 
72           continue;
73         desk->name = eina_stringshare_add(cfname->name);
74         ok = 1;
75         break;
76      }
77
78    if (!ok)
79      {
80         snprintf(name, sizeof(name), _(e_config->desktop_default_name), x, y);
81         desk->name = eina_stringshare_add(name);
82      }
83
84    return desk;
85 }
86
87 EAPI void
88 e_desk_name_set(E_Desk *desk, const char *name)
89 {
90    E_Event_Desk_Name_Change *ev;
91
92    E_OBJECT_CHECK(desk);
93    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
94    if (desk->name) eina_stringshare_del(desk->name);
95    desk->name = eina_stringshare_add(name);
96
97    ev = E_NEW(E_Event_Desk_Name_Change, 1);
98    ev->desk = desk;
99    e_object_ref(E_OBJECT(desk));
100    ecore_event_add(E_EVENT_DESK_NAME_CHANGE, ev, 
101                    _e_desk_event_desk_name_change_free, NULL);
102 }
103
104 EAPI void
105 e_desk_name_add(int container, int zone, int desk_x, int desk_y, const char *name)
106 {
107    E_Config_Desktop_Name *cfname;
108
109    e_desk_name_del(container, zone, desk_x, desk_y);
110    cfname = E_NEW(E_Config_Desktop_Name, 1);
111    cfname->container = container;
112    cfname->zone = zone;
113    cfname->desk_x = desk_x;
114    cfname->desk_y = desk_y;
115    if (name) cfname->name = eina_stringshare_add(name);
116    e_config->desktop_names = eina_list_append(e_config->desktop_names, cfname);
117 }
118
119 EAPI void
120 e_desk_name_del(int container, int zone, int desk_x, int desk_y)
121 {
122    Eina_List *l = NULL;
123    E_Config_Desktop_Name *cfname = NULL;
124
125    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
126      {
127         if ((cfname->container == container) && (cfname->zone == zone) &&
128             (cfname->desk_x == desk_x) && (cfname->desk_y == desk_y))
129           {
130              e_config->desktop_names = 
131                eina_list_remove_list(e_config->desktop_names, l);
132              if (cfname->name) eina_stringshare_del(cfname->name);
133              free(cfname);
134              break;
135           }
136      }
137 }
138
139 EAPI void
140 e_desk_name_update(void)
141 {
142    Eina_List *m, *c, *z, *l;
143    E_Manager *man;
144    E_Container *con;
145    E_Zone *zone;
146    E_Desk *desk;
147    E_Config_Desktop_Name *cfname;
148    int d_x, d_y, ok;
149    char name[40];
150
151    EINA_LIST_FOREACH(e_manager_list(), m, man)
152      {
153         EINA_LIST_FOREACH(man->containers, c, con)
154           {
155              EINA_LIST_FOREACH(con->zones, z, zone)
156                {
157                   for (d_x = 0; d_x < zone->desk_x_count; d_x++)
158                     {
159                        for (d_y = 0; d_y < zone->desk_y_count; d_y++)
160                          {
161                             desk = zone->desks[d_x + zone->desk_x_count * d_y];
162                             ok = 0;
163
164                             EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
165                               {
166                                  if ((cfname->container >= 0) &&
167                                      ((int) con->num != cfname->container)) continue;
168                                  if ((cfname->zone >= 0) &&
169                                      ((int) zone->num != cfname->zone)) continue;
170                                  if ((cfname->desk_x != d_x) || 
171                                      (cfname->desk_y != d_y)) continue;
172                                  e_desk_name_set(desk,cfname->name);
173                                  ok = 1;
174                                  break;
175                               }
176
177                             if (!ok)
178                               {
179                                  snprintf(name, sizeof(name), 
180                                           _(e_config->desktop_default_name), 
181                                           d_x, d_y);
182                                  e_desk_name_set(desk,name);
183                               }
184                          }
185                     }
186                }
187           }
188      }
189 }
190
191 EAPI void
192 e_desk_show(E_Desk *desk)
193 {
194    E_Border_List *bl;
195    E_Border *bd;
196    E_Event_Desk_Show *ev;
197    E_Event_Desk_Before_Show *eev;
198    E_Event_Desk_After_Show *eeev;
199    Eina_List *l;
200    E_Shelf *es;
201    int was_zone = 0, x, y, dx = 0, dy = 0, prev_x = 0, prev_y = 0;
202
203    E_OBJECT_CHECK(desk);
204    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
205    if (desk->visible) return;
206
207    eev = E_NEW(E_Event_Desk_Before_Show, 1);
208    eev->desk = e_desk_current_get(desk->zone);
209    e_object_ref(E_OBJECT(eev->desk));
210    ecore_event_add(E_EVENT_DESK_BEFORE_SHOW, eev, 
211                    _e_desk_event_desk_before_show_free, NULL);
212
213    ecore_x_window_shadow_tree_flush();
214    for (x = 0; x < desk->zone->desk_x_count; x++)
215      {
216         for (y = 0; y < desk->zone->desk_y_count; y++)
217           {
218              E_Desk *desk2;
219
220              desk2 = e_desk_at_xy_get(desk->zone, x, y);
221              if (desk2->visible)
222                {
223                   desk2->visible = 0;
224                   prev_x = desk2->x;
225                   prev_y = desk2->y;
226                   dx = desk->x - desk2->x;
227                   dy = desk->y - desk2->y;
228                   if (e_config->desk_flip_animate_mode > 0)
229                     _e_desk_hide_begin(desk2, e_config->desk_flip_animate_mode, 
230                                        dx, dy);
231                   break;
232                }
233           }
234      }
235
236    desk->zone->desk_x_current = desk->x;
237    desk->zone->desk_y_current = desk->y;
238    desk->visible = 1;
239
240    if (desk->zone->bg_object) was_zone = 1;
241    if (e_config->desk_flip_animate_mode == 0)
242      {
243         bl = e_container_border_list_first(desk->zone->container);
244         while ((bd = e_container_border_list_next(bl)))
245           {
246              if ((bd->desk->zone == desk->zone) && (!bd->iconic))
247                {
248                   if ((bd->desk == desk) || (bd->sticky))
249                     e_border_show(bd);
250                   else if (bd->moving)
251                     e_border_desk_set(bd, desk);
252                   else
253                     e_border_hide(bd, 2);
254                }
255           }
256         e_container_border_list_free(bl);
257      }
258
259    if (e_config->desk_flip_animate_mode > 0)
260      _e_desk_show_begin(desk, e_config->desk_flip_animate_mode, dx, dy);
261
262    if (e_config->focus_last_focused_per_desktop)
263      e_desk_last_focused_focus(desk);
264
265    if (was_zone)
266      {
267         if (e_config->desk_flip_pan_bg)
268           e_bg_zone_slide(desk->zone, prev_x, prev_y);
269         else
270           e_bg_zone_update(desk->zone, E_BG_TRANSITION_DESK);
271      }
272    else
273      e_bg_zone_update(desk->zone, E_BG_TRANSITION_START);
274
275    ev = E_NEW(E_Event_Desk_Show, 1);
276    ev->desk = desk;
277    e_object_ref(E_OBJECT(desk));
278    ecore_event_add(E_EVENT_DESK_SHOW, ev, _e_desk_event_desk_show_free, NULL);
279
280    EINA_LIST_FOREACH(e_shelf_list(), l, es)
281      {
282         Eina_List *ll;
283         E_Config_Shelf *cf_es;
284         E_Zone *zone;
285         E_Config_Shelf_Desk *sd;
286         int show_shelf=0;
287
288         if (!es) continue;
289         if (!es->cfg->desk_show_mode) continue;
290         cf_es = es->cfg;
291         if (!cf_es) continue;
292
293         zone = e_util_zone_current_get(e_manager_current_get());
294         if (cf_es->zone != (int) zone->num) continue;
295
296         EINA_LIST_FOREACH(es->cfg->desk_list, ll, sd)
297           {
298              if (!sd) continue;
299              if ((desk->x == sd->x) && (desk->y == sd->y))
300                {
301                   show_shelf = 1;
302                   break;
303                }
304           }
305         if (show_shelf)
306           e_shelf_show(es);
307         else
308           e_shelf_hide(es);
309      }
310
311    if (e_config->desk_flip_animate_mode == 0)
312      {
313         eeev = E_NEW(E_Event_Desk_After_Show, 1);
314         eeev->desk = e_desk_current_get(desk->zone);
315         e_object_ref(E_OBJECT(eeev->desk));
316         ecore_event_add(E_EVENT_DESK_AFTER_SHOW, eeev, 
317                         _e_desk_event_desk_after_show_free, NULL);
318      }
319
320 }
321
322 EAPI void
323 e_desk_deskshow(E_Zone *zone)
324 {
325    E_Border *bd;
326    E_Border_List *bl;
327    E_Desk *desk;
328    E_Event_Desk_Show *ev;
329
330    E_OBJECT_CHECK(zone);
331    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
332
333    desk = e_desk_current_get(zone);
334    bl = e_container_border_list_first(zone->container);
335    ecore_x_window_shadow_tree_flush();
336    while ((bd = e_container_border_list_next(bl))) 
337      {
338         if (bd->desk == desk)
339           {
340              if (desk->deskshow_toggle)
341                {
342                   if (bd->deskshow) e_border_uniconify(bd);
343                   bd->deskshow = 0;
344                }
345              else
346                {
347                   if (bd->iconic) continue;
348                   if (bd->client.netwm.state.skip_taskbar) continue;
349                   if (bd->user_skip_winlist) continue;
350                   e_border_iconify(bd);
351                   bd->deskshow = 1;
352                }
353           }
354      }
355    desk->deskshow_toggle = desk->deskshow_toggle ? 0 : 1;
356    e_container_border_list_free(bl);
357    ev = E_NEW(E_Event_Desk_Show, 1);
358    ev->desk = desk;
359    e_object_ref(E_OBJECT(desk));
360    ecore_event_add(E_EVENT_DESK_DESKSHOW, ev, 
361                    _e_desk_event_desk_deskshow_free, NULL);
362 }
363
364 EAPI void
365 e_desk_last_focused_focus(E_Desk *desk)
366 {
367    Eina_List *l = NULL;
368    E_Border *bd;
369    
370    EINA_LIST_FOREACH(e_border_focus_stack_get(), l, bd)
371      {
372         if ((!bd->iconic) && (bd->visible) &&
373             ((bd->desk == desk) || ((bd->zone == desk->zone) && bd->sticky)) &&
374             (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus) &&
375             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
376             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
377             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
378             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
379             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
380           {
381              /* this was the window last focused in this desktop */
382              if (!bd->lock_focus_out)
383                {
384                   e_border_focus_set(bd, 1, 1);
385                   break;
386                }
387           }
388      }
389 }
390
391 EAPI void
392 e_desk_row_add(E_Zone *zone)
393 {
394    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count + 1);
395 }
396
397 EAPI void
398 e_desk_row_remove(E_Zone *zone)
399 {
400    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count - 1);
401 }
402
403 EAPI void
404 e_desk_col_add(E_Zone *zone)
405 {
406    e_zone_desk_count_set(zone, zone->desk_x_count + 1, zone->desk_y_count);
407 }
408
409 EAPI void
410 e_desk_col_remove(E_Zone *zone)
411 {
412    e_zone_desk_count_set(zone, zone->desk_x_count - 1, zone->desk_y_count);
413 }
414
415 EAPI E_Desk *
416 e_desk_current_get(E_Zone *zone)
417 {
418    E_OBJECT_CHECK_RETURN(zone, NULL);
419    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
420
421    return e_desk_at_xy_get(zone, zone->desk_x_current, zone->desk_y_current);
422 }
423
424 EAPI E_Desk *
425 e_desk_at_xy_get(E_Zone *zone, int x, int y)
426 {
427    E_OBJECT_CHECK_RETURN(zone, NULL);
428    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
429
430    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
431      return NULL;
432    else if ((x < 0) || (y < 0))
433      return NULL;
434
435    return zone->desks[x + (y * zone->desk_x_count)];
436 }
437
438 EAPI E_Desk *
439 e_desk_at_pos_get(E_Zone *zone, int pos)
440 {
441    int x, y;
442
443    E_OBJECT_CHECK_RETURN(zone, NULL);
444    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
445
446    y = pos / zone->desk_x_count;
447    x = pos - (y * zone->desk_x_count);
448
449    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
450      return NULL;
451
452    return zone->desks[x + (y * zone->desk_x_count)];
453 }
454
455 EAPI void
456 e_desk_xy_get(E_Desk *desk, int *x, int *y)
457 {
458    E_OBJECT_CHECK(desk);
459    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
460
461    if (x) *x = desk->x;
462    if (y) *y = desk->y;
463 }
464
465 EAPI void
466 e_desk_next(E_Zone *zone)
467 {
468    int x, y;
469
470    E_OBJECT_CHECK(zone);
471    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
472
473    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
474      return;
475
476    x = zone->desk_x_current;
477    y = zone->desk_y_current;
478
479    x++;
480    if (x >= zone->desk_x_count)
481      {
482         x = 0;
483         y++;
484         if (y >= zone->desk_y_count) y = 0;
485      }
486
487    e_desk_show(e_desk_at_xy_get(zone, x, y));
488 }
489
490 EAPI void
491 e_desk_prev(E_Zone *zone)
492 {
493    int x, y;
494
495    E_OBJECT_CHECK(zone);
496    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
497
498    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
499      return;
500
501    x = zone->desk_x_current;
502    y = zone->desk_y_current;
503
504    x--;
505    if (x < 0)
506      {
507         x = zone->desk_x_count - 1;
508         y--;
509         if (y < 0) y = zone->desk_y_count - 1;
510      }
511    e_desk_show(e_desk_at_xy_get(zone, x, y));
512 }
513
514 static void
515 _e_desk_free(E_Desk *desk)
516 {
517    if (desk->name) eina_stringshare_del(desk->name);
518    if (desk->animator) ecore_animator_del(desk->animator);
519    free(desk);
520 }
521
522 static void
523 _e_desk_event_desk_show_free(void *data __UNUSED__, void *event)
524 {
525    E_Event_Desk_Show *ev;
526
527    ev = event;
528    e_object_unref(E_OBJECT(ev->desk));
529    free(ev);
530 }
531
532 static void
533 _e_desk_event_desk_before_show_free(void *data __UNUSED__, void *event)
534 {
535    E_Event_Desk_Before_Show *ev;
536
537    ev = event;
538    e_object_unref(E_OBJECT(ev->desk));
539    free(ev);
540 }
541
542 static void
543 _e_desk_event_desk_after_show_free(void *data __UNUSED__, void *event)
544 {
545    E_Event_Desk_After_Show *ev;
546
547    ev = event;
548    e_object_unref(E_OBJECT(ev->desk));
549    free(ev);
550 }
551
552 static void
553 _e_desk_event_desk_deskshow_free(void *data __UNUSED__, void *event)
554 {
555    E_Event_Desk_Show *ev;
556
557    ev = event;
558    e_object_unref(E_OBJECT(ev->desk));
559    free(ev);
560 }
561
562 static void
563 _e_desk_event_desk_name_change_free(void *data __UNUSED__, void *event)
564 {
565    E_Event_Desk_Name_Change *ev;
566
567    ev = event;
568    e_object_unref(E_OBJECT(ev->desk));
569    free(ev);
570 }
571
572 static void
573 _e_desk_show_begin(E_Desk *desk, int mode, int dx, int dy)
574 {
575    E_Border_List *bl;
576    E_Border *bd;
577    double t;
578
579    if (dx < 0) dx = -1;
580    if (dx > 0) dx = 1;
581    if (dy < 0) dy = -1;
582    if (dy > 0) dy = 1;
583    
584    t = ecore_loop_time_get();
585    bl = e_container_border_list_first(desk->zone->container);
586    while ((bd = e_container_border_list_next(bl)))
587      {
588         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
589           {
590              if (bd->moving)
591                {
592                   bd->fx.start.t = t;
593                   bd->fx.start.x = 0;
594                   bd->fx.start.y = 0;
595                   e_border_desk_set(bd, desk);
596                   e_border_show(bd);
597                }
598              else if ((bd->desk == desk) && (!bd->sticky))
599                {
600                   bd->fx.start.t = t;
601                   if (mode == 1)
602                     {
603                        bd->fx.start.x = bd->zone->w * (dx * 1.5);
604                        bd->fx.start.y = bd->zone->h * (dy * 1.5);
605                     }
606                   else if (mode == 2)
607                     {
608                        int mx, my, bx, by;
609                        double fx, fy, ang, rad, len, lmax;
610
611                        mx = bd->zone->x + (bd->zone->w / 2);
612                        my = bd->zone->y + (bd->zone->h / 2);
613
614                        bx = bd->x + (bd->w / 2) - mx;
615                        by = bd->y + (bd->h / 2) - my;
616                        if (bx == 0) bx = 1;
617                        if (by == 0) by = 1;
618                        fx = (double)bx / (double)(bd->zone->w / 2);
619                        fy = (double)by / (double)(bd->zone->h / 2);
620                        ang = atan(fy / fx);
621                        if (fx < 0.0)
622                          ang = M_PI + ang;
623                        len = sqrt((bx * bx) + (by * by));
624                        lmax = sqrt(((bd->zone->w / 2) * (bd->zone->w / 2)) +
625                                    ((bd->zone->h / 2) * (bd->zone->h / 2)));
626                        rad = sqrt((bd->w * bd->w) + (bd->h * bd->h)) / 2.0;
627                        bx = cos(ang) * (lmax - len + rad);
628                        by = sin(ang) * (lmax - len + rad);
629                        bd->fx.start.x = bx;
630                        bd->fx.start.y = by;
631                     }
632                   if (bd->fx.start.x < 0)
633                     bd->fx.start.x -= bd->zone->x;
634                   else
635                     bd->fx.start.x += bd->zone->container->w - (bd->zone->x + bd->zone->w);
636                   if (bd->fx.start.y < 0)
637                     bd->fx.start.y -= bd->zone->y;
638                   else
639                     bd->fx.start.y += bd->zone->container->h - (bd->zone->y + bd->zone->h);
640                   e_border_fx_offset(bd, bd->fx.start.x, bd->fx.start.y);
641                   e_border_comp_hidden_set(bd, EINA_TRUE);
642                }
643           }
644      }
645    e_container_border_list_free(bl);
646    if (desk->animator) ecore_animator_del(desk->animator);
647    desk->animator = ecore_animator_add(_e_desk_show_animator, desk);
648    desk->animating = EINA_TRUE;
649 }
650
651 static void
652 _e_desk_show_end(E_Desk *desk)
653 {
654    E_Event_Desk_After_Show *ev;
655    E_Border_List *bl;
656    E_Border *bd;
657
658    bl = e_container_border_list_first(desk->zone->container);
659    while ((bd = e_container_border_list_next(bl)))
660      {
661         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
662           {
663              if (bd->moving)
664                e_border_fx_offset(bd, 0, 0);
665              else if ((bd->desk == desk) && (!bd->sticky))
666                {
667                   e_border_fx_offset(bd, 0, 0);
668                   e_border_comp_hidden_set(bd, EINA_FALSE);
669
670                   if (!bd->visible)
671                     e_border_show(bd);
672                }
673           }
674      }
675
676    if (e_config->focus_last_focused_per_desktop)
677      e_desk_last_focused_focus(desk);
678
679    e_container_border_list_free(bl);
680    ecore_x_window_shadow_tree_flush();
681    ev = E_NEW(E_Event_Desk_After_Show, 1);
682    ev->desk = e_desk_current_get(desk->zone);
683    e_object_ref(E_OBJECT(ev->desk));
684    ecore_event_add(E_EVENT_DESK_AFTER_SHOW, ev, 
685                    _e_desk_event_desk_after_show_free, NULL);
686 }
687
688 static Eina_Bool
689 _e_desk_show_animator(void *data)
690 {
691    E_Desk *desk;
692    E_Border_List *bl;
693    E_Border *bd;
694    double t, dt, spd;
695
696    desk = data;
697
698    if (!desk->animating)
699      {
700         _e_desk_show_end(desk);
701         desk->animator = NULL;
702         return ECORE_CALLBACK_CANCEL;
703      }
704
705    t = ecore_loop_time_get();
706    dt = -1.0;
707    spd = e_config->desk_flip_animate_time;
708    bl = e_container_border_list_first(desk->zone->container);
709    while ((bd = e_container_border_list_next(bl)))
710      {
711         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
712           {
713              if (bd->moving)
714                {
715                }
716              else if ((bd->desk == desk) && (!bd->sticky))
717                {
718                   if (!bd->visible)
719                     e_border_show(bd);
720                   
721                   dt = (t - bd->fx.start.t) / spd;
722                   if (dt > 1.0) dt = 1.0;
723                   dt = 1.0 - dt;
724                   dt *= dt; /* decelerate - could be a better hack */
725                   e_border_fx_offset(bd,
726                                      ((double)bd->fx.start.x * dt),
727                                      ((double)bd->fx.start.y * dt));
728                }
729           }
730      }
731    e_container_border_list_free(bl);
732    if (dt <= 0.0)
733      desk->animating = EINA_FALSE;
734
735    return ECORE_CALLBACK_RENEW;
736 }
737
738 static void
739 _e_desk_hide_begin(E_Desk *desk, int mode, int dx, int dy)
740 {
741    E_Border_List *bl;
742    E_Border *bd;
743    double t;
744
745    if (dx < 0) dx = -1;
746    if (dx > 0) dx = 1;
747    if (dy < 0) dy = -1;
748    if (dy > 0) dy = 1;
749
750    t = ecore_loop_time_get();
751    bl = e_container_border_list_first(desk->zone->container);
752    while ((bd = e_container_border_list_next(bl)))
753      {
754         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
755           {
756              if (bd->moving)
757                {
758                   bd->fx.start.t = t;
759                   bd->fx.start.x = 0;
760                   bd->fx.start.y = 0;
761                }
762              else if ((bd->desk == desk) && (!bd->sticky))
763                {
764                   bd->fx.start.t = t;
765                   if (mode == 1)
766                     {
767                        bd->fx.start.x = bd->zone->w * (-dx * 1.5);
768                        bd->fx.start.y = bd->zone->h * (-dy * 1.5);
769                     }
770                   else if (mode == 2)
771                     {
772                        int mx, my, bx, by;
773                        double fx, fy, ang, rad, len, lmax;
774
775                        mx = bd->zone->x + (bd->zone->w / 2);
776                        my = bd->zone->y + (bd->zone->h / 2);
777
778                        bx = bd->x + (bd->w / 2) - mx;
779                        by = bd->y + (bd->h / 2) - my;
780                        if (bx == 0) bx = 1;
781                        if (by == 0) by = 1;
782                        fx = (double)bx / (double)(bd->zone->w / 2);
783                        fy = (double)by / (double)(bd->zone->h / 2);
784                        ang = atan(fy / fx);
785                        if (fx < 0.0)
786                          ang = M_PI + ang;
787                        len = sqrt((bx * bx) + (by * by));
788                        lmax = sqrt(((bd->zone->w / 2) * (bd->zone->w / 2)) +
789                                    ((bd->zone->h / 2) * (bd->zone->h / 2)));
790                        rad = sqrt((bd->w * bd->w) + (bd->h * bd->h)) / 2.0;
791                        bx = cos(ang) * (lmax - len + rad);
792                        by = sin(ang) * (lmax - len + rad);
793                        bd->fx.start.x = bx;
794                        bd->fx.start.y = by;
795                     }
796                   if (bd->fx.start.x < 0)
797                     bd->fx.start.x -= bd->zone->x;
798                   else
799                     bd->fx.start.x += bd->zone->container->w - (bd->zone->x + bd->zone->w);
800                   if (bd->fx.start.y < 0)
801                     bd->fx.start.y -= bd->zone->y;
802                   else
803                     bd->fx.start.y += bd->zone->container->h - (bd->zone->y + bd->zone->h);
804                   e_border_fx_offset(bd, 0, 0);
805                   e_border_comp_hidden_set(bd, EINA_TRUE);
806                }
807           }
808      }
809    e_container_border_list_free(bl);
810    if (desk->animator) ecore_animator_del(desk->animator);
811    desk->animator = ecore_animator_add(_e_desk_hide_animator, desk);
812    desk->animating = EINA_TRUE;
813 }
814
815 static void
816 _e_desk_hide_end(E_Desk *desk)
817 {
818    E_Border_List *bl;
819    E_Border *bd;
820
821    bl = e_container_border_list_first(desk->zone->container);
822    while ((bd = e_container_border_list_next(bl)))
823      {
824         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
825           {
826              if (bd->moving)
827                e_border_fx_offset(bd, 0, 0);
828              else if ((bd->desk == desk) && (!bd->sticky))
829                {
830                   e_border_fx_offset(bd, 0, 0);
831                   e_border_comp_hidden_set(bd, EINA_FALSE);
832                   e_border_hide(bd, 2);
833                }
834           }
835      }
836    e_container_border_list_free(bl);
837    ecore_x_window_shadow_tree_flush();
838 }
839
840 static Eina_Bool
841 _e_desk_hide_animator(void *data)
842 {
843    E_Desk *desk;
844    E_Border_List *bl;
845    E_Border *bd;
846    double t, dt, spd;
847
848    desk = data;
849
850    if (!desk->animating)
851      {
852         _e_desk_hide_end(desk);
853         desk->animator = NULL;
854         return ECORE_CALLBACK_CANCEL;
855      }
856    
857    t = ecore_loop_time_get();
858    dt = -1.0;
859    spd = e_config->desk_flip_animate_time;
860    bl = e_container_border_list_first(desk->zone->container);
861    while ((bd = e_container_border_list_next(bl)))
862      {
863         if ((bd->desk->zone == desk->zone) && (!bd->iconic))
864           {
865              if (bd->moving)
866                {
867                }
868              else if ((bd->desk == desk) && (!bd->sticky))
869                {
870                   dt = (t - bd->fx.start.t) / spd;
871                   if (dt > 1.0) dt = 1.0;
872                   dt *= dt; /* decelerate - could be a better hack */
873                   e_border_fx_offset(bd,
874                                      ((double)bd->fx.start.x * dt),
875                                      ((double)bd->fx.start.y * dt));
876                }
877           }
878      }
879    e_container_border_list_free(bl);
880
881    if ((dt < 0.0) || (dt >= 1.0))
882      desk->animating = EINA_FALSE;
883
884    return ECORE_CALLBACK_RENEW;
885 }