e_client: use e_client_visibility_set/get funtions
[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    if (e_config->use_desk_area)
1602      {
1603         for (int i=E_DESK_AREA_LAYER_COUNT-1; i>=0; i--)
1604           {
1605              EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
1606                {
1607                   e_object_del(E_OBJECT(eda));
1608                }
1609              eina_list_free(desk->desk_area.list[i]);
1610              desk->desk_area.list[i] = NULL;
1611           }
1612
1613         e_desk_desk_area_del(desk, desk->desk_area.base);
1614         desk->desk_area.base = NULL;
1615         desk->desk_area.active = NULL;
1616      }
1617
1618
1619    E_FREE_FUNC(desk->smart_obj, evas_object_del);
1620    eina_stringshare_del(desk->name);
1621    desk->name = NULL;
1622    E_FREE_LIST(desk->handlers, ecore_event_handler_del);
1623
1624    _e_desk_private_finish(desk);
1625    free(desk);
1626 }
1627
1628 static void
1629 _e_desk_event_desk_show_free(void *data EINA_UNUSED, void *event)
1630 {
1631    E_Event_Desk_Show *ev;
1632
1633    ev = event;
1634    e_object_unref(E_OBJECT(ev->desk));
1635    free(ev);
1636 }
1637
1638 static void
1639 _e_desk_event_desk_before_show_free(void *data EINA_UNUSED, void *event)
1640 {
1641    E_Event_Desk_Before_Show *ev;
1642
1643    ev = event;
1644    e_object_unref(E_OBJECT(ev->desk));
1645    free(ev);
1646 }
1647
1648 static void
1649 _e_desk_event_desk_after_show_free(void *data EINA_UNUSED, void *event)
1650 {
1651    E_Event_Desk_After_Show *ev;
1652
1653    ev = event;
1654    e_object_unref(E_OBJECT(ev->desk));
1655    free(ev);
1656 }
1657
1658 static void
1659 _e_desk_event_desk_geometry_change_free(void *data EINA_UNUSED, void *event)
1660 {
1661    E_Event_Desk_Geometry_Change *ev = event;
1662    e_object_unref(E_OBJECT(ev->desk));
1663    E_FREE(ev);
1664 }
1665
1666 static Eina_Bool
1667 _e_desk_transition_setup(E_Client *ec, int dx, int dy, int state)
1668 {
1669    e_comp_object_effect_set(ec->frame, "none");
1670
1671    return EINA_FALSE;
1672 }
1673
1674 static void
1675 _e_desk_show_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1676 {
1677    E_Client *ec = data;
1678    E_Zone *ec_zone;
1679    E_Desk *ec_desk;
1680
1681    ec_zone = e_comp_zone_find_by_ec(ec);
1682    ec_desk = e_zone_desk_find_by_ec(ec_zone, ec);
1683    if (ec_desk)
1684      ec_desk->animate_count--;
1685
1686    e_client_comp_hidden_set(ec, 0);
1687    e_comp_object_effect_unclip(ec->frame);
1688    ec->hidden = 0;
1689    if (!ec->visible) evas_object_show(ec->frame);
1690
1691    if (ec_desk != e_desk_current_get(ec_zone)) return;
1692 }
1693
1694 static void
1695 _e_desk_hide_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1696 {
1697    E_Client *ec = data;
1698    E_Desk *ec_desk;
1699
1700    ec_desk = e_comp_desk_find_by_ec(ec);
1701    if (ec_desk)
1702      ec_desk->animate_count--;
1703    ec->hidden = 1;
1704    evas_object_hide(ec->frame);
1705 }
1706
1707 static void
1708 _e_desk_show_begin(E_Desk *desk, int dx, int dy)
1709 {
1710    E_Client *ec;
1711
1712    if (dx < 0) dx = -1;
1713    if (dx > 0) dx = 1;
1714    if (dy < 0) dy = -1;
1715    if (dy > 0) dy = 1;
1716
1717    desk->animate_count = 0;
1718    E_CLIENT_FOREACH(ec)
1719      {
1720         if (e_client_util_ignored_get(ec) || (!e_zone_has_ec(desk->zone, ec)) || (ec->iconic)) continue;
1721         if (ec->moving)
1722           {
1723              e_desk_client_add(desk, ec);
1724              evas_object_show(ec->frame);
1725              continue;
1726           }
1727         if ((!e_desk_has_ec(desk, ec)) || (ec->sticky)) continue;
1728         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, dx, dy, 1))
1729           {
1730              e_comp_object_effect_stop(ec->frame, _e_desk_hide_end);
1731              e_comp_object_effect_start(ec->frame, _e_desk_show_end, ec);
1732              desk->animate_count++;
1733           }
1734         else
1735           ec->hidden = 0;
1736
1737         e_client_comp_hidden_set(ec, ec->hidden);
1738         evas_object_show(ec->frame);
1739      }
1740 }
1741
1742 static void
1743 _e_desk_hide_begin(E_Desk *desk, int dx, int dy)
1744 {
1745    E_Client *ec;
1746
1747    if (dx < 0) dx = -1;
1748    if (dx > 0) dx = 1;
1749    if (dy < 0) dy = -1;
1750    if (dy > 0) dy = 1;
1751
1752    desk->animate_count = 0;
1753    E_CLIENT_FOREACH(ec)
1754      {
1755         if (e_client_util_ignored_get(ec)) continue;
1756         if ((!e_zone_has_ec(desk->zone, ec)) || (ec->iconic)) continue;
1757         if (ec->moving) continue;
1758         if ((!e_desk_has_ec(desk, ec)) || (ec->sticky)) continue;
1759         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, -dx, -dy, 0))
1760           {
1761              e_comp_object_effect_stop(ec->frame, _e_desk_show_end);
1762              e_comp_object_effect_start(ec->frame, _e_desk_hide_end, ec);
1763              desk->animate_count++;
1764           }
1765         else
1766           {
1767              ec->hidden = 1;
1768              evas_object_show(ec->frame);
1769              ec->changes.visible = 0;
1770              evas_object_hide(ec->frame);
1771           }
1772         e_client_comp_hidden_set(ec, EINA_TRUE);
1773      }
1774 }
1775
1776 static void
1777 _e_desk_smart_init(E_Desk *desk)
1778 {
1779    E_Zone *zone;
1780
1781    zone = desk->zone;
1782
1783    desk->smart_obj = evas_object_smart_add(e_comp->evas, _e_desk_smart_class_new());
1784    e_desk_geometry_set(desk, zone->x, zone->y, zone->w, zone->h);
1785
1786    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1787
1788    sd->zoom.ratio_x = 1.0;
1789    sd->zoom.ratio_y = 1.0;
1790    sd->zoom.cord_x = 0;
1791    sd->zoom.cord_y = 0;
1792 }
1793
1794 static Eina_Bool
1795 _e_desk_smart_client_cb_resize(void *data, int type, void *event)
1796 {
1797    E_Event_Client *ev;
1798    E_Desk_Smart_Data *sd;
1799    E_Client *ec = NULL;
1800
1801    if (!data) goto end;
1802    if (!event) goto end;
1803
1804    ev = event;
1805    sd = data;
1806    ec = ev->ec;
1807    if (!ec) goto end;
1808
1809    if (!eina_list_data_find(sd->clients, ec))
1810      goto end;
1811
1812    if (sd->zoom.animator)
1813      goto end;
1814
1815    if (sd->zoom.enabled)
1816      _e_desk_client_zoom(ec,
1817                          sd->zoom.ratio_x, sd->zoom.ratio_y,
1818                          sd->zoom.cord_x, sd->zoom.cord_y);
1819 end:
1820    return ECORE_CALLBACK_PASS_ON;
1821 }
1822
1823 static void
1824 _e_desk_smart_add(Evas_Object *obj)
1825 {
1826    EVAS_SMART_DATA_ALLOC(obj, E_Desk_Smart_Data);
1827
1828    /* to apply zoom transformation whenever the client's size is changed. */
1829    E_LIST_HANDLER_APPEND(priv->handlers, E_EVENT_CLIENT_RESIZE, _e_desk_smart_client_cb_resize, priv);
1830
1831    /* FIXME hard coded, it will be laid upper than unpacked clients */
1832    evas_object_layer_set(obj, E_LAYER_DESK_OBJECT);
1833
1834    _e_desk_parent_sc->add(obj);
1835 }
1836
1837 static void
1838 _e_desk_smart_del(Evas_Object *obj)
1839 {
1840    _e_desk_parent_sc->del(obj);
1841
1842    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1843
1844    E_FREE_LIST(sd->handlers, ecore_event_handler_del);
1845    eina_list_free(sd->clients);
1846    free(sd);
1847
1848    evas_object_smart_data_set(obj, NULL);
1849 }
1850
1851 static void
1852 _e_desk_smart_member_add(Evas_Object *obj, Evas_Object *child)
1853 {
1854    E_Client *ec;
1855    E_Desk *ec_desk;
1856
1857    _e_desk_parent_sc->member_add(obj, child);
1858
1859    ec = evas_object_data_get(child, "E_Client");
1860    if (ec)
1861      {
1862         ec_desk = e_comp_desk_find_by_ec(ec);
1863         if (ec_desk)
1864           e_desk_client_del(ec_desk, ec);
1865      }
1866 }
1867
1868 static void
1869 _e_desk_smart_member_del(Evas_Object *obj, Evas_Object *child)
1870 {
1871    E_Client *ec = NULL;
1872    Evas_Object *parent = NULL;
1873    E_Zone*ec_zone;
1874    E_Desk *ec_desk;
1875
1876    _e_desk_parent_sc->member_del(obj, child);
1877
1878    // if quickpanel packed into mover smart obj, _e_desk_smart_member_del is called
1879    // but parent is still e_desk, because mover's parent is the same e_desk
1880    // than don't add ec on the sd->clists
1881    parent = evas_object_smart_parent_get(child);
1882    if (parent && (parent == obj)) return;
1883
1884    ec = evas_object_data_get(child, "E_Client");
1885    if (ec)
1886      {
1887         ec_zone = e_comp_zone_find_by_ec(ec);
1888         ec_desk = e_zone_desk_find_by_ec(ec_zone, ec);
1889         if (ec_desk)
1890           _e_desk_smart_client_add(ec_desk->smart_obj, ec);
1891      }
1892 }
1893
1894 static void
1895 _e_desk_smart_set_user(Evas_Smart_Class *sc)
1896 {
1897    sc->add = _e_desk_smart_add;
1898    sc->del = _e_desk_smart_del;
1899    sc->member_add = _e_desk_smart_member_add;
1900    sc->member_del = _e_desk_smart_member_del;
1901 }
1902
1903 static void
1904 _e_desk_smart_client_add(Evas_Object *obj, E_Client *ec)
1905 {
1906    Evas_Object *parent = NULL;
1907    E_Desk *ec_desk;
1908
1909    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1910
1911    ec_desk = e_comp_desk_find_by_ec(ec);
1912    if (!ec_desk) return;
1913
1914    // if ec is a member of e_desk, don't add it in data.
1915    parent = evas_object_smart_parent_get(ec->frame);
1916    if (parent && (parent == ec_desk->smart_obj)) return;
1917
1918    if (eina_list_data_find(sd->clients, ec))
1919      return;
1920
1921    sd->clients = eina_list_append(sd->clients, ec);
1922    evas_object_smart_changed(obj);
1923 }
1924
1925 static void
1926 _e_desk_smart_client_del(Evas_Object *obj, E_Client *ec)
1927 {
1928    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1929
1930    if (!eina_list_data_find(sd->clients, ec))
1931      return;
1932
1933    if (sd->zoom.enabled)
1934      _e_desk_client_zoom(ec, 1.0, 1.0, 0, 0);
1935
1936    sd->clients = eina_list_remove(sd->clients, ec);
1937    evas_object_smart_changed(obj);
1938 }
1939
1940 static void
1941 _e_desk_object_zoom(Evas_Object *obj, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1942 {
1943    E_Map *map;
1944
1945    if (!obj) return;
1946    if ((zoomx == 1.0) && (zoomy == 1.0))
1947      {
1948         e_comp_object_map_enable_set(obj, EINA_FALSE);
1949         e_comp_object_map_set(obj, NULL);
1950         return;
1951      }
1952
1953    map = e_map_new();
1954    e_map_util_points_populate_from_object(map, obj);
1955    e_map_util_zoom(map, zoomx, zoomy, cx, cy);
1956    e_comp_object_map_set(obj, map);
1957    e_comp_object_map_enable_set(obj, EINA_TRUE);
1958    e_map_free(map);
1959 }
1960
1961 static void
1962 _e_desk_client_subsurf_create(void *data, E_Client *subc)
1963 {
1964    E_Client *ec, *parent;
1965    ec = data;
1966
1967    if (ec != subc) return;
1968
1969    if (ec->desk_zoom.transform)
1970      {
1971         e_client_transform_core_remove(ec, ec->desk_zoom.transform);
1972         E_FREE_FUNC(ec->desk_zoom.transform, e_util_transform_del);
1973      }
1974
1975    parent = e_comp_wl_topmost_parent_get(ec);
1976    if (parent)
1977      {
1978         parent->transform_core.changed = EINA_TRUE;
1979         e_client_transform_core_update(parent);
1980      }
1981 }
1982
1983 static void
1984 _e_desk_client_deskzoom_set(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1985 {
1986    if (e_comp_wl_subsurface_check(ec)) return;
1987
1988    if ((zoomx == 1.0) && (zoomy == 1.0))
1989      {
1990         if (ec->desk_zoom.transform)
1991           e_client_transform_core_remove(ec, ec->desk_zoom.transform);
1992         e_client_transform_core_update(ec);
1993         return;
1994      }
1995
1996    if (!ec->desk_zoom.transform)
1997      {
1998         ec->desk_zoom.transform = e_util_transform_new();
1999         e_util_transform_role_set(ec->desk_zoom.transform, "desk_zoom");
2000
2001         if (!ec->desk_zoom.hook_subsurf_create)
2002           {
2003              ec->desk_zoom.hook_subsurf_create =
2004                  e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
2005                                     _e_desk_client_subsurf_create, ec);
2006           }
2007      }
2008
2009    e_util_transform_zoom_set(ec->desk_zoom.transform, zoomx, zoomy, cx, cy);
2010    e_client_transform_core_add(ec, ec->desk_zoom.transform);
2011
2012    e_client_transform_core_update(ec);
2013 }
2014
2015 static void
2016 _e_desk_client_zoom(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
2017 {
2018    if (e_object_is_del(E_OBJECT(ec))) return;
2019    if (ec->is_cursor) return;
2020
2021    if ((zoomx == 1.0) && (zoomy == 1.0))
2022      e_client_desk_zoom_enable_set(ec, EINA_FALSE);
2023    else
2024      e_client_desk_zoom_enable_set(ec, EINA_TRUE);
2025
2026    _e_desk_client_deskzoom_set(ec, zoomx, zoomy, cx, cy);
2027
2028    if (evas_object_visible_get(ec->frame))
2029      {
2030         // force update
2031         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
2032         e_comp_object_dirty(ec->frame);
2033         e_comp_object_render(ec->frame);
2034      }
2035 }
2036
2037 static unsigned int
2038 _e_desk_desk_area_layer_map(E_Desk_Area_Layer layer)
2039 {
2040    switch (layer)
2041      {
2042       case E_DESK_AREA_LAYER_BACKGROUND: return 0;
2043       case E_DESK_AREA_LAYER_NORMAL_BELOW: return 1;
2044       case E_DESK_AREA_LAYER_NORMAL: return 2;
2045       case E_DESK_AREA_LAYER_NORMAL_ABOVE: return 3;
2046       case E_DESK_AREA_LAYER_NOTIFICATION_LOW: return 4;
2047       case E_DESK_AREA_LAYER_NOTIFICATION_NORMAL: return 5;
2048       case E_DESK_AREA_LAYER_NOTIFICATION_HIGH: return 6;
2049       case E_DESK_AREA_LAYER_NOTIFICATION_TOP: return 7;
2050       case E_DESK_AREA_LAYER_SYSTEM: return 8;
2051       default: return 0;
2052      }
2053 }
2054
2055 E_API E_Desk_Area *
2056 e_desk_desk_area_add(E_Desk *desk, int x, int y, int w, int h, E_Desk_Area_Layer layer)
2057 {
2058    E_Desk_Area *eda;
2059    int id;
2060    unsigned int list_id;
2061
2062    if (!e_config->use_desk_area) return NULL;
2063
2064    E_OBJECT_CHECK_RETURN(desk, NULL);
2065    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2066
2067    id = desk->desk_area.id;
2068
2069    eda = e_desk_area_new(desk, id, x, y, w, h, layer);
2070    if (!eda)
2071      {
2072         return NULL;
2073      }
2074
2075    list_id = _e_desk_desk_area_layer_map(layer);
2076    desk->desk_area.list[list_id] = eina_list_prepend(desk->desk_area.list[list_id], eda);
2077    desk->desk_area.id++;
2078
2079    return eda;
2080 }
2081
2082 E_API void
2083 e_desk_desk_area_del(E_Desk *desk, E_Desk_Area *eda)
2084 {
2085    unsigned int list_id;
2086
2087    E_OBJECT_CHECK(desk);
2088    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2089
2090    if (!e_config->use_desk_area) return;
2091
2092    if (!eda) return;
2093
2094    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2095    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2096 }
2097
2098 #ifdef REFACTOR_DESK_AREA
2099 #else
2100 static Eina_Bool
2101 _e_desk_desk_area_base_new(E_Desk *desk)
2102 {
2103    if (!desk) return EINA_FALSE;
2104    if (!e_config->use_desk_area) return EINA_FALSE;
2105
2106    if (!desk->desk_area.base)
2107      {
2108         // Add a base e_desk_area
2109         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);
2110      }
2111
2112    if (!desk->desk_area.base)
2113      return EINA_FALSE;
2114    else
2115      return EINA_TRUE;
2116 }
2117 #endif
2118
2119 EINTERN E_Desk_Area *
2120 e_desk_desk_area_base_get(E_Desk *desk)
2121 {
2122    E_OBJECT_CHECK_RETURN(desk, NULL);
2123    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2124
2125    if (!e_config->use_desk_area) return NULL;
2126
2127    return desk->desk_area.base;
2128 }
2129
2130 EINTERN void
2131 e_desk_desk_area_active_set(E_Desk *desk, E_Desk_Area *eda)
2132 {
2133    E_OBJECT_CHECK(desk);
2134    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2135
2136    if (!e_config->use_desk_area) return;
2137    if (desk->desk_area.active == eda) return;
2138
2139    desk->desk_area.active = eda;
2140
2141    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_active_change, desk);
2142    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_ACTIVE_CHANGE, desk);
2143 }
2144
2145 EINTERN E_Desk_Area *
2146 e_desk_desk_area_active_get(E_Desk *desk)
2147 {
2148    E_OBJECT_CHECK_RETURN(desk, NULL);
2149    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
2150
2151    if (!e_config->use_desk_area) return NULL;
2152
2153    return desk->desk_area.active;
2154 }
2155
2156 #ifdef REFACTOR_DESK_AREA
2157 #else
2158 static void
2159 _e_desk_desk_area_check_ec_in_desk_area(E_Desk *desk)
2160 {
2161    E_Client *ec;
2162    Eina_List *ec_list = NULL;
2163
2164    E_CLIENT_FOREACH(ec)
2165      {
2166         if (!e_desk_has_ec(desk, ec)) continue;
2167         if (e_object_is_del(E_OBJECT(ec))) continue;
2168         if (ec->desk_area.desk_area) continue;
2169
2170         ec_list = eina_list_append(ec_list, ec);
2171      }
2172
2173    EINA_LIST_FREE(ec_list, ec)
2174       e_desk_area_ec_reassign(desk->desk_area.base, ec);
2175 }
2176
2177 E_API Eina_Bool
2178 e_desk_desk_area_enable(E_Desk *desk)
2179 {
2180    E_Desk_Area *eda = NULL;
2181    Eina_List *l;
2182
2183    if (!e_config->use_desk_area) return EINA_FALSE;
2184
2185    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2186    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2187
2188    ELOGF("EDG", "Enable Desk_Area...", NULL);
2189    if (desk->desk_area.enable) return EINA_TRUE;
2190    desk->desk_area.enable = EINA_TRUE;
2191
2192    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_enable, desk);
2193    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_ENABLE, desk);
2194
2195    // check all ec is included in desk group
2196    _e_desk_desk_area_check_ec_in_desk_area(desk);
2197
2198    for (int i=0; i<E_DESK_AREA_LAYER_COUNT; i++)
2199      {
2200         EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[i], l, eda)
2201           {
2202              e_desk_area_enable_set(eda, EINA_TRUE);
2203           }
2204      }
2205
2206    return EINA_TRUE;
2207 }
2208
2209 E_API Eina_Bool
2210 e_desk_desk_area_disable(E_Desk *desk)
2211 {
2212    E_Desk_Area *eda = NULL;
2213    Eina_List *l;
2214
2215    if (!e_config->use_desk_area) return EINA_FALSE;
2216
2217    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2218    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2219
2220    ELOGF("EDG", "Disable Desk_Area...", NULL);
2221    if (!desk->desk_area.enable) return EINA_TRUE;
2222    desk->desk_area.enable = EINA_FALSE;
2223
2224    wl_signal_emit_mutable(&PRI(desk)->events.desk_area_disable, desk);
2225    _e_desk_hook_call(E_DESK_HOOK_DESK_AREA_DISABLE, desk);
2226
2227    for (int i=0; i<E_DESK_AREA_LAYER_COUNT; i++)
2228      {
2229         EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[i], l, eda)
2230           {
2231              e_desk_area_enable_set(eda, EINA_FALSE);
2232           }
2233      }
2234    return EINA_TRUE;
2235 }
2236 #endif
2237
2238 EINTERN void
2239 e_desk_desk_area_raise(E_Desk *desk, E_Desk_Area *eda)
2240 {
2241    unsigned int list_id;
2242
2243    if (!e_config->use_desk_area) return;
2244
2245    E_OBJECT_CHECK(desk);
2246    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2247
2248    if (!eda) return;
2249
2250    ELOGF("EDG", "Raise Desk_Area... eda:%p", NULL, eda);
2251
2252    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2253    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2254    desk->desk_area.list[list_id] = eina_list_prepend(desk->desk_area.list[list_id], eda);
2255
2256    e_desk_area_raise(eda);
2257 }
2258
2259 EINTERN void
2260 e_desk_desk_area_lower(E_Desk *desk, E_Desk_Area *eda)
2261 {
2262    unsigned int list_id;
2263
2264    if (!e_config->use_desk_area) return;
2265
2266    E_OBJECT_CHECK(desk);
2267    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2268
2269    if (!eda) return;
2270
2271    ELOGF("EDG", "Lower Desk_Area...", NULL);
2272
2273    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2274    desk->desk_area.list[list_id] = eina_list_remove(desk->desk_area.list[list_id], eda);
2275    desk->desk_area.list[list_id] = eina_list_append(desk->desk_area.list[list_id], eda);
2276
2277    e_desk_area_lower(eda);
2278 }
2279
2280 // get above E_Desk_Area in the same eda layer
2281 EINTERN E_Desk_Area *
2282 e_desk_desk_area_above_get(E_Desk *desk, E_Desk_Area *eda)
2283 {
2284    Eina_List *l = NULL;
2285    E_Desk_Area *above = NULL;
2286    E_Desk_Area *temp = NULL;
2287    unsigned int list_id;
2288
2289    if (!desk) return NULL;
2290    if (!eda) return NULL;
2291
2292    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2293    EINA_LIST_FOREACH(desk->desk_area.list[list_id], l, temp)
2294      {
2295         if (temp != eda)
2296           above = temp;
2297         else
2298           break;
2299      }
2300
2301    ELOGF("EDG", "Get Above E_Desk_Area:%p... current:%p", NULL, above, eda);
2302    return above;
2303 }
2304
2305 // get below E_Desk_Area in the same eda layer
2306 EINTERN E_Desk_Area *
2307 e_desk_desk_area_below_get(E_Desk *desk, E_Desk_Area *eda)
2308 {
2309    Eina_List *l = NULL;
2310    E_Desk_Area *below = NULL;
2311    E_Desk_Area *temp = NULL;
2312    unsigned int list_id;
2313
2314    if (!desk) return NULL;
2315    if (!eda) return NULL;
2316
2317    list_id = _e_desk_desk_area_layer_map(e_desk_area_layer_get(eda));
2318    EINA_LIST_REVERSE_FOREACH(desk->desk_area.list[list_id], l, temp)
2319      {
2320         if (temp != eda)
2321           below = temp;
2322         else
2323           break;
2324      }
2325
2326    ELOGF("EDG", "Get Below E_Desk_Area:%p... current:%p", NULL, below, eda);
2327    return below;
2328 }
2329
2330 static void
2331 _e_desk_hooks_clean(void)
2332 {
2333    Eina_Inlist *l;
2334    E_Desk_Hook *dh;
2335    unsigned int x;
2336
2337    for (x = 0; x < E_DESK_HOOK_LAST; x++)
2338      EINA_INLIST_FOREACH_SAFE(_e_desk_hooks[x], l, dh)
2339        {
2340           if (!dh->delete_me) continue;
2341           _e_desk_hooks[x] = eina_inlist_remove(_e_desk_hooks[x], EINA_INLIST_GET(dh));
2342           free(dh);
2343        }
2344
2345    _e_desk_hooks_delete = 0;
2346 }
2347
2348 static Eina_Bool
2349 _e_desk_hook_call(E_Desk_Hook_Point hookpoint, E_Desk *desk)
2350 {
2351    E_Desk_Hook *dh;
2352
2353    e_object_ref(E_OBJECT(desk));
2354    _e_desk_hooks_walking++;
2355    EINA_INLIST_FOREACH(_e_desk_hooks[hookpoint], dh)
2356      {
2357         if (dh->delete_me) continue;
2358         dh->func(dh->data, desk);
2359      }
2360    _e_desk_hooks_walking--;
2361    if ((_e_desk_hooks_walking == 0) && (_e_desk_hooks_delete > 0))
2362      _e_desk_hooks_clean();
2363
2364    return !!e_object_unref(E_OBJECT(desk));
2365 }
2366
2367 E_API E_Desk_Hook *
2368 e_desk_hook_add(E_Desk_Hook_Point hookpoint, E_Desk_Hook_Cb func, const void *data)
2369 {
2370    E_Desk_Hook *dh;
2371
2372    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_DESK_HOOK_LAST, NULL);
2373    dh = E_NEW(E_Desk_Hook, 1);
2374    if (!dh) return NULL;
2375
2376    dh->hookpoint = hookpoint;
2377    dh->func = func;
2378    dh->data = (void*)data;
2379
2380    _e_desk_hooks[hookpoint] = eina_inlist_append(_e_desk_hooks[hookpoint], EINA_INLIST_GET(dh));
2381    return dh;
2382 }
2383
2384 E_API void
2385 e_desk_hook_del(E_Desk_Hook * dh)
2386 {
2387    dh->delete_me = 1;
2388    if (_e_desk_hooks_walking == 0)
2389      {
2390         _e_desk_hooks[dh->hookpoint] = eina_inlist_remove(_e_desk_hooks[dh->hookpoint], EINA_INLIST_GET(dh));
2391         free(dh);
2392      }
2393    else
2394      _e_desk_hooks_delete++;
2395 }
2396
2397 EINTERN void
2398 e_desk_desk_area_info_print(E_Desk *desk)
2399 {
2400    E_Desk_Area *eda = NULL;
2401    Eina_List *l;
2402
2403    E_OBJECT_CHECK(desk);
2404    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
2405
2406    for (int i=E_DESK_AREA_LAYER_COUNT-1; i>=0; i--)
2407      {
2408         EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
2409           {
2410              e_desk_area_info_print(eda);
2411           }
2412      }
2413 }
2414
2415 static void
2416 _e_desk_cb_splitscreen_destroy(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
2417 {
2418    //TODO:
2419 }
2420
2421 static void
2422 _e_desk_cb_split_desk_activate(struct wl_listener *listener, void *data)
2423 {
2424   E_Desk_Private *priv;
2425
2426   priv = container_of(listener, E_Desk_Private, ds_tizen_splitscreen_activate);
2427
2428   // call the hook for activating the splitscreen in this zone
2429   wl_signal_emit_mutable(&priv->events.split_desk_activate, NULL);
2430   _e_desk_hook_call(E_DESK_HOOK_SPLIT_DESK_ACTIVATE, priv->desk);
2431 }
2432
2433 static void
2434 _e_desk_cb_split_desk_deactivate(struct wl_listener *listener, void *data)
2435 {
2436   E_Desk_Private *priv;
2437
2438   priv = container_of(listener, E_Desk_Private, ds_tizen_splitscreen_deactivate);
2439
2440   // call the hook for deactivating the splitscreen in this desk
2441   wl_signal_emit_mutable(&priv->events.split_desk_deactivate, NULL);
2442   _e_desk_hook_call(E_DESK_HOOK_SPLIT_DESK_DEACTIVATE, priv->desk);
2443 }
2444
2445 EINTERN Eina_Bool
2446 e_desk_splitscreen_enable(E_Desk *desk,
2447       struct ds_tizen_splitscreen *splitscreen)
2448 {
2449    E_Desk_Area *eda;
2450    struct ds_tizen_splitscreen_region *splitscreen_region;
2451    Eina_List *l;
2452    int i;
2453    const char *eda_name;
2454    int x, y, w, h;
2455
2456    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
2457    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
2458    API_ENTRY_VAL(EINA_FALSE);
2459
2460    priv->splitscreen = splitscreen;
2461    priv->ds_tizen_splitscreen_destroy.notify = _e_desk_cb_splitscreen_destroy;
2462    ds_tizen_splitscreen_add_destroy_listener(priv->splitscreen,
2463           &priv->ds_tizen_splitscreen_destroy);
2464    priv->ds_tizen_splitscreen_activate.notify = _e_desk_cb_split_desk_activate;
2465    ds_tizen_splitscreen_add_activate_listener(priv->splitscreen,
2466           &priv->ds_tizen_splitscreen_activate);
2467    priv->ds_tizen_splitscreen_deactivate.notify = _e_desk_cb_split_desk_deactivate;
2468    ds_tizen_splitscreen_add_deactivate_listener(priv->splitscreen,
2469           &priv->ds_tizen_splitscreen_deactivate);
2470
2471    for (i = (E_DESK_AREA_LAYER_COUNT - 1); i >= 0; i--)
2472      {
2473         EINA_LIST_FOREACH(desk->desk_area.list[i], l, eda)
2474           {
2475              eda_name = e_desk_area_name_get(eda);
2476              // The eda->name can be an id of the desk group.
2477              if (!eda_name)
2478                {
2479                   ERR("E_Desk: eda->name is null.");
2480                   continue;
2481                }
2482
2483              e_desk_area_geometry_get(eda, &x, &y, &w, &h);
2484              splitscreen_region = ds_tizen_splitscreen_region_create(
2485                    splitscreen, eda_name, x, y, w, h);
2486              if (!splitscreen_region)
2487                {
2488                   ERR("E_Desk: ds_tizen_splitscreen_region_create() failed.");
2489                   continue;
2490                }
2491
2492             if (!e_desk_area_splitscreen_region_enable(eda, splitscreen_region))
2493                {
2494                   ERR("E_Desk: e_desk_area_splitscreen_region_enable() failed.");
2495                   continue;
2496                }
2497           }
2498      }
2499
2500    return EINA_TRUE;
2501 }
2502
2503 EINTERN Eina_Bool
2504 e_desk_has_ec(E_Desk *desk, E_Client *ec)
2505 {
2506    E_Desk *data;
2507
2508    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2509
2510    data = evas_object_data_get(ec->frame, DESK_EC_DATA_KEY);
2511    if (data == desk) return EINA_TRUE;
2512
2513    return EINA_FALSE;
2514 }
2515
2516 #ifdef REFACTOR_DESK_AREA
2517 EINTERN E_Client *
2518 e_desk_top_ec_get(E_Desk *desk)
2519 {
2520    E_Desk_Area *eda;
2521
2522    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2523
2524    // TODO: get the desk_area which is at top among the desk_areas in this desk
2525    eda = desk->desk_area.base;
2526
2527    return e_desk_area_top_ec_get(eda);
2528 }
2529
2530 EINTERN E_Client *
2531 e_desk_bottom_ec_get(E_Desk *desk)
2532 {
2533    E_Desk_Area *eda;
2534
2535    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
2536
2537    // TODO: get the desk_area which is at bottom among the desk_areas in this desk
2538    eda = desk->desk_area.base;
2539
2540    return e_desk_area_bottom_ec_get(eda);
2541 }
2542
2543 E_API E_Desk_Area *
2544 e_desk_desk_area_find_by_ec(E_Desk *desk, E_Client *ec)
2545 {
2546    E_Desk_Area *eda;
2547
2548    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, NULL);
2549    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
2550
2551    if (!e_desk_has_ec(desk, ec)) return NULL;
2552
2553    // TODO: find the desk_area which has the ec among the desk_areas in this desk
2554    eda = desk->desk_area.base;
2555    if (e_desk_area_has_ec(eda, ec))
2556      return eda;
2557
2558    return NULL;
2559 }
2560 #endif
2561
2562 EINTERN void
2563 e_desk_client_add_listener_add(E_Desk *desk, struct wl_listener *listener)
2564 {
2565    API_ENTRY;
2566    wl_signal_add(&priv->events.client_add, listener);
2567 }
2568
2569 EINTERN void
2570 e_desk_desk_area_enable_listener_add(E_Desk *desk, struct wl_listener *listener)
2571 {
2572    API_ENTRY;
2573    wl_signal_add(&priv->events.desk_area_enable, listener);
2574 }
2575
2576 EINTERN void
2577 e_desk_desk_area_disable_listener_add(E_Desk *desk, struct wl_listener *listener)
2578 {
2579    API_ENTRY;
2580    wl_signal_add(&priv->events.desk_area_disable, listener);
2581 }
2582
2583 EINTERN void
2584 e_desk_desk_area_active_change_listener_add(E_Desk *desk, struct wl_listener *listener)
2585 {
2586    API_ENTRY;
2587    wl_signal_add(&priv->events.desk_area_active_change, listener);
2588 }
2589
2590 EINTERN void
2591 e_desk_ssplit_desk_activate_listener_add(E_Desk *desk, struct wl_listener *listener)
2592 {
2593    API_ENTRY;
2594    wl_signal_add(&priv->events.split_desk_activate, listener);
2595 }
2596
2597 EINTERN void
2598 e_desk_split_desk_deactivate_listener_add(E_Desk *desk, struct wl_listener *listener)
2599 {
2600    API_ENTRY;
2601    wl_signal_add(&priv->events.split_desk_deactivate, listener);
2602 }
2603