e_desk_area: remove use_desk_area config value
[platform/upstream/enlightenment.git] / src / bin / e_desk.c
1 #include "e_desk_intern.h"
2 #include "e_desk_area_intern.h"
3 #include "e_client_intern.h"
4 #include "e_utils_intern.h"
5 #include "e_comp_screen_intern.h"
6 #include "e_comp_wl_subsurface_intern.h"
7 #include "e_output_intern.h"
8 #include "e_comp_object_intern.h"
9 #include "e_zone_intern.h"
10 #include "e_config_intern.h"
11 #include "e_policy_wl_intern.h"
12 #include "e_policy_intern.h"
13
14 #include <libds-tizen/screen.h>
15
16 /* E_Desk is a child object of E_Zone. A desk is essentially a background
17  * and an associated set of client windows. Each zone can have an arbitrary
18  * number of desktops.
19  */
20
21 typedef struct _E_Desk_Private    E_Desk_Private;
22 #ifdef REFACTOR_DESK_AREA
23 typedef struct _E_Desk_Private_Client  E_Desk_Private_Client;
24 #endif
25 typedef struct _E_Desk_Smart_Data E_Desk_Smart_Data;
26
27 #define DESK_EC_DATA_KEY  "E_Desk_Client"
28
29 #define PRI(desk) ((E_Desk_Private *)e_object_data_get(E_OBJECT(desk)))
30
31 #define API_ENTRY \
32    EINA_SAFETY_ON_NULL_RETURN(desk); \
33    E_Desk_Private *priv = PRI(desk)
34
35 #define E_DESK_SMART_DATA_GET(obj, ptr)                        \
36    E_Desk_Smart_Data *ptr = evas_object_smart_data_get(obj);
37
38 #define API_ENTRY_VAL(ret) \
39    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, ret); \
40    E_Desk_Private *priv = PRI(desk)
41
42 #define E_DESK_SMART_DATA_GET_OR_RETURN(obj, ptr)              \
43    E_DESK_SMART_DATA_GET(obj, ptr);                            \
44    if (!ptr) return
45
46 typedef enum _E_Desk_Zoom_Animating_Type
47 {
48    E_DESK_ZOOM_ANIMATING_TYPE_NONE,
49    E_DESK_ZOOM_ANIMATING_TYPE_ENABLE,
50    E_DESK_ZOOM_ANIMATING_TYPE_DISABLE,
51 } E_Desk_Zoom_Animating_Type;
52
53 struct _E_Desk_Private
54 {
55    E_Desk *desk;
56
57    struct
58      {
59         struct wl_signal client_add;
60         struct wl_signal desk_area_enable;
61         struct wl_signal desk_area_disable;
62         struct wl_signal desk_area_active_change;
63         struct wl_signal split_desk_activate;
64         struct wl_signal split_desk_deactivate;
65      } events;
66
67    struct ds_tizen_splitscreen *splitscreen;
68    struct wl_listener ds_tizen_splitscreen_destroy;
69    struct wl_listener ds_tizen_splitscreen_activate;
70    struct wl_listener ds_tizen_splitscreen_deactivate;
71 };
72
73 #ifdef REFACTOR_DESK_AREA
74 struct _E_Desk_Private_Client
75 {
76    E_Desk *desk;
77    E_Client *ec;
78
79    // client listeners
80    struct wl_listener client_destroy;
81    struct wl_listener client_activate_done;
82 };
83 #endif
84
85 struct _E_Desk_Smart_Data
86 {
87    Evas_Object_Smart_Clipped_Data base;
88    Eina_List      *clients;
89    Eina_List      *handlers;
90
91    struct
92    {
93       double       ratio_x, ratio_y;
94       int          cord_x, cord_y;
95       double       prev_ratio_x, prev_ratio_y;
96       int          prev_cord_x,  prev_cord_y;
97       Eina_Bool    enabled;
98       Ecore_Animator *animator;
99       E_Desk_Zoom_Animating_Type animating_type;
100    } zoom;
101 };
102
103 static int _e_desk_hooks_delete = 0;
104 static int _e_desk_hooks_walking = 0;
105
106 static Eina_Inlist *_e_desk_hooks[] =
107 {
108    [E_DESK_HOOK_CLIENT_ADD] = NULL,
109    [E_DESK_HOOK_DESK_AREA_ENABLE] = NULL,
110    [E_DESK_HOOK_DESK_AREA_DISABLE] = NULL,
111    [E_DESK_HOOK_DESK_AREA_ACTIVE_CHANGE] = NULL,
112    [E_DESK_HOOK_SPLIT_DESK_ACTIVATE] = NULL,
113    [E_DESK_HOOK_SPLIT_DESK_DEACTIVATE] = NULL,
114 };
115
116 static void      _e_desk_free(E_Desk *desk);
117 static void      _e_desk_event_desk_show_free(void *data, void *ev);
118 static void      _e_desk_event_desk_before_show_free(void *data, void *ev);
119 static void      _e_desk_event_desk_after_show_free(void *data, void *ev);
120 static void      _e_desk_show_begin(E_Desk *desk, int dx, int dy);
121 static void      _e_desk_hide_begin(E_Desk *desk, int dx, int dy);
122 static void      _e_desk_event_desk_geometry_change_free(void *data, void *ev);
123
124 static void      _e_desk_smart_init(E_Desk *desk);
125 static void      _e_desk_smart_add(Evas_Object *obj);
126 static void      _e_desk_smart_del(Evas_Object *obj);
127 static void      _e_desk_smart_client_add(Evas_Object *obj, E_Client *ec);
128 static void      _e_desk_smart_client_del(Evas_Object *obj, E_Client *ec);
129 static void      _e_desk_object_zoom(Evas_Object *obj, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy);
130 static void      _e_desk_client_zoom(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy);
131
132 #ifdef REFACTOR_DESK_AREA
133 #else
134 static Eina_Bool _e_desk_desk_area_base_new(E_Desk *desk);
135 #endif
136
137 static void        _e_desk_hooks_clean(void);
138 static Eina_Bool   _e_desk_hook_call(E_Desk_Hook_Point hookpoint, E_Desk *desk);
139
140 EVAS_SMART_SUBCLASS_NEW(E_DESK_SMART_OBJ_TYPE, _e_desk,
141                         Evas_Smart_Class, Evas_Smart_Class,
142                         evas_object_smart_clipped_class_get, NULL)
143
144 EINTERN int E_EVENT_DESK_SHOW = 0;
145 EINTERN int E_EVENT_DESK_BEFORE_SHOW = 0;
146 EINTERN int E_EVENT_DESK_AFTER_SHOW = 0;
147 EINTERN int E_EVENT_DESK_DESKSHOW = 0;
148 EINTERN int E_EVENT_DESK_NAME_CHANGE = 0;
149 E_API int E_EVENT_DESK_GEOMETRY_CHANGE = 0;
150 E_API int E_EVENT_DESK_ZOOM_SET = 0;
151 E_API int E_EVENT_DESK_ZOOM_UNSET = 0;
152
153 static Eina_Bool
154 _e_desk_private_init(E_Desk *desk)
155 {
156    E_Desk_Private *priv;
157
158    priv = E_NEW(E_Desk_Private, 1);
159    if (!priv)
160      return EINA_FALSE;
161
162    priv->desk = desk;
163
164    wl_signal_init(&priv->events.client_add);
165    wl_signal_init(&priv->events.desk_area_enable);
166    wl_signal_init(&priv->events.desk_area_disable);
167    wl_signal_init(&priv->events.desk_area_active_change);
168    wl_signal_init(&priv->events.split_desk_activate);
169    wl_signal_init(&priv->events.split_desk_deactivate);
170
171    e_object_data_set(E_OBJECT(desk), priv);
172
173    return EINA_TRUE;
174 }
175
176 static void
177 _e_desk_private_finish(E_Desk *desk)
178 {
179    E_Desk_Private *priv;
180
181    priv = PRI(desk);
182
183 #ifdef REFACTOR_DESK_AREA
184    wl_list_remove(&priv->ds_tizen_splitscreen_deactivate.link);
185    wl_list_remove(&priv->ds_tizen_splitscreen_activate.link);
186    wl_list_remove(&priv->ds_tizen_splitscreen_destroy.link);
187 #endif
188
189    e_object_data_set(E_OBJECT(desk), NULL);
190
191    priv->desk = NULL;
192
193    free(priv);
194 }
195
196 static void
197 _e_desk_event_simple_free(void *d EINA_UNUSED, E_Event_Desk *event)
198 {
199    E_Event_Desk *ev;
200
201    ev = event;
202    e_object_unref(E_OBJECT(ev->desk));
203    free(ev);
204 }
205
206 static void
207 _e_desk_event_simple_add(E_Desk *desk, int type)
208 {
209    E_Event_Desk *ev;
210
211    ev = E_NEW(E_Event_Desk, 1);
212    if (!ev) return;
213    ev->desk = desk;
214    e_object_ref(E_OBJECT(desk));
215
216    ecore_event_add(type, ev, (Ecore_End_Cb)_e_desk_event_simple_free, NULL);
217 }
218
219 EINTERN int
220 e_desk_init(void)
221 {
222    E_EVENT_DESK_SHOW = ecore_event_type_new();
223    E_EVENT_DESK_BEFORE_SHOW = ecore_event_type_new();
224    E_EVENT_DESK_AFTER_SHOW = ecore_event_type_new();
225    E_EVENT_DESK_DESKSHOW = ecore_event_type_new();
226    E_EVENT_DESK_NAME_CHANGE = ecore_event_type_new();
227    E_EVENT_DESK_GEOMETRY_CHANGE = ecore_event_type_new();
228    E_EVENT_DESK_ZOOM_SET = ecore_event_type_new();
229    E_EVENT_DESK_ZOOM_UNSET  = ecore_event_type_new();
230
231    return 1;
232 }
233
234 EINTERN int
235 e_desk_shutdown(void)
236 {
237    return 1;
238 }
239
240 EINTERN E_Desk *
241 e_desk_new(E_Zone *zone, int x, int y)
242 {
243    E_Desk *desk;
244    Eina_List *l;
245    E_Config_Desktop_Name *cfname;
246    char name[40];
247    int ok = 0;
248    static int desk_id = 0;
249
250    E_OBJECT_CHECK_RETURN(zone, NULL);
251    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
252
253    desk = E_OBJECT_ALLOC(E_Desk, E_DESK_TYPE, _e_desk_free);
254    if (!desk) return NULL;
255
256    if (!_e_desk_private_init(desk))
257      {
258         e_object_del(E_OBJECT(desk));
259         return NULL;
260      }
261
262    desk->zone = zone;
263    desk->x = x;
264    desk->y = y;
265    desk->id = desk_id++;
266
267    /* init smart object */
268    _e_desk_smart_init(desk);
269
270    /* Get current desktop's name */
271    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
272      {
273         if ((cfname->zone >= 0) &&
274             ((int)zone->num != cfname->zone)) continue;
275         if ((cfname->desk_x != desk->x) || (cfname->desk_y != desk->y))
276           continue;
277         desk->name = eina_stringshare_ref(cfname->name);
278         ok = 1;
279         break;
280      }
281
282    if (!ok)
283      {
284         snprintf(name, sizeof(name), _(e_config->desktop_default_name), x, y);
285         desk->name = eina_stringshare_add(name);
286      }
287
288    // new a base e_desk_area
289 #ifdef REFACTOR_DESK_AREA
290    desk->desk_area.base = e_desk_desk_area_add(desk,
291          desk->geom.x, desk->geom.y, desk->geom.w, desk->geom.h,
292          E_DESK_AREA_LAYER_NORMAL);
293    if (!desk->desk_area.base)
294      {
295         e_object_del(E_OBJECT(desk));
296         return NULL;
297      }
298 #else
299    _e_desk_desk_area_base_new(desk);
300 #endif
301
302    return desk;
303 }
304
305 EINTERN E_Client *
306 e_desk_client_top_visible_get(E_Desk *desk)
307 {
308    E_Client *ec;
309
310    E_OBJECT_CHECK_RETURN(desk, NULL);
311    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
312
313    E_CLIENT_REVERSE_FOREACH(ec)
314      if (e_desk_has_ec(desk, ec) && evas_object_visible_get(ec->frame)) return ec;
315    return NULL;
316 }
317
318 EINTERN void
319 e_desk_name_set(E_Desk *desk, const char *name)
320 {
321    E_OBJECT_CHECK(desk);
322    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
323
324    eina_stringshare_replace(&desk->name, name);
325
326    _e_desk_event_simple_add(desk, E_EVENT_DESK_NAME_CHANGE);
327 }
328
329 EINTERN void
330 e_desk_name_add(int zone, int desk_x, int desk_y, const char *name)
331 {
332    E_Config_Desktop_Name *cfname;
333
334    e_desk_name_del(zone, desk_x, desk_y);
335
336    cfname = E_NEW(E_Config_Desktop_Name, 1);
337    if (!cfname) return;
338    cfname->zone = zone;
339    cfname->desk_x = desk_x;
340    cfname->desk_y = desk_y;
341    if (name) cfname->name = eina_stringshare_add(name);
342    else cfname->name = NULL;
343    e_config->desktop_names = eina_list_append(e_config->desktop_names, cfname);
344 }
345
346 EINTERN void
347 e_desk_name_del(int zone, int desk_x, int desk_y)
348 {
349    Eina_List *l = NULL;
350    E_Config_Desktop_Name *cfname = NULL;
351
352    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
353      {
354         if ((cfname->zone == zone) &&
355             (cfname->desk_x == desk_x) && (cfname->desk_y == desk_y))
356           {
357              e_config->desktop_names =
358                eina_list_remove_list(e_config->desktop_names, l);
359              if (cfname->name) eina_stringshare_del(cfname->name);
360              E_FREE(cfname);
361              break;
362           }
363      }
364 }
365
366 EINTERN void
367 e_desk_name_update(void)
368 {
369    const Eina_List *z, *l;
370    E_Zone *zone;
371    E_Desk *desk;
372    E_Config_Desktop_Name *cfname;
373    int d_x, d_y, ok;
374    char name[40];
375
376    EINA_LIST_FOREACH(e_comp->zones, z, zone)
377      {
378         for (d_x = 0; d_x < zone->desk_x_count; d_x++)
379           {
380              for (d_y = 0; d_y < zone->desk_y_count; d_y++)
381                {
382                   desk = zone->desks[d_x + zone->desk_x_count * d_y];
383                   ok = 0;
384
385                   EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
386                     {
387                        if ((cfname->zone >= 0) &&
388                            ((int)zone->num != cfname->zone)) continue;
389                        if ((cfname->desk_x != d_x) ||
390                            (cfname->desk_y != d_y)) continue;
391                        e_desk_name_set(desk, cfname->name);
392                        ok = 1;
393                        break;
394                     }
395
396                   if (!ok)
397                     {
398                        snprintf(name, sizeof(name),
399                                 _(e_config->desktop_default_name),
400                                 d_x, d_y);
401                        e_desk_name_set(desk, name);
402                     }
403                }
404           }
405      }
406 }
407
408 EINTERN void
409 e_desk_show(E_Desk *desk)
410 {
411    E_Event_Desk_Show *ev = NULL;
412    E_Event_Desk_Before_Show *eev = NULL;
413    E_Event_Desk_After_Show *eeev = NULL;
414    Edje_Message_Float_Set *msg = NULL;
415    E_Desk *desk2 = NULL;
416    int dx = 0, dy = 0;
417    Ecore_Event *eev_ecore_event = NULL;
418    Ecore_Event *ev_ecore_event = NULL;
419
420    E_OBJECT_CHECK(desk);
421    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
422    if (desk->visible) return;
423
424    desk2 = e_desk_at_xy_get(desk->zone, desk->zone->desk_x_current, desk->zone->desk_y_current);
425    if ((!starting) && (!desk2->visible)) return;
426    eev = E_NEW(E_Event_Desk_Before_Show, 1);
427    if (!eev) return;
428    eev->desk = e_desk_current_get(desk->zone);
429    e_object_ref(E_OBJECT(eev->desk));
430    eev_ecore_event = ecore_event_add(E_EVENT_DESK_BEFORE_SHOW, eev,
431                                      _e_desk_event_desk_before_show_free, NULL);
432
433    if (desk2->visible)
434      {
435         desk2->visible = 0;
436         if ((!dx) && (!dy))
437           {
438              dx = desk->x - desk2->x;
439              dy = desk->y - desk2->y;
440           }
441         _e_desk_hide_begin(desk2, dx, dy);
442         if (desk2->smart_obj)
443           evas_object_hide(desk2->smart_obj);
444      }
445
446    desk->zone->desk_x_prev = desk->zone->desk_x_current;
447    desk->zone->desk_y_prev = desk->zone->desk_y_current;
448    desk->zone->desk_x_current = desk->x;
449    desk->zone->desk_y_current = desk->y;
450    desk->visible = 1;
451
452    msg = alloca(sizeof(Edje_Message_Float_Set) + (4 * sizeof(double)));
453    msg->count = 5;
454    msg->val[0] = 0.0;
455    msg->val[1] = desk->x;
456    msg->val[2] = desk->zone->desk_x_count;
457    msg->val[3] = desk->y;
458    msg->val[4] = desk->zone->desk_y_count;
459    if (desk->zone->bg_object)
460      edje_object_message_send(desk->zone->bg_object, EDJE_MESSAGE_FLOAT_SET, 0, msg);
461
462 #ifndef ENABLE_QUICK_INIT
463    int was_zone = 0;
464    if (desk->zone->bg_object) was_zone = 1;
465 #endif
466    _e_desk_show_begin(desk, dx, dy);
467    if (desk->smart_obj)
468      evas_object_show(desk->smart_obj);
469
470 #ifndef ENABLE_QUICK_INIT
471    if (was_zone)
472      e_bg_zone_update(desk->zone, E_BG_TRANSITION_DESK);
473    else
474      e_bg_zone_update(desk->zone, E_BG_TRANSITION_START);
475 #endif
476
477    ev = E_NEW(E_Event_Desk_Show, 1);
478    if (!ev) goto error;
479    ev->desk = desk;
480    e_object_ref(E_OBJECT(desk));
481    ev_ecore_event = ecore_event_add(E_EVENT_DESK_SHOW, ev, _e_desk_event_desk_show_free, NULL);
482
483    eeev = E_NEW(E_Event_Desk_After_Show, 1);
484    if (!eeev) goto error;
485    eeev->desk = e_desk_current_get(desk->zone);
486    e_object_ref(E_OBJECT(eeev->desk));
487    ecore_event_add(E_EVENT_DESK_AFTER_SHOW, eeev,
488                    _e_desk_event_desk_after_show_free, NULL);
489
490    return;
491
492 error:
493    if (ev)
494      {
495         if (ev_ecore_event)
496           ecore_event_del(ev_ecore_event);
497         e_object_unref(E_OBJECT(ev->desk));
498         free(ev);
499      }
500    if (eev)
501      {
502         if (eev_ecore_event)
503           ecore_event_del(eev_ecore_event);
504         e_object_unref(E_OBJECT(eev->desk));
505         free(eev);
506      }
507 }
508
509 EINTERN void
510 e_desk_deskshow(E_Zone *zone)
511 {
512    E_Client *ec;
513    E_Desk *desk;
514
515    E_OBJECT_CHECK(zone);
516    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
517
518    desk = e_desk_current_get(zone);
519    EINA_SAFETY_ON_NULL_RETURN(desk);
520
521    if (desk->deskshow_toggle)
522      {
523         /* uniconify raises windows and changes stacking order
524          * go top-down to avoid skipping windows
525          */
526         E_CLIENT_REVERSE_FOREACH(ec)
527           {
528              if (e_client_util_ignored_get(ec)) continue;
529              if (!e_desk_has_ec(desk, ec)) continue;
530              if (ec->deskshow)
531                {
532                   ec->deskshow = 0;
533                   e_client_uniconify(ec);
534                }
535           }
536      }
537    else
538      {
539         /*
540          * iconify raises, so we have to start from the bottom so we are going forward
541          */
542         E_CLIENT_FOREACH(ec)
543           {
544              if (e_client_util_ignored_get(ec)) continue;
545              if (!e_desk_has_ec(desk, ec)) continue;
546              if (ec->iconic) continue;
547              if (ec->netwm.state.skip_taskbar) continue;
548              if (ec->user_skip_winlist) continue;
549              ec->deskshow = 1;
550              e_client_iconify(ec);
551           }
552      }
553    desk->deskshow_toggle = !desk->deskshow_toggle;
554
555    _e_desk_event_simple_add(desk, E_EVENT_DESK_DESKSHOW);
556 }
557
558 EINTERN void
559 e_desk_row_add(E_Zone *zone)
560 {
561    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count + 1);
562 }
563
564 EINTERN void
565 e_desk_row_remove(E_Zone *zone)
566 {
567    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count - 1);
568 }
569
570 EINTERN void
571 e_desk_col_add(E_Zone *zone)
572 {
573    e_zone_desk_count_set(zone, zone->desk_x_count + 1, zone->desk_y_count);
574 }
575
576 EINTERN void
577 e_desk_col_remove(E_Zone *zone)
578 {
579    e_zone_desk_count_set(zone, zone->desk_x_count - 1, zone->desk_y_count);
580 }
581
582 E_API E_Desk *
583 e_desk_current_get(E_Zone *zone)
584 {
585    E_OBJECT_CHECK_RETURN(zone, NULL);
586    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
587
588    return e_desk_at_xy_get(zone, zone->desk_x_current, zone->desk_y_current);
589 }
590
591 EINTERN E_Desk *
592 e_desk_at_xy_get(E_Zone *zone, int x, int y)
593 {
594    E_OBJECT_CHECK_RETURN(zone, NULL);
595    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
596
597    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
598      return NULL;
599    else if ((x < 0) || (y < 0))
600      return NULL;
601
602    if (!zone->desks) return NULL;
603    return zone->desks[x + (y * zone->desk_x_count)];
604 }
605
606 EINTERN E_Desk *
607 e_desk_at_pos_get(E_Zone *zone, int pos)
608 {
609    int x, y;
610
611    E_OBJECT_CHECK_RETURN(zone, NULL);
612    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
613
614    y = pos / zone->desk_x_count;
615    x = pos - (y * zone->desk_x_count);
616
617    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
618      return NULL;
619
620    return zone->desks[x + (y * zone->desk_x_count)];
621 }
622
623 EINTERN void
624 e_desk_xy_get(E_Desk *desk, int *x, int *y)
625 {
626    E_OBJECT_CHECK(desk);
627    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
628
629    if (x) *x = desk->x;
630    if (y) *y = desk->y;
631 }
632
633 EINTERN void
634 e_desk_next(E_Zone *zone)
635 {
636    int x, y;
637
638    E_OBJECT_CHECK(zone);
639    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
640
641    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
642      return;
643
644    x = zone->desk_x_current;
645    y = zone->desk_y_current;
646
647    x++;
648    if (x >= zone->desk_x_count)
649      {
650         x = 0;
651         y++;
652         if (y >= zone->desk_y_count) y = 0;
653      }
654
655    e_desk_show(e_desk_at_xy_get(zone, x, y));
656 }
657
658 EINTERN void
659 e_desk_prev(E_Zone *zone)
660 {
661    int x, y;
662
663    E_OBJECT_CHECK(zone);
664    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
665
666    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
667      return;
668
669    x = zone->desk_x_current;
670    y = zone->desk_y_current;
671
672    x--;
673    if (x < 0)
674      {
675         x = zone->desk_x_count - 1;
676         y--;
677         if (y < 0) y = zone->desk_y_count - 1;
678      }
679    e_desk_show(e_desk_at_xy_get(zone, x, y));
680 }
681
682 EINTERN unsigned int
683 e_desks_count(void)
684 {
685    Eina_List *l;
686    E_Zone *zone;
687    unsigned int count = 0;
688
689    EINA_LIST_FOREACH(e_comp->zones, l, zone)
690      {
691         int cx = 0, cy = 0;
692
693         e_zone_desk_count_get(zone, &cx, &cy);
694         count += cx * cy;
695      }
696    return count;
697 }
698
699 static void
700 _e_desk_client_data_del(E_Desk *desk, E_Client *ec)
701 {
702    evas_object_data_del(ec->frame, DESK_EC_DATA_KEY);
703 }
704
705 static void
706 _e_desk_client_data_set(E_Desk *desk, E_Client *ec)
707 {
708   E_Desk *data;
709
710   data = evas_object_data_get(ec->frame, DESK_EC_DATA_KEY);
711   if (data)
712     {
713        if (data == desk)
714          {
715             ELOGF("E_DESK", "EC is already added to desk_id:%d", ec, desk->id);
716             return;
717          }
718
719        evas_object_data_del(ec->frame, DESK_EC_DATA_KEY);
720     }
721
722   evas_object_data_set(ec->frame, DESK_EC_DATA_KEY, desk);
723 }
724
725 #ifdef REFACTOR_DESK_AREA
726 #else
727 static void
728 _e_client_event_desk_set_free(void *d EINA_UNUSED, E_Event_Client_Desk_Set *ev)
729 {
730    UNREFD(ev->ec, 4);
731    e_object_unref(E_OBJECT(ev->ec));
732    e_object_unref(E_OBJECT(ev->desk));
733    free(ev);
734 }
735 #endif
736
737 static void
738 _e_desk_client_set(E_Desk *desk, E_Client *ec)
739 {
740 #ifdef REFACTOR_DESK_AREA
741 #else
742    E_Desk *old_desk;
743    E_Event_Client_Desk_Set *ev;
744
745    old_desk = e_comp_desk_find_by_ec(ec);
746    if (ec->fullscreen)
747      {
748         if (old_desk)
749           old_desk->fullscreen_clients = eina_list_remove(old_desk->fullscreen_clients, ec);
750
751         desk->fullscreen_clients = eina_list_append(desk->fullscreen_clients, ec);
752      }
753
754    if (old_desk)
755      e_desk_client_del(old_desk, ec);
756 #endif
757
758    ec->desk = desk; // FIXME: This line must be deleted.
759
760    if (!ec->new_client)
761      {
762         if (ec->frame)
763           {
764              e_comp_object_effect_unclip(ec->frame);
765              e_comp_object_effect_set(ec->frame, NULL);
766           }
767         if (desk->visible || ec->sticky)
768           {
769              if ((!ec->hidden) && (!ec->iconic))
770                evas_object_show(ec->frame);
771           }
772         else
773           {
774              ec->hidden = 1;
775              evas_object_hide(ec->frame);
776           }
777      }
778
779    e_client_comp_hidden_set(ec, (!desk->visible) && (!ec->sticky));
780
781 #ifdef REFACTOR_DESK_AREA
782 #else
783    if (old_desk)
784      {
785         // e_client_desk_set_event_notify(ec);
786         ev = E_NEW(E_Event_Client_Desk_Set, 1);
787         if (ev)
788           {
789              ev->ec = ec;
790              UNREFD(ec, 4);
791              e_object_ref(E_OBJECT(ec));
792              ev->desk = old_desk;
793              e_object_ref(E_OBJECT(old_desk));
794              ecore_event_add(E_EVENT_CLIENT_DESK_SET, ev, (Ecore_End_Cb)_e_client_event_desk_set_free, NULL);
795           }
796
797         if (e_zone_has_ec(old_desk->zone, ec))
798           {
799              e_client_res_change_geometry_save(ec);
800              e_client_res_change_geometry_restore(ec);
801              ec->pre_res_change.valid = 0;
802           }
803      }
804 #endif
805
806    if (e_config->transient.desktop)
807      {
808         E_Client *child;
809         const Eina_List *l;
810
811         EINA_LIST_FOREACH(ec->transients, l, child)
812           e_desk_client_add(desk, child);
813      }
814
815    evas_object_smart_callback_call(ec->frame, "desk_change", ec);
816
817 #ifdef REFACTOR_DESK_AREA
818 #else
819    if (desk->desk_area.enable)
820      {
821         if (!ec->desk_area.desk_area)
822           {
823              E_Desk_Area *eda;
824              eda = e_desk_desk_area_base_get(desk);
825              e_desk_area_ec_reassign(eda, ec);
826           }
827
828         e_desk_area_ec_enable_set(desk->desk_area.base, ec, EINA_TRUE);
829      }
830 #endif
831 }
832
833 #ifdef REFACTOR_DESK_AREA
834 static void
835 _e_desk_private_client_del(E_Desk_Private_Client *desk_client)
836 {
837    E_Desk *desk = desk_client->desk;
838    E_Client *ec = desk_client->ec;
839
840    _e_desk_smart_client_del(desk->smart_obj, ec);
841    _e_desk_client_data_del(desk, ec);
842
843    wl_list_remove(&desk_client->client_activate_done.link);
844    wl_list_remove(&desk_client->client_destroy.link);
845
846    E_FREE(desk_client);
847 }
848
849 static void
850 _desk_cb_client_destroy(struct wl_listener *listener, void *data)
851 {
852    E_Desk_Private_Client *desk_client;
853    E_Desk *desk;
854    E_Client *ec;
855
856    desk_client = wl_container_of(listener, desk_client, client_destroy);
857    desk = desk_client->desk;
858    ec = desk_client->ec;
859
860    ELOGF("DESK", "CLIENT DESTROY. desk:%p", ec, desk);
861
862    _e_desk_private_client_del(desk_client);
863 }
864
865 static void
866 _desk_cb_client_activate_done(struct wl_listener *listener, void *data)
867 {
868    E_Desk_Private_Client *desk_client;
869    E_Desk *desk;
870    E_Client *ec;
871
872    desk_client = wl_container_of(listener, desk_client, client_activate_done);
873    desk = desk_client->desk;
874    ec = desk_client->ec;
875
876    ELOGF("DESK", "CLIENT ACTIVATE DONE. desk:%p", ec, desk);
877
878    if ((!ec->iconic) && (!ec->sticky))
879      {
880         e_desk_show(desk);
881      }
882
883    if (!e_client_desk_iconify_skip_get(ec))
884      {
885         e_desk_visible_client_iconified_list_remove_all(desk);
886      }
887 }
888 #endif
889
890 EINTERN void
891 e_desk_client_add(E_Desk *desk, E_Client *ec)
892 {
893 #ifdef REFACTOR_DESK_AREA
894    E_Desk_Area *eda;
895    E_Desk_Private_Client *desk_client;
896 #endif
897    E_OBJECT_CHECK(desk);
898    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
899
900    E_OBJECT_CHECK(ec);
901    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
902
903    if (e_desk_has_ec(desk, ec)) return;
904
905    ELOGF("DESK", "CLIENT ADD. desk:%p", ec, desk);
906
907 #ifdef REFACTOR_DESK_AREA
908
909    desk_client = E_NEW(E_Desk_Private_Client, 1);
910    EINA_SAFETY_ON_NULL_RETURN(desk_client);
911
912    desk_client->desk = desk;
913    desk_client->ec = ec;
914
915    // e_client listeners
916    desk_client->client_destroy.notify = _desk_cb_client_destroy;
917    e_client_destroy_listener_add(ec, &desk_client->client_destroy);
918    desk_client->client_activate_done.notify = _desk_cb_client_activate_done;
919    e_client_activate_done_listener_add(ec, &desk_client->client_activate_done);
920 #endif
921
922    _e_desk_client_set(desk, ec);
923    _e_desk_client_data_set(desk, ec);
924
925 #ifdef REFACTOR_DESK_AREA
926    eda = e_desk_desk_area_base_get(desk);
927    e_desk_area_ec_add(eda, ec);
928
929    _e_desk_smart_client_add(desk->smart_obj, ec);
930
931    wl_signal_emit_mutable(&PRI(desk)->events.client_add, desk);
932    _e_desk_hook_call(E_DESK_HOOK_CLIENT_ADD, desk);
933 #else
934    if (desk->desk_area.enable)
935      {
936         E_Desk_Area *eda;
937         eda = e_desk_desk_area_base_get(desk);
938
939         e_desk_area_ec_add(eda, ec);
940         e_desk_area_ec_enable_set(desk->desk_area.base, ec, EINA_TRUE);
941      }
942
943
944    _e_desk_smart_client_add(desk->smart_obj, ec);
945
946    wl_signal_emit_mutable(&PRI(desk)->events.client_add, desk);
947    _e_desk_hook_call(E_DESK_HOOK_CLIENT_ADD, desk);
948
949 #endif
950 }
951
952 #ifdef REFACTOR_DESK_AREA
953 static E_Desk_Private_Client *
954 _e_desk_private_client_get(E_Client *ec)
955 {
956    E_Desk_Private_Client *desk_client;
957    struct wl_listener *listener;
958
959    listener = e_client_destroy_listener_get(ec, _desk_cb_client_destroy);
960    if (!listener) return NULL;
961
962    return wl_container_of(listener, desk_client, client_destroy);
963 }
964 #endif
965
966 E_API void
967 e_desk_client_del(E_Desk *desk, E_Client *ec)
968 {
969 #ifdef REFACTOR_DESK_AREA
970    E_Desk_Private_Client *desk_client;
971    E_Desk_Area *eda;
972 #endif
973    E_OBJECT_CHECK(desk);
974    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
975
976    E_OBJECT_CHECK(ec);
977    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
978
979 #ifdef REFACTOR_DESK_AREA
980    if (!e_desk_has_ec(desk, ec)) return;
981
982    ELOGF("DESK", "CLIENT REMOVE. desk:%p", ec, desk);
983
984    desk_client = _e_desk_private_client_get(ec);
985    EINA_SAFETY_ON_NULL_RETURN(desk_client);
986
987    eda = e_desk_desk_area_find_by_ec(desk, ec);
988    EINA_SAFETY_ON_NULL_RETURN(eda);
989
990    e_desk_area_ec_remove(eda, ec);
991
992    _e_desk_private_client_del(desk_client);
993 #else
994    _e_desk_smart_client_del(desk->smart_obj, ec);
995
996    if (desk->desk_area.enable)
997      {
998         E_Desk_Area *eda;
999         eda = e_desk_desk_area_base_get(desk);
1000
1001         e_desk_area_ec_enable_set(desk->desk_area.base, ec, EINA_FALSE);
1002         e_desk_area_ec_remove(eda, ec);
1003      }
1004
1005    _e_desk_client_data_del(desk, ec);
1006 #endif
1007 }
1008
1009 E_API void
1010 e_desk_geometry_set(E_Desk *desk, int x, int y, int w, int h)
1011 {
1012    E_Client *ec;
1013    E_Maximize max;
1014    Eina_List *l = NULL, *ll = NULL;
1015    Evas_Object *m;
1016    E_Event_Desk_Geometry_Change *ev = NULL;
1017
1018    int cx, cy, dx, dy;
1019
1020    E_OBJECT_CHECK(desk);
1021    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1022
1023    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1024
1025    if ((desk->geom.x == x) && (desk->geom.y == y) &&
1026        (desk->geom.w == w) && (desk->geom.h == h))
1027      return;
1028
1029    dx = x - desk->geom.x;
1030    dy = y - desk->geom.y;
1031    EINA_RECTANGLE_SET(&desk->geom, x, y, w, h);
1032
1033    EINA_LIST_FOREACH(sd->clients, l, ec)
1034      {
1035         if (e_object_is_del(E_OBJECT(ec))) continue;
1036
1037         /* even if the desktop geometry is chagned, the system partial windows such as virtual
1038          * keyboard and clipboard should be placed at the bottom of the desktop. */
1039         /* QUICK FIX */
1040         if (e_policy_client_is_keyboard(ec))
1041           {
1042              continue;
1043           }
1044         else if (e_comp_wl_subsurface_check(ec))
1045            {
1046               continue;
1047            }
1048         else if (ec->maximized)
1049           {
1050              max = ec->maximized;
1051              ec->maximized = E_MAXIMIZE_NONE;
1052              e_client_maximize(ec, max);
1053           }
1054         else
1055           {
1056              e_client_geometry_get(ec, &cx, &cy, NULL, NULL);
1057              e_client_util_move_without_frame(ec, cx + dx, cy + dy);
1058           }
1059      }
1060
1061    // E Client as an member of smart object is not changed even though parent obj is changed
1062    // Workaround : update max geometry if ec is a member of desk->smart_obj
1063    EINA_LIST_FOREACH(evas_object_smart_members_get(desk->smart_obj), ll, m)
1064      {
1065         ec = evas_object_data_get(m, "E_Client");
1066         if (ec && ec->maximized)
1067           {
1068              if (e_object_is_del(E_OBJECT(ec))) continue;
1069              max = ec->maximized;
1070              ec->maximized = E_MAXIMIZE_NONE;
1071              e_client_maximize(ec, max);
1072           }
1073      }
1074
1075    // apply geometry on smart obj
1076    evas_object_geometry_set(desk->smart_obj, x, y, w, h);
1077
1078    ev = E_NEW(E_Event_Desk_Geometry_Change, 1);
1079    if (ev)
1080      {
1081         ev->desk = desk;
1082         ev->x = x;
1083         ev->y = y;
1084         ev->w = w;
1085         ev->h = h;
1086         e_object_ref(E_OBJECT(desk));
1087         ecore_event_add(E_EVENT_DESK_GEOMETRY_CHANGE, ev,
1088                         _e_desk_event_desk_geometry_change_free, NULL);
1089      }
1090
1091    e_comp_render_queue();
1092 }
1093
1094 static Eina_Bool
1095 _e_desk_zoom_animate_cb(void *data, double pos)
1096 {
1097    E_Desk *desk;
1098    E_Client *ec;
1099    Eina_List *l;
1100    int cx, cy;
1101    double zoomx, zoomy;
1102    double progress;
1103    double diff_x, diff_y;
1104    double cBez[4] = {0.3, 0.0, 0.15, 1.0};
1105
1106    desk = (E_Desk*)data;
1107    if (!desk) return ECORE_CALLBACK_CANCEL;
1108
1109    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd) ECORE_CALLBACK_CANCEL;
1110
1111    progress = ecore_animator_pos_map_n(pos, ECORE_POS_MAP_CUBIC_BEZIER, 4, cBez);
1112
1113    diff_x = sd->zoom.prev_ratio_x - sd->zoom.ratio_x;
1114    diff_y = sd->zoom.prev_ratio_y - sd->zoom.ratio_y;
1115
1116    zoomx = sd->zoom.ratio_x + (diff_x * (1-progress));
1117    zoomy = sd->zoom.ratio_y + (diff_y * (1-progress));
1118    cx = sd->zoom.cord_x;
1119    cy = sd->zoom.cord_y;
1120
1121    EINA_LIST_FOREACH(sd->clients, l, ec)
1122      {
1123         if ((e_client_visibility_get(ec) == E_VISIBILITY_UNOBSCURED) ||
1124             (e_comp_wl_subsurface_check(ec)))
1125           _e_desk_client_zoom(ec, zoomx, zoomy, cx, cy);
1126      }
1127
1128    if (pos >= 1.0)
1129      {
1130         EINA_LIST_FOREACH(sd->clients, l, ec)
1131           {
1132              _e_desk_client_zoom(ec, zoomx, zoomy, cx, cy);
1133           }
1134
1135         if ((sd->zoom.ratio_x != 1.0) ||
1136             (sd->zoom.ratio_y != 1.0))
1137           {
1138              // Zoom enable done
1139              sd->zoom.enabled = EINA_TRUE;
1140           }
1141
1142         sd->zoom.animating_type = E_DESK_ZOOM_ANIMATING_TYPE_NONE;
1143         sd->zoom.animator = NULL;
1144      }
1145
1146    return ECORE_CALLBACK_PASS_ON;
1147 }
1148
1149 E_API void
1150 e_desk_zoom_set(E_Desk *desk, double zoomx, double zoomy, int cx, int cy)
1151 {
1152    E_Client *ec;
1153    Eina_List *l;
1154    E_Zone *zone = NULL;
1155    E_Output *eout = NULL;
1156
1157    E_OBJECT_CHECK(desk);
1158    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1159
1160    ELOGF("DESK", "ZOOM SET. desk:%p, zoom ratio(%f,%f) cpos(%d,%d)", NULL, desk, zoomx, zoomy, cx, cy);
1161
1162    if (e_config->use_pp_zoom)
1163      {
1164         if (e_comp_screen_pp_support())
1165           {
1166              zone = desk->zone;
1167              eout = e_output_find(zone->output_id);
1168              if (!eout)
1169                {
1170                   ERR("e_desk_zoom_set: fail get eout");
1171                   goto end;
1172                }
1173              if (!e_output_zoom_set(eout, zoomx, zoomy, cx, cy))
1174                ERR("e_desk_zoom_set: fail zoom set");
1175              else
1176                DBG("e_desk_zoom_set: zoomx:%f, zoomy:%f, x:%d, y:%d", zoomx, zoomy, cx, cy);
1177
1178              goto end;
1179           }
1180      }
1181
1182    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1183
1184    if ((sd->zoom.ratio_x != zoomx) || (sd->zoom.ratio_y != zoomy) ||
1185        (sd->zoom.cord_x != cx) || (sd->zoom.cord_y != cy))
1186      {
1187         sd->zoom.prev_ratio_x = sd->zoom.ratio_x;
1188         sd->zoom.prev_ratio_y = sd->zoom.ratio_y;
1189         sd->zoom.prev_cord_x = sd->zoom.cord_x;
1190         sd->zoom.prev_cord_y = sd->zoom.cord_y;
1191
1192         sd->zoom.ratio_x = zoomx;
1193         sd->zoom.ratio_y = zoomy;
1194         sd->zoom.cord_x = cx;
1195         sd->zoom.cord_y = cy;
1196
1197         if (e_config->desk_zoom_effect.enable)
1198           {
1199              if (sd->zoom.animator)
1200                {
1201                   ecore_animator_del(sd->zoom.animator);
1202                   sd->zoom.animator = NULL;
1203                }
1204
1205              sd->zoom.animating_type = E_DESK_ZOOM_ANIMATING_TYPE_ENABLE;
1206              sd->zoom.animator = ecore_animator_timeline_add(e_config->desk_zoom_effect.duration,
1207                                                              _e_desk_zoom_animate_cb, desk);
1208              _e_desk_object_zoom(desk->smart_obj, zoomx, zoomy, cx, cy);
1209           }
1210         else
1211           {
1212              _e_desk_object_zoom(desk->smart_obj, zoomx, zoomy, cx, cy);
1213              EINA_LIST_FOREACH(sd->clients, l, ec)
1214                {
1215                   _e_desk_client_zoom(ec, zoomx, zoomy, cx, cy);
1216                }
1217           }
1218      }
1219
1220    if (!sd->zoom.enabled)
1221      {
1222         /* if desk_zoom_effect is enabled,
1223            then sd->zoom.enabled will be set after finishing effect */
1224         if (!e_config->desk_zoom_effect.enable)
1225           sd->zoom.enabled = EINA_TRUE;
1226
1227         /*
1228          * NOTE: evas_object_map_enable_set is called in _e_desk_client_zoom()
1229          */
1230         /*
1231          * evas_object_map_enable_set(desk->smart_obj, EINA_TRUE);
1232          * EINA_LIST_FOREACH(sd->clients, l, ec)
1233          *   evas_object_map_enable_set(ec->frame, EINA_TRUE);
1234          */
1235      }
1236
1237 end:
1238    _e_desk_event_simple_add(desk, E_EVENT_DESK_ZOOM_SET);
1239 }
1240
1241 E_API Eina_Bool
1242 e_desk_zoom_get(E_Desk *desk, double *zoomx, double *zoomy, int *cx, int *cy)
1243 {
1244    E_Zone *zone = NULL;
1245    E_Output *eout = NULL;
1246    Eina_Bool res = EINA_FALSE;
1247
1248    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
1249    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
1250
1251    if (e_config->use_pp_zoom)
1252      {
1253         if (e_comp_screen_pp_support())
1254           {
1255              zone = desk->zone;
1256              eout = e_output_find(zone->output_id);
1257              if (!eout)
1258                {
1259                   ERR("e_desk_zoom_set: fail get eout");
1260                   return res;
1261                }
1262
1263              res = e_output_zoom_get(eout, zoomx, zoomy, cx, cy);
1264              return res;
1265           }
1266      }
1267
1268    E_DESK_SMART_DATA_GET(desk->smart_obj, sd);
1269    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
1270
1271    if (zoomx) *zoomx = sd->zoom.ratio_x;
1272    if (zoomy) *zoomy = sd->zoom.ratio_y;
1273    if (cx) *cx = sd->zoom.cord_x;
1274    if (cy) *cy = sd->zoom.cord_y;
1275
1276    return EINA_TRUE;
1277 }
1278
1279 EINTERN Eina_Bool
1280 e_desk_zoom_get_center_coordinate(E_Desk *desk, double zoomx, double zoomy, int rectx, int recty, int *cx, int *cy)
1281 {
1282    E_Zone *zone = NULL;
1283    E_Output *eout = NULL;
1284    int w, h;
1285    int zoomw, zoomh;
1286
1287    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
1288    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
1289
1290    zone = desk->zone;
1291    eout = e_output_find(zone->output_id);
1292
1293    e_output_size_get(eout, &w, &h);
1294
1295    zoomw = w / zoomx;
1296    zoomh = h / zoomy;
1297
1298    if (e_config->use_pp_zoom)
1299      {
1300         if (zoomx == 1 || rectx < 0 || zoomw + rectx >= w)
1301           return EINA_FALSE;
1302
1303         if (zoomy == 1 || recty < 0 || zoomh + recty >= h)
1304           return EINA_FALSE;
1305      }
1306    else
1307      {
1308         if (zoomx == 1 || zoomy == 1)
1309           return EINA_FALSE;
1310      }
1311
1312    if (rectx == 0)
1313      *cx = 0;
1314    else
1315      *cx = (int)((zoomx * (double)rectx) / (zoomx - 1.0));
1316
1317    if (recty == 0)
1318      *cy = 0;
1319    else
1320      *cy = (int)((zoomy * (double)recty) / (zoomy - 1.0));
1321
1322    return EINA_TRUE;
1323 }
1324
1325 E_API void
1326 e_desk_zoom_unset(E_Desk *desk)
1327 {
1328    E_Client *ec;
1329    Eina_List *l;
1330    E_Zone *zone = NULL;
1331    E_Output *eout = NULL;
1332
1333    E_OBJECT_CHECK(desk);
1334    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1335
1336    ELOGF("DESK", "ZOOM UNSET. desk:%p", NULL, desk);
1337
1338    if (e_config->use_pp_zoom)
1339      {
1340         if (e_comp_screen_pp_support())
1341           {
1342              zone = desk->zone;
1343              eout = e_output_find(zone->output_id);
1344              if (!eout)
1345                {
1346                   ERR("e_desk_zoom_unset: fail get eout");
1347                   goto end;
1348                }
1349
1350              e_output_zoom_unset(eout);
1351              DBG("e_desk_zoom_unset");
1352
1353              goto end;
1354           }
1355      }
1356
1357    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1358
1359    if (!sd->zoom.enabled)
1360      {
1361         if (sd->zoom.animating_type != E_DESK_ZOOM_ANIMATING_TYPE_ENABLE)
1362           {
1363              goto end;
1364           }
1365      }
1366
1367    sd->zoom.prev_ratio_x = sd->zoom.ratio_x;
1368    sd->zoom.prev_ratio_y = sd->zoom.ratio_y;
1369    sd->zoom.prev_cord_x = sd->zoom.cord_x;
1370    sd->zoom.prev_cord_y = sd->zoom.cord_y;
1371
1372    sd->zoom.ratio_x = 1.0;
1373    sd->zoom.ratio_y = 1.0;
1374    sd->zoom.cord_x = 0;
1375    sd->zoom.cord_y = 0;
1376    sd->zoom.enabled = EINA_FALSE;
1377
1378    if (e_config->desk_zoom_effect.enable)
1379      {
1380         if (sd->zoom.animator)
1381           {
1382              ecore_animator_del(sd->zoom.animator);
1383              sd->zoom.animator = NULL;
1384           }
1385
1386         sd->zoom.animating_type = E_DESK_ZOOM_ANIMATING_TYPE_DISABLE;
1387         sd->zoom.animator = ecore_animator_timeline_add(e_config->desk_zoom_effect.duration,
1388                                                         _e_desk_zoom_animate_cb, desk);
1389         _e_desk_object_zoom(desk->smart_obj, sd->zoom.ratio_x, sd->zoom.ratio_y,
1390                             sd->zoom.cord_x, sd->zoom.cord_y);
1391      }
1392    else
1393      {
1394         _e_desk_object_zoom(desk->smart_obj, sd->zoom.ratio_x, sd->zoom.ratio_y,
1395                             sd->zoom.cord_x, sd->zoom.cord_y);
1396         /*
1397          * NOTE: evas_object_map_enable_set is called in _e_desk_client_zoom()
1398          */
1399         /*
1400          * evas_object_map_enable_set(desk->smart_obj, EINA_FALSE);
1401          */
1402         EINA_LIST_FOREACH(sd->clients, l, ec)
1403           {
1404              /* NOTE Is it really necessary?
1405               * Why isn't it enough to just call evas_object_map_enable_set(false)? */
1406              _e_desk_client_zoom(ec, sd->zoom.ratio_x, sd->zoom.ratio_y,
1407                                  sd->zoom.cord_x, sd->zoom.cord_y);
1408              //evas_object_map_enable_set(ec->frame, EINA_FALSE);
1409           }
1410      }
1411
1412 end:
1413    _e_desk_event_simple_add(desk, E_EVENT_DESK_ZOOM_UNSET);
1414 }
1415
1416 E_API void
1417 e_desk_smart_member_add(E_Desk *desk, Evas_Object *obj)
1418 {
1419    E_OBJECT_CHECK(desk);
1420    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1421
1422    evas_object_smart_member_add(obj, desk->smart_obj);
1423 }
1424
1425 E_API void
1426 e_desk_smart_member_del(Evas_Object *obj)
1427 {
1428    evas_object_smart_member_del(obj);
1429 }
1430
1431 E_API Eina_Bool
1432 e_desk_client_zoom_skip_set(E_Desk * desk, E_Client * ec)
1433 {
1434    E_Desk *ec_desk;
1435
1436    if (!desk) return EINA_FALSE;
1437    if (!ec) return EINA_FALSE;
1438
1439    ec_desk = e_zone_desk_find_by_ec(desk->zone, ec);
1440    if (!ec_desk) return EINA_FALSE;
1441
1442    ELOGF("DESK", "Client zoom skip set. desk:%p, ec_desk:%p)", ec, desk, ec_desk);
1443
1444    if (!e_desk_has_ec(desk, ec)) return EINA_FALSE;
1445    e_desk_client_del(ec_desk, ec);
1446
1447    return EINA_TRUE;
1448 }
1449
1450 E_API Eina_Bool
1451 e_desk_client_zoom_skip_unset(E_Desk *desk, E_Client *ec)
1452 {
1453    E_Desk *ec_desk;
1454
1455    if (!desk) return EINA_FALSE;
1456    if (!ec) return EINA_FALSE;
1457
1458    ec_desk = e_zone_desk_find_by_ec(desk->zone, ec);
1459    if (!ec_desk) return EINA_FALSE;
1460
1461    ELOGF("DESK", "Client zoom skip set. desk:%p, ec_desk:%p)", ec, desk, ec_desk);
1462
1463    if (!e_desk_has_ec(desk, ec)) return EINA_FALSE;
1464
1465    _e_desk_smart_client_add(desk->smart_obj, ec);
1466
1467    return EINA_TRUE;
1468 }
1469
1470 EINTERN void
1471 e_desk_client_zoom_apply(E_Desk *desk, E_Client *ec)
1472 {
1473    E_OBJECT_CHECK(desk);
1474    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1475
1476    E_OBJECT_CHECK(ec);
1477    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
1478
1479    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1480    if (!eina_list_data_find(sd->clients, ec))
1481      return;
1482
1483    if (sd->zoom.enabled)
1484      {
1485         _e_desk_client_zoom(ec,
1486                             sd->zoom.ratio_x, sd->zoom.ratio_y,
1487                             sd->zoom.cord_x, sd->zoom.cord_y);
1488      }
1489 }
1490
1491 EINTERN Eina_Bool
1492 e_desk_zoom_is_animating(E_Desk *desk)
1493 {
1494    E_DESK_SMART_DATA_GET(desk->smart_obj, sd);
1495    if (!sd) return EINA_FALSE;
1496
1497    if (!e_config->desk_zoom_effect.enable) return EINA_FALSE;
1498
1499    return !!sd->zoom.animator;
1500 }
1501
1502 E_API void
1503 e_desk_visible_client_iconify_all(E_Desk *desk)
1504 {
1505    E_Client *ec;
1506    Eina_List *l;
1507
1508    if (!desk) return;
1509
1510    ELOGF("DESK", "ICONIFY ALL VISIBLE WINDOW", NULL);
1511    E_CLIENT_REVERSE_FOREACH(ec)
1512      {
1513         if (!e_desk_has_ec(desk, ec)) continue;
1514         if (e_object_is_del(E_OBJECT(ec))) continue;
1515         if (!ec->visible) continue;
1516         if (ec->netwm.type == E_WINDOW_TYPE_DESKTOP) continue;
1517         if (e_client_desk_iconify_skip_get(ec)) continue;
1518         if (e_client_visibility_get(ec) == E_VISIBILITY_UNKNOWN) continue;
1519         if (e_client_visibility_get(ec) != E_VISIBILITY_UNOBSCURED)
1520           {
1521              if (e_client_is_iconified_by_client(ec))
1522                continue;
1523           }
1524
1525         ELOGF("DESK", "Add to iconified list...", ec);
1526         desk->iconified_list = eina_list_remove(desk->iconified_list, ec);
1527         desk->iconified_list = eina_list_append(desk->iconified_list, ec);
1528      }
1529
1530    // bottom to top
1531    EINA_LIST_REVERSE_FOREACH(desk->iconified_list, l, ec)
1532      {
1533         e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT);
1534         e_policy_wl_iconify_state_change_send(ec, 1);
1535         e_client_iconify(ec);
1536      }
1537 }
1538
1539 E_API void
1540 e_desk_visible_client_restore_all(E_Desk *desk)
1541 {
1542    E_Client *ec;
1543    Eina_List *restore_list;
1544    Eina_List *l;
1545
1546    if (!desk) return;
1547    if (!desk->iconified_list) return;
1548
1549    ELOGF("DESK", "RESTORE ALL VISIBLE WINDOW", NULL);
1550
1551    restore_list = eina_list_clone(desk->iconified_list);
1552
1553    eina_list_free(desk->iconified_list);
1554    desk->iconified_list = NULL;
1555
1556    // bottom to top
1557    EINA_LIST_REVERSE_FOREACH(restore_list, l, ec)
1558      {
1559         ELOGF("DESK", "Restore from iconified list...", ec);
1560         e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
1561         e_policy_wl_iconify_state_change_send(ec, 0);
1562         e_client_uniconify(ec);
1563      }
1564    eina_list_free(restore_list);
1565 }
1566
1567 E_API void
1568 e_desk_visible_client_iconified_list_remove(E_Desk *desk, E_Client *ec)
1569 {
1570    if (!desk || !ec) return;
1571    if (!desk->iconified_list) return;
1572
1573    ELOGF("DESK", "Remove from iconified list", ec);
1574    desk->iconified_list = eina_list_remove(desk->iconified_list, ec);
1575 }
1576
1577 E_API void
1578 e_desk_visible_client_iconified_list_remove_all(E_Desk *desk)
1579 {
1580    if (!desk) return;
1581    if (!desk->iconified_list) return;
1582
1583    ELOGF("DESK", "Remove iconified list all", NULL);
1584    eina_list_free(desk->iconified_list);
1585    desk->iconified_list = NULL;
1586 }
1587
1588 E_API Eina_List *
1589 e_desk_visible_client_iconified_list_get(E_Desk *desk)
1590 {
1591    if (!desk) return NULL;
1592    return desk->iconified_list;
1593 }
1594
1595 static void
1596 _e_desk_free(E_Desk *desk)
1597 {
1598    Eina_List *l;
1599    E_Desk_Area *eda;
1600
1601    for (int i=E_DESK_AREA_LAYER_COUNT-1; i>=0; i--)
1602       {
1603          EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
1604          {
1605             e_object_del(E_OBJECT(eda));
1606          }
1607          eina_list_free(desk->desk_area.list[i]);
1608          desk->desk_area.list[i] = NULL;
1609       }
1610
1611    e_desk_desk_area_del(desk, desk->desk_area.base);
1612    desk->desk_area.base = NULL;
1613    desk->desk_area.active = NULL;
1614
1615
1616    E_FREE_FUNC(desk->smart_obj, evas_object_del);
1617    eina_stringshare_del(desk->name);
1618    desk->name = NULL;
1619    E_FREE_LIST(desk->handlers, ecore_event_handler_del);
1620
1621    _e_desk_private_finish(desk);
1622    free(desk);
1623 }
1624
1625 static void
1626 _e_desk_event_desk_show_free(void *data EINA_UNUSED, void *event)
1627 {
1628    E_Event_Desk_Show *ev;
1629
1630    ev = event;
1631    e_object_unref(E_OBJECT(ev->desk));
1632    free(ev);
1633 }
1634
1635 static void
1636 _e_desk_event_desk_before_show_free(void *data EINA_UNUSED, void *event)
1637 {
1638    E_Event_Desk_Before_Show *ev;
1639
1640    ev = event;
1641    e_object_unref(E_OBJECT(ev->desk));
1642    free(ev);
1643 }
1644
1645 static void
1646 _e_desk_event_desk_after_show_free(void *data EINA_UNUSED, void *event)
1647 {
1648    E_Event_Desk_After_Show *ev;
1649
1650    ev = event;
1651    e_object_unref(E_OBJECT(ev->desk));
1652    free(ev);
1653 }
1654
1655 static void
1656 _e_desk_event_desk_geometry_change_free(void *data EINA_UNUSED, void *event)
1657 {
1658    E_Event_Desk_Geometry_Change *ev = event;
1659    e_object_unref(E_OBJECT(ev->desk));
1660    E_FREE(ev);
1661 }
1662
1663 static Eina_Bool
1664 _e_desk_transition_setup(E_Client *ec, int dx, int dy, int state)
1665 {
1666    e_comp_object_effect_set(ec->frame, "none");
1667
1668    return EINA_FALSE;
1669 }
1670
1671 static void
1672 _e_desk_show_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1673 {
1674    E_Client *ec = data;
1675    E_Zone *ec_zone;
1676    E_Desk *ec_desk;
1677
1678    ec_zone = e_comp_zone_find_by_ec(ec);
1679    ec_desk = e_zone_desk_find_by_ec(ec_zone, ec);
1680    if (ec_desk)
1681      ec_desk->animate_count--;
1682
1683    e_client_comp_hidden_set(ec, 0);
1684    e_comp_object_effect_unclip(ec->frame);
1685    ec->hidden = 0;
1686    if (!ec->visible) evas_object_show(ec->frame);
1687
1688    if (ec_desk != e_desk_current_get(ec_zone)) return;
1689 }
1690
1691 static void
1692 _e_desk_hide_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1693 {
1694    E_Client *ec = data;
1695    E_Desk *ec_desk;
1696
1697    ec_desk = e_comp_desk_find_by_ec(ec);
1698    if (ec_desk)
1699      ec_desk->animate_count--;
1700    ec->hidden = 1;
1701    evas_object_hide(ec->frame);
1702 }
1703
1704 static void
1705 _e_desk_show_begin(E_Desk *desk, int dx, int dy)
1706 {
1707    E_Client *ec;
1708
1709    if (dx < 0) dx = -1;
1710    if (dx > 0) dx = 1;
1711    if (dy < 0) dy = -1;
1712    if (dy > 0) dy = 1;
1713
1714    desk->animate_count = 0;
1715    E_CLIENT_FOREACH(ec)
1716      {
1717         if (e_client_util_ignored_get(ec) || (!e_zone_has_ec(desk->zone, ec)) || (ec->iconic)) continue;
1718         if (ec->moving)
1719           {
1720              e_desk_client_add(desk, ec);
1721              evas_object_show(ec->frame);
1722              continue;
1723           }
1724         if ((!e_desk_has_ec(desk, ec)) || (ec->sticky)) continue;
1725         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, dx, dy, 1))
1726           {
1727              e_comp_object_effect_stop(ec->frame, _e_desk_hide_end);
1728              e_comp_object_effect_start(ec->frame, _e_desk_show_end, ec);
1729              desk->animate_count++;
1730           }
1731         else
1732           ec->hidden = 0;
1733
1734         e_client_comp_hidden_set(ec, ec->hidden);
1735         evas_object_show(ec->frame);
1736      }
1737 }
1738
1739 static void
1740 _e_desk_hide_begin(E_Desk *desk, int dx, int dy)
1741 {
1742    E_Client *ec;
1743
1744    if (dx < 0) dx = -1;
1745    if (dx > 0) dx = 1;
1746    if (dy < 0) dy = -1;
1747    if (dy > 0) dy = 1;
1748
1749    desk->animate_count = 0;
1750    E_CLIENT_FOREACH(ec)
1751      {
1752         if (e_client_util_ignored_get(ec)) continue;
1753         if ((!e_zone_has_ec(desk->zone, ec)) || (ec->iconic)) continue;
1754         if (ec->moving) continue;
1755         if ((!e_desk_has_ec(desk, ec)) || (ec->sticky)) continue;
1756         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, -dx, -dy, 0))
1757           {
1758              e_comp_object_effect_stop(ec->frame, _e_desk_show_end);
1759              e_comp_object_effect_start(ec->frame, _e_desk_hide_end, ec);
1760              desk->animate_count++;
1761           }
1762         else
1763           {
1764              ec->hidden = 1;
1765              evas_object_show(ec->frame);
1766              ec->changes.visible = 0;
1767              evas_object_hide(ec->frame);
1768           }
1769         e_client_comp_hidden_set(ec, EINA_TRUE);
1770      }
1771 }
1772
1773 static void
1774 _e_desk_smart_init(E_Desk *desk)
1775 {
1776    E_Zone *zone;
1777
1778    zone = desk->zone;
1779
1780    desk->smart_obj = evas_object_smart_add(e_comp->evas, _e_desk_smart_class_new());
1781    e_desk_geometry_set(desk, zone->x, zone->y, zone->w, zone->h);
1782
1783    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1784
1785    sd->zoom.ratio_x = 1.0;
1786    sd->zoom.ratio_y = 1.0;
1787    sd->zoom.cord_x = 0;
1788    sd->zoom.cord_y = 0;
1789 }
1790
1791 static Eina_Bool
1792 _e_desk_smart_client_cb_resize(void *data, int type, void *event)
1793 {
1794    E_Event_Client *ev;
1795    E_Desk_Smart_Data *sd;
1796    E_Client *ec = NULL;
1797
1798    if (!data) goto end;
1799    if (!event) goto end;
1800
1801    ev = event;
1802    sd = data;
1803    ec = ev->ec;
1804    if (!ec) goto end;
1805
1806    if (!eina_list_data_find(sd->clients, ec))
1807      goto end;
1808
1809    if (sd->zoom.animator)
1810      goto end;
1811
1812    if (sd->zoom.enabled)
1813      _e_desk_client_zoom(ec,
1814                          sd->zoom.ratio_x, sd->zoom.ratio_y,
1815                          sd->zoom.cord_x, sd->zoom.cord_y);
1816 end:
1817    return ECORE_CALLBACK_PASS_ON;
1818 }
1819
1820 static void
1821 _e_desk_smart_add(Evas_Object *obj)
1822 {
1823    EVAS_SMART_DATA_ALLOC(obj, E_Desk_Smart_Data);
1824
1825    /* to apply zoom transformation whenever the client's size is changed. */
1826    E_LIST_HANDLER_APPEND(priv->handlers, E_EVENT_CLIENT_RESIZE, _e_desk_smart_client_cb_resize, priv);
1827
1828    /* FIXME hard coded, it will be laid upper than unpacked clients */
1829    evas_object_layer_set(obj, E_LAYER_DESK_OBJECT);
1830
1831    _e_desk_parent_sc->add(obj);
1832 }
1833
1834 static void
1835 _e_desk_smart_del(Evas_Object *obj)
1836 {
1837    _e_desk_parent_sc->del(obj);
1838
1839    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1840
1841    E_FREE_LIST(sd->handlers, ecore_event_handler_del);
1842    eina_list_free(sd->clients);
1843    free(sd);
1844
1845    evas_object_smart_data_set(obj, NULL);
1846 }
1847
1848 static void
1849 _e_desk_smart_member_add(Evas_Object *obj, Evas_Object *child)
1850 {
1851    E_Client *ec;
1852    E_Desk *ec_desk;
1853
1854    _e_desk_parent_sc->member_add(obj, child);
1855
1856    ec = evas_object_data_get(child, "E_Client");
1857    if (ec)
1858      {
1859         ec_desk = e_comp_desk_find_by_ec(ec);
1860         if (ec_desk)
1861           e_desk_client_del(ec_desk, ec);
1862      }
1863 }
1864
1865 static void
1866 _e_desk_smart_member_del(Evas_Object *obj, Evas_Object *child)
1867 {
1868    E_Client *ec = NULL;
1869    Evas_Object *parent = NULL;
1870    E_Zone*ec_zone;
1871    E_Desk *ec_desk;
1872
1873    _e_desk_parent_sc->member_del(obj, child);
1874
1875    // if quickpanel packed into mover smart obj, _e_desk_smart_member_del is called
1876    // but parent is still e_desk, because mover's parent is the same e_desk
1877    // than don't add ec on the sd->clists
1878    parent = evas_object_smart_parent_get(child);
1879    if (parent && (parent == obj)) return;
1880
1881    ec = evas_object_data_get(child, "E_Client");
1882    if (ec)
1883      {
1884         ec_zone = e_comp_zone_find_by_ec(ec);
1885         ec_desk = e_zone_desk_find_by_ec(ec_zone, ec);
1886         if (ec_desk)
1887           _e_desk_smart_client_add(ec_desk->smart_obj, ec);
1888      }
1889 }
1890
1891 static void
1892 _e_desk_smart_set_user(Evas_Smart_Class *sc)
1893 {
1894    sc->add = _e_desk_smart_add;
1895    sc->del = _e_desk_smart_del;
1896    sc->member_add = _e_desk_smart_member_add;
1897    sc->member_del = _e_desk_smart_member_del;
1898 }
1899
1900 static void
1901 _e_desk_smart_client_add(Evas_Object *obj, E_Client *ec)
1902 {
1903    Evas_Object *parent = NULL;
1904    E_Desk *ec_desk;
1905
1906    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1907
1908    ec_desk = e_comp_desk_find_by_ec(ec);
1909    if (!ec_desk) return;
1910
1911    // if ec is a member of e_desk, don't add it in data.
1912    parent = evas_object_smart_parent_get(ec->frame);
1913    if (parent && (parent == ec_desk->smart_obj)) return;
1914
1915    if (eina_list_data_find(sd->clients, ec))
1916      return;
1917
1918    sd->clients = eina_list_append(sd->clients, ec);
1919    evas_object_smart_changed(obj);
1920 }
1921
1922 static void
1923 _e_desk_smart_client_del(Evas_Object *obj, E_Client *ec)
1924 {
1925    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1926
1927    if (!eina_list_data_find(sd->clients, ec))
1928      return;
1929
1930    if (sd->zoom.enabled)
1931      _e_desk_client_zoom(ec, 1.0, 1.0, 0, 0);
1932
1933    sd->clients = eina_list_remove(sd->clients, ec);
1934    evas_object_smart_changed(obj);
1935 }
1936
1937 static void
1938 _e_desk_object_zoom(Evas_Object *obj, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1939 {
1940    E_Map *map;
1941
1942    if (!obj) return;
1943    if ((zoomx == 1.0) && (zoomy == 1.0))
1944      {
1945         e_comp_object_map_enable_set(obj, EINA_FALSE);
1946         e_comp_object_map_set(obj, NULL);
1947         return;
1948      }
1949
1950    map = e_map_new();
1951    e_map_util_points_populate_from_object(map, obj);
1952    e_map_util_zoom(map, zoomx, zoomy, cx, cy);
1953    e_comp_object_map_set(obj, map);
1954    e_comp_object_map_enable_set(obj, EINA_TRUE);
1955    e_map_free(map);
1956 }
1957
1958 static void
1959 _e_desk_client_subsurf_create(void *data, E_Client *subc)
1960 {
1961    E_Client *ec, *parent;
1962    ec = data;
1963
1964    if (ec != subc) return;
1965
1966    if (ec->desk_zoom.transform)
1967      {
1968         e_client_transform_core_remove(ec, ec->desk_zoom.transform);
1969         E_FREE_FUNC(ec->desk_zoom.transform, e_util_transform_del);
1970      }
1971
1972    parent = e_comp_wl_topmost_parent_get(ec);
1973    if (parent)
1974      {
1975         parent->transform_core.changed = EINA_TRUE;
1976         e_client_transform_core_update(parent);
1977      }
1978 }
1979
1980 static void
1981 _e_desk_client_deskzoom_set(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1982 {
1983    if (e_comp_wl_subsurface_check(ec)) return;
1984
1985    if ((zoomx == 1.0) && (zoomy == 1.0))
1986      {
1987         if (ec->desk_zoom.transform)
1988           e_client_transform_core_remove(ec, ec->desk_zoom.transform);
1989         e_client_transform_core_update(ec);
1990         return;
1991      }
1992
1993    if (!ec->desk_zoom.transform)
1994      {
1995         ec->desk_zoom.transform = e_util_transform_new();
1996         e_util_transform_role_set(ec->desk_zoom.transform, "desk_zoom");
1997
1998         if (!ec->desk_zoom.hook_subsurf_create)
1999           {
2000              ec->desk_zoom.hook_subsurf_create =
2001                  e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
2002                                     _e_desk_client_subsurf_create, ec);
2003           }
2004      }
2005
2006    e_util_transform_zoom_set(ec->desk_zoom.transform, zoomx, zoomy, cx, cy);
2007    e_client_transform_core_add(ec, ec->desk_zoom.transform);
2008
2009    e_client_transform_core_update(ec);
2010 }
2011
2012 static void
2013 _e_desk_client_zoom(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
2014 {
2015    if (e_object_is_del(E_OBJECT(ec))) return;
2016    if (ec->is_cursor) return;
2017
2018    if ((zoomx == 1.0) && (zoomy == 1.0))
2019      e_client_desk_zoom_enable_set(ec, EINA_FALSE);
2020    else
2021      e_client_desk_zoom_enable_set(ec, EINA_TRUE);
2022
2023    _e_desk_client_deskzoom_set(ec, zoomx, zoomy, cx, cy);
2024
2025    if (evas_object_visible_get(ec->frame))
2026      {
2027         // force update
2028         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
2029         e_comp_object_dirty(ec->frame);
2030         e_comp_object_render(ec->frame);
2031      }
2032 }
2033
2034 static unsigned int
2035 _e_desk_desk_area_layer_map(E_Desk_Area_Layer layer)
2036 {
2037    switch (layer)
2038      {
2039       case E_DESK_AREA_LAYER_BACKGROUND: return 0;
2040       case E_DESK_AREA_LAYER_NORMAL_BELOW: return 1;
2041       case E_DESK_AREA_LAYER_NORMAL: return 2;
2042       case E_DESK_AREA_LAYER_NORMAL_ABOVE: return 3;
2043       case E_DESK_AREA_LAYER_NOTIFICATION_LOW: return 4;
2044       case E_DESK_AREA_LAYER_NOTIFICATION_NORMAL: return 5;
2045       case E_DESK_AREA_LAYER_NOTIFICATION_HIGH: return 6;
2046       case E_DESK_AREA_LAYER_NOTIFICATION_TOP: return 7;
2047       case E_DESK_AREA_LAYER_SYSTEM: return 8;
2048       default: return 0;
2049      }
2050 }
2051
2052 E_API E_Desk_Area *
2053 e_desk_desk_area_add(E_Desk *desk, int x, int y, int w, int h, E_Desk_Area_Layer layer)
2054 {
2055    E_Desk_Area *eda;
2056    int id;
2057    unsigned int list_id;
2058
2059    E_OBJECT_CHECK_RETURN(desk, NULL);
2060    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2061
2062    id = desk->desk_area.id;
2063
2064    eda = e_desk_area_new(desk, id, x, y, w, h, layer);
2065    if (!eda)
2066      {
2067         return NULL;
2068      }
2069
2070    list_id = _e_desk_desk_area_layer_map(layer);
2071    desk->desk_area.list[list_id] = eina_list_prepend(desk->desk_area.list[list_id], eda);
2072    desk->desk_area.id++;
2073
2074    return eda;
2075 }
2076
2077 E_API void
2078 e_desk_desk_area_del(E_Desk *desk, E_Desk_Area *eda)
2079 {
2080    unsigned int list_id;
2081
2082    E_OBJECT_CHECK(desk);
2083    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2084
2085    if (!eda) return;
2086
2087    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2088    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2089 }
2090
2091 #ifdef REFACTOR_DESK_AREA
2092 #else
2093 static Eina_Bool
2094 _e_desk_desk_area_base_new(E_Desk *desk)
2095 {
2096    if (!desk) return EINA_FALSE;
2097
2098    if (!desk->desk_area.base)
2099      {
2100         // Add a base e_desk_area
2101         desk->desk_area.base = e_desk_desk_area_add(desk, desk->geom.x, desk->geom.y, desk->geom.w, desk->geom.h, E_DESK_AREA_LAYER_NORMAL);
2102      }
2103
2104    if (!desk->desk_area.base)
2105      return EINA_FALSE;
2106    else
2107      return EINA_TRUE;
2108 }
2109 #endif
2110
2111 EINTERN E_Desk_Area *
2112 e_desk_desk_area_base_get(E_Desk *desk)
2113 {
2114    E_OBJECT_CHECK_RETURN(desk, NULL);
2115    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2116
2117    return desk->desk_area.base;
2118 }
2119
2120 EINTERN void
2121 e_desk_desk_area_active_set(E_Desk *desk, E_Desk_Area *eda)
2122 {
2123    E_OBJECT_CHECK(desk);
2124    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2125    if (desk->desk_area.active == eda) return;
2126
2127    desk->desk_area.active = eda;
2128
2129    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_active_change, desk);
2130    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_ACTIVE_CHANGE, desk);
2131 }
2132
2133 EINTERN E_Desk_Area *
2134 e_desk_desk_area_active_get(E_Desk *desk)
2135 {
2136    E_OBJECT_CHECK_RETURN(desk, NULL);
2137    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2138
2139    return desk->desk_area.active;
2140 }
2141
2142 #ifdef REFACTOR_DESK_AREA
2143 #else
2144 static void
2145 _e_desk_desk_area_check_ec_in_desk_area(E_Desk *desk)
2146 {
2147    E_Client *ec;
2148    Eina_List *ec_list = NULL;
2149
2150    E_CLIENT_FOREACH(ec)
2151      {
2152         if (!e_desk_has_ec(desk, ec)) continue;
2153         if (e_object_is_del(E_OBJECT(ec))) continue;
2154         if (ec->desk_area.desk_area) continue;
2155
2156         ec_list = eina_list_append(ec_list, ec);
2157      }
2158
2159    EINA_LIST_FREE(ec_list, ec)
2160       e_desk_area_ec_reassign(desk->desk_area.base, ec);
2161 }
2162
2163 E_API Eina_Bool
2164 e_desk_desk_area_enable(E_Desk *desk)
2165 {
2166    E_Desk_Area *eda = NULL;
2167    Eina_List *l;
2168
2169    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2170    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2171
2172    ELOGF("EDG", "Enable Desk_Area...", NULL);
2173    if (desk->desk_area.enable) return EINA_TRUE;
2174    desk->desk_area.enable = EINA_TRUE;
2175
2176    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_enable, desk);
2177    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_ENABLE, desk);
2178
2179    // check all ec is included in desk group
2180    _e_desk_desk_area_check_ec_in_desk_area(desk);
2181
2182    for (int i=0; i<E_DESK_AREA_LAYER_COUNT; i++)
2183      {
2184         EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[i], l, eda)
2185           {
2186              e_desk_area_enable_set(eda, EINA_TRUE);
2187           }
2188      }
2189
2190    return EINA_TRUE;
2191 }
2192
2193 E_API Eina_Bool
2194 e_desk_desk_area_disable(E_Desk *desk)
2195 {
2196    E_Desk_Area *eda = NULL;
2197    Eina_List *l;
2198
2199    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2200    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2201
2202    ELOGF("EDG", "Disable Desk_Area...", NULL);
2203    if (!desk->desk_area.enable) return EINA_TRUE;
2204    desk->desk_area.enable = EINA_FALSE;
2205
2206    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_disable, desk);
2207    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_DISABLE, desk);
2208
2209    for (int i=0; i<E_DESK_AREA_LAYER_COUNT; i++)
2210      {
2211         EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[i], l, eda)
2212           {
2213              e_desk_area_enable_set(eda, EINA_FALSE);
2214           }
2215      }
2216    return EINA_TRUE;
2217 }
2218 #endif
2219
2220 EINTERN void
2221 e_desk_desk_area_raise(E_Desk *desk, E_Desk_Area *eda)
2222 {
2223    unsigned int list_id;
2224
2225    E_OBJECT_CHECK(desk);
2226    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2227
2228    if (!eda) return;
2229
2230    ELOGF("EDG", "Raise Desk_Area... eda:%p", NULL, eda);
2231
2232    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2233    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2234    desk->desk_area.list[list_id] = eina_list_prepend(desk->desk_area.list[list_id], eda);
2235
2236    e_desk_area_raise(eda);
2237 }
2238
2239 EINTERN void
2240 e_desk_desk_area_lower(E_Desk *desk, E_Desk_Area *eda)
2241 {
2242    unsigned int list_id;
2243
2244    E_OBJECT_CHECK(desk);
2245    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2246
2247    if (!eda) return;
2248
2249    ELOGF("EDG", "Lower Desk_Area...", NULL);
2250
2251    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2252    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2253    desk->desk_area.list[list_id] = eina_list_append(desk->desk_area.list[list_id], eda);
2254
2255    e_desk_area_lower(eda);
2256 }
2257
2258 // get above E_Desk_Area in the same eda layer
2259 EINTERN E_Desk_Area *
2260 e_desk_desk_area_above_get(E_Desk *desk, E_Desk_Area *eda)
2261 {
2262    Eina_List *l = NULL;
2263    E_Desk_Area *above = NULL;
2264    E_Desk_Area *temp = NULL;
2265    unsigned int list_id;
2266
2267    if (!desk) return NULL;
2268    if (!eda) return NULL;
2269
2270    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2271    EINA_LIST_FOREACH(desk->desk_area.list[list_id], l, temp)
2272      {
2273         if (temp != eda)
2274           above = temp;
2275         else
2276           break;
2277      }
2278
2279    ELOGF("EDG", "Get Above E_Desk_Area:%p... current:%p", NULL, above, eda);
2280    return above;
2281 }
2282
2283 // get below E_Desk_Area in the same eda layer
2284 EINTERN E_Desk_Area *
2285 e_desk_desk_area_below_get(E_Desk *desk, E_Desk_Area *eda)
2286 {
2287    Eina_List *l = NULL;
2288    E_Desk_Area *below = NULL;
2289    E_Desk_Area *temp = NULL;
2290    unsigned int list_id;
2291
2292    if (!desk) return NULL;
2293    if (!eda) return NULL;
2294
2295    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2296    EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[list_id], l, temp)
2297      {
2298         if (temp != eda)
2299           below = temp;
2300         else
2301           break;
2302      }
2303
2304    ELOGF("EDG", "Get Below E_Desk_Area:%p... current:%p", NULL, below, eda);
2305    return below;
2306 }
2307
2308 static void
2309 _e_desk_hooks_clean(void)
2310 {
2311    Eina_Inlist *l;
2312    E_Desk_Hook *dh;
2313    unsigned int x;
2314
2315    for (x = 0; x < E_DESK_HOOK_LAST; x++)
2316      EINA_INLIST_FOREACH_SAFE(_e_desk_hooks[x], l, dh)
2317        {
2318           if (!dh->delete_me) continue;
2319           _e_desk_hooks[x] = eina_inlist_remove(_e_desk_hooks[x], EINA_INLIST_GET(dh));
2320           free(dh);
2321        }
2322
2323    _e_desk_hooks_delete = 0;
2324 }
2325
2326 static Eina_Bool
2327 _e_desk_hook_call(E_Desk_Hook_Point hookpoint, E_Desk *desk)
2328 {
2329    E_Desk_Hook *dh;
2330
2331    e_object_ref(E_OBJECT(desk));
2332    _e_desk_hooks_walking++;
2333    EINA_INLIST_FOREACH(_e_desk_hooks[hookpoint], dh)
2334      {
2335         if (dh->delete_me) continue;
2336         dh->func(dh->data, desk);
2337      }
2338    _e_desk_hooks_walking--;
2339    if ((_e_desk_hooks_walking == 0) && (_e_desk_hooks_delete > 0))
2340      _e_desk_hooks_clean();
2341
2342    return !!e_object_unref(E_OBJECT(desk));
2343 }
2344
2345 E_API E_Desk_Hook *
2346 e_desk_hook_add(E_Desk_Hook_Point hookpoint, E_Desk_Hook_Cb func, const void *data)
2347 {
2348    E_Desk_Hook *dh;
2349
2350    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_DESK_HOOK_LAST, NULL);
2351    dh = E_NEW(E_Desk_Hook, 1);
2352    if (!dh) return NULL;
2353
2354    dh->hookpoint = hookpoint;
2355    dh->func = func;
2356    dh->data = (void*)data;
2357
2358    _e_desk_hooks[hookpoint] = eina_inlist_append(_e_desk_hooks[hookpoint], EINA_INLIST_GET(dh));
2359    return dh;
2360 }
2361
2362 E_API void
2363 e_desk_hook_del(E_Desk_Hook * dh)
2364 {
2365    dh->delete_me = 1;
2366    if (_e_desk_hooks_walking == 0)
2367      {
2368         _e_desk_hooks[dh->hookpoint] = eina_inlist_remove(_e_desk_hooks[dh->hookpoint], EINA_INLIST_GET(dh));
2369         free(dh);
2370      }
2371    else
2372      _e_desk_hooks_delete++;
2373 }
2374
2375 EINTERN void
2376 e_desk_desk_area_info_print(E_Desk *desk)
2377 {
2378    E_Desk_Area *eda = NULL;
2379    Eina_List *l;
2380
2381    E_OBJECT_CHECK(desk);
2382    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2383
2384    for (int i=E_DESK_AREA_LAYER_COUNT-1; i>=0; i--)
2385      {
2386         EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
2387           {
2388              e_desk_area_info_print(eda);
2389           }
2390      }
2391 }
2392
2393 static void
2394 _e_desk_cb_splitscreen_destroy(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
2395 {
2396    //TODO:
2397 }
2398
2399 static void
2400 _e_desk_cb_split_desk_activate(struct wl_listener *listener, void *data)
2401 {
2402   E_Desk_Private *priv;
2403
2404   priv = container_of(listener, E_Desk_Private, ds_tizen_splitscreen_activate);
2405
2406   // call the hook for activating the splitscreen in this zone
2407   wl_signal_emit_mutable(&priv->events.split_desk_activate, NULL);
2408   _e_desk_hook_call(E_DESK_HOOK_SPLIT_DESK_ACTIVATE, priv->desk);
2409 }
2410
2411 static void
2412 _e_desk_cb_split_desk_deactivate(struct wl_listener *listener, void *data)
2413 {
2414   E_Desk_Private *priv;
2415
2416   priv = container_of(listener, E_Desk_Private, ds_tizen_splitscreen_deactivate);
2417
2418   // call the hook for deactivating the splitscreen in this desk
2419   wl_signal_emit_mutable(&priv->events.split_desk_deactivate, NULL);
2420   _e_desk_hook_call(E_DESK_HOOK_SPLIT_DESK_DEACTIVATE, priv->desk);
2421 }
2422
2423 EINTERN Eina_Bool
2424 e_desk_splitscreen_enable(E_Desk *desk,
2425       struct ds_tizen_splitscreen *splitscreen)
2426 {
2427    E_Desk_Area *eda;
2428    struct ds_tizen_splitscreen_region *splitscreen_region;
2429    Eina_List *l;
2430    int i;
2431    const char *eda_name;
2432    int x, y, w, h;
2433
2434    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2435    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2436    API_ENTRY_VAL(EINA_FALSE);
2437
2438    priv->splitscreen = splitscreen;
2439    priv->ds_tizen_splitscreen_destroy.notify = _e_desk_cb_splitscreen_destroy;
2440    ds_tizen_splitscreen_add_destroy_listener(priv->splitscreen,
2441           &priv->ds_tizen_splitscreen_destroy);
2442    priv->ds_tizen_splitscreen_activate.notify = _e_desk_cb_split_desk_activate;
2443    ds_tizen_splitscreen_add_activate_listener(priv->splitscreen,
2444           &priv->ds_tizen_splitscreen_activate);
2445    priv->ds_tizen_splitscreen_deactivate.notify = _e_desk_cb_split_desk_deactivate;
2446    ds_tizen_splitscreen_add_deactivate_listener(priv->splitscreen,
2447           &priv->ds_tizen_splitscreen_deactivate);
2448
2449    for (i = (E_DESK_AREA_LAYER_COUNT - 1); i >= 0; i--)
2450      {
2451         EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
2452           {
2453              eda_name = e_desk_area_name_get(eda);
2454              // The eda->name can be an id of the desk group.
2455              if (!eda_name)
2456                {
2457                   ERR("E_Desk: eda->name is null.");
2458                   continue;
2459                }
2460
2461              e_desk_area_geometry_get(eda, &x, &y, &w, &h);
2462              splitscreen_region = ds_tizen_splitscreen_region_create(
2463                    splitscreen, eda_name, x, y, w, h);
2464              if (!splitscreen_region)
2465                {
2466                   ERR("E_Desk: ds_tizen_splitscreen_region_create() failed.");
2467                   continue;
2468                }
2469
2470             if (!e_desk_area_splitscreen_region_enable(eda, splitscreen_region))
2471                {
2472                   ERR("E_Desk: e_desk_area_splitscreen_region_enable() failed.");
2473                   continue;
2474                }
2475           }
2476      }
2477
2478    return EINA_TRUE;
2479 }
2480
2481 EINTERN Eina_Bool
2482 e_desk_has_ec(E_Desk *desk, E_Client *ec)
2483 {
2484    E_Desk *data;
2485
2486    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2487
2488    data = evas_object_data_get(ec->frame, DESK_EC_DATA_KEY);
2489    if (data == desk) return EINA_TRUE;
2490
2491    return EINA_FALSE;
2492 }
2493
2494 #ifdef REFACTOR_DESK_AREA
2495 EINTERN E_Client *
2496 e_desk_top_ec_get(E_Desk *desk)
2497 {
2498    E_Desk_Area *eda;
2499
2500    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2501
2502    // TODO: get the desk_area which is at top among the desk_areas in this desk
2503    eda = desk->desk_area.base;
2504
2505    return e_desk_area_top_ec_get(eda);
2506 }
2507
2508 EINTERN E_Client *
2509 e_desk_bottom_ec_get(E_Desk *desk)
2510 {
2511    E_Desk_Area *eda;
2512
2513    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2514
2515    // TODO: get the desk_area which is at bottom among the desk_areas in this desk
2516    eda = desk->desk_area.base;
2517
2518    return e_desk_area_bottom_ec_get(eda);
2519 }
2520
2521 E_API E_Desk_Area *
2522 e_desk_desk_area_find_by_ec(E_Desk *desk, E_Client *ec)
2523 {
2524    E_Desk_Area *eda;
2525
2526    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, NULL);
2527    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
2528
2529    if (!e_desk_has_ec(desk, ec)) return NULL;
2530
2531    // TODO: find the desk_area which has the ec among the desk_areas in this desk
2532    eda = desk->desk_area.base;
2533    if (e_desk_area_has_ec(eda, ec))
2534      return eda;
2535
2536    return NULL;
2537 }
2538 #endif
2539
2540 EINTERN void
2541 e_desk_client_add_listener_add(E_Desk *desk, struct wl_listener *listener)
2542 {
2543    API_ENTRY;
2544    wl_signal_add(&priv->events.client_add, listener);
2545 }
2546
2547 EINTERN void
2548 e_desk_desk_area_enable_listener_add(E_Desk *desk, struct wl_listener *listener)
2549 {
2550    API_ENTRY;
2551    wl_signal_add(&priv->events.desk_area_enable, listener);
2552 }
2553
2554 EINTERN void
2555 e_desk_desk_area_disable_listener_add(E_Desk *desk, struct wl_listener *listener)
2556 {
2557    API_ENTRY;
2558    wl_signal_add(&priv->events.desk_area_disable, listener);
2559 }
2560
2561 EINTERN void
2562 e_desk_desk_area_active_change_listener_add(E_Desk *desk, struct wl_listener *listener)
2563 {
2564    API_ENTRY;
2565    wl_signal_add(&priv->events.desk_area_active_change, listener);
2566 }
2567
2568 EINTERN void
2569 e_desk_ssplit_desk_activate_listener_add(E_Desk *desk, struct wl_listener *listener)
2570 {
2571    API_ENTRY;
2572    wl_signal_add(&priv->events.split_desk_activate, listener);
2573 }
2574
2575 EINTERN void
2576 e_desk_split_desk_deactivate_listener_add(E_Desk *desk, struct wl_listener *listener)
2577 {
2578    API_ENTRY;
2579    wl_signal_add(&priv->events.split_desk_deactivate, listener);
2580 }
2581