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