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