dff42f2df48aed3d260f0c1d15582145c4718497
[platform/upstream/enlightenment.git] / src / bin / e_desk.c
1 #include "e.h"
2
3 /* E_Desk is a child object of E_Zone. A desk is essentially a background
4  * and an associated set of client windows. Each zone can have an arbitrary
5  * number of desktops.
6  */
7
8 #define E_DESK_SMART_DATA_GET(obj, ptr)                        \
9    E_Desk_Smart_Data *ptr = evas_object_smart_data_get(obj);
10
11 #define E_DESK_SMART_DATA_GET_OR_RETURN(obj, ptr)              \
12    E_DESK_SMART_DATA_GET(obj, ptr);                            \
13    if (!ptr) return
14
15 typedef struct _E_Desk_Smart_Data E_Desk_Smart_Data;
16
17 struct _E_Desk_Smart_Data
18 {
19    Evas_Object_Smart_Clipped_Data base;
20    Eina_List      *clients;
21    Eina_List      *handlers;
22
23    struct
24    {
25       double       ratio_x, ratio_y;
26       int          cord_x, cord_y;
27       Eina_Bool    enabled;
28    } zoom;
29 };
30
31 static void      _e_desk_free(E_Desk *desk);
32 static void      _e_desk_event_desk_show_free(void *data, void *ev);
33 static void      _e_desk_event_desk_before_show_free(void *data, void *ev);
34 static void      _e_desk_event_desk_after_show_free(void *data, void *ev);
35 static void      _e_desk_show_begin(E_Desk *desk, int dx, int dy);
36 static void      _e_desk_hide_begin(E_Desk *desk, int dx, int dy);
37 static void      _e_desk_event_desk_geometry_change_free(void *data, void *ev);
38 static Eina_Bool _e_desk_cb_zone_move_resize(void *data, int type EINA_UNUSED, void *event);
39
40 static void      _e_desk_smart_init(E_Desk *desk);
41 static void      _e_desk_smart_add(Evas_Object *obj);
42 static void      _e_desk_smart_del(Evas_Object *obj);
43 static void      _e_desk_smart_client_add(Evas_Object *obj, E_Client *ec);
44 static void      _e_desk_smart_client_del(Evas_Object *obj, E_Client *ec);
45 static void      _e_desk_object_zoom(Evas_Object *obj, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy);
46 static void      _e_desk_client_zoom(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy);
47 static void      _e_desk_util_comp_hwc_disable_set(Eina_Bool enable);
48
49 EVAS_SMART_SUBCLASS_NEW(E_DESK_SMART_OBJ_TYPE, _e_desk,
50                         Evas_Smart_Class, Evas_Smart_Class,
51                         evas_object_smart_clipped_class_get, NULL)
52
53 static E_Desk_Flip_Cb _e_desk_flip_cb = NULL;
54 static void *_e_desk_flip_data = NULL;
55
56 E_API int E_EVENT_DESK_SHOW = 0;
57 E_API int E_EVENT_DESK_BEFORE_SHOW = 0;
58 E_API int E_EVENT_DESK_AFTER_SHOW = 0;
59 E_API int E_EVENT_DESK_DESKSHOW = 0;
60 E_API int E_EVENT_DESK_NAME_CHANGE = 0;
61 E_API int E_EVENT_DESK_WINDOW_PROFILE_CHANGE = 0;
62 E_API int E_EVENT_DESK_GEOMETRY_CHANGE = 0;
63 E_API int E_EVENT_DESK_ZOOM_SET = 0;
64 E_API int E_EVENT_DESK_ZOOM_UNSET = 0;
65
66
67 static void
68 _e_desk_event_simple_free(void *d EINA_UNUSED, E_Event_Desk *event)
69 {
70    E_Event_Desk *ev;
71
72    ev = event;
73    e_object_unref(E_OBJECT(ev->desk));
74    free(ev);
75 }
76
77 static void
78 _e_desk_event_simple_add(E_Desk *desk, int type)
79 {
80    E_Event_Desk *ev;
81
82    ev = E_NEW(E_Event_Desk, 1);
83    if (!ev) return;
84    ev->desk = desk;
85    e_object_ref(E_OBJECT(desk));
86
87    ecore_event_add(type, ev, (Ecore_End_Cb)_e_desk_event_simple_free, NULL);
88 }
89
90 EINTERN int
91 e_desk_init(void)
92 {
93    E_EVENT_DESK_SHOW = ecore_event_type_new();
94    E_EVENT_DESK_BEFORE_SHOW = ecore_event_type_new();
95    E_EVENT_DESK_AFTER_SHOW = ecore_event_type_new();
96    E_EVENT_DESK_DESKSHOW = ecore_event_type_new();
97    E_EVENT_DESK_NAME_CHANGE = ecore_event_type_new();
98    E_EVENT_DESK_WINDOW_PROFILE_CHANGE = ecore_event_type_new();
99    E_EVENT_DESK_GEOMETRY_CHANGE = ecore_event_type_new();
100    E_EVENT_DESK_ZOOM_SET = ecore_event_type_new();
101    E_EVENT_DESK_ZOOM_UNSET  = ecore_event_type_new();
102
103    return 1;
104 }
105
106 EINTERN int
107 e_desk_shutdown(void)
108 {
109    return 1;
110 }
111
112 E_API E_Desk *
113 e_desk_new(E_Zone *zone, int x, int y)
114 {
115    E_Desk *desk;
116    Eina_List *l;
117    E_Config_Desktop_Name *cfname;
118    E_Config_Desktop_Window_Profile *cfprof;
119    char name[40];
120    int ok = 0;
121
122    E_OBJECT_CHECK_RETURN(zone, NULL);
123    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
124
125    desk = E_OBJECT_ALLOC(E_Desk, E_DESK_TYPE, _e_desk_free);
126    if (!desk) return NULL;
127
128    desk->zone = zone;
129    desk->x = x;
130    desk->y = y;
131
132    if (!e_config->use_desk_smart_obj)
133      {
134         /* need to set geometry of desk even if disable the smart object,
135          * because 'E_Client' can be reconfigured base on desk.geom as a member
136          * of desk. the reason why this is necessary is all of 'E_Client' is not
137          * members of the smart object so far.
138          */
139         EINA_RECTANGLE_SET(&desk->geom, zone->x, zone->y, zone->w, zone->h);
140         E_LIST_HANDLER_APPEND(desk->handlers, E_EVENT_ZONE_MOVE_RESIZE, _e_desk_cb_zone_move_resize, desk);
141      }
142    else
143      {
144         /* init smart object */
145         _e_desk_smart_init(desk);
146      }
147
148    /* Get current desktop's name */
149    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
150      {
151         if ((cfname->zone >= 0) &&
152             ((int)zone->num != cfname->zone)) continue;
153         if ((cfname->desk_x != desk->x) || (cfname->desk_y != desk->y))
154           continue;
155         desk->name = eina_stringshare_ref(cfname->name);
156         ok = 1;
157         break;
158      }
159
160    if (!ok)
161      {
162         snprintf(name, sizeof(name), _(e_config->desktop_default_name), x, y);
163         desk->name = eina_stringshare_add(name);
164      }
165    /* Get window profile name for current desktop */
166    ok = 0;
167    EINA_LIST_FOREACH(e_config->desktop_window_profiles, l, cfprof)
168      {
169         if ((cfprof->zone >= 0) &&
170             ((int)zone->num != cfprof->zone)) continue;
171         if ((cfprof->desk_x != desk->x) || (cfprof->desk_y != desk->y))
172           continue;
173         desk->window_profile = eina_stringshare_ref(cfprof->profile);
174         ok = 1;
175         break;
176      }
177
178    if (!ok)
179      desk->window_profile = eina_stringshare_ref(e_config->desktop_default_window_profile);
180    return desk;
181 }
182
183 E_API E_Client *
184 e_desk_client_top_visible_get(const E_Desk *desk)
185 {
186    E_Client *ec;
187
188    E_OBJECT_CHECK_RETURN(desk, NULL);
189    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
190
191    E_CLIENT_REVERSE_FOREACH(ec)
192      if (e_client_util_desk_visible(ec, desk) && evas_object_visible_get(ec->frame)) return ec;
193    return NULL;
194 }
195
196 E_API void
197 e_desk_name_set(E_Desk *desk, const char *name)
198 {
199    E_OBJECT_CHECK(desk);
200    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
201
202    eina_stringshare_replace(&desk->name, name);
203
204    _e_desk_event_simple_add(desk, E_EVENT_DESK_NAME_CHANGE);
205 }
206
207 E_API void
208 e_desk_name_add(int zone, int desk_x, int desk_y, const char *name)
209 {
210    E_Config_Desktop_Name *cfname;
211
212    e_desk_name_del(zone, desk_x, desk_y);
213
214    cfname = E_NEW(E_Config_Desktop_Name, 1);
215    if (!cfname) return;
216    cfname->zone = zone;
217    cfname->desk_x = desk_x;
218    cfname->desk_y = desk_y;
219    if (name) cfname->name = eina_stringshare_add(name);
220    else cfname->name = NULL;
221    e_config->desktop_names = eina_list_append(e_config->desktop_names, cfname);
222 }
223
224 E_API void
225 e_desk_name_del(int zone, int desk_x, int desk_y)
226 {
227    Eina_List *l = NULL;
228    E_Config_Desktop_Name *cfname = NULL;
229
230    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
231      {
232         if ((cfname->zone == zone) &&
233             (cfname->desk_x == desk_x) && (cfname->desk_y == desk_y))
234           {
235              e_config->desktop_names =
236                eina_list_remove_list(e_config->desktop_names, l);
237              if (cfname->name) eina_stringshare_del(cfname->name);
238              E_FREE(cfname);
239              break;
240           }
241      }
242 }
243
244 E_API void
245 e_desk_name_update(void)
246 {
247    const Eina_List *z, *l;
248    E_Zone *zone;
249    E_Desk *desk;
250    E_Config_Desktop_Name *cfname;
251    int d_x, d_y, ok;
252    char name[40];
253
254    EINA_LIST_FOREACH(e_comp->zones, z, zone)
255      {
256         for (d_x = 0; d_x < zone->desk_x_count; d_x++)
257           {
258              for (d_y = 0; d_y < zone->desk_y_count; d_y++)
259                {
260                   desk = zone->desks[d_x + zone->desk_x_count * d_y];
261                   ok = 0;
262
263                   EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
264                     {
265                        if ((cfname->zone >= 0) &&
266                            ((int)zone->num != cfname->zone)) continue;
267                        if ((cfname->desk_x != d_x) ||
268                            (cfname->desk_y != d_y)) continue;
269                        e_desk_name_set(desk, cfname->name);
270                        ok = 1;
271                        break;
272                     }
273
274                   if (!ok)
275                     {
276                        snprintf(name, sizeof(name),
277                                 _(e_config->desktop_default_name),
278                                 d_x, d_y);
279                        e_desk_name_set(desk, name);
280                     }
281                }
282           }
283      }
284 }
285
286 E_API void
287 e_desk_show(E_Desk *desk)
288 {
289    E_Event_Desk_Show *ev = NULL;
290    E_Event_Desk_Before_Show *eev = NULL;
291    E_Event_Desk_After_Show *eeev = NULL;
292    Edje_Message_Float_Set *msg = NULL;
293    E_Desk *desk2 = NULL;
294    int dx = 0, dy = 0;
295    Ecore_Event *eev_ecore_event = NULL;
296    Ecore_Event *ev_ecore_event = NULL;
297
298    E_OBJECT_CHECK(desk);
299    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
300    if (desk->visible) return;
301
302    desk2 = e_desk_at_xy_get(desk->zone, desk->zone->desk_x_current, desk->zone->desk_y_current);
303    if ((!starting) && (!desk2->visible)) return;
304    eev = E_NEW(E_Event_Desk_Before_Show, 1);
305    if (!eev) return;
306    eev->desk = e_desk_current_get(desk->zone);
307    e_object_ref(E_OBJECT(eev->desk));
308    eev_ecore_event = ecore_event_add(E_EVENT_DESK_BEFORE_SHOW, eev,
309                                      _e_desk_event_desk_before_show_free, NULL);
310
311    if (desk2->visible)
312      {
313         desk2->visible = 0;
314         if ((!dx) && (!dy))
315           {
316              dx = desk->x - desk2->x;
317              dy = desk->y - desk2->y;
318           }
319         _e_desk_hide_begin(desk2, dx, dy);
320         if (desk2->smart_obj)
321           evas_object_hide(desk2->smart_obj);
322      }
323
324    desk->zone->desk_x_prev = desk->zone->desk_x_current;
325    desk->zone->desk_y_prev = desk->zone->desk_y_current;
326    desk->zone->desk_x_current = desk->x;
327    desk->zone->desk_y_current = desk->y;
328    desk->visible = 1;
329
330    msg = alloca(sizeof(Edje_Message_Float_Set) + (4 * sizeof(double)));
331    msg->count = 5;
332    msg->val[0] = 0.0;
333    msg->val[1] = desk->x;
334    msg->val[2] = desk->zone->desk_x_count;
335    msg->val[3] = desk->y;
336    msg->val[4] = desk->zone->desk_y_count;
337    if (desk->zone->bg_object)
338      edje_object_message_send(desk->zone->bg_object, EDJE_MESSAGE_FLOAT_SET, 0, msg);
339
340 #ifndef ENABLE_QUICK_INIT
341    int was_zone = 0;
342    if (desk->zone->bg_object) was_zone = 1;
343 #endif
344    _e_desk_show_begin(desk, dx, dy);
345    if (desk->smart_obj)
346      evas_object_show(desk->smart_obj);
347
348 #ifndef ENABLE_QUICK_INIT
349    if (was_zone)
350      e_bg_zone_update(desk->zone, E_BG_TRANSITION_DESK);
351    else
352      e_bg_zone_update(desk->zone, E_BG_TRANSITION_START);
353 #endif
354
355    ev = E_NEW(E_Event_Desk_Show, 1);
356    if (!ev) goto error;
357    ev->desk = desk;
358    e_object_ref(E_OBJECT(desk));
359    ev_ecore_event = ecore_event_add(E_EVENT_DESK_SHOW, ev, _e_desk_event_desk_show_free, NULL);
360
361    eeev = E_NEW(E_Event_Desk_After_Show, 1);
362    if (!eeev) goto error;
363    eeev->desk = e_desk_current_get(desk->zone);
364    e_object_ref(E_OBJECT(eeev->desk));
365    ecore_event_add(E_EVENT_DESK_AFTER_SHOW, eeev,
366                    _e_desk_event_desk_after_show_free, NULL);
367    e_zone_edge_flip_eval(desk->zone);
368
369    return;
370
371 error:
372    if (ev)
373      {
374         if (ev_ecore_event)
375           ecore_event_del(ev_ecore_event);
376         e_object_unref(E_OBJECT(ev->desk));
377         free(ev);
378      }
379    if (eev)
380      {
381         if (eev_ecore_event)
382           ecore_event_del(eev_ecore_event);
383         e_object_unref(E_OBJECT(eev->desk));
384         free(eev);
385      }
386 }
387
388 E_API void
389 e_desk_deskshow(E_Zone *zone)
390 {
391    E_Client *ec;
392    E_Desk *desk;
393
394    E_OBJECT_CHECK(zone);
395    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
396
397    desk = e_desk_current_get(zone);
398    EINA_SAFETY_ON_NULL_RETURN(desk);
399
400    if (desk->deskshow_toggle)
401      {
402         /* uniconify raises windows and changes stacking order
403          * go top-down to avoid skipping windows
404          */
405         E_CLIENT_REVERSE_FOREACH(ec)
406           {
407              if (e_client_util_ignored_get(ec)) continue;
408              if (ec->desk != desk) continue;
409              if (ec->deskshow)
410                {
411                   ec->deskshow = 0;
412                   e_client_uniconify(ec);
413                }
414           }
415      }
416    else
417      {
418         /*
419          * iconify raises, so we have to start from the bottom so we are going forward
420          */
421         E_CLIENT_FOREACH(ec)
422           {
423              if (e_client_util_ignored_get(ec)) continue;
424              if (ec->desk != desk) continue;
425              if (ec->iconic) continue;
426              if (ec->netwm.state.skip_taskbar) continue;
427              if (ec->user_skip_winlist) continue;
428              ec->deskshow = 1;
429              e_client_iconify(ec);
430           }
431      }
432    desk->deskshow_toggle = !desk->deskshow_toggle;
433
434    _e_desk_event_simple_add(desk, E_EVENT_DESK_DESKSHOW);
435 }
436
437 E_API E_Client *
438 e_desk_last_focused_focus(E_Desk *desk)
439 {
440    Eina_List *l = NULL;
441    E_Client *ec, *ecs = NULL, *focus_ec = NULL;
442
443    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
444      {
445         if ((!ec->iconic) && (evas_object_visible_get(ec->frame) || ec->changes.visible) &&
446             ((ec->desk == desk) || ((ec->zone == desk->zone) && ec->sticky)) &&
447             (ec->icccm.accepts_focus || ec->icccm.take_focus) &&
448             (ec->netwm.type != E_WINDOW_TYPE_DOCK) &&
449             (ec->netwm.type != E_WINDOW_TYPE_TOOLBAR) &&
450             (ec->netwm.type != E_WINDOW_TYPE_MENU) &&
451             (ec->netwm.type != E_WINDOW_TYPE_SPLASH) &&
452             (ec->netwm.type != E_WINDOW_TYPE_DESKTOP))
453           {
454              /* this was the window last focused in this desktop */
455              if (!ec->lock_focus_out)
456                {
457                   if (ec->sticky)
458                     {
459                        ecs = ec;
460                        continue;
461                     }
462                   if (ec->changes.visible && (!evas_object_visible_get(ec->frame)))
463                     ec->want_focus = ec->take_focus = 1;
464                   else
465                     e_client_focus_set_with_pointer(ec);
466                   if (e_config->raise_on_revert_focus)
467                     e_client_raise(ec);
468                   return ec;
469                }
470           }
471      }
472    if (ecs)
473      {
474         if (ecs->changes.visible && (!evas_object_visible_get(ecs->frame)))
475           ecs->want_focus = ecs->take_focus = 1;
476         else
477           e_client_focus_set_with_pointer(ecs);
478         if (e_config->raise_on_revert_focus)
479           e_client_raise(ecs);
480         return ecs;
481      }
482
483    focus_ec = e_client_focused_get();
484    if (focus_ec)
485      {
486         if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
487           {
488              ELOGF("FOCUS", "focus unset | last_focused_focus", focus_ec);
489              e_client_frame_focus_set(focus_ec, EINA_FALSE);
490           }
491      }
492
493    return NULL;
494 }
495
496 E_API void
497 e_desk_row_add(E_Zone *zone)
498 {
499    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count + 1);
500 }
501
502 E_API void
503 e_desk_row_remove(E_Zone *zone)
504 {
505    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count - 1);
506 }
507
508 E_API void
509 e_desk_col_add(E_Zone *zone)
510 {
511    e_zone_desk_count_set(zone, zone->desk_x_count + 1, zone->desk_y_count);
512 }
513
514 E_API void
515 e_desk_col_remove(E_Zone *zone)
516 {
517    e_zone_desk_count_set(zone, zone->desk_x_count - 1, zone->desk_y_count);
518 }
519
520 E_API E_Desk *
521 e_desk_current_get(E_Zone *zone)
522 {
523    E_OBJECT_CHECK_RETURN(zone, NULL);
524    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
525
526    return e_desk_at_xy_get(zone, zone->desk_x_current, zone->desk_y_current);
527 }
528
529 E_API E_Desk *
530 e_desk_at_xy_get(E_Zone *zone, int x, int y)
531 {
532    E_OBJECT_CHECK_RETURN(zone, NULL);
533    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
534
535    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
536      return NULL;
537    else if ((x < 0) || (y < 0))
538      return NULL;
539
540    if (!zone->desks) return NULL;
541    return zone->desks[x + (y * zone->desk_x_count)];
542 }
543
544 E_API E_Desk *
545 e_desk_at_pos_get(E_Zone *zone, int pos)
546 {
547    int x, y;
548
549    E_OBJECT_CHECK_RETURN(zone, NULL);
550    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
551
552    y = pos / zone->desk_x_count;
553    x = pos - (y * zone->desk_x_count);
554
555    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
556      return NULL;
557
558    return zone->desks[x + (y * zone->desk_x_count)];
559 }
560
561 E_API void
562 e_desk_xy_get(E_Desk *desk, int *x, int *y)
563 {
564    E_OBJECT_CHECK(desk);
565    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
566
567    if (x) *x = desk->x;
568    if (y) *y = desk->y;
569 }
570
571 E_API void
572 e_desk_next(E_Zone *zone)
573 {
574    int x, y;
575
576    E_OBJECT_CHECK(zone);
577    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
578
579    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
580      return;
581
582    x = zone->desk_x_current;
583    y = zone->desk_y_current;
584
585    x++;
586    if (x >= zone->desk_x_count)
587      {
588         x = 0;
589         y++;
590         if (y >= zone->desk_y_count) y = 0;
591      }
592
593    e_desk_show(e_desk_at_xy_get(zone, x, y));
594 }
595
596 E_API void
597 e_desk_prev(E_Zone *zone)
598 {
599    int x, y;
600
601    E_OBJECT_CHECK(zone);
602    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
603
604    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
605      return;
606
607    x = zone->desk_x_current;
608    y = zone->desk_y_current;
609
610    x--;
611    if (x < 0)
612      {
613         x = zone->desk_x_count - 1;
614         y--;
615         if (y < 0) y = zone->desk_y_count - 1;
616      }
617    e_desk_show(e_desk_at_xy_get(zone, x, y));
618 }
619
620 E_API void
621 e_desk_window_profile_set(E_Desk *desk,
622                           const char *profile)
623 {
624    E_OBJECT_CHECK(desk);
625    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
626
627    eina_stringshare_replace(&desk->window_profile, profile);
628
629    _e_desk_event_simple_add(desk, E_EVENT_DESK_WINDOW_PROFILE_CHANGE);
630 }
631
632 E_API void
633 e_desk_window_profile_add(int zone,
634                           int desk_x,
635                           int desk_y,
636                           const char *profile)
637 {
638    E_Config_Desktop_Window_Profile *cfprof;
639
640    e_desk_window_profile_del(zone, desk_x, desk_y);
641
642    cfprof = E_NEW(E_Config_Desktop_Window_Profile, 1);
643    if (!cfprof) return;
644    cfprof->zone = zone;
645    cfprof->desk_x = desk_x;
646    cfprof->desk_y = desk_y;
647    cfprof->profile = eina_stringshare_add(profile);
648    e_config->desktop_window_profiles = eina_list_append(e_config->desktop_window_profiles, cfprof);
649 }
650
651 E_API void
652 e_desk_window_profile_del(int zone,
653                           int desk_x,
654                           int desk_y)
655 {
656    Eina_List *l = NULL;
657    E_Config_Desktop_Window_Profile *cfprof = NULL;
658
659    EINA_LIST_FOREACH(e_config->desktop_window_profiles, l, cfprof)
660      {
661         if (!((cfprof->zone == zone) &&
662               (cfprof->desk_x == desk_x) &&
663               (cfprof->desk_y == desk_y)))
664           continue;
665
666         e_config->desktop_window_profiles =
667           eina_list_remove_list(e_config->desktop_window_profiles, l);
668         eina_stringshare_del(cfprof->profile);
669         free(cfprof);
670         break;
671      }
672 }
673
674 E_API void
675 e_desk_window_profile_update(void)
676 {
677    const Eina_List *z, *l;
678    E_Zone *zone;
679    E_Desk *desk;
680    E_Config_Desktop_Window_Profile *cfprof;
681    int d_x, d_y, ok;
682
683    if (!(e_config->use_desktop_window_profile))
684      return;
685
686    EINA_LIST_FOREACH(e_comp->zones, z, zone)
687      {
688         for (d_x = 0; d_x < zone->desk_x_count; d_x++)
689           {
690              for (d_y = 0; d_y < zone->desk_y_count; d_y++)
691                {
692                   desk = zone->desks[d_x + zone->desk_x_count * d_y];
693                   ok = 0;
694
695                   EINA_LIST_FOREACH(e_config->desktop_window_profiles, l, cfprof)
696                     {
697                        if ((cfprof->zone >= 0) &&
698                            ((int)zone->num != cfprof->zone)) continue;
699                        if ((cfprof->desk_x != d_x) ||
700                            (cfprof->desk_y != d_y)) continue;
701                        e_desk_window_profile_set(desk, cfprof->profile);
702                        ok = 1;
703                        break;
704                     }
705
706                   if (!ok)
707                     {
708                        e_desk_window_profile_set
709                          (desk, e_config->desktop_default_window_profile);
710                     }
711                }
712           }
713      }
714 }
715
716 E_API void
717 e_desk_flip_cb_set(E_Desk_Flip_Cb cb, const void *data)
718 {
719    _e_desk_flip_cb = cb;
720    _e_desk_flip_data = (void*)data;
721 }
722
723 E_API void
724 e_desk_flip_end(E_Desk *desk)
725 {
726    E_Client *ec;
727
728    _e_desk_event_simple_add(desk, E_EVENT_DESK_AFTER_SHOW);
729
730    if ((e_config->focus_policy == E_FOCUS_MOUSE) ||
731        (e_config->focus_policy == E_FOCUS_SLOPPY))
732      {
733         ec = e_client_focused_get();
734         /* only set focus/warp pointer if currently focused window
735          * is on same screen (user hasn't switched screens during transition)
736          */
737         if (ec && ec->desk && (ec->desk->zone != desk->zone)) return;
738      }
739    if (starting) return;
740    ec = e_desk_last_focused_focus(desk);
741    if ((e_config->focus_policy != E_FOCUS_MOUSE) && (!ec))
742      {
743         /* we didn't previously have a focused window on this desk
744          * but we should, so this is probably the first time the
745          * user has flipped to this desk. let's be helpful and
746          * focus a random window!
747          */
748          E_CLIENT_REVERSE_FOREACH(ec)
749            {
750               /* start with top and go down... */
751               if (e_client_util_ignored_get(ec)) continue;
752               if (!e_client_util_desk_visible(ec, desk)) continue;
753               if (ec->iconic) continue;
754               if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
755                 {
756                    ELOGF("FOCUS", "focus set   | desk flip end", ec);
757                    e_client_frame_focus_set(ec, EINA_TRUE);
758                 }
759               if (e_config->raise_on_revert_focus)
760                 e_client_raise(ec);
761               return;
762            }
763      }
764 }
765
766 E_API unsigned int
767 e_desks_count(void)
768 {
769    Eina_List *l;
770    E_Zone *zone;
771    unsigned int count = 0;
772
773    EINA_LIST_FOREACH(e_comp->zones, l, zone)
774      {
775         int cx = 0, cy = 0;
776
777         e_zone_desk_count_get(zone, &cx, &cy);
778         count += cx * cy;
779      }
780    return count;
781 }
782
783 E_API void
784 e_desk_client_add(E_Desk *desk, E_Client *ec)
785 {
786    if (!e_config->use_desk_smart_obj)
787      return;
788
789    E_OBJECT_CHECK(desk);
790    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
791
792    E_OBJECT_CHECK(ec);
793    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
794
795    _e_desk_smart_client_add(desk->smart_obj, ec);
796 }
797
798 E_API void
799 e_desk_client_del(E_Desk *desk, E_Client *ec)
800 {
801    if (!e_config->use_desk_smart_obj)
802      return;
803
804    E_OBJECT_CHECK(desk);
805    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
806
807    E_OBJECT_CHECK(ec);
808    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
809
810    _e_desk_smart_client_del(desk->smart_obj, ec);
811 }
812
813 E_API void
814 e_desk_geometry_set(E_Desk *desk, int x, int y, int w, int h)
815 {
816    E_Client *ec;
817    E_Maximize max;
818    Eina_List *l = NULL, *ll = NULL;
819    Evas_Object *m;
820    E_Event_Desk_Geometry_Change *ev = NULL;
821
822    int cx, cy, dx, dy;
823
824    if (!e_config->use_desk_smart_obj)
825      {
826         DBG("Do nothing, Desk Smart Object is disabled");
827         return;
828      }
829
830    E_OBJECT_CHECK(desk);
831    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
832
833    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
834
835    if ((desk->geom.x == x) && (desk->geom.y == y) &&
836        (desk->geom.w == w) && (desk->geom.h == h))
837      return;
838
839    dx = x - desk->geom.x;
840    dy = y - desk->geom.y;
841    EINA_RECTANGLE_SET(&desk->geom, x, y, w, h);
842
843    EINA_LIST_FOREACH(sd->clients, l, ec)
844      {
845         /* even if the desktop geometry is chagned, the system partial windows such as virtual
846          * keyboard and clipboard should be placed at the bottom of the desktop. */
847         /* QUICK FIX */
848         if (e_policy_client_is_keyboard(ec))
849           {
850              continue;
851           }
852         else if ((ec->comp_data) && (ec->comp_data->sub.data))
853            {
854               continue;
855            }
856         else if (ec->maximized)
857           {
858              max = ec->maximized;
859              ec->maximized = E_MAXIMIZE_NONE;
860              e_client_maximize(ec, max);
861           }
862         else
863           {
864              e_client_geometry_get(ec, &cx, &cy, NULL, NULL);
865              e_client_util_move_without_frame(ec, cx + dx, cy + dy);
866           }
867      }
868
869    // E Client as an member of smart object is not changed even though parent obj is changed
870    // Workaround : update max geometry if ec is a member of desk->smart_obj
871    EINA_LIST_FOREACH(evas_object_smart_members_get(desk->smart_obj), ll, m)
872      {
873         ec = evas_object_data_get(m, "E_Client");
874         if (ec && ec->maximized)
875           {
876              max = ec->maximized;
877              ec->maximized = E_MAXIMIZE_NONE;
878              e_client_maximize(ec, max);
879           }
880      }
881
882    // apply geometry on smart obj
883    evas_object_geometry_set(desk->smart_obj, x, y, w, h);
884
885    ev = E_NEW(E_Event_Desk_Geometry_Change, 1);
886    if (ev)
887      {
888         ev->desk = desk;
889         ev->x = x;
890         ev->y = y;
891         ev->w = w;
892         ev->h = h;
893         e_object_ref(E_OBJECT(desk));
894         ecore_event_add(E_EVENT_DESK_GEOMETRY_CHANGE, ev,
895                         _e_desk_event_desk_geometry_change_free, NULL);
896      }
897
898    e_comp_render_queue();
899 }
900
901 E_API void
902 e_desk_zoom_set(E_Desk *desk, double zoomx, double zoomy, int cx, int cy)
903 {
904    E_Client *ec;
905    Eina_List *l;
906    E_Zone *zone = NULL;
907    E_Output *eout = NULL;
908
909    E_OBJECT_CHECK(desk);
910    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
911
912    if (e_config->use_pp_zoom)
913      {
914         if (e_comp_screen_pp_support())
915           {
916              zone = desk->zone;
917              eout = e_output_find(zone->output_id);
918              if (!eout)
919                {
920                   ERR("e_desk_zoom_set: fail get eout");
921                   goto end;
922                }
923              if (!e_output_zoom_set(eout, zoomx, zoomy, cx, cy))
924                ERR("e_desk_zoom_set: fail zoom set");
925              else
926                DBG("e_desk_zoom_set: zoomx:%f, zoomy:%f, x:%d, y:%d", zoomx, zoomy, cx, cy);
927
928              goto end;
929           }
930      }
931
932    if (e_config->use_desk_smart_obj)
933      {
934         E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
935
936         if ((sd->zoom.ratio_x != zoomx) || (sd->zoom.ratio_y != zoomy) ||
937             (sd->zoom.cord_x != cx) || (sd->zoom.cord_y != cy))
938           {
939              sd->zoom.ratio_x = zoomx;
940              sd->zoom.ratio_y = zoomy;
941              sd->zoom.cord_x = cx;
942              sd->zoom.cord_y = cy;
943
944              _e_desk_object_zoom(desk->smart_obj, zoomx, zoomy, cx, cy);
945              EINA_LIST_FOREACH(sd->clients, l, ec)
946                _e_desk_client_zoom(ec, zoomx, zoomy, cx, cy);
947           }
948
949         if (!sd->zoom.enabled)
950           {
951              sd->zoom.enabled = EINA_TRUE;
952
953              /*
954               * NOTE: evas_object_map_enable_set is called in _e_desk_client_zoom()
955               */
956              /*
957               * evas_object_map_enable_set(desk->smart_obj, EINA_TRUE);
958               * EINA_LIST_FOREACH(sd->clients, l, ec)
959               *   evas_object_map_enable_set(ec->frame, EINA_TRUE);
960               */
961
962              /* FIXME TEMP disable hwc */
963              _e_desk_util_comp_hwc_disable_set(EINA_TRUE);
964           }
965      }
966
967 end:
968    _e_desk_event_simple_add(desk, E_EVENT_DESK_ZOOM_SET);
969 }
970
971 E_API Eina_Bool
972 e_desk_zoom_get(E_Desk *desk, double *zoomx, double *zoomy, int *cx, int *cy)
973 {
974    E_Zone *zone = NULL;
975    E_Output *eout = NULL;
976    Eina_Bool res = EINA_FALSE;
977
978    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
979    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
980
981    if (e_config->use_pp_zoom)
982      {
983         if (e_comp_screen_pp_support())
984           {
985              zone = desk->zone;
986              eout = e_output_find(zone->output_id);
987              if (!eout)
988                {
989                   ERR("e_desk_zoom_set: fail get eout");
990                   return res;
991                }
992
993              res = e_output_zoom_get(eout, zoomx, zoomy, cx, cy);
994              return res;
995           }
996      }
997
998    if (e_config->use_desk_smart_obj)
999      {
1000         E_DESK_SMART_DATA_GET(desk->smart_obj, sd);
1001         EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
1002
1003         if (zoomx) *zoomx = sd->zoom.ratio_x;
1004         if (zoomy) *zoomy = sd->zoom.ratio_y;
1005         if (cx) *cx = sd->zoom.cord_x;
1006         if (cy) *cy = sd->zoom.cord_y;
1007
1008         res = EINA_TRUE;
1009      }
1010
1011    return res;
1012 }
1013
1014 E_API Eina_Bool
1015 e_desk_zoom_get_center_coordinate(E_Desk *desk, double zoomx, double zoomy, int rectx, int recty, int *cx, int *cy)
1016 {
1017    E_Zone *zone = NULL;
1018    E_Output *eout = NULL;
1019    int w, h;
1020    int zoomw, zoomh;
1021
1022    E_OBJECT_CHECK_RETURN(desk, EINA_FALSE);
1023    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE);
1024
1025    zone = desk->zone;
1026    eout = e_output_find(zone->output_id);
1027
1028    e_output_size_get(eout, &w, &h);
1029
1030    zoomw = w / zoomx;
1031    zoomh = h / zoomy;
1032
1033    if (e_config->use_pp_zoom)
1034      {
1035         if (zoomx == 1 || rectx < 0 || zoomw + rectx >= w)
1036           return EINA_FALSE;
1037
1038         if (zoomy == 1 || recty < 0 || zoomh + recty >= h)
1039           return EINA_FALSE;
1040      }
1041    else
1042      {
1043         if (zoomx == 1 || zoomy == 1)
1044           return EINA_FALSE;
1045      }
1046
1047    if (rectx == 0)
1048      *cx = 0;
1049    else
1050      *cx = (int)((zoomx * (double)rectx) / (zoomx - 1.0));
1051
1052    if (recty == 0)
1053      *cy = 0;
1054    else
1055      *cy = (int)((zoomy * (double)recty) / (zoomy - 1.0));
1056
1057    return EINA_TRUE;
1058 }
1059
1060 E_API void
1061 e_desk_zoom_unset(E_Desk *desk)
1062 {
1063    E_Client *ec;
1064    Eina_List *l;
1065    E_Zone *zone = NULL;
1066    E_Output *eout = NULL;
1067
1068    E_OBJECT_CHECK(desk);
1069    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1070
1071    if (e_config->use_pp_zoom)
1072      {
1073         if (e_comp_screen_pp_support())
1074           {
1075              zone = desk->zone;
1076              eout = e_output_find(zone->output_id);
1077              if (!eout)
1078                {
1079                   ERR("e_desk_zoom_unset: fail get eout");
1080                   goto end;
1081                }
1082
1083              e_output_zoom_unset(eout);
1084              DBG("e_desk_zoom_unset");
1085
1086              goto end;
1087           }
1088      }
1089
1090    if (e_config->use_desk_smart_obj)
1091      {
1092         E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1093
1094         if (!sd->zoom.enabled)
1095           goto end;
1096
1097         sd->zoom.ratio_x = 1.0;
1098         sd->zoom.ratio_y = 1.0;
1099         sd->zoom.cord_x = 0;
1100         sd->zoom.cord_y = 0;
1101         sd->zoom.enabled = EINA_FALSE;
1102
1103         _e_desk_object_zoom(desk->smart_obj, sd->zoom.ratio_x, sd->zoom.ratio_y,
1104                             sd->zoom.cord_x, sd->zoom.cord_y);
1105         /*
1106          * NOTE: evas_object_map_enable_set is called in _e_desk_client_zoom()
1107          */
1108         /*
1109          * evas_object_map_enable_set(desk->smart_obj, EINA_FALSE);
1110          */
1111         EINA_LIST_FOREACH(sd->clients, l, ec)
1112           {
1113              /* NOTE Is it really necessary?
1114               * Why isn't it enough to just call evas_object_map_enable_set(false)? */
1115              _e_desk_client_zoom(ec, sd->zoom.ratio_x, sd->zoom.ratio_y,
1116                                  sd->zoom.cord_x, sd->zoom.cord_y);
1117              //evas_object_map_enable_set(ec->frame, EINA_FALSE);
1118           }
1119
1120         /* FIXME TEMP enable hwc */
1121         _e_desk_util_comp_hwc_disable_set(EINA_FALSE);
1122      }
1123
1124 end:
1125    _e_desk_event_simple_add(desk, E_EVENT_DESK_ZOOM_UNSET);
1126 }
1127
1128 E_API void
1129 e_desk_smart_member_add(E_Desk *desk, Evas_Object *obj)
1130 {
1131    if (!e_config->use_desk_smart_obj)
1132      return;
1133
1134    E_OBJECT_CHECK(desk);
1135    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1136
1137    evas_object_smart_member_add(obj, desk->smart_obj);
1138 }
1139
1140 E_API void
1141 e_desk_smart_member_del(Evas_Object *obj)
1142 {
1143    if (!e_config->use_desk_smart_obj)
1144      return;
1145
1146    evas_object_smart_member_del(obj);
1147 }
1148
1149 EINTERN void
1150 e_desk_client_zoom_apply(E_Desk *desk, E_Client *ec)
1151 {
1152    if (!e_config->use_desk_smart_obj)
1153      return;
1154
1155    E_OBJECT_CHECK(desk);
1156    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1157
1158    E_OBJECT_CHECK(ec);
1159    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
1160
1161    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1162
1163    if (sd->zoom.enabled)
1164      {
1165         _e_desk_client_zoom(ec,
1166                             sd->zoom.ratio_x, sd->zoom.ratio_y,
1167                             sd->zoom.cord_x, sd->zoom.cord_y);
1168      }
1169 }
1170
1171 static void
1172 _e_desk_free(E_Desk *desk)
1173 {
1174    E_FREE_FUNC(desk->smart_obj, evas_object_del);
1175    eina_stringshare_del(desk->name);
1176    desk->name = NULL;
1177    E_FREE_LIST(desk->handlers, ecore_event_handler_del);
1178    free(desk);
1179 }
1180
1181 static void
1182 _e_desk_event_desk_show_free(void *data EINA_UNUSED, void *event)
1183 {
1184    E_Event_Desk_Show *ev;
1185
1186    ev = event;
1187    e_object_unref(E_OBJECT(ev->desk));
1188    free(ev);
1189 }
1190
1191 static void
1192 _e_desk_event_desk_before_show_free(void *data EINA_UNUSED, void *event)
1193 {
1194    E_Event_Desk_Before_Show *ev;
1195
1196    ev = event;
1197    e_object_unref(E_OBJECT(ev->desk));
1198    free(ev);
1199 }
1200
1201 static void
1202 _e_desk_event_desk_after_show_free(void *data EINA_UNUSED, void *event)
1203 {
1204    E_Event_Desk_After_Show *ev;
1205
1206    ev = event;
1207    e_object_unref(E_OBJECT(ev->desk));
1208    free(ev);
1209 }
1210
1211 static void
1212 _e_desk_event_desk_geometry_change_free(void *data EINA_UNUSED, void *event)
1213 {
1214    E_Event_Desk_Geometry_Change *ev = event;
1215    e_object_unref(E_OBJECT(ev->desk));
1216    E_FREE(ev);
1217 }
1218
1219 static Eina_Bool
1220 _e_desk_cb_zone_move_resize(void *data, int type EINA_UNUSED, void *event)
1221 {
1222    E_Event_Zone_Move_Resize *ev;
1223    E_Desk *desk;
1224
1225    ev = event;
1226    if (!ev) return ECORE_CALLBACK_PASS_ON;
1227
1228    desk = data;
1229    if (!desk) return ECORE_CALLBACK_PASS_ON;
1230
1231    if (ev->zone != desk->zone)
1232      return ECORE_CALLBACK_PASS_ON;
1233
1234    EINA_RECTANGLE_SET(&desk->geom, ev->zone->x, ev->zone->y, ev->zone->w, ev->zone->h);
1235
1236    return ECORE_CALLBACK_PASS_ON;
1237 }
1238
1239 static Eina_Bool
1240 _e_desk_transition_setup(E_Client *ec, int dx, int dy, int state)
1241 {
1242    e_comp_object_effect_set(ec->frame, "none");
1243
1244    return EINA_FALSE;
1245 }
1246
1247 static void
1248 _e_desk_show_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1249 {
1250    E_Client *ec = data;
1251
1252    ec->desk->animate_count--;
1253    e_client_comp_hidden_set(ec, ec->shaded);
1254    e_comp_object_effect_unclip(ec->frame);
1255    ec->hidden = 0;
1256    if (!ec->visible) evas_object_show(ec->frame);
1257    if (ec->desk != e_desk_current_get(ec->zone)) return;
1258    if (!ec->desk->animate_count) e_desk_flip_end(ec->desk);
1259 }
1260
1261 static void
1262 _e_desk_hide_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
1263 {
1264    E_Client *ec = data;
1265
1266    ec->desk->animate_count--;
1267    ec->hidden = 1;
1268    evas_object_hide(ec->frame);
1269 }
1270
1271 static void
1272 _e_desk_show_begin(E_Desk *desk, int dx, int dy)
1273 {
1274    E_Client *ec;
1275
1276    if (dx < 0) dx = -1;
1277    if (dx > 0) dx = 1;
1278    if (dy < 0) dy = -1;
1279    if (dy > 0) dy = 1;
1280
1281    desk->animate_count = 0;
1282    E_CLIENT_FOREACH(ec)
1283      {
1284         if (e_client_util_ignored_get(ec) || (ec->desk->zone != desk->zone) || (ec->iconic)) continue;
1285         if (ec->moving)
1286           {
1287              e_client_desk_set(ec, desk);
1288              evas_object_show(ec->frame);
1289              continue;
1290           }
1291         if ((ec->desk != desk) || (ec->sticky)) continue;
1292         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, dx, dy, 1))
1293           {
1294              e_comp_object_effect_stop(ec->frame, _e_desk_hide_end);
1295              e_comp_object_effect_start(ec->frame, _e_desk_show_end, ec);
1296              desk->animate_count++;
1297           }
1298         else
1299           ec->hidden = 0;
1300
1301         e_client_comp_hidden_set(ec, ec->hidden || ec->shaded);
1302         evas_object_show(ec->frame);
1303      }
1304    e_desk_flip_end(desk);
1305 }
1306
1307 static void
1308 _e_desk_hide_begin(E_Desk *desk, int dx, int dy)
1309 {
1310    E_Client *ec;
1311
1312    if (dx < 0) dx = -1;
1313    if (dx > 0) dx = 1;
1314    if (dy < 0) dy = -1;
1315    if (dy > 0) dy = 1;
1316
1317    desk->animate_count = 0;
1318    E_CLIENT_FOREACH(ec)
1319      {
1320         if (e_client_util_ignored_get(ec) || (ec->desk->zone != desk->zone) || (ec->iconic)) continue;
1321         if (ec->moving) continue;
1322         if ((ec->desk != desk) || (ec->sticky)) continue;
1323         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, -dx, -dy, 0))
1324           {
1325              e_comp_object_effect_stop(ec->frame, _e_desk_show_end);
1326              e_comp_object_effect_start(ec->frame, _e_desk_hide_end, ec);
1327              desk->animate_count++;
1328           }
1329         else
1330           {
1331              ec->hidden = 1;
1332              evas_object_show(ec->frame);
1333              ec->changes.visible = 0;
1334              evas_object_hide(ec->frame);
1335           }
1336         e_client_comp_hidden_set(ec, EINA_TRUE);
1337      }
1338 }
1339
1340 static void
1341 _e_desk_smart_init(E_Desk *desk)
1342 {
1343    E_Zone *zone;
1344
1345    zone = desk->zone;
1346
1347    if (!e_config->use_desk_smart_obj)
1348      return;
1349
1350    desk->smart_obj = evas_object_smart_add(e_comp->evas, _e_desk_smart_class_new());
1351    e_desk_geometry_set(desk, zone->x, zone->y, zone->w, zone->h);
1352
1353    E_DESK_SMART_DATA_GET_OR_RETURN(desk->smart_obj, sd);
1354
1355    sd->zoom.ratio_x = 1.0;
1356    sd->zoom.ratio_y = 1.0;
1357    sd->zoom.cord_x = 0;
1358    sd->zoom.cord_y = 0;
1359 }
1360
1361 static Eina_Bool
1362 _e_desk_smart_client_cb_resize(void *data, int type, void *event)
1363 {
1364    E_Event_Client *ev;
1365    E_Desk_Smart_Data *sd;
1366    E_Client *ec = NULL;
1367
1368    if (!data) goto end;
1369    if (!event) goto end;
1370
1371    ev = event;
1372    sd = data;
1373    ec = ev->ec;
1374    if (!ec) goto end;
1375
1376    if (!eina_list_data_find(sd->clients, ec))
1377      goto end;
1378
1379    if (sd->zoom.enabled)
1380      _e_desk_client_zoom(ec,
1381                          sd->zoom.ratio_x, sd->zoom.ratio_y,
1382                          sd->zoom.cord_x, sd->zoom.cord_y);
1383 end:
1384    return ECORE_CALLBACK_PASS_ON;
1385 }
1386
1387 static void
1388 _e_desk_smart_add(Evas_Object *obj)
1389 {
1390    EVAS_SMART_DATA_ALLOC(obj, E_Desk_Smart_Data);
1391
1392    /* to apply zoom transformation whenever the client's size is changed. */
1393    E_LIST_HANDLER_APPEND(priv->handlers, E_EVENT_CLIENT_RESIZE, _e_desk_smart_client_cb_resize, priv);
1394
1395    /* FIXME hard coded, it will be laid upper than unpacked clients */
1396    evas_object_layer_set(obj, E_LAYER_DESK_OBJECT);
1397
1398    _e_desk_parent_sc->add(obj);
1399 }
1400
1401 static void
1402 _e_desk_smart_del(Evas_Object *obj)
1403 {
1404    _e_desk_parent_sc->del(obj);
1405
1406    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1407
1408    E_FREE_LIST(sd->handlers, ecore_event_handler_del);
1409    eina_list_free(sd->clients);
1410    free(sd);
1411
1412    evas_object_smart_data_set(obj, NULL);
1413 }
1414
1415 static void
1416 _e_desk_smart_member_add(Evas_Object *obj, Evas_Object *child)
1417 {
1418    E_Client *ec;
1419
1420    _e_desk_parent_sc->member_add(obj, child);
1421
1422    ec = evas_object_data_get(child, "E_Client");
1423    if (ec)
1424      e_desk_client_del(ec->desk, ec);
1425 }
1426
1427 static void
1428 _e_desk_smart_member_del(Evas_Object *obj, Evas_Object *child)
1429 {
1430    E_Client *ec = NULL;
1431    Evas_Object *parent = NULL;
1432
1433    _e_desk_parent_sc->member_del(obj, child);
1434
1435    // if quickpanel packed into mover smart obj, _e_desk_smart_member_del is called
1436    // but parent is still e_desk, because mover's parent is the same e_desk
1437    // than don't add ec on the sd->clists
1438    parent = evas_object_smart_parent_get(child);
1439    if (parent && (parent == obj)) return;
1440
1441    ec = evas_object_data_get(child, "E_Client");
1442    if (ec)
1443      e_desk_client_add(ec->desk, ec);
1444 }
1445
1446 static void
1447 _e_desk_smart_set_user(Evas_Smart_Class *sc)
1448 {
1449    sc->add = _e_desk_smart_add;
1450    sc->del = _e_desk_smart_del;
1451    sc->member_add = _e_desk_smart_member_add;
1452    sc->member_del = _e_desk_smart_member_del;
1453 }
1454
1455 static void
1456 _e_desk_smart_client_add(Evas_Object *obj, E_Client *ec)
1457 {
1458    Evas_Object *parent = NULL;
1459
1460    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1461
1462    // if ec is a member of e_desk, don't add it in data.
1463    parent = evas_object_smart_parent_get(ec->frame);
1464    if (parent && (parent == ec->desk->smart_obj)) return;
1465
1466    if (eina_list_data_find(sd->clients, ec))
1467      return;
1468
1469    sd->clients = eina_list_append(sd->clients, ec);
1470    evas_object_smart_changed(obj);
1471 }
1472
1473 static void
1474 _e_desk_smart_client_del(Evas_Object *obj, E_Client *ec)
1475 {
1476    E_DESK_SMART_DATA_GET_OR_RETURN(obj, sd);
1477
1478    if (!eina_list_data_find(sd->clients, ec))
1479      return;
1480
1481    if (sd->zoom.enabled)
1482      _e_desk_client_zoom(ec, 1.0, 1.0, 0, 0);
1483
1484    sd->clients = eina_list_remove(sd->clients, ec);
1485    evas_object_smart_changed(obj);
1486 }
1487
1488 static void
1489 _e_desk_util_comp_hwc_disable_set(Eina_Bool disable)
1490 {
1491    if (disable)
1492      e_comp_hwc_end("in runtime by e_desk");
1493
1494    e_comp_hwc_deactive_set(disable);
1495 }
1496
1497 static void
1498 _e_desk_object_zoom(Evas_Object *obj, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1499 {
1500    Evas_Map *map;
1501    Eina_Bool enabled;
1502
1503    map = evas_map_new(4);
1504    evas_map_util_object_move_sync_set(map, EINA_TRUE);
1505    evas_map_util_points_populate_from_object(map, obj);
1506    evas_map_util_zoom(map, zoomx, zoomy, cx, cy);
1507    evas_object_map_set(obj, map);
1508    enabled = ((zoomx != 1.0) || (zoomy != 1.0));
1509    evas_object_map_enable_set(obj, enabled);
1510    evas_map_free(map);
1511 }
1512
1513 static void
1514 _e_desk_client_zoom(E_Client *ec, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1515 {
1516    Eina_Bool transformed;
1517
1518    if (e_object_is_del(E_OBJECT(ec))) return;
1519    if (ec->is_cursor) return;
1520
1521    transformed = e_client_transform_core_enable_get(ec);
1522
1523    if (transformed)
1524      e_client_transform_core_update_with_desk_zoom(ec);
1525    else
1526      _e_desk_object_zoom(ec->frame, zoomx, zoomy, cx, cy);
1527
1528    if (evas_object_visible_get(ec->frame))
1529      {
1530         // force update
1531         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1532         e_comp_object_dirty(ec->frame);
1533         e_comp_object_render(ec->frame);
1534      }
1535 }