effect: if parent is animating an effect, do not set additional effect on child window
[platform/core/uifw/e-mod-tizen-effect.git] / src / e_mod_effect.c
1 #include "e_mod_effect.h"
2 #include <tdm.h>
3
4 static E_Effect *_eff = NULL;
5
6 typedef struct _E_Effect_Client
7 {
8    E_Client *ec;
9    unsigned int animating;
10    unsigned int delay_del_ref;
11    E_Comp_Wl_Buffer_Ref buffer_ref;
12    E_Pixmap *ep;
13    E_Client *reverse_ec;
14
15    Evas_Object *under;
16    unsigned int under_ref;
17
18    unsigned int bg_animating;
19 } E_Effect_Client;
20
21 typedef struct
22 {
23    tdm_layer *tlayer;
24    int zpos;
25 } Under_Layer;
26
27 static int
28 _eff_object_underlayer_sort(const void *data1, const void *data2)
29 {
30    const Under_Layer *layer1, *layer2;
31
32    layer1 = data1;
33    layer2 = data2;
34
35    if (layer1->zpos < layer2->zpos)
36      return -1;
37    else if (layer1->zpos > layer2->zpos)
38      return 1;
39    else
40      return 0;
41 }
42
43 static Evas_Object *
44 _eff_object_underlayer_get(E_Client *ec)
45 {
46    Evas_Object *underlay = NULL;
47    E_Comp_Screen *e_comp_screen;
48    Eina_List *l;
49    Under_Layer *ulayer;
50
51    e_comp_screen = e_comp->e_comp_screen;
52    if (!e_comp_screen)
53      return NULL;
54
55    if (e_client_video_client_has(ec))
56      {
57         if ((!_eff->under_layers) && (!_eff->under_checked))
58           {
59              tdm_layer_capability capabilities;
60              E_Output *eoutput;
61              E_Plane *plane;
62              const Eina_List *planes, *l;
63
64              if (!ec->zone) return NULL;
65
66              eoutput = e_output_find(ec->zone->output_id);
67              if (eoutput) return NULL;
68
69              planes = e_output_planes_get(eoutput);
70              if (!planes) return NULL;
71
72              /* Find a plane which is placed under primary and used for video.
73               * planes is supposed to be sorted by zpos (lower -> higher) */
74              EINA_LIST_FOREACH(planes, l, plane)
75                {
76                   if (e_plane_is_primary(plane))
77                     break;
78
79                   if (!plane->is_video)
80                     continue;
81
82                   tdm_layer_get_capabilities(plane->tlayer, &capabilities);
83                   if (!(capabilities & TDM_LAYER_CAPABILITY_GRAPHIC)) continue;
84
85                   ulayer = E_NEW(Under_Layer, 1);
86                   if (!ulayer) continue;
87                   ulayer->zpos = plane->zpos;
88                   ulayer->tlayer = plane->tlayer;
89
90                   _eff->under_layers = eina_list_append(_eff->under_layers,
91                                                         ulayer);
92                }
93
94              _eff->under_checked = EINA_TRUE;
95
96              if (!_eff->under_layers)
97                return NULL;
98
99              _eff->under_layers = eina_list_sort(_eff->under_layers,
100                                                  eina_list_count(_eff->under_layers),
101                                                  _eff_object_underlayer_sort);
102           }
103
104         if (!_eff->under_layers) return NULL;
105
106         EINA_LIST_FOREACH(_eff->under_layers, l, ulayer)
107           {
108              tdm_layer *layer;
109              Evas_Object *img;
110              tbm_surface_h buffer;
111              Evas_Native_Surface ns;
112              tdm_info_layer info;
113              tdm_error err = TDM_ERROR_NONE;
114
115              layer = ulayer->tlayer;
116
117              buffer = tdm_layer_get_displaying_buffer(layer, NULL);
118              if (!buffer) continue;
119
120              err = tdm_layer_get_info(layer, &info);
121              if (err != TDM_ERROR_NONE) continue;
122
123              if (info.dst_pos.w <= 0 || info.dst_pos.h <= 0)
124                continue;
125
126              img = evas_object_image_filled_add(e_comp->evas);
127              if (!img) continue;
128
129              memset(&ns, 0, sizeof(Evas_Native_Surface));
130              ns.version = EVAS_NATIVE_SURFACE_VERSION;
131              ns.type = EVAS_NATIVE_SURFACE_TBM;
132              ns.data.tbm.buffer = buffer;
133
134              evas_object_image_size_set(img, info.dst_pos.w, info.dst_pos.h);
135              evas_object_image_native_surface_set(img, &ns);
136              evas_object_image_pixels_dirty_set(img, EINA_TRUE);
137
138              if (!underlay)
139                {
140                   Evas_Object *bg;
141
142                   underlay = e_layout_add(e_comp->evas);
143                   if (!underlay)
144                     {
145                        evas_object_del(img);
146                        return NULL;
147                     }
148
149                   evas_object_name_set(underlay, "effect-under-layout");
150                   e_layout_virtual_size_set(underlay, ec->zone->w, ec->zone->h);
151                   evas_object_move(underlay, ec->zone->x, ec->zone->y);
152
153                   bg = evas_object_rectangle_add(e_comp->evas);
154                   evas_object_color_set(bg, 0, 0, 0, 255);
155                   e_layout_pack(underlay, bg);
156                   e_layout_child_move(bg, 0, 0);
157                   e_layout_child_resize(bg, ec->zone->w, ec->zone->h);
158                   evas_object_show(bg);
159                }
160
161              e_layout_pack(underlay, img);
162              e_layout_child_move(img, info.dst_pos.x, info.dst_pos.y);
163              e_layout_child_resize(img, info.dst_pos.w, info.dst_pos.h);
164              e_layout_child_raise(img);
165              evas_object_show(img);
166
167              EFFDBG("Video Object Created img(%p) %d,%d %dx%d underlay(%p)",
168                     ec,
169                     img, info.dst_pos.x, info.dst_pos.y, info.dst_pos.w, info.dst_pos.h,
170                     underlay);
171           }
172      }
173
174    return underlay;
175 }
176
177 static void
178 _eff_event_send(E_Client *ec, Eina_Bool start, E_Effect_Type type)
179 {
180    struct wl_resource *res_surf;
181    struct wl_resource *res_eff;
182    struct wl_client *wc;
183    unsigned int tizen_effect_type = TIZEN_EFFECT_TYPE_NONE;
184
185    if (!_eff) return;
186    if ((!ec) || (!ec->comp_data)) return;
187    if (e_object_is_del(E_OBJECT(ec))) return;
188
189    res_surf = ec->comp_data->surface;
190    if (!res_surf) return;
191
192    wc = wl_resource_get_client(res_surf);
193    if (!wc) return;
194
195    res_eff = eina_hash_find(_eff->resources, &wc);
196    if (!res_eff) return;
197
198    switch(type)
199      {
200       case E_EFFECT_TYPE_SHOW:
201          tizen_effect_type = TIZEN_EFFECT_TYPE_SHOW;
202          break;
203       case E_EFFECT_TYPE_HIDE:
204          tizen_effect_type = TIZEN_EFFECT_TYPE_HIDE;
205          break;
206       case E_EFFECT_TYPE_RESTACK_SHOW:
207       case E_EFFECT_TYPE_RESTACK_HIDE:
208          tizen_effect_type = TIZEN_EFFECT_TYPE_RESTACK;
209          break;
210       default:
211          ERR("Unsupported effect type: %d for %p", type, ec);
212          return;
213      }
214
215    EFFINF("SEND %.5s|type:%d|win:0x%08x|tz_effect:0x%08x",
216           ec,
217           start ? "START" : "END", type,
218           (unsigned int)e_client_util_win_get(ec),
219           (unsigned int)res_eff);
220
221    if (start)
222      tizen_effect_send_start(res_eff, res_surf, tizen_effect_type);
223    else
224      {
225         tizen_effect_send_end(res_eff, res_surf, tizen_effect_type);
226
227         EFFINF("Un-SET EXTRA_ANIMATING...", ec);
228         ec->extra_animating = EINA_FALSE;
229         if (ec->launching == EINA_TRUE)
230           {
231              ELOGF("COMP", "Un-Set launching flag..", ec);
232              ec->launching = EINA_FALSE;
233              if (ec->first_mapped)
234                {
235                   ELOGF("LAUNCH", "SHOW real win", ec);
236                   e_comp_object_signal_emit(ec->frame, "e,action,launch_real,done", "e");
237                }
238              e_comp_object_signal_emit(ec->frame, "e,action,launch,done", "e");
239           }
240      }
241 }
242
243 static E_Effect_Client*
244 _eff_client_new(E_Client *ec)
245 {
246    E_Effect_Client *efc;
247
248    efc = E_NEW(E_Effect_Client, 1);
249    if (!efc) return NULL;
250    efc->ec = ec;
251    efc->animating = 0;
252    efc->delay_del_ref = 0;
253    efc->ep = NULL;
254    efc->under_ref = 0;
255    efc->under = NULL;
256
257    return efc;
258 }
259
260 static E_Effect_Client *
261 _eff_client_get(E_Client *ec)
262 {
263    if (!_eff) return NULL;
264    return eina_hash_find(_eff->clients, &ec);
265 }
266
267 static E_Effect_Group
268 _eff_group_get(E_Client *ec)
269 {
270    E_Effect_Group group = E_EFFECT_GROUP_NORMAL;
271
272    /* animatable setting by aux_hint */
273    if (!ec->animatable) return E_EFFECT_GROUP_NONE;
274
275    /* client_type */
276    switch (ec->client_type)
277      {
278       case 1: //homescreen
279          group = E_EFFECT_GROUP_HOME;
280          break;
281       case 2: //lockscreen
282          group = E_EFFECT_GROUP_LOCKSCREEN;
283          break;
284       default:
285          break;
286      }
287
288    /* subsurface */
289    if ((ec->comp_data) && (ec->comp_data->sub.data))
290      group = E_EFFECT_GROUP_NONE;
291
292    /* client layer */
293    if (group == E_EFFECT_GROUP_NORMAL)
294      {
295         if (ec->layer > E_LAYER_CLIENT_NORMAL)
296           group = E_EFFECT_GROUP_NONE;
297      }
298
299    /* window_role */
300
301    /* etc */
302    if (ec->vkbd.vkbd)
303      group = E_EFFECT_GROUP_KEYBOARD;
304
305    return group;
306 }
307
308 static int
309 _eff_group_angle_get(E_Client *ec, E_Effect_Group group)
310 {
311    if (group == E_EFFECT_GROUP_KEYBOARD)
312      {
313          if (ec->parent)
314           {
315              int buffer_transform = e_comp_wl_output_buffer_transform_get(ec);
316              int rot = ec->parent->e.state.rot.ang.curr;
317
318              rot = (rot + (buffer_transform * 90)) % 360;
319
320              return rot;
321           }
322      }
323
324    return ec->e.state.rot.ang.curr;
325 }
326
327 static void
328 _eff_object_setup(E_Client *ec, E_Effect_Group group)
329 {
330    E_Comp_Config *cfg;
331    cfg = e_comp_config_get();
332
333    if (!ec) return;
334
335    if (group == E_EFFECT_GROUP_KEYBOARD)
336      e_comp_object_effect_set(ec->frame, cfg->kbd_effect_style);
337    else if (group == E_EFFECT_GROUP_BACKGROUND)
338      e_comp_object_effect_set(ec->frame, cfg->bg_effect_style);
339    else
340      {
341         E_Effect_Client *efc = NULL;
342         E_Client *parent_ec = ec;
343
344         efc = _eff_client_get(ec);
345
346         while (parent_ec->parent)
347           parent_ec = parent_ec->parent;
348
349         if ((parent_ec != ec) && (parent_ec->launching)) // Launchig case with parent at same time
350           e_comp_object_effect_set(ec->frame, "no-effect");
351         else if ((efc) && (e_policy_client_is_home_screen(efc->reverse_ec))) // Home key effect senario
352           e_comp_object_effect_set(ec->frame, cfg->effect_style);
353         else if ((cfg) && (cfg->depth_in_style) && (ec->effect_type)) //depth-in senario
354           e_comp_object_effect_set(ec->frame, cfg->depth_in_style);
355         else if ((cfg) && (cfg->effect_style))  // normal launching case
356           e_comp_object_effect_set(ec->frame, cfg->effect_style);
357         else
358           e_comp_object_effect_set(ec->frame, "no-effect");
359
360         EFFINF("eff Setup efc(%p) home(%d) type(%d) parent(%d)",
361                ec, efc,
362                efc? e_policy_client_is_home_screen(efc->reverse_ec) : 0,
363                ec->effect_type,
364                parent_ec == ec ? -1 : parent_ec->launching);
365      }
366 }
367
368 static void
369 _eff_object_under_cb_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
370 {
371    E_Effect_Client *efc = (E_Effect_Client *)data;
372    Eina_List *children;
373    Evas_Object *child;
374
375    if (efc->under != obj) return;
376
377    children = e_layout_children_get(obj);
378    EINA_LIST_FREE(children, child)
379      {
380         e_layout_unpack(child);
381         evas_object_del(child);
382      }
383
384    efc->under = NULL;
385    efc->under_ref = 0;
386 }
387
388 static void
389 _eff_object_under_setup(E_Client *ec)
390 {
391    E_Effect_Client *efc = NULL;
392    Evas_Object *underlay = NULL;
393
394    efc = _eff_client_get(ec);
395    if (!efc) return;
396
397    if (efc->under)
398      {
399         efc->under_ref ++;
400      }
401    else if ((underlay = _eff_object_underlayer_get(ec)))
402      {
403         Eina_List *children;
404         Evas_Object *child;
405
406         if (e_comp_object_effect_object_part_swallow(ec->frame, "under", underlay))
407           {
408              evas_object_event_callback_add(underlay,
409                                             EVAS_CALLBACK_DEL,
410                                             _eff_object_under_cb_del,
411                                             efc);
412              evas_object_show(underlay);
413              efc->under = underlay;
414              efc->under_ref ++;
415           }
416         else
417           {
418              children = e_layout_children_get(underlay);
419              EINA_LIST_FREE(children, child)
420                {
421                   e_layout_unpack(child);
422                   evas_object_del(child);
423                }
424
425              evas_object_del(underlay);
426           }
427      }
428 }
429
430 static void
431 _eff_object_under_del(E_Client *ec)
432 {
433    E_Effect_Client *efc = NULL;
434    Eina_List *children;
435    Evas_Object *child;
436
437    efc = _eff_client_get(ec);
438    if (!efc) return;
439    if (!efc->under) return;
440    if (efc->under_ref <= 0)
441      {
442         efc->under_ref = 0;
443         return;
444      }
445
446    efc->under_ref --;
447    if (efc->under_ref > 0) return;
448
449    evas_object_event_callback_del_full(efc->under,
450                                        EVAS_CALLBACK_DEL,
451                                        _eff_object_under_cb_del,
452                                        efc);
453
454    children = e_layout_children_get(efc->under);
455    EINA_LIST_FREE(children, child)
456      {
457         e_layout_unpack(child);
458         evas_object_del(child);
459      }
460
461    evas_object_del(efc->under);
462    efc->under = NULL;
463 }
464
465 static void
466 _eff_object_background_below_clients_get(E_Client *ec, E_Effect_Type type, Eina_List **below_list)
467 {
468    Eina_List *stack = NULL, *list, *next;
469    E_Client *below = NULL;
470
471    if (!_eff) return;
472
473    if (type == E_EFFECT_TYPE_RESTACK_HIDE)
474      stack = _eff->stack.old;
475    else
476      stack = _eff->stack.cur;
477
478    if (!stack) return;
479
480    list = eina_list_data_find_list(stack, ec);
481    if (!list) return;
482
483    next = list;
484    while ((next = eina_list_next(next)))
485      {
486         below = eina_list_data_get(next);
487         if (below == ec)
488           {
489              eina_list_free(*below_list);
490              *below_list = NULL;
491              return;
492           }
493
494         if (e_object_is_del(E_OBJECT(below))) continue;
495         if (ec->zone != below->zone) continue;
496         if (e_client_util_ignored_get(below) ||
497             (!evas_object_visible_get(below->frame))) continue;
498
499         if (below->vkbd.vkbd)
500           continue;
501
502         *below_list = eina_list_prepend(*below_list, below);
503
504         if (!below->argb)
505           break;
506         else
507           {
508              if (below->visibility.opaque > 0)
509                break;
510           }
511      }
512 }
513
514 static void
515 _eff_object_background_cb_zoom_in_done(void *data, Evas_Object *obj, const char *sig, const char *src)
516 {
517    E_Client *bg_ec;
518    E_Effect_Client *bg_efc;
519
520    bg_ec = (E_Client *)data;
521    if (!bg_ec) return;
522
523    bg_efc = _eff_client_get(bg_ec);
524    if (bg_efc)
525      bg_efc->bg_animating = 0;
526
527    e_object_unref(E_OBJECT(bg_ec));
528 }
529
530 static void
531 _eff_object_background_cb_zoom_out_done(void *data, Evas_Object *obj, const char *sig, const char *src)
532 {
533    E_Client *bg_ec;
534    E_Effect_Client *bg_efc;
535
536    bg_ec = (E_Client *)data;
537    if (!bg_ec) return;
538
539    bg_efc = _eff_client_get(bg_ec);
540    if (bg_efc)
541      bg_efc->bg_animating = 0;
542
543    e_object_unref(E_OBJECT(bg_ec));
544 }
545
546 static void
547 _eff_object_background_start(E_Client *bg_ec, E_Effect_Type type, int bg_opaque)
548 {
549    E_Effect_Client *bg_efc = NULL;
550    int ang = -1;
551
552    if (!bg_ec) return;
553    if (e_object_is_del(E_OBJECT(bg_ec))) return;
554    if (!bg_ec->animatable) return;
555
556    bg_efc = _eff_client_get(bg_ec);
557    if (!bg_efc) return;
558    if ((bg_efc->bg_animating) ||
559        ((bg_efc->animating) && !((bg_ec->launching) && (bg_efc->animating == 1))))
560      return;
561
562    // 1st param : zoom-in(0) zoom-out(1)
563    // 2nd param : rotation angle
564    // 3rd param : background rect transparency(0) opaque(1)
565    switch (type)
566      {
567       case E_EFFECT_TYPE_SHOW:
568       case E_EFFECT_TYPE_RESTACK_SHOW:
569          if (bg_ec->visibility.obscured != E_VISIBILITY_FULLY_OBSCURED)
570            {
571               e_object_ref(E_OBJECT(bg_ec));
572               _eff_object_setup(bg_ec, E_EFFECT_GROUP_BACKGROUND);
573               ang = _eff_group_angle_get(bg_ec, E_EFFECT_GROUP_BACKGROUND);
574               e_comp_object_effect_params_set(bg_ec->frame, 0, (int[]){0, ang, bg_opaque}, 3);
575               e_comp_object_effect_start(bg_ec->frame, _eff_object_background_cb_zoom_in_done, bg_ec);
576               bg_efc->bg_animating = 1;
577            }
578          break;
579
580       case E_EFFECT_TYPE_RESTACK_HIDE:
581          e_object_ref(E_OBJECT(bg_ec));
582          _eff_object_setup(bg_ec, E_EFFECT_GROUP_BACKGROUND);
583          ang = _eff_group_angle_get(bg_ec, E_EFFECT_GROUP_BACKGROUND);
584          e_comp_object_effect_params_set(bg_ec->frame, 0, (int[]){1, ang, bg_opaque}, 3);
585          e_comp_object_effect_start(bg_ec->frame, _eff_object_background_cb_zoom_out_done, bg_ec);
586          bg_efc->bg_animating = 1;
587          break;
588
589       case E_EFFECT_TYPE_HIDE:
590          if (bg_ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
591            {
592               e_object_ref(E_OBJECT(bg_ec));
593               _eff_object_setup(bg_ec, E_EFFECT_GROUP_BACKGROUND);
594               ang = _eff_group_angle_get(bg_ec, E_EFFECT_GROUP_BACKGROUND);
595               e_comp_object_effect_params_set(bg_ec->frame, 0, (int[]){1, ang, bg_opaque}, 3);
596               e_comp_object_effect_start(bg_ec->frame, _eff_object_background_cb_zoom_out_done, bg_ec);
597               bg_efc->bg_animating = 1;
598            }
599          break;
600
601       default:
602          /* do nothing */
603          break;
604      }
605 }
606
607 static void
608 _eff_object_background_setup(E_Client *ec, E_Client *home_ec, E_Effect_Group group, E_Effect_Type type)
609 {
610    E_Comp_Config *cfg;
611    E_Client *bg_ec = NULL;
612    Eina_List *bg_list = NULL;
613
614    cfg = e_comp_config_get();
615    if (!cfg) return;
616    if (!cfg->bg_effect_style) return;
617
618    if (!ec) return;
619    if (group != E_EFFECT_GROUP_NORMAL) return;
620    if ((ec->argb) || (ec->effect_type)) return; //need to check opaque?
621
622    if (home_ec)
623      _eff_object_background_start(home_ec, type, 1);
624    else
625      {
626         int first = 1;
627
628         _eff_object_background_below_clients_get(ec, type, &bg_list);
629         if (!bg_list) return;
630
631         EINA_LIST_FREE(bg_list, bg_ec)
632           {
633              if (first)
634                {
635                   EFFDBG("make bottom most background to be opaque", bg_ec);
636                   _eff_object_background_start(bg_ec, type, 1);
637                   first = 0;
638                }
639              else
640                {
641                   _eff_object_background_start(bg_ec, type, 0);
642                }
643           }
644      }
645 }
646
647 static void
648 _eff_object_layer_up(E_Client *ec)
649 {
650    int map_ly;
651
652    map_ly = e_comp_canvas_client_layer_map(ec->layer);
653    if (map_ly == 9999) return;
654
655    if (!_eff->layers[map_ly].obj)
656      {
657         _eff->layers[map_ly].obj = evas_object_rectangle_add(e_comp->evas);
658         evas_object_layer_set(_eff->layers[map_ly].obj, ec->layer + 1);
659         evas_object_name_set(_eff->layers[map_ly].obj, "layer_obj(effect)");
660      }
661
662    ec->layer_pending = 1;
663    evas_object_layer_set(ec->frame, ec->layer + 1);
664 }
665
666 static void
667 _eff_object_layer_down(E_Client *ec)
668 {
669    evas_object_layer_set(ec->frame, ec->layer);
670    ec->layer_pending = 0;
671 }
672
673 static void
674 _eff_pending_effect_start(void)
675 {
676    E_Client *ec;
677
678    ec = _eff->next_done.ec;
679    if (!ec) return;
680
681    EFFINF("Pending eff Start type(%d)",
682           ec, _eff->next_done.type);
683
684    if (_eff->next_done.cb)
685      {
686         _eff_event_send(ec, EINA_TRUE, _eff->next_done.type);
687         e_comp_object_effect_start(ec->frame,
688                                    _eff->next_done.cb,
689                                    _eff->next_done.data);
690      }
691
692    memset(&_eff->next_done, 0, sizeof(_eff->next_done));
693 }
694
695 static void
696 _eff_pending_effect_set(E_Client *ec, void *data, E_Effect_Type type, Edje_Signal_Cb done_cb)
697 {
698    _eff_pending_effect_start();
699
700    EFFINF("Pending eff Set type(%d)",
701           ec, type);
702
703    _eff->next_done.cb = done_cb;
704    _eff->next_done.ec = ec;
705    _eff->next_done.data = data;
706    _eff->next_done.type = type;
707 }
708
709 static void
710 _eff_stack_update(void)
711 {
712    E_Client *ec;
713    Evas_Object *o;
714
715    if (!_eff) return;
716
717    _eff->stack.old = eina_list_free(_eff->stack.old);
718    _eff->stack.old = eina_list_clone(_eff->stack.cur);
719
720    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
721      {
722         ec = evas_object_data_get(o, "E_Client");
723         if (!ec) continue;
724         if (e_client_util_ignored_get(ec)) continue;
725         if (e_object_is_del(E_OBJECT(ec))) continue;
726
727         _eff->stack.cur = eina_list_remove(_eff->stack.cur, ec);
728         _eff->stack.cur = eina_list_append(_eff->stack.cur, ec);
729      }
730 }
731
732 static Eina_Bool
733 _eff_visibility_stack_check(E_Client *ec, Eina_List *stack)
734 {
735    Eina_List *l;
736    E_Client *_ec;
737    Eina_Tiler *tiler;
738    Eina_Rectangle r;
739    Eina_Bool vis = EINA_TRUE;
740    int x, y, w, h;
741
742    if (!stack) return EINA_FALSE;
743
744    tiler = eina_tiler_new(ec->desk->geom.w, ec->desk->geom.h);
745    eina_tiler_tile_size_set(tiler, 1, 1);
746    EINA_RECTANGLE_SET(&r, ec->desk->geom.x, ec->desk->geom.y, ec->desk->geom.w, ec->desk->geom.h);
747    eina_tiler_rect_add(tiler, &r);
748
749    EINA_LIST_FOREACH(stack, l, _ec)
750      {
751         if (_ec == ec) break;
752         if (!_ec->visible) continue;
753         if (!evas_object_visible_get(_ec->frame))
754           {
755              if (!_ec->iconic) continue;
756              if (_ec->iconic && _ec->exp_iconify.by_client) continue;
757           }
758         if (!e_pixmap_resource_get(_ec->pixmap)) continue;
759         if ((_ec->argb) && (_ec->visibility.opaque != 1)) continue;
760
761         e_client_geometry_get(_ec, &x, &y, &w, &h);
762
763         EINA_RECTANGLE_SET(&r, x, y, w, h);
764         eina_tiler_rect_del(tiler, &r);
765
766         if (eina_tiler_empty(tiler))
767           {
768              vis = EINA_FALSE;
769              break;
770           }
771      }
772    eina_tiler_free(tiler);
773
774    return vis;
775 }
776
777 static const char *
778 _eff_restack_effect_check(E_Client *ec)
779 {
780    const char *emission = NULL;
781    Eina_Bool v1, v2;
782    E_Effect_Client *efc;
783
784    if (!evas_object_visible_get(ec->frame)) return NULL;
785    if (ec->new_client) return NULL;
786
787    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
788    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
789
790    if (v1 != v2)
791      {
792         if ((v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED))
793           emission = "e,action,restack,show";
794         else if ((!v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED))
795           emission = "e,action,restack,hide";
796      }
797    else
798      {
799         efc = _eff_client_get(ec);
800
801         // TODO : it's for transients windows. wish using other check */
802         if ((efc) && (!efc->animating))
803           {
804              if ((v2) && (!ec->iconic) &&
805                  (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED))
806                emission = "e,action,restack,show";
807              else if ((!v2) && (ec->iconic) &&
808                       (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED))
809                emission = "e,action,restack,hide";
810           }
811      }
812
813    EFFINF("Restack eff Check v1(%d) -> v2(%d) iconic:%d "
814           "obscured:%d(%d) emission:%s",
815           ec,
816           v1, v2, ec->iconic,
817           ec->visibility.obscured, ec->visibility.changed, emission);
818
819    return emission;
820 }
821
822 static Eina_Bool
823 _eff_ref(E_Client *ec)
824 {
825    E_Effect_Client *efc;
826
827    if (!_eff) return EINA_FALSE;
828
829    efc = _eff_client_get(ec);
830    if (!efc) return EINA_FALSE;
831
832    if (e_object_is_del(E_OBJECT(ec)))
833      {
834         if (!e_object_delay_del_ref_get(E_OBJECT(ec)))
835           {
836              ERR("Client is deleted already! ec(%p)", ec);
837              eina_hash_del_by_key(_eff->clients, &ec);
838              return EINA_FALSE;
839           }
840      }
841
842    if (!ec->pixmap) return EINA_FALSE;
843    if ((e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) &&
844        (!e_comp_object_native_usable_get(ec->frame)))
845      return EINA_FALSE;
846
847    if (e_object_is_del(E_OBJECT(ec)))
848      {
849         e_object_delay_del_ref(E_OBJECT(ec));
850         efc->delay_del_ref ++;
851      }
852
853    efc->bg_animating = 0;
854    efc->animating++;
855    e_object_ref(E_OBJECT(ec));
856    efc->ep = e_pixmap_ref(ec->pixmap);
857
858    EFFINF("effect ref efc(%p) animating:%d",
859           efc->ec, efc, efc->animating);
860
861    return EINA_TRUE;
862 }
863
864 static E_Client *
865 _eff_unref(E_Client *ec)
866 {
867    E_Effect_Client *efc;
868    int do_unref = 1;
869
870    if (!_eff) return NULL;
871    if (!ec) return NULL;
872
873    efc = _eff_client_get(ec);
874    if (!efc) return NULL;
875
876    while (efc->delay_del_ref)
877      {
878         e_object_delay_del_unref(E_OBJECT(ec));
879         efc->delay_del_ref--;
880      }
881
882    if (e_object_is_del(E_OBJECT(ec)))
883      do_unref = efc->animating;
884
885    efc->animating -= do_unref;
886    while (do_unref)
887      {
888         e_pixmap_free(efc->ep);
889         if (efc->under)
890           _eff_object_under_del(ec);
891         if (!e_object_unref(E_OBJECT(ec)))
892           {
893              EFFINF("eff unref ec(%p) ep(%p) efc(%p) Client free'd",
894                     NULL, ec, efc->ep, efc);
895
896              efc->ec = NULL;
897              efc = NULL;
898              eina_hash_del_by_key(_eff->clients, &ec);
899              return NULL;
900           }
901         do_unref --;
902      }
903
904    EFFINF("eff Unref efc(%p) animating:%d",
905           ec, efc, efc->animating);
906
907    /* The reference count of wl_buffer will get decremented
908     * immediately after window effect.
909     */
910    if ((efc) && (efc->buffer_ref.buffer))
911      e_comp_wl_buffer_reference(&efc->buffer_ref, NULL);
912
913    return ec;
914 }
915
916 static void
917 _eff_cb_visible_done(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
918 {
919    E_Client *ec = (E_Client *)data;
920
921    if (ec)
922      {
923         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_SHOW);
924         e_comp_client_override_del(ec);
925         _eff_unref(ec);
926      }
927
928    _eff_stack_update();
929 }
930
931 static Eina_Bool
932 _eff_cb_visible(void *data, Evas_Object *obj, const char *signal)
933 {
934    E_Client *ec;
935    E_Effect_Group group;
936    int ang = -1;
937
938    if (!_eff) return EINA_FALSE;
939
940    ec = e_comp_object_client_get(obj);
941    if (!ec) return EINA_FALSE;
942    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
943
944    group = _eff_group_get(ec);
945    if ((group != E_EFFECT_GROUP_NORMAL) &&
946        (group != E_EFFECT_GROUP_KEYBOARD))
947      {
948         e_comp_object_effect_set(ec->frame, NULL);
949         return EINA_FALSE;
950      }
951
952    if (evas_object_visible_get(obj)) return EINA_FALSE;
953
954    e_comp_client_override_add(ec);
955
956    if (!_eff_ref(ec))
957      {
958         e_comp_client_override_del(ec);
959         return EINA_FALSE;
960      }
961
962    _eff_stack_update();
963
964    EFFINF("SET EXTRA_ANIMATING...", ec);
965    ec->extra_animating = EINA_TRUE;
966
967    _eff_object_setup(ec, group);
968    _eff_object_under_setup(ec);
969
970    ang = _eff_group_angle_get(ec, group);
971    e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
972    if (e_comp->nocomp)
973      {
974         _eff_pending_effect_set(ec,
975                                 (void *)ec,
976                                 E_EFFECT_TYPE_SHOW,
977                                 _eff_cb_visible_done);
978         return EINA_TRUE;
979      }
980
981    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
982
983    e_comp_object_effect_start(ec->frame, _eff_cb_visible_done, ec);
984
985    _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_SHOW);
986
987    return EINA_TRUE;
988 }
989
990 static void
991 _eff_cb_hidden_done(void *data, Evas_Object *obj, const char *sig, const char *src)
992 {
993    E_Client *ec = (E_Client *)data;
994
995    if (ec)
996      {
997         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
998         e_comp_client_override_del(ec);
999         if (_eff_unref(ec))
1000           {
1001              if (_eff_client_get(ec))
1002                {
1003                   _eff_object_layer_down(ec);
1004                   evas_object_hide(ec->frame);
1005                   e_comp_object_effect_hiding_set(ec->frame, 0);
1006                }
1007           }
1008      }
1009 }
1010
1011 static Eina_Bool
1012 _eff_cb_hidden(void *data, Evas_Object *obj, const char *signal)
1013 {
1014    E_Client *ec;
1015    E_Effect_Group group;
1016    Eina_Bool lowered = 0;
1017    Evas_Object *below;
1018    int map_ly;
1019    int ang = -1;
1020    Eina_Bool v1, v2;
1021
1022    if (!_eff) return EINA_FALSE;
1023
1024    ec = e_comp_object_client_get(obj);
1025    if (!ec) return EINA_FALSE;
1026    if (e_object_is_del(E_OBJECT(ec)))
1027      {
1028         if (!e_object_delay_del_ref_get(E_OBJECT(ec))) return EINA_FALSE;
1029      }
1030
1031    /* check for effect group */
1032    group = _eff_group_get(ec);
1033    if ((group != E_EFFECT_GROUP_NORMAL) &&
1034        (group != E_EFFECT_GROUP_KEYBOARD))
1035      {
1036         e_comp_object_effect_set(ec->frame, NULL);
1037         return EINA_FALSE;
1038      }
1039
1040    if (group == E_EFFECT_GROUP_KEYBOARD)
1041      {
1042         if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
1043           return EINA_FALSE;
1044      }
1045
1046    /* check for object visibility */
1047    if (!evas_object_visible_get(obj)) return EINA_FALSE;
1048
1049    /* check for stack visibility */
1050    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1051    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1052    if ((!v1) && (!v2)) return EINA_FALSE;
1053
1054    e_comp_client_override_add(ec);
1055
1056    if (!_eff_ref(ec))
1057      {
1058         e_comp_client_override_del(ec);
1059         return EINA_FALSE;
1060      }
1061
1062    // check if client was lowered
1063    below = evas_object_below_get(obj);
1064    map_ly = e_comp_canvas_layer_map(evas_object_layer_get(obj));
1065    if ((below) && (map_ly != 9999) &&
1066        (evas_object_layer_get(below) != evas_object_layer_get(obj)) &&
1067        (evas_object_above_get(obj) != e_comp->layers[map_ly].obj))
1068      lowered = 1;
1069
1070    if (lowered)
1071      _eff_object_layer_up(ec);
1072
1073    _eff_object_setup(ec, group);
1074    _eff_object_under_setup(ec);
1075
1076    ang = _eff_group_angle_get(ec, group);
1077    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
1078
1079    if (e_comp->nocomp)
1080      {
1081         _eff_pending_effect_set(ec,
1082                                 (void *)ec,
1083                                 E_EFFECT_TYPE_HIDE,
1084                                 _eff_cb_hidden_done);
1085         return EINA_TRUE;
1086      }
1087
1088    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
1089    if (e_comp_object_effect_start(ec->frame, _eff_cb_hidden_done, ec))
1090      {
1091         e_comp_object_effect_hiding_set(ec->frame, 1);
1092      }
1093
1094    _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_HIDE);
1095
1096    return EINA_TRUE;
1097 }
1098
1099 static void
1100 _eff_cb_uniconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1101 {
1102    E_Client *ec = (E_Client *)data;
1103
1104    if (ec)
1105      {
1106         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_SHOW);
1107         e_comp_client_override_del(ec);
1108         _eff_unref(ec);
1109      }
1110 }
1111
1112 static Eina_Bool
1113 _eff_cb_uniconify(void *data, Evas_Object *obj, const char *signal)
1114 {
1115    E_Client *ec;
1116    E_Effect_Group group;
1117    Eina_Bool v1, v2;
1118    int ang = -1;
1119
1120    if (!_eff) return EINA_FALSE;
1121
1122    ec = e_comp_object_client_get(obj);
1123    if (!ec) return EINA_FALSE;
1124    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1125
1126    if (evas_object_visible_get(obj)) return EINA_FALSE;
1127
1128    group = _eff_group_get(ec);
1129
1130    /* for HOME group */
1131    if (group == E_EFFECT_GROUP_HOME)
1132      {
1133         E_Client *below;
1134
1135         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1136         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1137
1138         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1139                ec,
1140                v1, v2, ec->visibility.obscured, ec->visibility.changed);
1141
1142         if (v1 == v2) return EINA_FALSE;
1143         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1144         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1145
1146         below = e_client_below_get(ec);
1147         while (below)
1148           {
1149              if ((evas_object_visible_get(below->frame)) &&
1150                  (below->layer == ec->layer) &&
1151                  ((below->visibility.obscured == E_VISIBILITY_UNOBSCURED) ||
1152                   (below->visibility.changed)))
1153                break;
1154
1155              below = e_client_below_get(below);
1156           }
1157
1158         if (!below) return EINA_FALSE;
1159         group = _eff_group_get(below);
1160         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
1161
1162         EFFINF("Uniconify HOME group do hide eff of %p",
1163                ec, below);
1164
1165         e_comp_object_signal_emit(below->frame, "e,action,restack,hide", "e");
1166         return EINA_TRUE;
1167      }
1168    /* for NORMAL and KEYBOARD group */
1169    else if ((group == E_EFFECT_GROUP_NORMAL) ||
1170             (group == E_EFFECT_GROUP_KEYBOARD))
1171      {
1172         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1173         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1174
1175         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1176                ec,
1177                v1, v2, ec->visibility.obscured, ec->visibility.changed);
1178
1179         if (v1 == v2) return EINA_FALSE;
1180         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1181         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1182
1183         e_comp_client_override_add(ec);
1184
1185         if (!_eff_ref(ec))
1186           {
1187              e_comp_client_override_del(ec);
1188              return EINA_FALSE;
1189           }
1190
1191         _eff_object_setup(ec, group);
1192         _eff_object_under_setup(ec);
1193
1194         ang = _eff_group_angle_get(ec, group);
1195         e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
1196
1197         if (e_comp->nocomp)
1198           {
1199              _eff_pending_effect_set(ec,
1200                                      (void *)ec,
1201                                      E_EFFECT_TYPE_SHOW,
1202                                      _eff_cb_uniconify_done);
1203              return EINA_TRUE;
1204           }
1205
1206         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
1207         e_comp_object_effect_start(ec->frame, _eff_cb_uniconify_done, ec);
1208         return EINA_TRUE;
1209      }
1210    else
1211      {
1212         e_comp_object_effect_set(ec->frame, NULL);
1213      }
1214
1215    return EINA_FALSE;
1216 }
1217
1218 static void
1219 _eff_cb_iconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1220 {
1221    E_Client *ec = (E_Client *)data;
1222
1223    if (ec)
1224      {
1225         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
1226         e_comp_client_override_del(ec);
1227         if (_eff_unref(ec))
1228           {
1229              if (_eff_client_get(ec))
1230                {
1231                   evas_object_hide(ec->frame);
1232                   e_comp_object_effect_hiding_set(ec->frame, 0);
1233                }
1234           }
1235      }
1236 }
1237
1238 static Eina_Bool
1239 _eff_cb_iconify(void *data, Evas_Object *obj, const char *signal)
1240 {
1241    E_Client *ec;
1242    E_Effect_Group group;
1243    Eina_Bool v1, v2;
1244    int ang = -1;
1245
1246    if (!_eff) return EINA_FALSE;
1247
1248    ec = e_comp_object_client_get(obj);
1249    if (!ec) return EINA_FALSE;
1250    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1251
1252    group = _eff_group_get(ec);
1253    if ((group != E_EFFECT_GROUP_NORMAL) &&
1254        (group != E_EFFECT_GROUP_KEYBOARD))
1255      {
1256         e_comp_object_effect_set(ec->frame, NULL);
1257         return EINA_FALSE;
1258      }
1259
1260    if (!evas_object_visible_get(obj)) return EINA_FALSE;
1261
1262    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1263    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1264
1265    EFFINF("Iconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1266           ec,
1267           v1, v2, ec->visibility.obscured, ec->visibility.changed);
1268
1269    if (v1 == v2) return EINA_FALSE;
1270    if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1271    if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1272
1273    e_comp_client_override_add(ec);
1274
1275    if (!_eff_ref(ec))
1276      {
1277         e_comp_client_override_del(ec);
1278         return EINA_FALSE;
1279      }
1280
1281    _eff_object_setup(ec, group);
1282    _eff_object_under_setup(ec);
1283
1284    ang = _eff_group_angle_get(ec, group);
1285    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
1286
1287    if (e_comp->nocomp)
1288      {
1289         _eff_pending_effect_set(ec,
1290                                 (void *)ec,
1291                                 E_EFFECT_TYPE_HIDE,
1292                                 _eff_cb_iconify_done);
1293         return EINA_TRUE;
1294      }
1295
1296    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
1297    if (e_comp_object_effect_start(ec->frame, _eff_cb_iconify_done, ec))
1298      {
1299         e_comp_object_effect_hiding_set(ec->frame, 1);
1300      }
1301
1302    return EINA_TRUE;
1303 }
1304
1305 static void
1306 _eff_cb_restack_show_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1307 {
1308    E_Client *ec = (E_Client *)data;
1309
1310    if (ec)
1311      {
1312         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_SHOW);
1313         e_comp_client_override_del(ec);
1314         _eff_unref(ec);
1315      }
1316
1317    _eff_stack_update();
1318 }
1319
1320 static void
1321 _eff_cb_restack_hide_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1322 {
1323    E_Client *ec = (E_Client *)data;
1324
1325    if (ec)
1326      {
1327         e_comp_client_override_del(ec);
1328         if (_eff_unref(ec))
1329           {
1330              if (_eff_client_get(ec))
1331                {
1332                   _eff_object_layer_down(ec);
1333                   e_comp_object_signal_emit(ec->frame,
1334                                             "e,action,restack,finish",
1335                                             "e");
1336                   e_comp_object_effect_hiding_set(ec->frame, 0);
1337                }
1338           }
1339      }
1340
1341    _eff_stack_update();
1342 }
1343
1344 static void
1345 _eff_cb_restack_finish_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1346 {
1347    E_Client *ec = (E_Client *)data;
1348    E_Effect_Client *efc = NULL;
1349
1350    if (ec)
1351      {
1352         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_HIDE);
1353         efc = _eff_client_get(ec);
1354         if (efc && efc->reverse_ec)
1355           {
1356              E_Client *ec_home = efc->reverse_ec;
1357              if (ec_home->extra_animating)
1358                {
1359                   ec_home->extra_animating = EINA_FALSE;
1360                   if (ec_home->launching == EINA_TRUE)
1361                     {
1362                        ELOGF("COMP", "Un-Set launching flag..", ec_home);
1363                        ec_home->launching = EINA_FALSE;
1364                        if (ec_home->first_mapped)
1365                          {
1366                             ELOGF("LAUNCH", "SHOW real win", ec_home);
1367                             e_comp_object_signal_emit(ec_home->frame, "e,action,launch_real,done", "e");
1368                          }
1369
1370                        e_comp_object_signal_emit(ec_home->frame, "e,action,launch,done", "e");
1371                     }
1372                   _eff_unref(ec_home);
1373                }
1374              efc->reverse_ec = NULL;
1375           }
1376
1377         e_comp_client_override_del(ec);
1378         _eff_unref(ec);
1379      }
1380 }
1381
1382 static Eina_Bool
1383 _eff_cb_restack(void *data, Evas_Object *obj, const char *signal)
1384 {
1385    E_Client *ec;
1386    E_Effect_Group group;
1387    const char *emission;
1388    E_Client *ec_home = NULL;
1389    int ang = -1;
1390
1391    if (!_eff) return EINA_FALSE;
1392
1393    ec = e_comp_object_client_get(obj);
1394    if (!ec) return EINA_FALSE;
1395    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1396
1397    group = _eff_group_get(ec);
1398    emission = eina_stringshare_add(signal);
1399
1400    /* for HOME group: replace eff target client */
1401    if (group == E_EFFECT_GROUP_HOME)
1402      {
1403         E_Client *below;
1404
1405         below = e_client_below_get(ec);
1406         while (below)
1407           {
1408              if ((!e_object_is_del(E_OBJECT(below))) &&
1409                  (evas_object_visible_get(below->frame)) &&
1410                  (below->visibility.obscured == E_VISIBILITY_UNOBSCURED) &&
1411                  (below->layer == ec->layer))
1412                break;
1413
1414              below = e_client_below_get(below);
1415           }
1416
1417         if (!below) return EINA_FALSE;
1418         if (e_util_strcmp(signal, "e,action,restack,show")) return EINA_FALSE;
1419
1420         ec_home = ec;
1421         ec = below;
1422         group = _eff_group_get(ec);
1423         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
1424
1425         if (emission) eina_stringshare_del(emission);
1426         emission = eina_stringshare_add("e,action,restack,hide");
1427      }
1428
1429    if ((group != E_EFFECT_GROUP_NORMAL) &&
1430        (group != E_EFFECT_GROUP_KEYBOARD))
1431      {
1432         e_comp_object_effect_set(ec->frame, NULL);
1433         return EINA_FALSE;
1434      }
1435
1436    if ((!e_util_strcmp(emission, "e,action,restack,show")))
1437      {
1438         /* if ec wass changed to non-animatable, just up and down layer */
1439         if (!ec->animatable)
1440           {
1441              _eff_object_layer_up(ec);
1442              _eff_object_layer_down(ec);
1443              return EINA_FALSE;
1444           }
1445
1446         e_comp_client_override_add(ec);
1447
1448         if (!_eff_ref(ec))
1449           {
1450              e_comp_client_override_del(ec);
1451              return EINA_FALSE;
1452           }
1453
1454         EFFINF("SET EXTRA_ANIMATING...", ec);
1455         ec->extra_animating = EINA_TRUE;
1456
1457         _eff_object_setup(ec, group);
1458         _eff_object_under_setup(ec);
1459
1460         ang = _eff_group_angle_get(ec, group);
1461         e_comp_object_effect_params_set(ec->frame, 0, (int[]){2, ang}, 2);
1462
1463         if (e_comp->nocomp)
1464           {
1465              _eff_pending_effect_set(ec,
1466                                      (void *)ec,
1467                                      E_EFFECT_TYPE_SHOW,
1468                                      _eff_cb_restack_show_done);
1469              return EINA_TRUE;
1470           }
1471
1472         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_SHOW);
1473         e_comp_object_effect_start(ec->frame, _eff_cb_restack_show_done, ec);
1474         _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_RESTACK_SHOW);
1475      }
1476    else if (!e_util_strcmp(emission, "e,action,restack,hide"))
1477      {
1478         /* if ec was changed to non-animatable, just up and down layer */
1479         if (!ec->animatable)
1480           {
1481              _eff_object_layer_up(ec);
1482              _eff_object_layer_down(ec);
1483              return EINA_FALSE;
1484           }
1485
1486         e_comp_client_override_add(ec);
1487
1488         if (!_eff_ref(ec))
1489           {
1490              e_comp_client_override_del(ec);
1491              return EINA_FALSE;
1492           }
1493
1494         if (ec_home)
1495           {
1496              E_Effect_Client *efc = NULL;
1497              efc = _eff_client_get(ec);
1498              if (efc)
1499                {
1500                   if (_eff_ref(ec_home))
1501                     {
1502                        EFFINF("SET EXTRA_ANIMATING...", ec_home);
1503                        ec_home->extra_animating = EINA_TRUE;
1504
1505                        efc->reverse_ec = ec_home;
1506
1507                        EFFINF("SET EXTRA_ANIMATING...", ec);
1508                        ec->extra_animating = EINA_TRUE;
1509                     }
1510                }
1511           }
1512
1513         _eff_object_layer_up(ec);
1514
1515         _eff_object_setup(ec, group);
1516         _eff_object_under_setup(ec);
1517
1518         ang = _eff_group_angle_get(ec, group);
1519         e_comp_object_effect_params_set(ec->frame, 0, (int[]){3, ang}, 2);
1520
1521         if (e_comp->nocomp)
1522           {
1523              _eff_pending_effect_set(ec,
1524                                      (void *)ec,
1525                                      E_EFFECT_TYPE_HIDE,
1526                                      _eff_cb_restack_hide_done);
1527              return EINA_TRUE;
1528           }
1529
1530         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_HIDE);
1531         if (e_comp_object_effect_start(ec->frame, _eff_cb_restack_hide_done, ec))
1532           {
1533              e_comp_object_effect_hiding_set(ec->frame, 1);
1534           }
1535
1536         _eff_object_background_setup(ec, ec_home, group, E_EFFECT_TYPE_RESTACK_HIDE);
1537      }
1538    else if (!e_util_strcmp(emission, "e,action,restack,finish"))
1539      {
1540         e_comp_client_override_add(ec);
1541
1542         if (!_eff_ref(ec))
1543           {
1544              e_comp_client_override_del(ec);
1545              return EINA_FALSE;
1546           }
1547
1548         _eff_object_setup(ec, group);
1549         _eff_object_under_setup(ec);
1550
1551         ang = _eff_group_angle_get(ec, group);
1552         e_comp_object_effect_params_set(ec->frame, 0, (int[]){4, ang}, 2);
1553
1554         if (e_comp->nocomp)
1555           {
1556              _eff_pending_effect_set(ec,
1557                                      (void *)ec,
1558                                      E_EFFECT_TYPE_HIDE,
1559                                      _eff_cb_restack_finish_done);
1560              return EINA_TRUE;
1561           }
1562
1563         e_comp_object_effect_start(ec->frame, _eff_cb_restack_finish_done, ec);
1564      }
1565
1566    return EINA_TRUE;
1567 }
1568
1569 static Eina_Bool
1570 _eff_cb_launch(void *data, Evas_Object *obj, const char *signal)
1571 {
1572    E_Client *ec;
1573    struct wl_resource *res_surf;
1574    struct wl_resource *res_eff;
1575    struct wl_client *wc;
1576    unsigned int tizen_effect_type = 4;
1577
1578    if (!_eff) return EINA_FALSE;
1579
1580    ec = e_comp_object_client_get(obj);
1581    if ((!ec) || (!ec->comp_data)) return EINA_FALSE;
1582    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1583
1584    res_surf = ec->comp_data->surface;
1585    if (!res_surf) return EINA_FALSE;
1586
1587    wc = wl_resource_get_client(res_surf);
1588    if (!wc) return EINA_FALSE;
1589
1590    res_eff = eina_hash_find(_eff->resources, &wc);
1591    if (!res_eff) return EINA_FALSE;
1592
1593    EFFINF("SEND END  |type:LAUNCH|win:0x%08x|tz_effect:0x%08x",
1594           ec,
1595           (unsigned int)e_client_util_win_get(ec),
1596           (unsigned int)res_eff);
1597
1598    tizen_effect_send_end(res_eff, res_surf, tizen_effect_type);
1599
1600    return EINA_TRUE;
1601 }
1602
1603 static void
1604 _eff_cb_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
1605 {
1606    E_Effect_Client *efc;
1607
1608    if (!_eff) return;
1609
1610    efc = _eff_client_get(ec);
1611    if (efc) return;
1612
1613    efc = _eff_client_new(ec);
1614    if (efc)
1615      eina_hash_add(_eff->clients, &ec, efc);
1616 }
1617
1618 static void
1619 _eff_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
1620 {
1621    E_Effect_Client *efc = NULL;
1622
1623    if (!_eff) return;
1624
1625    _eff->stack.old = eina_list_remove(_eff->stack.old, ec);
1626    _eff->stack.cur = eina_list_remove(_eff->stack.cur, ec);
1627
1628    if (_eff->next_done.ec == ec)
1629      memset(&_eff->next_done, 0, sizeof(_eff->next_done));
1630
1631    if ((efc = _eff_client_get(ec)))
1632      {
1633         if (!efc->animating)
1634           {
1635              _eff_object_under_del(ec);
1636              eina_hash_del_by_key(_eff->clients, &ec);
1637           }
1638      }
1639 }
1640
1641 static Eina_Bool
1642 _eff_cb_client_restack(void *data, int type, void *event)
1643 {
1644    E_Client *ec;
1645    E_Event_Client *ev = event;
1646    const char *emission = NULL;
1647
1648    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1649
1650    ec = ev->ec;
1651    if (!ec) return ECORE_CALLBACK_PASS_ON;
1652    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
1653
1654    EFFINF("Client restacked", ec);
1655
1656    _eff_stack_update();
1657
1658    if (!ec->animatable) return ECORE_CALLBACK_PASS_ON;
1659    if (!_eff_client_get(ec)) return ECORE_CALLBACK_PASS_ON;
1660
1661    if ((emission = _eff_restack_effect_check(ec)))
1662      e_comp_object_signal_emit(ec->frame, emission, "e");
1663
1664    return ECORE_CALLBACK_PASS_ON;
1665 }
1666
1667 static Eina_Bool
1668 _eff_cb_comp_enabled(void *data, int ev_type, void *event)
1669 {
1670    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1671
1672    _eff_pending_effect_start();
1673
1674    return ECORE_CALLBACK_PASS_ON;
1675 }
1676
1677 static Eina_Bool
1678 _eff_cb_client_buffer_change(void *data, int ev_type, void *event)
1679 {
1680    E_Event_Client *ev = event;
1681    E_Client *ec;
1682    E_Effect_Client *efc;
1683    E_Comp_Wl_Buffer *buffer = NULL;
1684
1685    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1686
1687    ec = ev->ec;
1688    if (!ec) return ECORE_CALLBACK_PASS_ON;
1689
1690    efc = _eff_client_get(ec);
1691    if (!efc) return ECORE_CALLBACK_PASS_ON;
1692    if (!efc->animating) return ECORE_CALLBACK_PASS_ON;
1693
1694    if (ec->pixmap)
1695      {
1696         buffer = e_pixmap_resource_get(ec->pixmap);
1697         if (buffer != efc->buffer_ref.buffer)
1698           {
1699              e_comp_wl_buffer_reference(&efc->buffer_ref, buffer);
1700           }
1701      }
1702
1703    return ECORE_CALLBACK_PASS_ON;
1704 }
1705
1706 static void
1707 _tz_effect_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *tz_res_eff)
1708 {
1709    wl_resource_destroy(tz_res_eff);
1710 }
1711
1712 static const struct tizen_effect_interface _tz_effect_interface =
1713 {
1714    _tz_effect_cb_destroy,
1715 };
1716
1717 static void
1718 _tz_effect_cb_effect_destroy(struct wl_resource *tz_res_eff)
1719 {
1720    if ((!_eff) || (!_eff->resources)) return;
1721
1722    eina_hash_del_by_data(_eff->resources, tz_res_eff);
1723 }
1724
1725 static void
1726 _eff_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
1727 {
1728    struct wl_resource *res;
1729
1730    if (!(res = wl_resource_create(client, &tizen_effect_interface, 1, id)))
1731      {
1732         ERR("Could not create tizen_effect interface");
1733         wl_client_post_no_memory(client);
1734         return;
1735      }
1736
1737    wl_resource_set_implementation(res,
1738                                   &_tz_effect_interface,
1739                                   NULL,
1740                                   _tz_effect_cb_effect_destroy);
1741
1742    eina_hash_add(_eff->resources, &client, res);
1743 }
1744
1745 static void
1746 _eff_cb_client_data_free(void *data)
1747 {
1748    E_Effect_Client *efc = data;
1749
1750    if (!efc) return;
1751
1752    if (efc->buffer_ref.buffer)
1753      e_comp_wl_buffer_reference(&efc->buffer_ref, NULL);
1754
1755    free(efc);
1756 }
1757
1758 #undef E_CLIENT_HOOK_APPEND
1759 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
1760   do                                      \
1761     {                                     \
1762        E_Client_Hook *_h;                 \
1763        _h = e_client_hook_add(t, cb, d);  \
1764        assert(_h);                        \
1765        l = eina_list_append(l, _h);       \
1766     }                                     \
1767   while (0)
1768
1769 #undef E_COMP_OBJ_EFF_MOVER_APPEND
1770 #define E_COMP_OBJ_EFF_MOVER_APPEND(l, i, s, p, d)      \
1771   do                                                    \
1772     {                                                   \
1773        E_Comp_Object_Mover *_m;                         \
1774        _m = e_comp_object_effect_mover_add(i, s, p, d); \
1775        assert(_m);                                      \
1776        l = eina_list_append(l, _m);                     \
1777     }                                                   \
1778   while (0)
1779
1780 EAPI Eina_Bool
1781 e_mod_effect_init(void)
1782 {
1783    E_Effect *eff;
1784    E_Comp_Config *cfg;
1785    Eina_List *l;
1786    E_Client *ec;
1787    E_Effect_Client *efc;
1788
1789    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1790    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->evas, EINA_FALSE);
1791
1792    eff = E_NEW(E_Effect, 1);
1793    EINA_SAFETY_ON_NULL_RETURN_VAL(eff, EINA_FALSE);
1794
1795    _eff = eff;
1796
1797    if ((cfg = e_comp_config_get()))
1798      {
1799         eff->file = eina_stringshare_add(cfg->effect_file);
1800         eff->style = eina_stringshare_add(cfg->effect_style);
1801      }
1802    else
1803      {
1804         eff->file = "";
1805         eff->style = "no-effect";
1806      }
1807
1808    eff->clients = eina_hash_pointer_new(_eff_cb_client_data_free);
1809    EINA_SAFETY_ON_NULL_GOTO(eff->clients, err);
1810
1811    EINA_LIST_FOREACH(e_comp->clients, l, ec)
1812      {
1813         if (ec->ignored) continue;
1814
1815         efc = _eff_client_get(ec);
1816         if (!efc)
1817           efc = _eff_client_new(ec);
1818         if (efc)
1819           eina_hash_add(eff->clients, &ec, efc);
1820      }
1821
1822    eff->resources = eina_hash_pointer_new(NULL);
1823    EINA_SAFETY_ON_NULL_GOTO(eff->resources, err);
1824
1825    eff->global = wl_global_create(e_comp_wl->wl.disp,
1826                                   &tizen_effect_interface,
1827                                   1,
1828                                   eff,
1829                                   _eff_cb_bind);
1830    if (!eff->global)
1831      {
1832         ERR("Could not add tizen_efffect wayland globals: %m");
1833         goto err;
1834      }
1835
1836    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_COMPOSITOR_ENABLE,    _eff_cb_comp_enabled,         eff);
1837    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_BUFFER_CHANGE, _eff_cb_client_buffer_change, eff);
1838    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_STACK,         _eff_cb_client_restack,       eff);
1839    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_NEW_CLIENT,     _eff_cb_hook_client_new,      eff);
1840    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_DEL,            _eff_cb_hook_client_del,      eff);
1841    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,visible",            _eff_cb_visible,              eff);
1842    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,hidden",             _eff_cb_hidden,               eff);
1843    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,iconify",           _eff_cb_iconify,              eff);
1844    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,uniconify",         _eff_cb_uniconify,            eff);
1845    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,restack*",          _eff_cb_restack,              eff);
1846    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,launch,done",       _eff_cb_launch,               eff);
1847
1848    return EINA_TRUE;
1849
1850 err:
1851    e_mod_effect_shutdown();
1852    return EINA_FALSE;
1853 }
1854
1855 EAPI void
1856 e_mod_effect_shutdown()
1857 {
1858    if (!_eff) return;
1859
1860    E_FREE_FUNC(_eff->stack.old, eina_list_free);
1861    E_FREE_FUNC(_eff->stack.cur, eina_list_free);
1862
1863    E_FREE_LIST(_eff->under_layers, free);
1864    E_FREE_LIST(_eff->providers, e_comp_object_effect_mover_del);
1865    E_FREE_LIST(_eff->event_hdlrs, ecore_event_handler_del);
1866    E_FREE_LIST(_eff->hooks_ec, e_client_hook_del);
1867
1868    if (_eff->global)
1869      wl_global_destroy(_eff->global);
1870
1871    E_FREE_FUNC(_eff->resources, eina_hash_free);
1872    E_FREE_FUNC(_eff->clients, eina_hash_free);
1873
1874    if (e_comp_config_get())
1875      {
1876         eina_stringshare_del(_eff->file);
1877         eina_stringshare_del(_eff->style);
1878      }
1879
1880    E_FREE(_eff);
1881 }