get rid of unused e_pixmap parameter of ELOG
[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, cfg->effect_style);
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_pixmap_usable_get(ec->pixmap)))
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         _eff_unref(ec);
925      }
926
927    _eff_stack_update();
928    e_comp_override_del();
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)) return EINA_FALSE;
947
948    if (evas_object_visible_get(obj)) return EINA_FALSE;
949    if (!_eff_ref(ec)) return EINA_FALSE;
950
951    _eff_stack_update();
952    e_comp_override_add();
953
954    EFFINF("SET EXTRA_ANIMATING...", ec);
955    ec->extra_animating = EINA_TRUE;
956
957    _eff_object_setup(ec, group);
958    _eff_object_under_setup(ec);
959
960    ang = _eff_group_angle_get(ec, group);
961    e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
962    if (e_comp->nocomp)
963      {
964         _eff_pending_effect_set(ec,
965                                 (void *)ec,
966                                 E_EFFECT_TYPE_SHOW,
967                                 _eff_cb_visible_done);
968         return EINA_TRUE;
969      }
970
971    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
972
973    e_comp_object_effect_start(ec->frame, _eff_cb_visible_done, ec);
974
975    _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_SHOW);
976
977    return EINA_TRUE;
978 }
979
980 static void
981 _eff_cb_hidden_done(void *data, Evas_Object *obj, const char *sig, const char *src)
982 {
983    E_Client *ec = (E_Client *)data;
984
985    if (ec)
986      {
987         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
988         if (_eff_unref(ec))
989           {
990              if (_eff_client_get(ec))
991                {
992                   _eff_object_layer_down(ec);
993                   evas_object_hide(ec->frame);
994                }
995           }
996      }
997
998    e_comp_override_del();
999 }
1000
1001 static Eina_Bool
1002 _eff_cb_hidden(void *data, Evas_Object *obj, const char *signal)
1003 {
1004    E_Client *ec;
1005    E_Effect_Group group;
1006    Eina_Bool lowered = 0;
1007    Evas_Object *below;
1008    int map_ly;
1009    int ang = -1;
1010    Eina_Bool v1, v2;
1011
1012    if (!_eff) return EINA_FALSE;
1013
1014    ec = e_comp_object_client_get(obj);
1015    if (!ec) return EINA_FALSE;
1016    if (e_object_is_del(E_OBJECT(ec)))
1017      {
1018         if (!e_object_delay_del_ref_get(E_OBJECT(ec))) return EINA_FALSE;
1019      }
1020
1021    /* check for effect group */
1022    group = _eff_group_get(ec);
1023    if ((group != E_EFFECT_GROUP_NORMAL) &&
1024        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
1025
1026    if (group == E_EFFECT_GROUP_KEYBOARD)
1027      {
1028         if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
1029           return EINA_FALSE;
1030      }
1031
1032    /* check for object visibility */
1033    if (!evas_object_visible_get(obj)) return EINA_FALSE;
1034
1035    /* check for stack visibility */
1036    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1037    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1038    if ((!v1) && (!v2)) return EINA_FALSE;
1039
1040    if (!_eff_ref(ec)) return EINA_FALSE;
1041
1042    e_comp_override_add();
1043
1044    // check if client was lowered
1045    below = evas_object_below_get(obj);
1046    map_ly = e_comp_canvas_layer_map(evas_object_layer_get(obj));
1047    if ((below) && (map_ly != 9999) &&
1048        (evas_object_layer_get(below) != evas_object_layer_get(obj)) &&
1049        (evas_object_above_get(obj) != e_comp->layers[map_ly].obj))
1050      lowered = 1;
1051
1052    if (lowered)
1053      _eff_object_layer_up(ec);
1054
1055    _eff_object_setup(ec, group);
1056    _eff_object_under_setup(ec);
1057
1058    ang = _eff_group_angle_get(ec, group);
1059    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
1060
1061    if (e_comp->nocomp)
1062      {
1063         _eff_pending_effect_set(ec,
1064                                 (void *)ec,
1065                                 E_EFFECT_TYPE_HIDE,
1066                                 _eff_cb_hidden_done);
1067         return EINA_TRUE;
1068      }
1069
1070    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
1071    e_comp_object_effect_start(ec->frame, _eff_cb_hidden_done, ec);
1072    _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_HIDE);
1073
1074    return EINA_TRUE;
1075 }
1076
1077 static void
1078 _eff_cb_uniconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1079 {
1080    E_Client *ec = (E_Client *)data;
1081
1082    if (ec)
1083      {
1084         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_SHOW);
1085         _eff_unref(ec);
1086      }
1087
1088    e_comp_override_del();
1089 }
1090
1091 static Eina_Bool
1092 _eff_cb_uniconify(void *data, Evas_Object *obj, const char *signal)
1093 {
1094    E_Client *ec;
1095    E_Effect_Group group;
1096    Eina_Bool v1, v2;
1097    int ang = -1;
1098
1099    if (!_eff) return EINA_FALSE;
1100
1101    ec = e_comp_object_client_get(obj);
1102    if (!ec) return EINA_FALSE;
1103    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1104
1105    if (evas_object_visible_get(obj)) return EINA_FALSE;
1106
1107    group = _eff_group_get(ec);
1108
1109    /* for HOME group */
1110    if (group == E_EFFECT_GROUP_HOME)
1111      {
1112         E_Client *below;
1113
1114         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1115         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1116
1117         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1118                ec,
1119                v1, v2, ec->visibility.obscured, ec->visibility.changed);
1120
1121         if (v1 == v2) return EINA_FALSE;
1122         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1123         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1124
1125         below = e_client_below_get(ec);
1126         while (below)
1127           {
1128              if ((evas_object_visible_get(below->frame)) &&
1129                  (below->layer == ec->layer) &&
1130                  ((below->visibility.obscured == E_VISIBILITY_UNOBSCURED) ||
1131                   (below->visibility.changed)))
1132                break;
1133
1134              below = e_client_below_get(below);
1135           }
1136
1137         if (!below) return EINA_FALSE;
1138         group = _eff_group_get(below);
1139         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
1140
1141         EFFINF("Uniconify HOME group do hide eff of %p",
1142                ec, below);
1143
1144         e_comp_object_signal_emit(below->frame, "e,action,restack,hide", "e");
1145         return EINA_TRUE;
1146      }
1147    /* for NORMAL and KEYBOARD group */
1148    else if ((group == E_EFFECT_GROUP_NORMAL) ||
1149             (group == E_EFFECT_GROUP_KEYBOARD))
1150      {
1151         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1152         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1153
1154         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1155                ec,
1156                v1, v2, ec->visibility.obscured, ec->visibility.changed);
1157
1158         if (v1 == v2) return EINA_FALSE;
1159         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1160         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1161
1162         if (!_eff_ref(ec)) return EINA_FALSE;
1163
1164         e_comp_override_add();
1165
1166         _eff_object_setup(ec, group);
1167         _eff_object_under_setup(ec);
1168
1169         ang = _eff_group_angle_get(ec, group);
1170         e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
1171
1172         if (e_comp->nocomp)
1173           {
1174              _eff_pending_effect_set(ec,
1175                                      (void *)ec,
1176                                      E_EFFECT_TYPE_SHOW,
1177                                      _eff_cb_uniconify_done);
1178              return EINA_TRUE;
1179           }
1180
1181         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
1182         e_comp_object_effect_start(ec->frame, _eff_cb_uniconify_done, ec);
1183         return EINA_TRUE;
1184      }
1185
1186    return EINA_FALSE;
1187 }
1188
1189 static void
1190 _eff_cb_iconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1191 {
1192    E_Client *ec = (E_Client *)data;
1193
1194    if (ec)
1195      {
1196         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
1197         if (_eff_unref(ec))
1198           {
1199              if (_eff_client_get(ec))
1200                evas_object_hide(ec->frame);
1201           }
1202      }
1203
1204    e_comp_override_del();
1205 }
1206
1207 static Eina_Bool
1208 _eff_cb_iconify(void *data, Evas_Object *obj, const char *signal)
1209 {
1210    E_Client *ec;
1211    E_Effect_Group group;
1212    Eina_Bool v1, v2;
1213    int ang = -1;
1214
1215    if (!_eff) return EINA_FALSE;
1216
1217    ec = e_comp_object_client_get(obj);
1218    if (!ec) return EINA_FALSE;
1219    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1220
1221    group = _eff_group_get(ec);
1222    if ((group != E_EFFECT_GROUP_NORMAL) &&
1223        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
1224
1225    if (!evas_object_visible_get(obj)) return EINA_FALSE;
1226
1227    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
1228    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
1229
1230    EFFINF("Iconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
1231           ec,
1232           v1, v2, ec->visibility.obscured, ec->visibility.changed);
1233
1234    if (v1 == v2) return EINA_FALSE;
1235    if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1236    if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
1237
1238    if (!_eff_ref(ec)) return EINA_FALSE;
1239
1240    e_comp_override_add();
1241
1242    _eff_object_setup(ec, group);
1243    _eff_object_under_setup(ec);
1244
1245    ang = _eff_group_angle_get(ec, group);
1246    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
1247
1248    if (e_comp->nocomp)
1249      {
1250         _eff_pending_effect_set(ec,
1251                                 (void *)ec,
1252                                 E_EFFECT_TYPE_HIDE,
1253                                 _eff_cb_iconify_done);
1254         return EINA_TRUE;
1255      }
1256
1257    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
1258    e_comp_object_effect_start(ec->frame, _eff_cb_iconify_done, ec);
1259
1260    return EINA_TRUE;
1261 }
1262
1263 static void
1264 _eff_cb_restack_show_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1265 {
1266    E_Client *ec = (E_Client *)data;
1267
1268    if (ec)
1269      {
1270         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_SHOW);
1271         _eff_unref(ec);
1272      }
1273
1274    _eff_stack_update();
1275    e_comp_override_del();
1276 }
1277
1278 static void
1279 _eff_cb_restack_hide_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1280 {
1281    E_Client *ec = (E_Client *)data;
1282
1283    if (ec)
1284      {
1285         if (_eff_unref(ec))
1286           {
1287              if (_eff_client_get(ec))
1288                {
1289                   _eff_object_layer_down(ec);
1290                   e_comp_object_signal_emit(ec->frame,
1291                                             "e,action,restack,finish",
1292                                             "e");
1293                }
1294           }
1295      }
1296
1297    _eff_stack_update();
1298    e_comp_override_del();
1299 }
1300
1301 static void
1302 _eff_cb_restack_finish_done(void *data, Evas_Object *obj, const char *sig, const char *src)
1303 {
1304    E_Client *ec = (E_Client *)data;
1305    E_Effect_Client *efc = NULL;
1306
1307    if (ec)
1308      {
1309         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_HIDE);
1310         efc = _eff_client_get(ec);
1311         if (efc && efc->reverse_ec)
1312           {
1313              E_Client *ec_home = efc->reverse_ec;
1314              if (ec_home->extra_animating)
1315                {
1316                   ec_home->extra_animating = EINA_FALSE;
1317                   if (ec_home->launching == EINA_TRUE)
1318                     {
1319                        ELOGF("COMP", "Un-Set launching flag..", ec_home);
1320                        ec_home->launching = EINA_FALSE;
1321                        if (ec_home->first_mapped)
1322                          {
1323                             ELOGF("LAUNCH", "SHOW real win", ec_home);
1324                             e_comp_object_signal_emit(ec_home->frame, "e,action,launch_real,done", "e");
1325                          }
1326
1327                        e_comp_object_signal_emit(ec_home->frame, "e,action,launch,done", "e");
1328                     }
1329                   _eff_unref(ec_home);
1330                }
1331              efc->reverse_ec = NULL;
1332           }
1333
1334         _eff_unref(ec);
1335      }
1336
1337    e_comp_override_del();
1338 }
1339
1340 static Eina_Bool
1341 _eff_cb_restack(void *data, Evas_Object *obj, const char *signal)
1342 {
1343    E_Client *ec;
1344    E_Effect_Group group;
1345    const char *emission;
1346    E_Client *ec_home = NULL;
1347    int ang = -1;
1348
1349    if (!_eff) return EINA_FALSE;
1350
1351    ec = e_comp_object_client_get(obj);
1352    if (!ec) return EINA_FALSE;
1353    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1354
1355    group = _eff_group_get(ec);
1356    emission = eina_stringshare_add(signal);
1357
1358    /* for HOME group: replace eff target client */
1359    if (group == E_EFFECT_GROUP_HOME)
1360      {
1361         E_Client *below;
1362
1363         below = e_client_below_get(ec);
1364         while (below)
1365           {
1366              if ((!e_object_is_del(E_OBJECT(below))) &&
1367                  (evas_object_visible_get(below->frame)) &&
1368                  (below->visibility.obscured == E_VISIBILITY_UNOBSCURED) &&
1369                  (below->layer == ec->layer))
1370                break;
1371
1372              below = e_client_below_get(below);
1373           }
1374
1375         if (!below) return EINA_FALSE;
1376         if (e_util_strcmp(signal, "e,action,restack,show")) return EINA_FALSE;
1377
1378         ec_home = ec;
1379         ec = below;
1380         group = _eff_group_get(ec);
1381         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
1382
1383         if (emission) eina_stringshare_del(emission);
1384         emission = eina_stringshare_add("e,action,restack,hide");
1385      }
1386
1387    if ((group != E_EFFECT_GROUP_NORMAL) &&
1388        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
1389
1390    if ((!e_util_strcmp(emission, "e,action,restack,show")))
1391      {
1392         /* if ec wass changed to non-animatable, just up and down layer */
1393         if (!ec->animatable)
1394           {
1395              _eff_object_layer_up(ec);
1396              _eff_object_layer_down(ec);
1397              return EINA_FALSE;
1398           }
1399         if (!_eff_ref(ec)) return EINA_FALSE;
1400
1401         EFFINF("SET EXTRA_ANIMATING...", ec);
1402         ec->extra_animating = EINA_TRUE;
1403
1404         e_comp_override_add();
1405
1406         _eff_object_setup(ec, group);
1407         _eff_object_under_setup(ec);
1408
1409         ang = _eff_group_angle_get(ec, group);
1410         e_comp_object_effect_params_set(ec->frame, 0, (int[]){2, ang}, 2);
1411
1412         if (e_comp->nocomp)
1413           {
1414              _eff_pending_effect_set(ec,
1415                                      (void *)ec,
1416                                      E_EFFECT_TYPE_SHOW,
1417                                      _eff_cb_restack_show_done);
1418              return EINA_TRUE;
1419           }
1420
1421         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_SHOW);
1422         e_comp_object_effect_start(ec->frame, _eff_cb_restack_show_done, ec);
1423         _eff_object_background_setup(ec, NULL, group, E_EFFECT_TYPE_RESTACK_SHOW);
1424      }
1425    else if (!e_util_strcmp(emission, "e,action,restack,hide"))
1426      {
1427         /* if ec was changed to non-animatable, just up and down layer */
1428         if (!ec->animatable)
1429           {
1430              _eff_object_layer_up(ec);
1431              _eff_object_layer_down(ec);
1432              return EINA_FALSE;
1433           }
1434         if (!_eff_ref(ec)) return EINA_FALSE;
1435
1436         if (ec_home)
1437           {
1438              E_Effect_Client *efc = NULL;
1439              efc = _eff_client_get(ec);
1440              if (efc)
1441                {
1442                   if (_eff_ref(ec_home))
1443                     {
1444                        EFFINF("SET EXTRA_ANIMATING...", ec_home);
1445                        ec_home->extra_animating = EINA_TRUE;
1446
1447                        efc->reverse_ec = ec_home;
1448
1449                        EFFINF("SET EXTRA_ANIMATING...", ec);
1450                        ec->extra_animating = EINA_TRUE;
1451                     }
1452                }
1453           }
1454
1455         e_comp_override_add();
1456
1457         _eff_object_layer_up(ec);
1458
1459         _eff_object_setup(ec, group);
1460         _eff_object_under_setup(ec);
1461
1462         ang = _eff_group_angle_get(ec, group);
1463         e_comp_object_effect_params_set(ec->frame, 0, (int[]){3, ang}, 2);
1464
1465         if (e_comp->nocomp)
1466           {
1467              _eff_pending_effect_set(ec,
1468                                      (void *)ec,
1469                                      E_EFFECT_TYPE_HIDE,
1470                                      _eff_cb_restack_hide_done);
1471              return EINA_TRUE;
1472           }
1473
1474         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_HIDE);
1475         e_comp_object_effect_start(ec->frame, _eff_cb_restack_hide_done, ec);
1476         _eff_object_background_setup(ec, ec_home, group, E_EFFECT_TYPE_RESTACK_HIDE);
1477      }
1478    else if (!e_util_strcmp(emission, "e,action,restack,finish"))
1479      {
1480         if (!_eff_ref(ec)) return EINA_FALSE;
1481
1482         e_comp_override_add();
1483
1484         _eff_object_setup(ec, group);
1485         _eff_object_under_setup(ec);
1486
1487         ang = _eff_group_angle_get(ec, group);
1488         e_comp_object_effect_params_set(ec->frame, 0, (int[]){4, ang}, 2);
1489
1490         if (e_comp->nocomp)
1491           {
1492              _eff_pending_effect_set(ec,
1493                                      (void *)ec,
1494                                      E_EFFECT_TYPE_HIDE,
1495                                      _eff_cb_restack_finish_done);
1496              return EINA_TRUE;
1497           }
1498
1499         e_comp_object_effect_start(ec->frame, _eff_cb_restack_finish_done, ec);
1500      }
1501
1502    return EINA_TRUE;
1503 }
1504
1505 static Eina_Bool
1506 _eff_cb_launch(void *data, Evas_Object *obj, const char *signal)
1507 {
1508    E_Client *ec;
1509    struct wl_resource *res_surf;
1510    struct wl_resource *res_eff;
1511    struct wl_client *wc;
1512    unsigned int tizen_effect_type = 4;
1513
1514    if (!_eff) return EINA_FALSE;
1515
1516    ec = e_comp_object_client_get(obj);
1517    if ((!ec) || (!ec->comp_data)) return EINA_FALSE;
1518    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1519
1520    res_surf = ec->comp_data->surface;
1521    if (!res_surf) return EINA_FALSE;
1522
1523    wc = wl_resource_get_client(res_surf);
1524    if (!wc) return EINA_FALSE;
1525
1526    res_eff = eina_hash_find(_eff->resources, &wc);
1527    if (!res_eff) return EINA_FALSE;
1528
1529    EFFINF("SEND END  |type:LAUNCH|win:0x%08x|tz_effect:0x%08x",
1530           ec,
1531           (unsigned int)e_client_util_win_get(ec),
1532           (unsigned int)res_eff);
1533
1534    tizen_effect_send_end(res_eff, res_surf, tizen_effect_type);
1535
1536    return EINA_TRUE;
1537 }
1538
1539 static void
1540 _eff_cb_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
1541 {
1542    E_Effect_Client *efc;
1543
1544    if (!_eff) return;
1545
1546    efc = _eff_client_get(ec);
1547    if (efc) return;
1548
1549    efc = _eff_client_new(ec);
1550    if (efc)
1551      eina_hash_add(_eff->clients, &ec, efc);
1552 }
1553
1554 static void
1555 _eff_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
1556 {
1557    E_Effect_Client *efc = NULL;
1558
1559    if (!_eff) return;
1560
1561    _eff->stack.old = eina_list_remove(_eff->stack.old, ec);
1562    _eff->stack.cur = eina_list_remove(_eff->stack.cur, ec);
1563
1564    if (_eff->next_done.ec == ec)
1565      memset(&_eff->next_done, 0, sizeof(_eff->next_done));
1566
1567    if ((efc = _eff_client_get(ec)))
1568      {
1569         if (!efc->animating)
1570           {
1571              _eff_object_under_del(ec);
1572              eina_hash_del_by_key(_eff->clients, &ec);
1573           }
1574      }
1575 }
1576
1577 static Eina_Bool
1578 _eff_cb_client_restack(void *data, int type, void *event)
1579 {
1580    E_Client *ec;
1581    E_Event_Client *ev = event;
1582    const char *emission = NULL;
1583
1584    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1585
1586    ec = ev->ec;
1587    if (!ec) return ECORE_CALLBACK_PASS_ON;
1588    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
1589
1590    EFFINF("Client restacked", ec);
1591
1592    _eff_stack_update();
1593
1594    if (!ec->animatable) return ECORE_CALLBACK_PASS_ON;
1595    if (!_eff_client_get(ec)) return ECORE_CALLBACK_PASS_ON;
1596
1597    if ((emission = _eff_restack_effect_check(ec)))
1598      e_comp_object_signal_emit(ec->frame, emission, "e");
1599
1600    return ECORE_CALLBACK_PASS_ON;
1601 }
1602
1603 static Eina_Bool
1604 _eff_cb_comp_enabled(void *data, int ev_type, void *event)
1605 {
1606    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1607
1608    _eff_pending_effect_start();
1609
1610    return ECORE_CALLBACK_PASS_ON;
1611 }
1612
1613 static Eina_Bool
1614 _eff_cb_client_buffer_change(void *data, int ev_type, void *event)
1615 {
1616    E_Event_Client *ev = event;
1617    E_Client *ec;
1618    E_Effect_Client *efc;
1619    E_Comp_Wl_Buffer *buffer = NULL;
1620
1621    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1622
1623    ec = ev->ec;
1624    if (!ec) return ECORE_CALLBACK_PASS_ON;
1625
1626    efc = _eff_client_get(ec);
1627    if (!efc) return ECORE_CALLBACK_PASS_ON;
1628    if (!efc->animating) return ECORE_CALLBACK_PASS_ON;
1629
1630    if (ec->pixmap)
1631      {
1632         buffer = e_pixmap_resource_get(ec->pixmap);
1633         if (buffer != efc->buffer_ref.buffer)
1634           {
1635              e_comp_wl_buffer_reference(&efc->buffer_ref, buffer);
1636           }
1637      }
1638
1639    return ECORE_CALLBACK_PASS_ON;
1640 }
1641
1642 static void
1643 _tz_effect_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *tz_res_eff)
1644 {
1645    wl_resource_destroy(tz_res_eff);
1646 }
1647
1648 static const struct tizen_effect_interface _tz_effect_interface =
1649 {
1650    _tz_effect_cb_destroy,
1651 };
1652
1653 static void
1654 _tz_effect_cb_effect_destroy(struct wl_resource *tz_res_eff)
1655 {
1656    if ((!_eff) || (!_eff->resources)) return;
1657
1658    eina_hash_del_by_data(_eff->resources, tz_res_eff);
1659 }
1660
1661 static void
1662 _eff_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
1663 {
1664    struct wl_resource *res;
1665
1666    if (!(res = wl_resource_create(client, &tizen_effect_interface, 1, id)))
1667      {
1668         ERR("Could not create tizen_effect interface");
1669         wl_client_post_no_memory(client);
1670         return;
1671      }
1672
1673    wl_resource_set_implementation(res,
1674                                   &_tz_effect_interface,
1675                                   NULL,
1676                                   _tz_effect_cb_effect_destroy);
1677
1678    eina_hash_add(_eff->resources, &client, res);
1679 }
1680
1681 static void
1682 _eff_cb_client_data_free(void *data)
1683 {
1684    E_Effect_Client *efc = data;
1685
1686    if (!efc) return;
1687
1688    if (efc->buffer_ref.buffer)
1689      e_comp_wl_buffer_reference(&efc->buffer_ref, NULL);
1690
1691    free(efc);
1692 }
1693
1694 #undef E_CLIENT_HOOK_APPEND
1695 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
1696   do                                      \
1697     {                                     \
1698        E_Client_Hook *_h;                 \
1699        _h = e_client_hook_add(t, cb, d);  \
1700        assert(_h);                        \
1701        l = eina_list_append(l, _h);       \
1702     }                                     \
1703   while (0)
1704
1705 #undef E_COMP_OBJ_EFF_MOVER_APPEND
1706 #define E_COMP_OBJ_EFF_MOVER_APPEND(l, i, s, p, d)      \
1707   do                                                    \
1708     {                                                   \
1709        E_Comp_Object_Mover *_m;                         \
1710        _m = e_comp_object_effect_mover_add(i, s, p, d); \
1711        assert(_m);                                      \
1712        l = eina_list_append(l, _m);                     \
1713     }                                                   \
1714   while (0)
1715
1716 EAPI Eina_Bool
1717 e_mod_effect_init(void)
1718 {
1719    E_Effect *eff;
1720    E_Comp_Config *cfg;
1721    Eina_List *l;
1722    E_Client *ec;
1723    E_Effect_Client *efc;
1724
1725    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1726    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->evas, EINA_FALSE);
1727
1728    eff = E_NEW(E_Effect, 1);
1729    EINA_SAFETY_ON_NULL_RETURN_VAL(eff, EINA_FALSE);
1730
1731    _eff = eff;
1732
1733    if ((cfg = e_comp_config_get()))
1734      {
1735         eff->file = eina_stringshare_add(cfg->effect_file);
1736         eff->style = eina_stringshare_add(cfg->effect_style);
1737      }
1738    else
1739      {
1740         eff->file = "";
1741         eff->style = "no-effect";
1742      }
1743
1744    eff->clients = eina_hash_pointer_new(_eff_cb_client_data_free);
1745    EINA_SAFETY_ON_NULL_GOTO(eff->clients, err);
1746
1747    EINA_LIST_FOREACH(e_comp->clients, l, ec)
1748      {
1749         if (ec->ignored) continue;
1750
1751         efc = _eff_client_get(ec);
1752         if (!efc)
1753           efc = _eff_client_new(ec);
1754         if (efc)
1755           eina_hash_add(eff->clients, &ec, efc);
1756      }
1757
1758    eff->resources = eina_hash_pointer_new(NULL);
1759    EINA_SAFETY_ON_NULL_GOTO(eff->resources, err);
1760
1761    eff->global = wl_global_create(e_comp_wl->wl.disp,
1762                                   &tizen_effect_interface,
1763                                   1,
1764                                   eff,
1765                                   _eff_cb_bind);
1766    if (!eff->global)
1767      {
1768         ERR("Could not add tizen_efffect wayland globals: %m");
1769         goto err;
1770      }
1771
1772    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_COMPOSITOR_ENABLE,    _eff_cb_comp_enabled,         eff);
1773    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_BUFFER_CHANGE, _eff_cb_client_buffer_change, eff);
1774    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_STACK,         _eff_cb_client_restack,       eff);
1775    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_NEW_CLIENT,     _eff_cb_hook_client_new,      eff);
1776    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_DEL,            _eff_cb_hook_client_del,      eff);
1777    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,visible",            _eff_cb_visible,              eff);
1778    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,hidden",             _eff_cb_hidden,               eff);
1779    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,iconify",           _eff_cb_iconify,              eff);
1780    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,uniconify",         _eff_cb_uniconify,            eff);
1781    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,restack*",          _eff_cb_restack,              eff);
1782    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,launch,done",       _eff_cb_launch,               eff);
1783
1784    return EINA_TRUE;
1785
1786 err:
1787    e_mod_effect_shutdown();
1788    return EINA_FALSE;
1789 }
1790
1791 EAPI void
1792 e_mod_effect_shutdown()
1793 {
1794    if (!_eff) return;
1795
1796    E_FREE_FUNC(_eff->stack.old, eina_list_free);
1797    E_FREE_FUNC(_eff->stack.cur, eina_list_free);
1798
1799    E_FREE_LIST(_eff->under_layers, free);
1800    E_FREE_LIST(_eff->providers, e_comp_object_effect_mover_del);
1801    E_FREE_LIST(_eff->event_hdlrs, ecore_event_handler_del);
1802    E_FREE_LIST(_eff->hooks_ec, e_client_hook_del);
1803
1804    if (_eff->global)
1805      wl_global_destroy(_eff->global);
1806
1807    E_FREE_FUNC(_eff->resources, eina_hash_free);
1808    E_FREE_FUNC(_eff->clients, eina_hash_free);
1809
1810    if (e_comp_config_get())
1811      {
1812         eina_stringshare_del(_eff->file);
1813         eina_stringshare_del(_eff->style);
1814      }
1815
1816    E_FREE(_eff);
1817 }