7356b7dd4c5f81897c30aec7540b643bb59fc7df
[platform/core/uifw/e-mod-tizen-effect.git] / src / e_mod_effect.c
1 #include "e_mod_effect.h"
2
3 static E_Effect *_eff = NULL;
4
5 typedef struct _E_Effect_Client
6 {
7    E_Client *ec;
8    unsigned int animating;
9    E_Comp_Wl_Buffer_Ref buffer_ref;
10    E_Pixmap *ep;
11    E_Client *reverse_ec;
12 } E_Effect_Client;
13
14 static void
15 _eff_event_send(E_Client *ec, Eina_Bool start, E_Effect_Type type)
16 {
17    struct wl_resource *res_surf;
18    struct wl_resource *res_eff;
19    struct wl_client *wc;
20    unsigned int tizen_effect_type = TIZEN_EFFECT_TYPE_NONE;
21
22    if (!_eff) return;
23    if ((!ec) || (!ec->comp_data)) return;
24    if (e_object_is_del(E_OBJECT(ec))) return;
25
26    res_surf = ec->comp_data->surface;
27    if (!res_surf) return;
28
29    wc = wl_resource_get_client(res_surf);
30    if (!wc) return;
31
32    res_eff = eina_hash_find(_eff->resources, &wc);
33    if (!res_eff) return;
34
35    switch(type)
36      {
37       case E_EFFECT_TYPE_SHOW:
38          tizen_effect_type = TIZEN_EFFECT_TYPE_SHOW;
39          break;
40       case E_EFFECT_TYPE_HIDE:
41          tizen_effect_type = TIZEN_EFFECT_TYPE_HIDE;
42          break;
43       case E_EFFECT_TYPE_RESTACK_SHOW:
44       case E_EFFECT_TYPE_RESTACK_HIDE:
45          tizen_effect_type = TIZEN_EFFECT_TYPE_RESTACK;
46          break;
47       default:
48          ERR("Unsupported effect type: %d for %p", type, ec);
49          return;
50      }
51
52    EFFINF("SEND %.5s|type:%d|win:0x%08x|tz_effect:0x%08x",
53           ec->pixmap, ec,
54           start ? "START" : "END", type,
55           (unsigned int)e_client_util_win_get(ec),
56           (unsigned int)res_eff);
57
58    if (start)
59      tizen_effect_send_start(res_eff, res_surf, tizen_effect_type);
60    else
61      {
62         tizen_effect_send_end(res_eff, res_surf, tizen_effect_type);
63
64         EFFINF("Un-SET EXTRA_ANIMATING...", ec->pixmap, ec);
65         ec->extra_animating = EINA_FALSE;
66         if (ec->launching == EINA_TRUE)
67           {
68              ec->launching = EINA_FALSE;
69              e_comp_object_signal_emit(ec->frame, "e,action,launch,done", "e");
70           }
71      }
72 }
73
74 static E_Effect_Client*
75 _eff_client_new(E_Client *ec)
76 {
77    E_Effect_Client *efc;
78
79    efc = E_NEW(E_Effect_Client, 1);
80    efc->ec = ec;
81    efc->animating = 0;
82    efc->ep = NULL;
83
84    return efc;
85 }
86
87 static E_Effect_Client *
88 _eff_client_get(E_Client *ec)
89 {
90    if (!_eff) return NULL;
91    return eina_hash_find(_eff->clients, &ec);
92 }
93
94 static E_Effect_Group
95 _eff_group_get(E_Client *ec)
96 {
97    E_Effect_Group group = E_EFFECT_GROUP_NORMAL;
98
99    /* animatable setting by aux_hint */
100    if (!ec->animatable) return E_EFFECT_GROUP_NONE;
101
102    /* client_type */
103    switch (ec->client_type)
104      {
105       case 1: //homescreen
106          group = E_EFFECT_GROUP_HOME;
107          break;
108       case 2: //lockscreen
109          group = E_EFFECT_GROUP_LOCKSCREEN;
110          break;
111       default:
112          break;
113      }
114
115    /* client layer */
116    if (group == E_EFFECT_GROUP_NORMAL)
117      {
118         if (ec->layer > E_LAYER_CLIENT_NORMAL)
119           group = E_EFFECT_GROUP_NONE;
120      }
121
122    /* window_role */
123
124    /* etc */
125    if (ec->vkbd.vkbd)
126      group = E_EFFECT_GROUP_KEYBOARD;
127
128    return group;
129 }
130
131 static int
132 _eff_group_angle_get(E_Client *ec, E_Effect_Group group)
133 {
134    if (group == E_EFFECT_GROUP_KEYBOARD)
135      {
136         if (ec->parent)
137           return ec->parent->e.state.rot.ang.curr;
138      }
139
140    return ec->e.state.rot.ang.curr;
141 }
142
143 static Eina_Bool
144 _eff_ref(E_Client *ec)
145 {
146    E_Effect_Client *efc;
147
148    if (!_eff) return EINA_FALSE;
149
150    if (e_object_is_del(E_OBJECT(ec)))
151      {
152         ERR("Client is deleted already! ec(%p)", ec);
153         eina_hash_del_by_key(_eff->clients, &ec);
154         return EINA_FALSE;
155      }
156
157    efc = _eff_client_get(ec);
158    if (!efc) return EINA_FALSE;
159
160    if (!ec->pixmap) return EINA_FALSE;
161    if ((e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) &&
162        (!e_pixmap_usable_get(ec->pixmap)))
163      return EINA_FALSE;
164
165    efc->animating++;
166    e_object_ref(E_OBJECT(ec));
167    efc->ep = e_pixmap_ref(ec->pixmap);
168
169    EFFINF("effect ref efc(%p) animating:%d",
170           efc->ep, efc->ec, efc, efc->animating);
171
172    return EINA_TRUE;
173 }
174
175 static E_Client *
176 _eff_unref(E_Client *ec)
177 {
178    E_Effect_Client *efc;
179    int do_unref = 1;
180
181    if (!_eff) return NULL;
182    if (!ec) return NULL;
183
184    efc = _eff_client_get(ec);
185    if (!efc) return NULL;
186
187    if (e_object_is_del(E_OBJECT(ec)))
188      do_unref = efc->animating;
189
190    efc->animating -= do_unref;
191    while (do_unref)
192      {
193         e_pixmap_free(efc->ep);
194         if (!e_object_unref(E_OBJECT(ec)))
195           {
196              EFFINF("eff unref ec(%p) ep(%p) efc(%p) Client free'd",
197                     NULL, NULL, ec, efc->ep, efc);
198
199              efc->ec = NULL;
200              efc = NULL;
201              eina_hash_del_by_key(_eff->clients, &ec);
202              return NULL;
203           }
204         do_unref --;
205      }
206
207    EFFINF("eff Unref efc(%p) animating:%d",
208           ec->pixmap, ec, efc, efc->animating);
209
210    /* The reference count of wl_buffer will get decremented
211     * immediately after window effect.
212     */
213    if ((efc) && (efc->buffer_ref.buffer))
214      e_comp_wl_buffer_reference(&efc->buffer_ref, NULL);
215
216    return ec;
217 }
218
219 static void
220 _eff_object_setup(E_Client *ec, E_Effect_Group group)
221 {
222    E_Comp_Config *cfg;
223    cfg = e_comp_config_get();
224
225    if (group == E_EFFECT_GROUP_KEYBOARD)
226      e_comp_object_effect_set(ec->frame, "keyboard");
227    else
228      {
229         if ((cfg) && (cfg->effect_style))
230           e_comp_object_effect_set(ec->frame, cfg->effect_style);
231         else
232           e_comp_object_effect_set(ec->frame, "no-effect");
233      }
234 }
235
236 static void
237 _eff_object_layer_up(E_Client *ec)
238 {
239    int map_ly;
240
241    map_ly = e_comp_canvas_client_layer_map(ec->layer);
242    if (map_ly == 9999) return;
243
244    if (!_eff->layers[map_ly].obj)
245      {
246         _eff->layers[map_ly].obj = evas_object_rectangle_add(e_comp->evas);
247         evas_object_layer_set(_eff->layers[map_ly].obj, ec->layer + 1);
248         evas_object_name_set(_eff->layers[map_ly].obj, "layer_obj(effect)");
249      }
250
251    ec->layer_pending = 1;
252    evas_object_layer_set(ec->frame, ec->layer + 1);
253 }
254
255 static void
256 _eff_object_layer_down(E_Client *ec)
257 {
258    evas_object_layer_set(ec->frame, ec->layer);
259    ec->layer_pending = 0;
260 }
261
262 static void
263 _eff_pending_effect_start(void)
264 {
265    E_Client *ec;
266
267    ec = _eff->next_done.ec;
268    if (!ec) return;
269
270    EFFINF("Pending eff Start type(%d)",
271           ec->pixmap, ec, _eff->next_done.type);
272
273    if (_eff->next_done.cb)
274      {
275         _eff_event_send(ec, EINA_TRUE, _eff->next_done.type);
276         e_comp_object_effect_start(ec->frame,
277                                    _eff->next_done.cb,
278                                    _eff->next_done.data);
279      }
280
281    memset(&_eff->next_done, 0, sizeof(_eff->next_done));
282 }
283
284 static void
285 _eff_pending_effect_set(E_Client *ec, void *data, E_Effect_Type type, Edje_Signal_Cb done_cb)
286 {
287    _eff_pending_effect_start();
288
289    EFFINF("Pending eff Set type(%d)",
290           ec->pixmap, ec, type);
291
292    _eff->next_done.cb = done_cb;
293    _eff->next_done.ec = ec;
294    _eff->next_done.data = data;
295    _eff->next_done.type = type;
296 }
297
298 static void
299 _eff_stack_update(void)
300 {
301    E_Client *ec;
302    Evas_Object *o;
303
304    if (!_eff) return;
305
306    _eff->stack.old = eina_list_free(_eff->stack.old);
307    _eff->stack.old = eina_list_clone(_eff->stack.cur);
308
309    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
310      {
311         ec = evas_object_data_get(o, "E_Client");
312         if (!ec) continue;
313         if (e_client_util_ignored_get(ec)) continue;
314         if (e_object_is_del(E_OBJECT(ec))) continue;
315
316         _eff->stack.cur = eina_list_remove(_eff->stack.cur, ec);
317         _eff->stack.cur = eina_list_append(_eff->stack.cur, ec);
318      }
319 }
320
321 static Eina_Bool
322 _eff_visibility_stack_check(E_Client *ec, Eina_List *stack)
323 {
324    Eina_List *l;
325    E_Client *_ec;
326    Eina_Tiler *tiler;
327    Eina_Rectangle r;
328    Eina_Bool vis = EINA_TRUE;
329    int x, y, w, h;
330
331    if (!stack) return EINA_FALSE;
332
333    tiler = eina_tiler_new(ec->desk->geom.w, ec->desk->geom.h);
334    eina_tiler_tile_size_set(tiler, 1, 1);
335    EINA_RECTANGLE_SET(&r, ec->desk->geom.x, ec->desk->geom.y, ec->desk->geom.w, ec->desk->geom.h);
336    eina_tiler_rect_add(tiler, &r);
337
338    EINA_LIST_FOREACH(stack, l, _ec)
339      {
340         if (_ec == ec) break;
341         if (!_ec->visible) continue;
342         if (!evas_object_visible_get(_ec->frame))
343           {
344              if (!_ec->iconic) continue;
345              if (_ec->iconic && _ec->exp_iconify.by_client) continue;
346           }
347         if (!e_pixmap_resource_get(_ec->pixmap)) continue;
348
349         e_client_geometry_get(_ec, &x, &y, &w, &h);
350
351         EINA_RECTANGLE_SET(&r, x, y, w, h);
352         eina_tiler_rect_del(tiler, &r);
353
354         if (eina_tiler_empty(tiler))
355           {
356              vis = EINA_FALSE;
357              break;
358           }
359      }
360    eina_tiler_free(tiler);
361
362    return vis;
363 }
364
365 static const char *
366 _eff_restack_effect_check(E_Client *ec)
367 {
368    const char *emission = NULL;
369    Eina_Bool v1, v2;
370    E_Effect_Client *efc;
371
372    if (!evas_object_visible_get(ec->frame)) return NULL;
373    if (ec->new_client) return NULL;
374
375    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
376    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
377
378    if (v1 != v2)
379      {
380         if ((v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED))
381           emission = "e,action,restack,show";
382         else if ((!v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED))
383           emission = "e,action,restack,hide";
384      }
385    else
386      {
387         efc = _eff_client_get(ec);
388
389         // TODO : it's for transients windows. wish using other check */
390         if ((efc) && (!efc->animating))
391           {
392              if ((v2) && (!ec->iconic) &&
393                  (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED))
394                emission = "e,action,restack,show";
395              else if ((!v2) && (ec->iconic) &&
396                       (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED))
397                emission = "e,action,restack,hide";
398           }
399      }
400
401    EFFINF("Restack eff Check v1(%d) -> v2(%d) iconic:%d "
402           "obscured:%d(%d) emission:%s",
403           ec->pixmap, ec,
404           v1, v2, ec->iconic,
405           ec->visibility.obscured, ec->visibility.changed, emission);
406
407    return emission;
408 }
409
410 static void
411 _eff_cb_visible_done(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
412 {
413    E_Client *ec = (E_Client *)data;
414
415    if (ec)
416      {
417         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_SHOW);
418         _eff_unref(ec);
419      }
420
421    _eff_stack_update();
422    e_comp_override_del();
423 }
424
425 static Eina_Bool
426 _eff_cb_visible(void *data, Evas_Object *obj, const char *signal)
427 {
428    E_Client *ec;
429    E_Effect_Group group;
430    int ang = -1;
431
432    if (!_eff) return EINA_FALSE;
433
434    ec = e_comp_object_client_get(obj);
435    if (!ec) return EINA_FALSE;
436    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
437
438    group = _eff_group_get(ec);
439    if ((group != E_EFFECT_GROUP_NORMAL) &&
440        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
441
442    if (evas_object_visible_get(obj)) return EINA_FALSE;
443    if (!_eff_ref(ec)) return EINA_FALSE;
444
445    e_comp_override_add();
446
447    EFFINF("SET EXTRA_ANIMATING...", ec->pixmap, ec);
448    ec->extra_animating = EINA_TRUE;
449
450    _eff_object_setup(ec, group);
451    ang = _eff_group_angle_get(ec, group);
452    e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
453    if (e_comp->nocomp)
454      {
455         _eff_pending_effect_set(ec,
456                                 (void *)ec,
457                                 E_EFFECT_TYPE_SHOW,
458                                 _eff_cb_visible_done);
459         return EINA_TRUE;
460      }
461
462    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
463
464    e_comp_object_effect_start(ec->frame, _eff_cb_visible_done, ec);
465
466    return EINA_TRUE;
467 }
468
469 static void
470 _eff_cb_hidden_done(void *data, Evas_Object *obj, const char *sig, const char *src)
471 {
472    E_Client *ec = (E_Client *)data;
473
474    if (ec)
475      {
476         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
477         if (_eff_unref(ec))
478           {
479              if (_eff_client_get(ec))
480                {
481                   _eff_object_layer_down(ec);
482                   evas_object_hide(ec->frame);
483                }
484           }
485      }
486
487    e_comp_override_del();
488 }
489
490 static Eina_Bool
491 _eff_cb_hidden(void *data, Evas_Object *obj, const char *signal)
492 {
493    E_Client *ec;
494    E_Effect_Group group;
495    Eina_Bool lowered = 0;
496    Evas_Object *below;
497    int map_ly;
498    int ang = -1;
499
500    if (!_eff) return EINA_FALSE;
501
502    ec = e_comp_object_client_get(obj);
503    if (!ec) return EINA_FALSE;
504    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
505
506    /* check for effect group */
507    group = _eff_group_get(ec);
508    if ((group != E_EFFECT_GROUP_NORMAL) &&
509        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
510
511    if (group == E_EFFECT_GROUP_KEYBOARD)
512      {
513         if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
514           return EINA_FALSE;
515      }
516
517    if (!evas_object_visible_get(obj)) return EINA_FALSE;
518    if (!_eff_ref(ec)) return EINA_FALSE;
519
520    e_comp_override_add();
521
522    // check if client was lowered
523    below = evas_object_below_get(obj);
524    map_ly = e_comp_canvas_layer_map(evas_object_layer_get(obj));
525    if ((below) && (map_ly != 9999) &&
526        (evas_object_layer_get(below) != evas_object_layer_get(obj)) &&
527        (evas_object_above_get(obj) != e_comp->layers[map_ly].obj))
528      lowered = 1;
529
530    if (lowered)
531      _eff_object_layer_up(ec);
532
533    _eff_object_setup(ec, group);
534    ang = _eff_group_angle_get(ec, group);
535    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
536
537    if (e_comp->nocomp)
538      {
539         _eff_pending_effect_set(ec,
540                                 (void *)ec,
541                                 E_EFFECT_TYPE_HIDE,
542                                 _eff_cb_hidden_done);
543         return EINA_TRUE;
544      }
545
546    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
547    e_comp_object_effect_start(ec->frame, _eff_cb_hidden_done, ec);
548
549    return EINA_TRUE;
550 }
551
552 static void
553 _eff_cb_uniconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
554 {
555    E_Client *ec = (E_Client *)data;
556
557    if (ec)
558      {
559         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_SHOW);
560         _eff_unref(ec);
561      }
562
563    e_comp_override_del();
564 }
565
566 static Eina_Bool
567 _eff_cb_uniconify(void *data, Evas_Object *obj, const char *signal)
568 {
569    E_Client *ec;
570    E_Effect_Group group;
571    Eina_Bool v1, v2;
572    int ang = -1;
573
574    if (!_eff) return EINA_FALSE;
575
576    ec = e_comp_object_client_get(obj);
577    if (!ec) return EINA_FALSE;
578    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
579
580    if (evas_object_visible_get(obj)) return EINA_FALSE;
581
582    group = _eff_group_get(ec);
583
584    /* for HOME group */
585    if (group == E_EFFECT_GROUP_HOME)
586      {
587         E_Client *below;
588
589         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
590         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
591
592         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
593                ec->pixmap, ec,
594                v1, v2, ec->visibility.obscured, ec->visibility.changed);
595
596         if (v1 == v2) return EINA_FALSE;
597         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
598         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
599
600         below = e_client_below_get(ec);
601         while (below)
602           {
603              if ((evas_object_visible_get(below->frame)) &&
604                  (below->layer == ec->layer) &&
605                  ((below->visibility.obscured == E_VISIBILITY_UNOBSCURED) ||
606                   (below->visibility.changed)))
607                break;
608
609              below = e_client_below_get(below);
610           }
611
612         if (!below) return EINA_FALSE;
613         group = _eff_group_get(below);
614         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
615
616         EFFINF("Uniconify HOME group do hide eff of %p",
617                ec->pixmap, ec, below);
618
619         e_comp_object_signal_emit(below->frame, "e,action,restack,hide", "e");
620         return EINA_TRUE;
621      }
622    /* for NORMAL and KEYBOARD group */
623    else if ((group == E_EFFECT_GROUP_NORMAL) ||
624             (group == E_EFFECT_GROUP_KEYBOARD))
625      {
626         v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
627         v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
628
629         EFFINF("Uniconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
630                ec->pixmap, ec,
631                v1, v2, ec->visibility.obscured, ec->visibility.changed);
632
633         if (v1 == v2) return EINA_FALSE;
634         if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
635         if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
636
637         if (!_eff_ref(ec)) return EINA_FALSE;
638
639         e_comp_override_add();
640
641         _eff_object_setup(ec, group);
642         ang = _eff_group_angle_get(ec, group);
643         e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2);
644
645         if (e_comp->nocomp)
646           {
647              _eff_pending_effect_set(ec,
648                                      (void *)ec,
649                                      E_EFFECT_TYPE_SHOW,
650                                      _eff_cb_uniconify_done);
651              return EINA_TRUE;
652           }
653
654         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_SHOW);
655         e_comp_object_effect_start(ec->frame, _eff_cb_uniconify_done, ec);
656         return EINA_TRUE;
657      }
658
659    return EINA_FALSE;
660 }
661
662 static void
663 _eff_cb_iconify_done(void *data, Evas_Object *obj, const char *sig, const char *src)
664 {
665    E_Client *ec = (E_Client *)data;
666
667    if (ec)
668      {
669         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_HIDE);
670         if (_eff_unref(ec))
671           {
672              if (_eff_client_get(ec))
673                evas_object_hide(ec->frame);
674           }
675      }
676
677    e_comp_override_del();
678 }
679
680 static Eina_Bool
681 _eff_cb_iconify(void *data, Evas_Object *obj, const char *signal)
682 {
683    E_Client *ec;
684    E_Effect_Group group;
685    Eina_Bool v1, v2;
686    int ang = -1;
687
688    if (!_eff) return EINA_FALSE;
689
690    ec = e_comp_object_client_get(obj);
691    if (!ec) return EINA_FALSE;
692    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
693
694    group = _eff_group_get(ec);
695    if ((group != E_EFFECT_GROUP_NORMAL) &&
696        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
697
698    if (!evas_object_visible_get(obj)) return EINA_FALSE;
699
700    v1 = _eff_visibility_stack_check(ec, _eff->stack.old);
701    v2 = _eff_visibility_stack_check(ec, _eff->stack.cur);
702
703    EFFINF("Iconify eff Check v1(%d) -> v2(%d) obscured:%d changed:%d",
704           ec->pixmap, ec,
705           v1, v2, ec->visibility.obscured, ec->visibility.changed);
706
707    if (v1 == v2) return EINA_FALSE;
708    if ((v2) && (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
709    if ((!v2) && (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)) return EINA_FALSE;
710
711    if (!_eff_ref(ec)) return EINA_FALSE;
712
713    e_comp_override_add();
714
715    _eff_object_setup(ec, group);
716    ang = _eff_group_angle_get(ec, group);
717    e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2);
718
719    if (e_comp->nocomp)
720      {
721         _eff_pending_effect_set(ec,
722                                 (void *)ec,
723                                 E_EFFECT_TYPE_HIDE,
724                                 _eff_cb_iconify_done);
725         return EINA_TRUE;
726      }
727
728    _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_HIDE);
729    e_comp_object_effect_start(ec->frame, _eff_cb_iconify_done, ec);
730
731    return EINA_TRUE;
732 }
733
734 static void
735 _eff_cb_restack_show_done(void *data, Evas_Object *obj, const char *sig, const char *src)
736 {
737    E_Client *ec = (E_Client *)data;
738
739    if (ec)
740      {
741         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_SHOW);
742         if (_eff_unref(ec))
743           {
744              if (_eff_client_get(ec))
745                _eff_object_layer_down(ec);
746           }
747      }
748
749    _eff_stack_update();
750    e_comp_override_del();
751 }
752
753 static void
754 _eff_cb_restack_hide_done(void *data, Evas_Object *obj, const char *sig, const char *src)
755 {
756    E_Client *ec = (E_Client *)data;
757
758    if (ec)
759      {
760         if (_eff_unref(ec))
761           {
762              if (_eff_client_get(ec))
763                {
764                   _eff_object_layer_down(ec);
765                   e_comp_object_signal_emit(ec->frame,
766                                             "e,action,restack,finish",
767                                             "e");
768                }
769           }
770      }
771
772    _eff_stack_update();
773    e_comp_override_del();
774 }
775
776 static void
777 _eff_cb_restack_finish_done(void *data, Evas_Object *obj, const char *sig, const char *src)
778 {
779    E_Client *ec = (E_Client *)data;
780    E_Effect_Client *efc = NULL;
781
782    if (ec)
783      {
784         _eff_event_send(ec, EINA_FALSE, E_EFFECT_TYPE_RESTACK_HIDE);
785         efc = _eff_client_get(ec);
786         if (efc && efc->reverse_ec)
787           {
788              E_Client *ec_home = efc->reverse_ec;
789              if (ec_home->extra_animating)
790                {
791                   ec_home->extra_animating = EINA_FALSE;
792                   if (ec_home->launching == EINA_TRUE)
793                     {
794                        ec_home->launching = EINA_FALSE;
795                        e_comp_object_signal_emit(ec_home->frame, "e,action,launch,done", "e");
796                     }
797                   _eff_unref(ec_home);
798                }
799           }
800
801         _eff_unref(ec);
802      }
803
804    e_comp_override_del();
805 }
806
807 static Eina_Bool
808 _eff_cb_restack(void *data, Evas_Object *obj, const char *signal)
809 {
810    E_Client *ec;
811    E_Effect_Group group;
812    const char *emission;
813    E_Client *ec_home = NULL;
814    int ang = -1;
815
816    if (!_eff) return EINA_FALSE;
817
818    ec = e_comp_object_client_get(obj);
819    if (!ec) return EINA_FALSE;
820    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
821
822    group = _eff_group_get(ec);
823    emission = eina_stringshare_add(signal);
824
825    /* for HOME group: replace eff target client */
826    if (group == E_EFFECT_GROUP_HOME)
827      {
828         E_Client *below;
829
830         below = e_client_below_get(ec);
831         while (below)
832           {
833              if ((!e_object_is_del(E_OBJECT(below))) &&
834                  (evas_object_visible_get(below->frame)) &&
835                  (below->visibility.obscured == E_VISIBILITY_UNOBSCURED) &&
836                  (below->layer == ec->layer))
837                break;
838
839              below = e_client_below_get(below);
840           }
841
842         if (!below) return EINA_FALSE;
843         if (e_util_strcmp(signal, "e,action,restack,show")) return EINA_FALSE;
844
845         ec_home = ec;
846         ec = below;
847         group = _eff_group_get(ec);
848         if (group != E_EFFECT_GROUP_NORMAL) return EINA_FALSE;
849
850         if (emission) eina_stringshare_del(emission);
851         emission = eina_stringshare_add("e,action,restack,hide");
852      }
853
854    if ((group != E_EFFECT_GROUP_NORMAL) &&
855        (group != E_EFFECT_GROUP_KEYBOARD)) return EINA_FALSE;
856
857    if ((!e_util_strcmp(emission, "e,action,restack,show")))
858      {
859         if (!_eff_ref(ec)) return EINA_FALSE;
860
861         EFFINF("SET EXTRA_ANIMATING...", ec->pixmap, ec);
862         ec->extra_animating = EINA_TRUE;
863
864         e_comp_override_add();
865
866         _eff_object_layer_up(ec);
867
868         _eff_object_setup(ec, group);
869         ang = _eff_group_angle_get(ec, group);
870         e_comp_object_effect_params_set(ec->frame, 0, (int[]){2, ang}, 2);
871
872         if (e_comp->nocomp)
873           {
874              _eff_pending_effect_set(ec,
875                                      (void *)ec,
876                                      E_EFFECT_TYPE_SHOW,
877                                      _eff_cb_restack_show_done);
878              return EINA_TRUE;
879           }
880
881         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_SHOW);
882         e_comp_object_effect_start(ec->frame, _eff_cb_restack_show_done, ec);
883      }
884    else if (!e_util_strcmp(emission, "e,action,restack,hide"))
885      {
886         if (!_eff_ref(ec)) return EINA_FALSE;
887
888         if (ec_home)
889           {
890              E_Effect_Client *efc = NULL;
891              efc = _eff_client_get(ec);
892              if (efc)
893                {
894                   if (_eff_ref(ec_home))
895                     {
896                        EFFINF("SET EXTRA_ANIMATING...", ec_home->pixmap, ec_home);
897                        ec_home->extra_animating = EINA_TRUE;
898
899                        efc->reverse_ec = ec_home;
900
901                        EFFINF("SET EXTRA_ANIMATING...", ec->pixmap, ec);
902                        ec->extra_animating = EINA_TRUE;
903                     }
904                }
905           }
906
907         e_comp_override_add();
908
909         _eff_object_layer_up(ec);
910
911         _eff_object_setup(ec, group);
912         ang = _eff_group_angle_get(ec, group);
913         e_comp_object_effect_params_set(ec->frame, 0, (int[]){3, ang}, 2);
914
915         if (e_comp->nocomp)
916           {
917              _eff_pending_effect_set(ec,
918                                      (void *)ec,
919                                      E_EFFECT_TYPE_HIDE,
920                                      _eff_cb_restack_hide_done);
921              return EINA_TRUE;
922           }
923
924         _eff_event_send(ec, EINA_TRUE, E_EFFECT_TYPE_RESTACK_HIDE);
925         e_comp_object_effect_start(ec->frame, _eff_cb_restack_hide_done, ec);
926      }
927    else if (!e_util_strcmp(emission, "e,action,restack,finish"))
928      {
929         if (!_eff_ref(ec)) return EINA_FALSE;
930
931         e_comp_override_add();
932
933         _eff_object_setup(ec, group);
934         ang = _eff_group_angle_get(ec, group);
935         e_comp_object_effect_params_set(ec->frame, 0, (int[]){4, ang}, 2);
936
937         if (e_comp->nocomp)
938           {
939              _eff_pending_effect_set(ec,
940                                      (void *)ec,
941                                      E_EFFECT_TYPE_HIDE,
942                                      _eff_cb_restack_finish_done);
943              return EINA_TRUE;
944           }
945
946         e_comp_object_effect_start(ec->frame, _eff_cb_restack_finish_done, ec);
947      }
948
949    return EINA_TRUE;
950 }
951
952 static Eina_Bool
953 _eff_cb_launch(void *data, Evas_Object *obj, const char *signal)
954 {
955    E_Client *ec;
956    struct wl_resource *res_surf;
957    struct wl_resource *res_eff;
958    struct wl_client *wc;
959    unsigned int tizen_effect_type = 4;
960
961    if (!_eff) return EINA_FALSE;
962
963    ec = e_comp_object_client_get(obj);
964    if ((!ec) || (!ec->comp_data)) return EINA_FALSE;
965    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
966
967    res_surf = ec->comp_data->surface;
968    if (!res_surf) return EINA_FALSE;
969
970    wc = wl_resource_get_client(res_surf);
971    if (!wc) return EINA_FALSE;
972
973    res_eff = eina_hash_find(_eff->resources, &wc);
974    if (!res_eff) return EINA_FALSE;
975
976    EFFINF("SEND END  |type:LAUNCH|win:0x%08x|tz_effect:0x%08x",
977           ec->pixmap, ec,
978           (unsigned int)e_client_util_win_get(ec),
979           (unsigned int)res_eff);
980
981    tizen_effect_send_end(res_eff, res_surf, tizen_effect_type);
982
983    return EINA_TRUE;
984 }
985
986 static void
987 _eff_cb_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
988 {
989    E_Effect_Client *efc;
990
991    if (!_eff) return;
992
993    efc = _eff_client_get(ec);
994    if (efc) return;
995
996    efc = _eff_client_new(ec);
997    if (efc)
998      eina_hash_add(_eff->clients, &ec, efc);
999 }
1000
1001 static void
1002 _eff_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
1003 {
1004    E_Effect_Client *efc = NULL;
1005
1006    if (!_eff) return;
1007
1008    _eff->stack.old = eina_list_remove(_eff->stack.old, ec);
1009    _eff->stack.cur = eina_list_remove(_eff->stack.cur, ec);
1010
1011    if (_eff->next_done.ec == ec)
1012      memset(&_eff->next_done, 0, sizeof(_eff->next_done));
1013
1014    if ((efc = _eff_client_get(ec)))
1015      {
1016         if (!efc->animating)
1017           eina_hash_del_by_key(_eff->clients, &ec);
1018      }
1019 }
1020
1021 static Eina_Bool
1022 _eff_cb_client_restack(void *data, int type, void *event)
1023 {
1024    E_Client *ec;
1025    E_Event_Client *ev = event;
1026    const char *emission = NULL;
1027
1028    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1029
1030    ec = ev->ec;
1031    if (!ec) return ECORE_CALLBACK_PASS_ON;
1032    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
1033
1034    EFFINF("Client restacked", ec->pixmap, ec);
1035
1036    _eff_stack_update();
1037
1038    if (!_eff_client_get(ec)) return ECORE_CALLBACK_PASS_ON;
1039
1040    if ((emission = _eff_restack_effect_check(ec)))
1041      e_comp_object_signal_emit(ec->frame, emission, "e");
1042
1043    return ECORE_CALLBACK_PASS_ON;
1044 }
1045
1046 static Eina_Bool
1047 _eff_cb_comp_enabled(void *data, int ev_type, void *event)
1048 {
1049    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1050
1051    _eff_pending_effect_start();
1052
1053    return ECORE_CALLBACK_PASS_ON;
1054 }
1055
1056 static Eina_Bool
1057 _eff_cb_client_buffer_change(void *data, int ev_type, void *event)
1058 {
1059    E_Event_Client *ev = event;
1060    E_Client *ec;
1061    E_Effect_Client *efc;
1062    E_Comp_Wl_Buffer *buffer = NULL;
1063
1064    if (!_eff) return ECORE_CALLBACK_PASS_ON;
1065
1066    ec = ev->ec;
1067    if (!ec) return ECORE_CALLBACK_PASS_ON;
1068
1069    efc = _eff_client_get(ec);
1070    if (!efc) return ECORE_CALLBACK_PASS_ON;
1071
1072    if (ec->pixmap)
1073      {
1074         buffer = e_pixmap_resource_get(ec->pixmap);
1075         if (buffer != efc->buffer_ref.buffer)
1076           {
1077              e_comp_wl_buffer_reference(&efc->buffer_ref, buffer);
1078           }
1079      }
1080
1081    return ECORE_CALLBACK_PASS_ON;
1082 }
1083
1084 static void
1085 _tz_effect_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *tz_res_eff)
1086 {
1087    wl_resource_destroy(tz_res_eff);
1088 }
1089
1090 static const struct tizen_effect_interface _tz_effect_interface =
1091 {
1092    _tz_effect_cb_destroy,
1093 };
1094
1095 static void
1096 _tz_effect_cb_effect_destroy(struct wl_resource *tz_res_eff)
1097 {
1098    if ((!_eff) || (!_eff->resources)) return;
1099
1100    eina_hash_del_by_data(_eff->resources, tz_res_eff);
1101 }
1102
1103 static void
1104 _eff_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
1105 {
1106    struct wl_resource *res;
1107
1108    if (!(res = wl_resource_create(client, &tizen_effect_interface, 1, id)))
1109      {
1110         ERR("Could not create tizen_effect interface");
1111         wl_client_post_no_memory(client);
1112         return;
1113      }
1114
1115    wl_resource_set_implementation(res,
1116                                   &_tz_effect_interface,
1117                                   NULL,
1118                                   _tz_effect_cb_effect_destroy);
1119
1120    eina_hash_add(_eff->resources, &client, res);
1121 }
1122
1123 static void
1124 _eff_cb_client_data_free(void *data)
1125 {
1126    E_Effect_Client *efc = data;
1127
1128    if (!efc) return;
1129
1130    if (efc->buffer_ref.buffer)
1131      e_comp_wl_buffer_reference(&efc->buffer_ref, NULL);
1132
1133    free(efc);
1134 }
1135
1136 #undef E_CLIENT_HOOK_APPEND
1137 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
1138   do                                      \
1139     {                                     \
1140        E_Client_Hook *_h;                 \
1141        _h = e_client_hook_add(t, cb, d);  \
1142        assert(_h);                        \
1143        l = eina_list_append(l, _h);       \
1144     }                                     \
1145   while (0)
1146
1147 #undef E_COMP_OBJ_EFF_MOVER_APPEND
1148 #define E_COMP_OBJ_EFF_MOVER_APPEND(l, i, s, p, d)      \
1149   do                                                    \
1150     {                                                   \
1151        E_Comp_Object_Mover *_m;                         \
1152        _m = e_comp_object_effect_mover_add(i, s, p, d); \
1153        assert(_m);                                      \
1154        l = eina_list_append(l, _m);                     \
1155     }                                                   \
1156   while (0)
1157
1158 EAPI Eina_Bool
1159 e_mod_effect_init(void)
1160 {
1161    E_Effect *eff;
1162    E_Comp_Config *cfg;
1163    Eina_List *l;
1164    E_Client *ec;
1165    E_Effect_Client *efc;
1166
1167    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1168    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->evas, EINA_FALSE);
1169
1170    eff = E_NEW(E_Effect, 1);
1171    EINA_SAFETY_ON_NULL_RETURN_VAL(eff, EINA_FALSE);
1172
1173    if ((cfg = e_comp_config_get()))
1174      {
1175         eff->file = eina_stringshare_add(cfg->effect_file);
1176         eff->style = eina_stringshare_add(cfg->effect_style);
1177      }
1178    else
1179      {
1180         eff->file = "";
1181         eff->style = "no-effect";
1182      }
1183
1184    eff->clients = eina_hash_pointer_new(_eff_cb_client_data_free);
1185    EINA_SAFETY_ON_NULL_GOTO(eff->clients, err);
1186
1187    EINA_LIST_FOREACH(e_comp->clients, l, ec)
1188      {
1189         if (ec->ignored) continue;
1190
1191         efc = _eff_client_get(ec);
1192         if (!efc)
1193           efc = _eff_client_new(ec);
1194         if (efc)
1195           eina_hash_add(eff->clients, &ec, efc);
1196      }
1197
1198    eff->resources = eina_hash_pointer_new(NULL);
1199    EINA_SAFETY_ON_NULL_GOTO(eff->resources, err);
1200
1201    eff->global = wl_global_create(e_comp_wl->wl.disp,
1202                                   &tizen_effect_interface,
1203                                   1,
1204                                   eff,
1205                                   _eff_cb_bind);
1206    if (!eff->global)
1207      {
1208         ERR("Could not add tizen_efffect wayland globals: %m");
1209         goto err;
1210      }
1211
1212    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_COMPOSITOR_ENABLE,    _eff_cb_comp_enabled,         eff);
1213    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_BUFFER_CHANGE, _eff_cb_client_buffer_change, eff);
1214    E_LIST_HANDLER_APPEND(eff->event_hdlrs,          E_EVENT_CLIENT_STACK,         _eff_cb_client_restack,       eff);
1215    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_NEW_CLIENT,     _eff_cb_hook_client_new,      eff);
1216    E_CLIENT_HOOK_APPEND(eff->hooks_ec,              E_CLIENT_HOOK_DEL,            _eff_cb_hook_client_del,      eff);
1217    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,visible",            _eff_cb_visible,              eff);
1218    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,state,hidden",             _eff_cb_hidden,               eff);
1219    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,iconify",           _eff_cb_iconify,              eff);
1220    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,uniconify",         _eff_cb_uniconify,            eff);
1221    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,restack*",          _eff_cb_restack,              eff);
1222    E_COMP_OBJ_EFF_MOVER_APPEND(eff->providers, 100, "e,action,launch,done",       _eff_cb_launch,               eff);
1223
1224    _eff = eff;
1225
1226    return EINA_TRUE;
1227
1228 err:
1229    e_mod_effect_shutdown();
1230    return EINA_FALSE;
1231 }
1232
1233 EAPI void
1234 e_mod_effect_shutdown()
1235 {
1236    if (!_eff) return;
1237
1238    E_FREE_FUNC(_eff->stack.old, eina_list_free);
1239    E_FREE_FUNC(_eff->stack.cur, eina_list_free);
1240
1241    E_FREE_LIST(_eff->providers, e_comp_object_effect_mover_del);
1242    E_FREE_LIST(_eff->event_hdlrs, ecore_event_handler_del);
1243    E_FREE_LIST(_eff->hooks_ec, e_client_hook_del);
1244
1245    if (_eff->global)
1246      wl_global_destroy(_eff->global);
1247
1248    E_FREE_FUNC(_eff->resources, eina_hash_free);
1249    E_FREE_FUNC(_eff->clients, eina_hash_free);
1250
1251    E_FREE(_eff);
1252 }