Merged with devel
[platform/core/uifw/e17-extra-modules.git] / comp-tizen / src / e_mod_comp_effect.c
1 #include "e_mod_comp_shared_types.h"
2 #include "e_mod_comp.h"
3 #include "e_mod_comp_atoms.h"
4 #include "e_mod_comp_debug.h"
5 #include <X11/Xlib.h>
6
7 struct _E_Comp_Effect_Type
8 {
9    Eina_Bool           animatable : 1; // if this valuse is true then window can show animaton.
10    E_Comp_Effect_Style show;           // indicate show effect type
11    E_Comp_Effect_Style hide;           // indicate hide effect type
12    E_Comp_Effect_Style restack;        // indicate restack effect type
13    E_Comp_Effect_Style rotation;       // indicate rotation effect type
14    E_Comp_Effect_Style focusin;        // indicate focus in effect type
15    E_Comp_Effect_Style focusout;       // indicate focus out effect type
16 };
17
18 struct _E_Comp_Effect_Job
19 {
20    Evas_Object   *o;
21    E_Comp_Canvas *canvas;
22    Ecore_X_Window win;
23    Ecore_X_Window cwin;
24    char           emission[1024];
25    char           src[1024];
26    Eina_Bool      emitted;
27    Eina_Bool      effect_obj;
28 };
29
30 static Eina_List *effect_jobs = NULL;
31
32 /* local subsystem functions */
33 static E_Comp_Effect_Style _effect_style_get(Ecore_X_Atom a);
34 static Eina_Bool           _state_send(E_Comp_Win *cw, Eina_Bool state);
35 static Eina_Bool           _effect_signal_del_intern(E_Comp_Win *cw, Evas_Object *obj, const char *name, Eina_Bool clean_all);
36
37 static void                _effect_win_set(E_Comp_Win *cw, const char *emission);
38 static void                _effect_below_wins_set(E_Comp_Win *cw);
39 static void                _effect_above_wins_set(E_Comp_Win *cw, Eina_Bool show);
40 static void                _effect_show(E_Comp_Win *cw);
41 static void                _effect_hide(E_Comp_Win *cw);
42 static Eina_Bool           _effect_obj_win_set(E_Comp_Effect_Object *o, E_Comp_Win *cw);
43 static void                _effect_obj_effect_done(void *data, Evas_Object *obj, const char *emission, const char *source);
44 static Eina_Bool           _effect_obj_find(E_Comp_Win *cw);
45
46 /* externally accessible functions */
47 EINTERN E_Comp_Effect_Object *
48 e_mod_comp_effect_object_new(E_Comp_Layer *ly,
49                              E_Comp_Win   *cw)
50 {
51    E_Comp_Effect_Object *o = NULL;
52    Eina_Bool res;
53    E_CHECK_RETURN(ly, NULL);
54    E_CHECK_RETURN(cw, NULL);
55
56    res = _effect_obj_find(cw);
57    /* TODO: clean up previous effect job */
58    E_CHECK_RETURN(!res, NULL);
59
60    o = E_NEW(E_Comp_Effect_Object, 1);
61    E_CHECK_RETURN(o, NULL);
62
63    o->edje = edje_object_add(ly->canvas->evas);
64    E_CHECK_GOTO(o->edje, fail);
65
66    e_mod_comp_layer_populate(ly, o->edje);
67
68    evas_object_data_set(o->edje, "comp.effect_obj.ly", ly);
69    evas_object_data_set(o->edje, "comp.effect_obj.cwin",
70                         (void *)e_mod_comp_util_client_xid_get(cw));
71
72    res = _effect_obj_win_set(o, cw);
73    E_CHECK_GOTO(res, fail);
74
75    ly->objs = eina_list_append(ly->objs, o);
76
77    ELBF(ELBT_COMP, 0, o->cwin,
78         "%15.15s| OBJ_NEW %p", "EFFECT", o->edje);
79
80    return o;
81
82 fail:
83    ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
84         "%15.15s| OBJ_NEW Failed", "EFFECT");
85    if (o)
86      {
87         if (o->edje)
88           {
89              e_layout_unpack(o->edje);
90              evas_object_del(o->edje);
91           }
92         E_FREE(o);
93      }
94    return NULL;
95 }
96
97 EINTERN void
98 e_mod_comp_effect_object_free(E_Comp_Effect_Object *o)
99 {
100    E_CHECK(o);
101
102    if ((o->edje) && (o->img))
103      edje_object_part_unswallow(o->edje, o->img);
104
105    if (o->img)
106      {
107         /* TODO: consider when using an xim */
108         evas_object_image_native_surface_set(o->img, NULL);
109         evas_object_image_size_set(o->img, 1, 1);
110         evas_object_image_data_set(o->img, NULL);
111         evas_object_hide(o->img);
112         evas_object_del(o->img);
113      }
114
115    if (o->pixmap)
116      ecore_x_pixmap_free(o->pixmap);
117
118    if (o->edje)
119      {
120         evas_object_data_del(o->edje, "comp.effect_obj.ly");
121         evas_object_data_del(o->edje, "comp.effect_obj.cwin");
122         evas_object_hide(o->edje);
123         evas_object_del(o->edje);
124      }
125
126    ELBF(ELBT_COMP, 0, o->cwin,
127         "%15.15s| OBJ_FREE", "EFFECT");
128
129    memset(o, 0, sizeof(E_Comp_Effect_Object));
130
131    E_FREE(o);
132 }
133
134 EINTERN Eina_Bool
135 e_mod_comp_effect_signal_del(E_Comp_Win  *cw,
136                              Evas_Object *obj,
137                              const char  *name)
138 {
139    return _effect_signal_del_intern(cw, obj, name, EINA_FALSE);
140 }
141
142 EINTERN Eina_Bool
143 e_mod_comp_effect_jobs_clean(E_Comp_Win  *cw,
144                              Evas_Object *obj,
145                              const char  *name)
146 {
147    return _effect_signal_del_intern(cw, obj, name, EINA_TRUE);
148 }
149
150 EINTERN Eina_Bool
151 e_mod_comp_effect_signal_flush(void)
152 {
153    E_Comp_Effect_Job *job;
154    Eina_List *l;
155    E_Comp_Win *cw;
156    E_Comp_Layer *ly;
157
158    EINA_LIST_FOREACH(effect_jobs, l, job)
159      {
160         if (!job) continue;
161         if (job->emitted) continue;
162
163         if ((job->win) && (job->canvas))
164           {
165              if ((cw = e_mod_comp_win_find(job->win)))
166                {
167                   if (cw->animating)
168                     {
169                        ELBF(ELBT_COMP, 0, job->cwin,
170                             "%15.15s|     SIG_PEND:%s", "EFFECT",
171                             job->emission);
172                        continue;
173                     }
174                   else
175                     {
176                        e_mod_comp_effect_animating_set(cw->c, cw, EINA_TRUE);
177                        job->emitted = EINA_TRUE;
178
179                        edje_object_signal_emit(job->o, job->emission, job->src);
180
181                        ELBF(ELBT_COMP, 0, job->cwin,
182                             "%15.15s|     SIG_EMIT>%s", "EFFECT",
183                             job->emission);
184                     }
185                }
186              else
187                {
188                   ELBF(ELBT_COMP, 0, job->cwin,
189                        "%15.15s|     SIG_DEL :%s", "EFFECT",
190                        job->emission);
191
192                   /* remove this job if cw was already removed */
193                   effect_jobs = eina_list_remove(effect_jobs, job);
194                   E_FREE(job);
195                }
196           }
197         else
198           {
199              edje_object_signal_emit(job->o, job->emission, job->src);
200
201              ELBF(ELBT_COMP, 0, job->cwin,
202                   "%15.15s| OBJ SIG_EMIT>%s", "EFFECT",
203                   job->emission);
204
205              ly = evas_object_data_get(job->o, "comp.effect_obj.ly");
206              if (ly) e_mod_comp_layer_effect_set(ly, EINA_TRUE);
207
208              effect_jobs = eina_list_remove(effect_jobs, job);
209              E_FREE(job);
210           }
211      }
212
213    return EINA_TRUE;
214 }
215
216 EINTERN E_Comp_Effect_Type *
217 e_mod_comp_effect_type_new(void)
218 {
219    E_Comp_Effect_Type *t;
220    t = E_NEW(E_Comp_Effect_Type, 1);
221    E_CHECK_RETURN(t, 0);
222    t->animatable = EINA_TRUE;
223    return t;
224 }
225
226 EINTERN void
227 e_mod_comp_effect_type_free(E_Comp_Effect_Type *type)
228 {
229    E_CHECK(type);
230    E_FREE(type);
231 }
232
233 EINTERN Eina_Bool
234 e_mod_comp_effect_type_setup(E_Comp_Effect_Type *type,
235                              Ecore_X_Window win)
236 {
237    E_CHECK_RETURN(type, 0);
238    E_CHECK_RETURN(win, 0);
239
240    e_mod_comp_effect_state_setup(type, win);
241    e_mod_comp_effect_style_setup(type, win);
242
243    return EINA_TRUE;
244 }
245
246 EINTERN Eina_Bool
247 e_mod_comp_effect_state_setup(E_Comp_Effect_Type *type,
248                               Ecore_X_Window win)
249 {
250    Atom type_ret = 0;
251    int ret, size_ret = 0;
252    unsigned long num_ret = 0, bytes = 0;
253    unsigned char *prop_ret = NULL;
254    Ecore_X_Display *dpy;
255    Eina_Bool is_ok;
256
257    E_CHECK_RETURN(type, 0);
258    E_CHECK_RETURN(win, 0);
259
260    dpy = ecore_x_display_get();
261    ret = XGetWindowProperty(dpy, win, ATOM_WINDOW_EFFECT_ENABLE, 0, LONG_MAX,
262                             False, ECORE_X_ATOM_CARDINAL, &type_ret, &size_ret,
263                             &num_ret, &bytes, &prop_ret);
264    if (ret == 0) // success
265      {
266         if (prop_ret && num_ret)
267           {
268              type->animatable =  prop_ret[0];
269              is_ok = EINA_TRUE;
270           }
271         else
272           is_ok = EINA_FALSE;
273      }
274    else // error
275      {
276         is_ok = EINA_FALSE;
277      }
278
279    if (prop_ret) XFree(prop_ret);
280    return is_ok;
281 }
282
283 EINTERN Eina_Bool
284 e_mod_comp_effect_state_get(E_Comp_Effect_Type *type)
285 {
286    E_CHECK_RETURN(type, 0);
287    return type->animatable;
288 }
289
290 EINTERN Eina_Bool
291 e_mod_comp_effect_style_setup(E_Comp_Effect_Type *type,
292                               Ecore_X_Window win)
293 {
294    Ecore_X_Atom *atoms = NULL;
295    Eina_Bool res = EINA_FALSE;
296    int num = 0;
297
298    E_CHECK_RETURN(type, 0);
299    E_CHECK_RETURN(win, 0);
300
301    num = ecore_x_window_prop_atom_list_get
302            (win, ATOM_WINDOW_EFFECT_TYPE, &atoms);
303    E_CHECK_GOTO((num == 6), cleanup);
304    E_CHECK_GOTO(atoms, cleanup);
305
306    type->show     = _effect_style_get(atoms[0]);
307    type->hide     = _effect_style_get(atoms[1]);
308    type->restack  = _effect_style_get(atoms[2]);
309    type->rotation = _effect_style_get(atoms[3]);
310    type->focusin  = _effect_style_get(atoms[4]);
311    type->focusout = _effect_style_get(atoms[5]);
312
313    res = EINA_TRUE;
314
315 cleanup:
316    if (atoms) E_FREE(atoms);
317    return res;
318 }
319
320 EINTERN E_Comp_Effect_Style
321 e_mod_comp_effect_style_get(E_Comp_Effect_Type *type,
322                             E_Comp_Effect_Kind kind)
323 {
324    E_Comp_Effect_Style res;
325    E_CHECK_RETURN(type, E_COMP_EFFECT_STYLE_NONE);
326    switch (kind)
327      {
328       case E_COMP_EFFECT_KIND_SHOW:     res = type->show;     break;
329       case E_COMP_EFFECT_KIND_HIDE:     res = type->hide;     break;
330       case E_COMP_EFFECT_KIND_RESTACK:  res = type->restack;  break;
331       case E_COMP_EFFECT_KIND_ROTATION: res = type->rotation; break;
332       case E_COMP_EFFECT_KIND_FOCUSIN:  res = type->focusin;  break;
333       case E_COMP_EFFECT_KIND_FOCUSOUT: res = type->focusout; break;
334       default: res = E_COMP_EFFECT_STYLE_NONE;                break;
335      }
336    return res;
337 }
338
339 #define _MAKE_EMISSION(f, x...) do { snprintf(emission, sizeof(emission), f, ##x); } while(0)
340
341 EINTERN void
342 e_mod_comp_effect_win_restack(E_Comp_Win *cw,
343                               Eina_Bool   v1,
344                               Eina_Bool   v2)
345 {
346    Eina_Bool animatable = e_mod_comp_effect_state_get(cw->eff_type);
347    if (!((cw->c->animatable) && (animatable))) return;
348    if ((v1) == (v2)) return;
349
350    if ((!v1) && (v2))
351      _effect_show(cw);
352    else
353      _effect_hide(cw);
354 }
355
356 EINTERN void
357 e_mod_comp_effect_win_show(E_Comp_Win *cw)
358 {
359    Eina_Bool animatable = e_mod_comp_effect_state_get(cw->eff_type);
360
361    if (cw->c->fake_image_launch)
362      {
363         if ((e_mod_comp_effect_image_launch_window_check(cw->c->eff_img, cw)) &&
364             (e_mod_comp_effect_image_launch_running_check(cw->c->eff_img)))
365           {
366              if (e_mod_comp_effect_image_launch_fake_show_done_check(cw->c->eff_img))
367                {
368                   e_mod_comp_effect_image_launch_disable(cw->c->eff_img);
369                   goto postjob;
370                }
371              else
372                e_mod_comp_effect_image_launch_window_set(cw->c->eff_img, cw->win);
373              return;
374           }
375      }
376
377    if ((cw->c->animatable) && (animatable))
378      {
379         _effect_show(cw);
380      }
381
382 postjob:
383    /* for the composite window */
384    e_mod_comp_effect_signal_add(cw, NULL, "e,state,visible,on,noeffect", "e");
385
386    /* TODO: message of comp object visibility should be sent after finishing effect */
387    e_mod_comp_comp_event_src_visibility_send(cw);
388 }
389
390 EINTERN Eina_Bool
391 e_mod_comp_effect_win_hide(E_Comp_Win *cw)
392 {
393    Eina_Bool animatable, visible;
394
395    animatable = e_mod_comp_effect_state_get(cw->eff_type);
396    visible = e_mod_comp_util_win_visible_get(cw);
397
398    ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
399         "%15.15s| CHECK visible:%d cw->visible:%d a:%d", "EFFECT",
400         visible, cw->visible, animatable);
401
402    if ((cw->c->animatable) && (animatable) &&
403        (visible))
404      {
405         _effect_hide(cw);
406      }
407
408    /* for the composite window */
409    e_mod_comp_effect_signal_add(cw, NULL, "e,state,visible,off,noeffect", "e");
410
411    /* TODO: message of comp object visibility should be sent after finishing effect */
412    e_mod_comp_comp_event_src_visibility_send(cw);
413    return EINA_TRUE;
414 }
415
416 EINTERN Eina_Bool
417 e_mod_comp_effect_signal_add(E_Comp_Win  *cw,
418                              Evas_Object *o,
419                              const char  *emission,
420                              const char  *src)
421
422 {
423    Eina_List *l;
424    E_Comp *c = NULL;
425    E_Comp_Object *co;
426    E_Comp_Effect_Job *job = NULL;
427    size_t len;
428
429    E_CHECK_RETURN((cw || o), 0);
430    E_CHECK_RETURN(emission, 0);
431    E_CHECK_RETURN(src, 0);
432
433    if (cw)
434      {
435         c = cw->c;
436
437         EINA_LIST_FOREACH(cw->objs, l, co)
438           {
439              if (!co) continue;
440              if (!co->shadow) continue;
441
442              job = E_NEW(E_Comp_Effect_Job, 1);
443              if (!job) continue;
444
445              job->o = co->shadow;
446              job->win = cw->win;
447              job->cwin = e_mod_comp_util_client_xid_get(cw);
448              job->canvas = co->canvas;
449
450              len = sizeof(job->emission);
451              strncpy(job->emission, emission, len);
452              job->emission[len-1] = '\0';
453
454              len = sizeof(job->src);
455              strncpy(job->src, src, len);
456              job->src[len-1] = '\0';
457
458              effect_jobs = eina_list_append(effect_jobs, job);
459
460              e_mod_comp_hw_ov_win_msg_show
461                (E_COMP_LOG_TYPE_EFFECT,
462                "SIG_ADD 0x%x %s",
463                job->cwin, emission);
464           }
465      }
466    else
467      {
468         job = E_NEW(E_Comp_Effect_Job, 1);
469         if (job)
470           {
471              job->effect_obj = EINA_TRUE;
472              job->o = o;
473              job->win = 0;
474              job->cwin = (Ecore_X_Window)evas_object_data_get(o, "comp.effect_obj.cwin");
475
476              len = sizeof(job->emission);
477              strncpy(job->emission, emission, len);
478              job->emission[len-1] = '\0';
479
480              len = sizeof(job->src);
481              strncpy(job->src, src, len);
482              job->src[len-1] = '\0';
483
484              effect_jobs = eina_list_append(effect_jobs, job);
485           }
486      }
487
488    if (job)
489      {
490         ELBF(ELBT_COMP, 0, job->cwin,
491              "%15.15s| %s  SIG_ADD:%s", "EFFECT",
492              job->effect_obj ? "OBJ" : "   ",
493              emission);
494      }
495
496    return EINA_TRUE;
497 }
498
499 EINTERN Eina_Bool
500 e_mod_comp_effect_animating_set(E_Comp *c,
501                                 E_Comp_Win *cw,
502                                 Eina_Bool set)
503 {
504    Eina_Bool state;
505    E_CHECK_RETURN(c, 0);
506    E_CHECK_GOTO(cw, postjob);
507
508    if (set)
509      {
510         if (cw->animating)
511           {
512              c->animating--;
513              _state_send(cw, EINA_FALSE);
514           }
515         state = EINA_TRUE;
516      }
517    else
518      {
519         state = EINA_FALSE;
520      }
521
522    cw->animating = state;
523    _state_send(cw, state);
524
525 postjob:
526    if (set) c->animating++;
527    else c->animating--;
528    return EINA_TRUE;
529 }
530
531 /* local subsystem functions */
532 static E_Comp_Effect_Style
533 _effect_style_get(Ecore_X_Atom a)
534 {
535    E_CHECK_RETURN(a, E_COMP_EFFECT_STYLE_NONE);
536
537    if      (a == ATOM_EFFECT_DEFAULT) return E_COMP_EFFECT_STYLE_DEFAULT;
538    else if (a == ATOM_EFFECT_NONE   ) return E_COMP_EFFECT_STYLE_NONE;
539    else if (a == ATOM_EFFECT_CUSTOM0) return E_COMP_EFFECT_STYLE_CUSTOM0;
540    else if (a == ATOM_EFFECT_CUSTOM1) return E_COMP_EFFECT_STYLE_CUSTOM1;
541    else if (a == ATOM_EFFECT_CUSTOM2) return E_COMP_EFFECT_STYLE_CUSTOM2;
542    else if (a == ATOM_EFFECT_CUSTOM3) return E_COMP_EFFECT_STYLE_CUSTOM3;
543    else if (a == ATOM_EFFECT_CUSTOM4) return E_COMP_EFFECT_STYLE_CUSTOM4;
544    else if (a == ATOM_EFFECT_CUSTOM5) return E_COMP_EFFECT_STYLE_CUSTOM5;
545    else if (a == ATOM_EFFECT_CUSTOM6) return E_COMP_EFFECT_STYLE_CUSTOM6;
546    else if (a == ATOM_EFFECT_CUSTOM7) return E_COMP_EFFECT_STYLE_CUSTOM7;
547    else if (a == ATOM_EFFECT_CUSTOM8) return E_COMP_EFFECT_STYLE_CUSTOM8;
548    else if (a == ATOM_EFFECT_CUSTOM9) return E_COMP_EFFECT_STYLE_CUSTOM9;
549
550    return E_COMP_EFFECT_STYLE_NONE;
551 }
552
553 static Eina_Bool
554 _state_send(E_Comp_Win *cw,
555             Eina_Bool state)
556 {
557    long d[5] = {0L, 0L, 0L, 0L, 0L};
558    Ecore_X_Window win;
559    E_CHECK_RETURN(cw, 0);
560
561    win = e_mod_comp_util_client_xid_get(cw);
562    E_CHECK_RETURN(win, 0);
563
564    if (state) d[0] = 1L;
565    else d[1] = 1L;
566
567    ecore_x_client_message32_send
568      (win, ATOM_WINDOW_EFFECT_CLIENT_STATE,
569      ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
570      d[0], d[1], d[2], d[3], d[4]);
571
572    return EINA_TRUE;
573 }
574
575 static Eina_Bool
576 _effect_signal_del_intern(E_Comp_Win  *cw,
577                           Evas_Object *obj,
578                           const char  *name,
579                           Eina_Bool    clean_all)
580 {
581    E_Comp_Effect_Job *job;
582    Eina_List *l;
583    EINA_LIST_FOREACH(effect_jobs, l, job)
584      {
585         if (!job) continue;
586         if (!job->emitted) continue;
587         if (!job->win) continue;
588         if (!job->canvas) continue;
589
590         Ecore_X_Window win = cw ? cw->win : 0;
591         if (job->win == win)
592           {
593              job->canvas->animation.num--;
594
595              if (job->canvas->animation.num <= 0)
596                {
597                   job->canvas->animation.run = 0;
598                   job->canvas->animation.num = 0;
599                }
600
601              ELBF(ELBT_COMP, 0, job->cwin,
602                   "%15.15s|     SIG_DEL :%s", "EFFECT",
603                   job->emission);
604
605              e_mod_comp_hw_ov_win_msg_show
606                (E_COMP_LOG_TYPE_EFFECT,
607                "SIG_DEL 0x%x %s",
608                job->win, job->emission);
609
610              effect_jobs = eina_list_remove(effect_jobs, job);
611
612              E_FREE(job);
613
614              if (!clean_all) break;
615           }
616      }
617    return EINA_TRUE;
618 }
619
620 static Eina_Bool
621 _effect_obj_win_set(E_Comp_Effect_Object *o,
622                     E_Comp_Win           *cw)
623 {
624    E_Comp_Object *co = NULL;
625    E_Comp_Layer *ly = NULL;
626    const char *file = NULL, *group = NULL;
627    int ok = 0, pw = 0, ph = 0;
628
629    ly = evas_object_data_get(o->edje, "comp.effect_obj.ly");
630    E_CHECK_RETURN(ly, EINA_FALSE);
631    E_CHECK_RETURN(ly->canvas, EINA_FALSE);
632
633    co = eina_list_nth(cw->objs, 0);
634    E_CHECK_RETURN(co, EINA_FALSE);
635
636    edje_object_file_get(co->shadow, &file, &group);
637    E_CHECK_RETURN(file, EINA_FALSE);
638    E_CHECK_RETURN(group, EINA_FALSE);
639
640    ok = edje_object_file_set(o->edje, file, group);
641    E_CHECK_RETURN(ok, EINA_FALSE);
642
643    o->img = evas_object_image_filled_add(ly->canvas->evas);
644    E_CHECK_RETURN(o->img, EINA_FALSE);
645
646    evas_object_image_colorspace_set(o->img, EVAS_COLORSPACE_ARGB8888);
647    evas_object_image_smooth_scale_set(o->img, _comp_mod->conf->smooth_windows);
648    if (cw->argb) evas_object_image_alpha_set(o->img, 1);
649    else evas_object_image_alpha_set(o->img, 0);
650
651    /* set nocomp mode before getting named pixmap */
652    E_Comp_Win *nocomp_cw = e_mod_comp_util_win_nocomp_get(cw->c, ly->canvas->zone);
653    if (nocomp_cw == cw)
654      e_mod_comp_canvas_nocomp_end(ly->canvas);
655
656    o->pixmap = ecore_x_composite_name_window_pixmap_get(cw->win);
657    E_CHECK_GOTO(o->pixmap, fail);
658
659    ecore_x_pixmap_geometry_get(o->pixmap, NULL, NULL, &pw, &ph);
660    E_CHECK_GOTO((pw > 0), fail);
661    E_CHECK_GOTO((ph > 0), fail);
662
663    Evas_Native_Surface ns;
664    ns.version = EVAS_NATIVE_SURFACE_VERSION;
665    ns.type = EVAS_NATIVE_SURFACE_X11;
666    ns.data.x11.visual = cw->vis;
667    ns.data.x11.pixmap = o->pixmap;
668
669    evas_object_image_size_set(o->img, pw, ph);
670    evas_object_image_native_surface_set(o->img, &ns);
671    evas_object_image_data_update_add(o->img, 0, 0, pw, ph);
672
673    ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
674         "%15.15s| OBJ_NEW pix:0x%x %dx%d", "EFFECT",
675         o->pixmap, pw, ph);
676
677    edje_object_part_swallow(o->edje, "e.swallow.content", o->img);
678
679    e_layout_child_move(o->edje, cw->x, cw->y);
680    e_layout_child_resize(o->edje, pw, ph);
681
682    edje_object_signal_callback_add(o->edje, "e,action,show,done", "e", _effect_obj_effect_done, o);
683    edje_object_signal_callback_add(o->edje, "e,action,hide,done", "e", _effect_obj_effect_done, o);
684
685    o->win = cw->win;
686    o->cwin = e_mod_comp_util_client_xid_get(cw);
687
688    return EINA_TRUE;
689
690 fail:
691    if (o->img)
692      {
693         evas_object_del(o->img);
694         o->img = NULL;
695      }
696    if (o->pixmap)
697      {
698         ecore_x_pixmap_free(o->pixmap);
699         o->pixmap = 0;
700      }
701    return EINA_FALSE;
702 }
703
704 static void
705 _effect_obj_effect_done(void                 *data,
706                         Evas_Object          *obj,
707                         const char  *emission __UNUSED__,
708                         const char  *source   __UNUSED__)
709 {
710    E_Comp_Effect_Object *o = data;
711    E_Comp_Layer *ly;
712    E_CHECK(o);
713    E_CHECK(obj);
714
715    ly = evas_object_data_get(obj, "comp.effect_obj.ly");
716    E_CHECK(ly);
717
718    /* decrease effect count and hide effect layer if it is 0 */
719    e_mod_comp_layer_effect_set(ly, EINA_FALSE);
720 }
721
722 static void
723 _effect_win_set(E_Comp_Win *cw,
724                 const char *emission)
725 {
726    E_Comp_Canvas *canvas;
727    E_Comp_Layer *ly;
728    E_Comp_Effect_Object *o;
729
730    canvas = eina_list_nth(cw->c->canvases, 0);
731    ly = e_mod_comp_canvas_layer_get(canvas, "effect");
732    if (ly)
733      {
734         o = e_mod_comp_effect_object_new(ly, cw);
735         if (o)
736           {
737              evas_object_show(o->img);
738              evas_object_show(o->edje);
739              e_mod_comp_effect_signal_add(NULL, o->edje, emission, "e");
740           }
741      }
742 }
743
744 static void
745 _effect_below_wins_set(E_Comp_Win *cw)
746 {
747    E_Comp_Canvas *canvas;
748    E_Comp_Layer *ly;
749    E_Comp_Effect_Object *o;
750    Eina_Inlist *l;
751    E_Comp_Win *_cw = cw, *nocomp_cw = NULL;
752    E_Zone *zone;
753    char emission[64];
754    _MAKE_EMISSION("e,state,visible,on,noeffect");
755
756    canvas = eina_list_nth(cw->c->canvases, 0);
757    ly = e_mod_comp_canvas_layer_get(canvas, "effect");
758    E_CHECK(ly);
759
760    zone = canvas->zone;
761    E_CHECK(zone);
762
763    nocomp_cw = e_mod_comp_util_win_nocomp_get(cw->c, zone);
764
765    /* create effect objects until finding a non-alpha full-screen window */
766    while ((l = EINA_INLIST_GET(_cw)->prev))
767      {
768         _cw = _EINA_INLIST_CONTAINER(_cw, l);
769         if (!(_cw->visible)) continue;
770         if (_cw->invalid) continue;
771         if (_cw->input_only) continue;
772         if (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
773                           _cw->x, _cw->y, _cw->w, _cw->h))
774           continue;
775
776         /* if nocomp exist, change mode to the composite mode */
777         if ((nocomp_cw) && (nocomp_cw == _cw))
778           {
779              ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(_cw),
780                   "%15.15s| END EFFECT_OBJ_NEW", "NOCOMP");
781              e_mod_comp_canvas_nocomp_end(canvas);
782           }
783         else if (!((_cw->pixmap) &&
784                    (_cw->pw > 0) && (_cw->ph > 0) &&
785                    (_cw->dmg_updates >= 1)))
786           {
787              continue;
788           }
789
790         o = e_mod_comp_effect_object_new(ly, _cw);
791         if (o)
792           {
793              evas_object_show(o->img);
794              evas_object_show(o->edje);
795              e_mod_comp_effect_signal_add(NULL, o->edje, emission, "e");
796
797              /* change the stack position of the object to the bottom
798               * of layer and also background object too
799               */
800              e_layout_child_lower(o->edje);
801              e_mod_comp_layer_bg_adjust(ly);
802           }
803
804         /* found a non-alpha full-screen window */
805         if ((REGION_EQUAL_TO_ZONE(_cw, zone)) && !(_cw->argb))
806           break;
807      }
808 }
809
810 static void
811 _effect_above_wins_set(E_Comp_Win *cw,
812                        Eina_Bool   show)
813 {
814    E_Comp_Canvas *canvas;
815    E_Comp_Layer *ly;
816    E_Comp_Effect_Object *o;
817    Eina_Inlist *l;
818    E_Comp_Win *_cw = cw;
819    E_Zone *zone;
820    char emission[64];
821
822    canvas = eina_list_nth(cw->c->canvases, 0);
823    ly = e_mod_comp_canvas_layer_get(canvas, "effect");
824    E_CHECK(ly);
825
826    zone = canvas->zone;
827    E_CHECK(zone);
828
829    while ((l = EINA_INLIST_GET(_cw)->next))
830      {
831         _cw = _EINA_INLIST_CONTAINER(_cw, l);
832         if (!(_cw->visible)) continue;
833         if (_cw->invalid) continue;
834         if (_cw->input_only) continue;
835         if (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h,
836                           _cw->x, _cw->y, _cw->w, _cw->h))
837           continue;
838         if (!((_cw->pixmap) &&
839               (_cw->pw > 0) && (_cw->ph > 0) &&
840               (_cw->dmg_updates >= 1)))
841           continue;
842
843         _MAKE_EMISSION("e,state,visible,on,noeffect");
844
845         if ((TYPE_KEYBOARD_CHECK(_cw)) && (!show))
846           {
847              if (cw->c->keyboard_effect)
848                {
849                   if (e_mod_comp_effect_win_angle_get(_cw))
850                     _MAKE_EMISSION("e,state,visible,off,angle,%d", _cw->angle);
851                   else
852                     _MAKE_EMISSION("e,state,visible,off,angle,0");
853                }
854              else
855                continue;
856           }
857
858         o = e_mod_comp_effect_object_new(ly, _cw);
859         if (o)
860           {
861              evas_object_show(o->img);
862              evas_object_show(o->edje);
863              e_mod_comp_effect_signal_add(NULL, o->edje, emission, "e");
864           }
865      }
866 }
867
868 static Eina_Bool
869 _effect_obj_find(E_Comp_Win *cw)
870 {
871    E_Comp_Canvas *canvas = eina_list_nth(cw->c->canvases, 0);
872    E_CHECK_RETURN(canvas, EINA_FALSE);
873
874    E_Comp_Layer *ly = e_mod_comp_canvas_layer_get(canvas, "effect");
875    E_CHECK_RETURN(ly, EINA_FALSE);
876
877    Eina_List *l;
878    E_Comp_Effect_Object *o = NULL;
879    EINA_LIST_FOREACH(ly->objs, l, o)
880      {
881         if (!o) continue;
882         if (o->win == cw->win)
883           {
884              ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
885                   "%15.15s| OBJ already exists!", "EFFECT");
886              return EINA_TRUE;
887           }
888      }
889
890    return EINA_FALSE;
891 }
892
893 static void
894 _effect_show(E_Comp_Win *cw)
895 {
896    E_Comp_Effect_Style st;
897    char emission[64];
898    E_Comp_Win *cw2 = NULL;
899    Eina_Bool launch, visible;
900
901    Eina_Bool res = _effect_obj_find(cw);
902    E_CHECK(!res);
903
904    /* check effect condition and make emission string */
905    st = e_mod_comp_effect_style_get(cw->eff_type, E_COMP_EFFECT_KIND_SHOW);
906    visible = e_mod_comp_util_win_visible_get(cw);
907
908    ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
909         "%15.15s|SHOW", "EFFECT");
910
911    if (E_COMP_EFFECT_STYLE_DEFAULT == st)
912      {
913         launch = e_mod_comp_policy_app_launch_check(cw);
914         if ((launch) && (visible))
915           {
916              _effect_below_wins_set(cw);
917
918              ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
919                   "%15.15s|>FG", "EFFECT");
920
921              _MAKE_EMISSION("e,state,visible,on");
922              _effect_win_set(cw, emission);
923              _effect_above_wins_set(cw, EINA_TRUE);
924           }
925         else if ((TYPE_KEYBOARD_CHECK(cw)) && (visible))
926           {
927              if (cw->c->keyboard_effect)
928                {
929                   _effect_below_wins_set(cw);
930
931                   if (e_mod_comp_effect_win_angle_get(cw))
932                     _MAKE_EMISSION("e,state,window,angle,%d", cw->angle);
933                   else
934                     _MAKE_EMISSION("e,state,window,angle,0");
935
936                   _effect_win_set(cw, emission);
937                   _effect_above_wins_set(cw, EINA_TRUE);
938                }
939           }
940         /* in most cases, border show events of home window are generated
941          * by pressing the h/w home button. at that moment, home window
942          * is invisible thus the wm doesn't need to check visibility for
943          * home window. just make app closing effect except lock and
944          * setup wizard window.
945          */
946         else if (TYPE_HOME_CHECK(cw))
947           {
948              /* app window hide effect by pressing the h/w home button */
949              cw2 = e_mod_comp_util_win_normal_get(NULL);
950              if (cw2)
951                {
952                   /* do nothing, if cw2 is such exceptional windows as lock
953                    * and setup wizard window. this case usually happens when
954                    * system is booting. (first show of the home window)
955                    */
956                   res = e_mod_comp_policy_home_app_win_check(cw2);
957
958                   ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
959                        "%15.15s|>BG HOME 0x%08x FG 0x%08x SKIP:%d", "EFFECT",
960                        e_mod_comp_util_client_xid_get(cw),
961                        e_mod_comp_util_client_xid_get(cw2),
962                        !(res));
963
964                   E_CHECK(res);
965
966                   /* background is home */
967                   _MAKE_EMISSION("e,state,visible,on,noeffect");
968                   _effect_win_set(cw, emission);
969
970                   /* app window will hide */
971                   _MAKE_EMISSION("e,state,visible,off");
972                   _effect_win_set(cw2, emission);
973                   _effect_above_wins_set(cw2, EINA_FALSE);
974                }
975           }
976      }
977 }
978
979 static void
980 _effect_hide(E_Comp_Win *cw)
981 {
982    E_Comp_Effect_Style st;
983    char emission[64];
984    E_Comp_Win *cw2 = NULL;
985    Eina_Bool close;
986
987    Eina_Bool res = _effect_obj_find(cw);
988    E_CHECK(!res);
989
990    /* check effect condition and make emission string */
991    st = e_mod_comp_effect_style_get(cw->eff_type, E_COMP_EFFECT_KIND_HIDE);
992
993    ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
994         "%15.15s|HIDE", "EFFECT");
995
996    if (E_COMP_EFFECT_STYLE_DEFAULT == st)
997      {
998         close = e_mod_comp_policy_app_close_check(cw);
999         if (close)
1000           {
1001              /* background window */
1002              cw2 = e_mod_comp_util_win_normal_get(cw);
1003              if (cw2)
1004                {
1005                   ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
1006                        "%15.15s|>BG 0x%08x", "EFFECT",
1007                        e_mod_comp_util_client_xid_get(cw2));
1008
1009                   _MAKE_EMISSION("e,state,visible,on,noeffect");
1010                   _effect_win_set(cw2, emission);
1011                }
1012
1013              ELBF(ELBT_COMP, 0, e_mod_comp_util_client_xid_get(cw),
1014                   "%15.15s|>FG", "EFFECT");
1015
1016              _MAKE_EMISSION("e,state,visible,off");
1017              _effect_win_set(cw, emission);
1018              _effect_above_wins_set(cw, EINA_FALSE);
1019           }
1020         else if (TYPE_KEYBOARD_CHECK(cw))
1021           {
1022              if (cw->c->keyboard_effect)
1023                {
1024                   _effect_below_wins_set(cw);
1025
1026                   if (e_mod_comp_effect_win_angle_get(cw))
1027                     _MAKE_EMISSION("e,state,visible,off,angle,%d", cw->angle);
1028                   else
1029                     _MAKE_EMISSION("e,state,visible,off,angle,0");
1030
1031                   _effect_win_set(cw, emission);
1032                   _effect_above_wins_set(cw, EINA_FALSE);
1033                }
1034           }
1035      }
1036 }