e_comp: make an internal header
[platform/upstream/enlightenment.git] / src / bin / e_comp_object.c
1 #include "e.h"
2 #ifdef REFACTOR_DESK_AREA
3 #include "e_comp_object_intern.h"
4 #endif
5 #include "e_bindings_intern.h"
6 #include "e_utils_intern.h"
7 #ifdef REFACTOR_DESK_AREA
8 #else
9 #include "e_comp_canvas_intern.h"
10 #endif
11
12 #include "e_comp_cfdata_intern.h"
13 #include "e_comp_wl_subsurface_intern.h"
14 #include "e_comp_wl_tbm_intern.h"
15 #include "e_comp_intern.h"
16
17 /* data keys:
18
19    = keys that return objects =
20    - E_Client: the client associated with the object (E_Client*)
21    - comp_smart_obj: cw->smart_obj (Evas_Object*)
22    - comp_obj: cw (E_Comp_Object*)
23
24    = keys that are bool flags =
25    - client_restack: client needs a protocol-level restack
26    - comp_override: object is triggering a nocomp override to force compositing
27    - comp_ref: object has a ref from visibility animations
28    - comp_showing: object is currently running its show animation
29    - comp_hiding: object is currently running its hiding animation
30    - comp_object: object is a compositor-created object
31    - comp_object_skip: object has a name which prohibits theme shadows
32    - comp_object-to_del: list of objects which will be deleted when this object is deleted
33    - comp_mirror: object is the result of e_comp_object_util_mirror_add()
34    - effect_running: object is animating by external module
35 */
36
37 #define UPDATE_MAX 512 // same as evas
38 #define FAILURE_MAX 2 // seems reasonable
39 #define SMART_NAME     "e_comp_object"
40 #define INPUT_OBJ_SMART_NAME "input_object"
41
42 /* for non-util functions */
43 #define API_ENTRY      E_Comp_Object *cw; \
44                        cw = evas_object_smart_data_get(obj); \
45                        if ((!obj) || (!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) return
46
47 /* for util functions (obj may or may not be E_Comp_Object */
48 #define SOFT_ENTRY(...)      E_Comp_Object *cw; \
49                        if (!obj) \
50                          { \
51                             CRI("YOU PASSED NULL! ARGH!"); \
52                             return __VA_ARGS__; \
53                          } \
54                        cw = evas_object_smart_data_get(obj); \
55                        if ((!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) \
56                          cw = NULL
57 #define INTERNAL_ENTRY E_Comp_Object *cw; cw = evas_object_smart_data_get(obj); if (!cw) return;
58
59 /* enable for lots of client size info in console output */
60 #if 1
61 # define e_util_size_debug_set(x, y)
62 #endif
63
64 /* enable along with display-specific damage INF calls to enable render tracing
65  * SLOW!
66  */
67 #if 0
68 #define RENDER_DEBUG(...) INF(__VA_ARGS__)
69 #else
70 #define RENDER_DEBUG(...)
71 #endif
72
73 #ifdef REFACTOR_DESK_AREA
74 #else
75 typedef struct _E_Comp_Object
76 {
77    EINA_INLIST;
78
79    int                  x, y, w, h;  // geometry
80
81    E_Client *ec;
82
83    E_Comp_Object_Frame client_inset;
84
85    Eina_Stringshare   *frame_theme;
86    Eina_Stringshare   *frame_name;
87    Eina_Stringshare   *visibility_effect; //effect when toggling visibility
88
89    E_Comp_Object_Content_Type content_type; // type of e.swallow.content
90
91    Evas_Object         *smart_obj;  // smart object
92    Evas_Object         *clip; // clipper over effect object
93    Evas_Object         *input_obj; // input smart object
94    Evas_Object         *obj;  // composite object
95    Evas_Object         *frame_object; // for client frames
96    Evas_Object         *shobj;  // shadow object
97    Evas_Object         *effect_obj; // effects object
98    Evas_Object         *transform_bg_obj;   // transform backgroung with keep_ratio option
99    struct
100      {
101         int r, g, b, a;
102      } transform_bg_color;
103    Evas_Object         *transform_tranp_obj;// transform transp rect obj
104    Evas_Object         *default_input_obj; // default input object
105    unsigned int         layer; //e_comp_canvas_layer_map(cw->ec->layer)
106    Eina_List           *obj_mirror;  // extra mirror objects
107    Eina_Tiler          *updates; //render update regions
108    Eina_Tiler          *pending_updates; //render update regions which are about to render
109
110    Evas_Native_Surface *ns; //for custom gl rendering
111
112    struct wl_listener   buffer_destroy_listener;
113
114    unsigned int         update_count;  // how many updates have happened to this obj
115
116    unsigned int         opacity;  // opacity set with _NET_WM_WINDOW_OPACITY
117
118    unsigned int         animating;  // it's busy animating
119    unsigned int         failures; //number of consecutive e_pixmap_image_draw() failures
120    unsigned int         force_visible; //number of visible obj_mirror objects
121    Eina_Bool            delete_pending : 1;  // delete pending
122    Eina_Bool            defer_hide : 1;  // flag to get hide to work on deferred hide
123    Eina_Bool            showing : 1;  // object is currently in "show" animation
124    Eina_Bool            hiding : 1;   // object is currently in "hide" animation
125    Eina_Bool            visible : 1;  // is visible
126
127    Eina_Bool            shaped : 1;  // is shaped
128    Eina_Bool            update : 1;  // has updates to fetch
129    Eina_Bool            redirected : 1;  // has updates to fetch
130    Eina_Bool            native : 1;  // native
131
132    Eina_Bool            nocomp : 1;  // nocomp applied
133    Eina_Bool            hwc_need_update : 1;  // this window updated while on e_plane to do hw composite
134    Eina_Bool            real_hid : 1;  // last hide was a real window unmap
135
136    Eina_Bool            effect_set : 1; //effect_obj has a valid group
137    Eina_Bool            effect_running : 1; //effect_obj is playing an animation
138    Eina_Bool            effect_clip : 1; //effect_obj is clipped
139    Eina_Bool            effect_clip_able : 1; //effect_obj will be clipped for effects
140
141    Eina_Bool            updates_exist : 1;
142    Eina_Bool            updates_full : 1; // entire object will be updated
143
144    Eina_Bool            force_move : 1;
145    Eina_Bool            frame_extends : 1; //frame may extend beyond object size
146    Eina_Bool            blanked : 1; //window is rendering blank content (externally composited)
147    Eina_Bool            external_content : 1; // e.swallow.content(obj) is set by external evas object
148    Eina_Bool            user_alpha_set : 1;
149    Eina_Bool            user_alpha : 1;
150
151    struct
152      {
153         Evas_Object         *obj; // mask object: transparent parts of this comp object allow to copy the alpha to current H/W plane.
154         Evas_Render_Op       saved_render_op; // saved render operation value to restore when clear a mask.
155      } mask;
156
157    struct
158      {
159         Evas_Object         *obj;
160         int                  w, h;
161      } indicator; //indicator object for internal client
162
163    struct
164      {
165         Evas_Object         *mask_obj;
166         Eina_Bool           enable;
167         Eina_Bool           mask_set;
168         int                 mask_x, mask_y, mask_w, mask_h;
169      } dim;
170
171    Eina_Bool            render_trace : 1; // trace co->obj rendering on canvas
172
173    tbm_surface_h        tbm_surface;
174    E_Comp_Image_Filter  image_filter;
175    Eina_Bool            set_mouse_callbacks;
176
177    struct
178      {
179         int lock;
180         E_Comp_Wl_Buffer_Ref buffer_ref;
181         Eina_Bool            pending_move_set;
182         int                  pending_move_x, pending_move_y;
183         Eina_Bool            pending_resize_set;
184         int                  pending_resize_w, pending_resize_h;
185      } render_update_lock;
186
187    struct
188      {
189         Eina_Bool        set;
190         int              user_r;
191         int              user_g;
192         int              user_b;
193         int              user_a;
194      } transparent;
195
196    struct
197      {
198         struct wl_signal lower;
199 //#ifdef REFACTOR_DESK_AREA
200         struct wl_signal raise;
201 //#endif
202         struct wl_signal show;
203         struct wl_signal hide;
204 //#ifdef REFACTOR_DESK_AREA
205         struct wl_signal set_layer;
206         struct wl_signal stack_above;
207         struct wl_signal stack_below;
208 //#endif
209      } events;
210 } E_Comp_Object;
211 #endif
212
213 typedef struct _E_Input_Rect_Data
214 {
215    Eina_Rectangle rect;
216    Evas_Object *obj;
217 } E_Input_Rect_Data;
218
219 typedef struct _E_Input_Rect_Smart_Data
220 {
221    Eina_List *input_rect_data_list;
222    E_Comp_Object *cw;
223 } E_Input_Rect_Smart_Data;
224
225 struct E_Comp_Object_Mover
226 {
227    EINA_INLIST;
228    E_Comp_Object_Mover_Cb func;
229    const char *sig;
230    void *data;
231    int pri;
232 };
233
234 static Eina_Inlist *_e_comp_object_movers = NULL;
235 static Evas_Smart *_e_comp_smart = NULL;
236 static Evas_Smart *_e_comp_input_obj_smart = NULL;
237
238 static int _e_comp_object_hooks_delete = 0;
239 static int _e_comp_object_hooks_walking = 0;
240
241 static Eina_Inlist *_e_comp_object_hooks[] =
242 {
243    [E_COMP_OBJECT_HOOK_EFFECT_START] = NULL,
244    [E_COMP_OBJECT_HOOK_EFFECT_END] = NULL,
245    [E_COMP_OBJECT_HOOK_RESTACK] = NULL,
246    [E_COMP_OBJECT_HOOK_OBJECT_SETUP] = NULL,
247    [E_COMP_OBJECT_HOOK_LAYER_SET] = NULL,
248    [E_COMP_OBJECT_HOOK_MASK_OBJECT_SET] = NULL,
249    [E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET] = NULL,
250    [E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET] = NULL,
251 };
252
253 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
254 static int _e_comp_object_intercept_hooks_delete = 0;
255 static int _e_comp_object_intercept_hooks_walking = 0;
256
257 static Eina_Inlist *_e_comp_object_intercept_hooks[] =
258 {
259    [E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER] = NULL,
260    [E_COMP_OBJECT_INTERCEPT_HOOK_HIDE] = NULL,
261 };
262 #endif
263
264 static Eina_Bool _damage_trace = EINA_FALSE;
265 static Eina_List *_damage_trace_objs = NULL;
266 static Eina_List *_damage_trace_post_objs = NULL;
267
268 /* sekrit functionzzz */
269 EINTERN void e_client_focused_set(E_Client *ec);
270
271 /* emitted every time a new noteworthy comp object is added */
272 EINTERN int E_EVENT_COMP_OBJECT_ADD = -1;
273
274 /* ecore event define */
275 EINTERN int E_EVENT_COMP_OBJECT_IMG_RENDER = -1;
276 EINTERN int E_EVENT_COMP_OBJECT_EFFECT_START = -1;
277 EINTERN int E_EVENT_COMP_OBJECT_EFFECT_END = -1;
278
279 static void           _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect);
280 static Eina_Bool      _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj);
281 static void           _e_comp_object_dim_update(E_Comp_Object *cw);
282 static void           _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror);
283 #ifdef REFACTOR_DESK_AREA
284 #else
285 static void           _e_comp_object_layer_set(Evas_Object *obj, short layer);
286 #endif
287
288 static E_Client       *dim_client = NULL;
289
290 static void
291 _e_comp_object_hooks_clean(void)
292 {
293    Eina_Inlist *l;
294    E_Comp_Object_Hook *ch;
295    unsigned int x;
296
297    for (x = 0; x < E_COMP_OBJECT_HOOK_LAST; x++)
298      EINA_INLIST_FOREACH_SAFE(_e_comp_object_hooks[x], l, ch)
299        {
300           if (!ch->delete_me) continue;
301           _e_comp_object_hooks[x] = eina_inlist_remove(_e_comp_object_hooks[x], EINA_INLIST_GET(ch));
302           free(ch);
303        }
304 }
305
306 static Eina_Bool
307 _e_comp_object_hook_call(E_Comp_Object_Hook_Point hookpoint, E_Client *ec)
308 {
309    E_Comp_Object_Hook *ch;
310    Eina_Bool ret = EINA_TRUE;
311
312    if (e_object_is_del(E_OBJECT(ec)))
313      {
314         if ((hookpoint != E_COMP_OBJECT_HOOK_EFFECT_START) &&
315             (hookpoint != E_COMP_OBJECT_HOOK_EFFECT_END) &&
316             (hookpoint != E_COMP_OBJECT_HOOK_OBJECT_SETUP) &&
317             (hookpoint != E_COMP_OBJECT_HOOK_LAYER_SET) &&
318             (hookpoint != E_COMP_OBJECT_HOOK_RESTACK) &&
319             (hookpoint != E_COMP_OBJECT_HOOK_MASK_OBJECT_SET) &&
320             (hookpoint != E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET) &&
321             (hookpoint != E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET)
322             )
323           {
324              return ret;
325           }
326      }
327    e_object_ref(E_OBJECT(ec));
328    _e_comp_object_hooks_walking++;
329    EINA_INLIST_FOREACH(_e_comp_object_hooks[hookpoint], ch)
330      {
331         if (ch->delete_me) continue;
332         if (!(ch->func(ch->data, ec)))
333           {
334              ret = EINA_FALSE;
335              break;
336           }
337      }
338    _e_comp_object_hooks_walking--;
339    if ((_e_comp_object_hooks_walking == 0) && (_e_comp_object_hooks_delete > 0))
340      _e_comp_object_hooks_clean();
341
342    e_object_unref(E_OBJECT(ec));
343
344    return ret;
345 }
346
347 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
348 static void
349 _e_comp_object_intercept_hooks_clean(void)
350 {
351    Eina_Inlist *l;
352    E_Comp_Object_Intercept_Hook *ch;
353    unsigned int x;
354
355    for (x = 0; x < E_COMP_OBJECT_INTERCEPT_HOOK_LAST; x++)
356      EINA_INLIST_FOREACH_SAFE(_e_comp_object_intercept_hooks[x], l, ch)
357        {
358           if (!ch->delete_me) continue;
359           _e_comp_object_intercept_hooks[x] = eina_inlist_remove(_e_comp_object_intercept_hooks[x], EINA_INLIST_GET(ch));
360           free(ch);
361        }
362 }
363
364 static Eina_Bool
365 _e_comp_object_intercept_hook_call(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Client *ec)
366 {
367    E_Comp_Object_Intercept_Hook *ch;
368    Eina_Bool ret = EINA_TRUE;
369
370    if (e_object_is_del(E_OBJECT(ec))) return ret;
371    e_object_ref(E_OBJECT(ec));
372    _e_comp_object_intercept_hooks_walking++;
373    EINA_INLIST_FOREACH(_e_comp_object_intercept_hooks[hookpoint], ch)
374      {
375         if (ch->delete_me) continue;
376         if (!(ch->func(ch->data, ec)))
377           {
378              ret = EINA_FALSE;
379              break;
380           }
381      }
382    _e_comp_object_intercept_hooks_walking--;
383    if ((_e_comp_object_intercept_hooks_walking == 0) && (_e_comp_object_intercept_hooks_delete > 0))
384      _e_comp_object_intercept_hooks_clean();
385
386    e_object_unref(E_OBJECT(ec));
387
388    return ret;
389 }
390 #endif
391
392 static void
393 _e_comp_object_event_free(void *d EINA_UNUSED, void *event)
394 {
395    E_Event_Comp_Object *ev = event;
396    E_Client *ec;
397
398    ec = evas_object_data_get(ev->comp_object, "E_Client");
399    if (ec)
400      {
401         UNREFD(ec, 1);
402         e_object_unref(E_OBJECT(ec));
403      }
404    evas_object_unref(ev->comp_object);
405    free(ev);
406 }
407
408 static void
409 _e_comp_object_event_add(Evas_Object *obj)
410 {
411    E_Event_Comp_Object *ev;
412    E_Client *ec;
413
414    if (stopping) return;
415    ev = E_NEW(E_Event_Comp_Object, 1);
416    EINA_SAFETY_ON_NULL_RETURN(ev);
417
418    evas_object_ref(obj);
419    ev->comp_object = obj;
420    ec = evas_object_data_get(ev->comp_object, "E_Client");
421    if (ec)
422      {
423         REFD(ec, 1);
424         e_object_ref(E_OBJECT(ec));
425      }
426    ecore_event_add(E_EVENT_COMP_OBJECT_ADD, ev, _e_comp_object_event_free, NULL);
427 }
428
429 static void
430 _e_comp_object_simple_free(void *d EINA_UNUSED, void *event)
431 {
432    E_Event_Comp_Object *ev = event;
433    E_Client *ec;
434
435    ec = evas_object_data_get(ev->comp_object, "E_Client");
436    if (ec)
437      {
438         UNREFD(ec, 1);
439         e_object_unref(E_OBJECT(ec));
440      }
441    evas_object_unref(ev->comp_object);
442    free(ev);
443 }
444
445 static void
446 _e_comp_object_event_simple(Evas_Object *obj, int type)
447 {
448    E_Event_Comp_Object *ev;
449    E_Client *ec;
450
451    ev = E_NEW(E_Event_Comp_Object, 1);
452    if (!ev) return;
453
454    evas_object_ref(obj);
455    ev->comp_object = obj;
456    ec = evas_object_data_get(ev->comp_object, "E_Client");
457    if (ec)
458      {
459         REFD(ec, 1);
460         e_object_ref(E_OBJECT(ec));
461      }
462    ecore_event_add(type, ev, (Ecore_End_Cb)_e_comp_object_simple_free, NULL);
463 }
464 /////////////////////////////////////
465
466 static void
467 _e_comp_object_cb_mirror_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
468 {
469    E_Comp_Object *cw = data;
470
471    cw->obj_mirror = eina_list_remove(cw->obj_mirror, obj);
472 }
473
474 static void
475 _e_comp_object_cb_mirror_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
476 {
477    E_Comp_Object *cw = data;
478
479    if ((!cw->force_visible) && (!e_object_is_del(E_OBJECT(cw->ec))))
480      evas_object_smart_callback_call(cw->smart_obj, "visibility_force", cw->ec);
481    cw->force_visible++;
482
483    if (e_comp->hwc && !e_comp_is_on_overlay(cw->ec))
484      e_comp_hwc_client_end(cw->ec, __FUNCTION__);
485 }
486
487 static void
488 _e_comp_object_cb_mirror_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
489 {
490    E_Comp_Object *cw = data;
491
492    cw->force_visible--;
493    if ((!cw->force_visible) && (!e_object_is_del(E_OBJECT(cw->ec))))
494      evas_object_smart_callback_call(cw->smart_obj, "visibility_normal", cw->ec);
495 }
496
497 /////////////////////////////////////
498
499 #ifdef REFACTOR_DESK_AREA
500 EINTERN void
501 _e_comp_object_transform_obj_stack_update(Evas_Object *obj)
502 #else
503 static void
504 _e_comp_object_transform_obj_stack_update(Evas_Object *obj)
505 #endif
506 {
507    int layer = 0;
508    API_ENTRY;
509    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
510    if (cw->ec->input_only) return;
511
512    layer = evas_object_layer_get(obj);
513
514    if (cw->transform_bg_obj)
515      {
516         if (layer != evas_object_layer_get(cw->transform_bg_obj))
517           {
518              evas_object_layer_set(cw->transform_bg_obj, layer);
519           }
520
521         evas_object_stack_below(cw->transform_bg_obj, obj);
522      }
523
524    if (cw->transform_tranp_obj)
525      {
526         if (layer != evas_object_layer_get(cw->transform_tranp_obj))
527           {
528              evas_object_layer_set(cw->transform_tranp_obj, layer);
529           }
530
531         evas_object_stack_below(cw->transform_tranp_obj, obj);
532      }
533 }
534
535 static E_Map *
536 _e_comp_object_transform_obj_map_new(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
537 {
538    E_Map *map;
539    int i;
540    int x, y;
541
542    map = e_map_new();
543    if (!map) return NULL;
544
545    e_map_util_points_populate_from_object_full(map, obj, 0);
546    e_map_util_points_color_set(map, 255, 255, 255, 255);
547
548    for (i = 0 ; i < 4 ; ++i)
549      {
550         x = 0;
551         y = 0;
552
553         e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
554         e_map_point_coord_set(map, i, x, y, 1.0);
555      }
556
557    return map;
558 }
559
560 static void
561 _e_comp_object_transform_obj_map_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
562 {
563    if (!obj) return;
564
565    if (vertices)
566      {
567         E_Map *map = _e_comp_object_transform_obj_map_new(obj, vertices);
568         if (map)
569           {
570              e_comp_object_map_set(obj, map);
571              e_comp_object_map_enable_set(obj, EINA_TRUE);
572
573              e_map_free(map);
574           }
575      }
576    else
577      {
578         evas_object_map_enable_set(obj, EINA_FALSE);
579      }
580 }
581
582 static void
583 _e_comp_object_transform_obj_map_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
584 {
585    if (!obj) return;
586
587    if (vertices)
588      {
589         E_Map *map = _e_comp_object_transform_obj_map_new(obj, vertices);
590         if (map)
591           {
592              e_map_util_zoom(map, zoom.zoom_x, zoom.zoom_y, zoom.cx, zoom.cy);
593
594              e_comp_object_map_set(obj, map);
595              e_comp_object_map_enable_set(obj, EINA_TRUE);
596
597              e_map_free(map);
598           }
599      }
600    else
601      {
602         evas_object_map_enable_set(obj, EINA_FALSE);
603      }
604 }
605 /////////////////////////////////////
606
607 static inline Eina_Bool
608 _e_comp_shaped_check(int w, int h, const Eina_Rectangle *rects, int num)
609 {
610    if (num > 1) return EINA_TRUE;
611    if ((rects[0].x == 0) && (rects[0].y == 0) &&
612        ((int)rects[0].w == w) && ((int)rects[0].h == h))
613      return EINA_FALSE;
614    return EINA_TRUE;
615 }
616
617 /////////////////////////////////////
618
619 /* add a client to the layer-client list */
620 #ifdef REFACTOR_DESK_AREA
621 #else
622 static void
623 _e_comp_object_layers_add(E_Comp_Object *cw, E_Comp_Object *above, E_Comp_Object *below, Eina_Bool prepend)
624 {
625    g_rec_mutex_lock(&e_comp->ec_list_mutex);
626
627    if (above)
628     e_comp->layers[above->layer].clients = eina_inlist_append_relative(e_comp->layers[above->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(above->ec));
629    else if (below)
630      e_comp->layers[below->layer].clients = eina_inlist_prepend_relative(e_comp->layers[below->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(below->ec));
631    if ((!above) && (!below))
632      {
633         if (prepend)
634           e_comp->layers[cw->layer].clients = eina_inlist_prepend(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
635         else //this is either the layer object or a tough actin tinactin^W^W^Wfast stacking client
636           e_comp->layers[cw->layer].clients = eina_inlist_append(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
637      }
638    e_comp->layers[cw->layer].clients_count++;
639
640    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
641 }
642
643 static void
644 _e_comp_object_layers_remove(E_Comp_Object *cw)
645 {
646    g_rec_mutex_lock(&e_comp->ec_list_mutex);
647
648    if (cw->ec && e_comp->layers[cw->layer].clients)
649      {
650         e_comp->layers[cw->layer].clients = eina_inlist_remove(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
651         e_comp->layers[cw->layer].clients_count--;
652      }
653
654    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
655 }
656 #endif
657
658 /////////////////////////////////////
659 static void
660 _e_comp_object_alpha_set(E_Comp_Object *cw)
661 {
662    Eina_Bool alpha = cw->ec->argb;
663
664    if ((cw->external_content) &&
665        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
666      {
667         return;
668      }
669
670    if (cw->blanked || cw->ns || cw->ec->shaped) alpha = EINA_TRUE;
671    if (cw->user_alpha_set) alpha = cw->user_alpha;
672
673    evas_object_image_alpha_set(cw->obj, alpha);
674 }
675
676 static void
677 _e_comp_object_shadow(E_Comp_Object *cw)
678 {
679    if (e_client_util_shadow_state_get(cw->ec))
680      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,on", "e");
681    else
682      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,off", "e");
683    if (cw->frame_object)
684      edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
685    evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
686 }
687
688 /* convert from the surface coordinates to the buffer coordinates */
689 static void
690 _e_comp_object_map_transform_pos(E_Client *ec, int sx, int sy, int *dx, int *dy)
691 {
692    E_Comp_Wl_Buffer_Viewport *vp;
693    E_Comp_Wl_Client_Data *cdata;
694    int transform;
695    int bw, bh, tx, ty;
696
697   cdata = e_client_cdata_get(ec);
698
699    if (!ec || !cdata || e_object_is_del(E_OBJECT(ec)))
700      {
701         *dx = sx;
702         *dy = sy;
703         return;
704      }
705
706    vp = &cdata->scaler.buffer_viewport;
707    transform = e_comp_wl_output_buffer_transform_get(ec);
708
709    e_pixmap_size_get(ec->pixmap, &bw, &bh);
710
711    /* for subsurface, it should be swap 90 and 270 */
712    if (e_comp_wl_subsurface_check(ec))
713      switch (transform)
714        {
715         case WL_OUTPUT_TRANSFORM_90:          transform = WL_OUTPUT_TRANSFORM_270;         break;
716         case WL_OUTPUT_TRANSFORM_270:         transform = WL_OUTPUT_TRANSFORM_90;          break;
717         case WL_OUTPUT_TRANSFORM_FLIPPED_90:  transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; break;
718         case WL_OUTPUT_TRANSFORM_FLIPPED_270: transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;  break;
719         default: break;
720        }
721
722    switch (transform)
723      {
724       case WL_OUTPUT_TRANSFORM_NORMAL:
725       default:                              tx = sx,      ty = sy;      break;
726       case WL_OUTPUT_TRANSFORM_90:          tx = sy,      ty = bw - sx; break;
727       case WL_OUTPUT_TRANSFORM_180:         tx = bw - sx, ty = bh - sy; break;
728       case WL_OUTPUT_TRANSFORM_270:         tx = bh - sy, ty = sx;      break;
729       case WL_OUTPUT_TRANSFORM_FLIPPED:     tx = bw - sx, ty = sy;      break;
730       case WL_OUTPUT_TRANSFORM_FLIPPED_90:  tx = sy,      ty = sx;      break;
731       case WL_OUTPUT_TRANSFORM_FLIPPED_180: tx = sx,      ty = bh - sy; break;
732       case WL_OUTPUT_TRANSFORM_FLIPPED_270: tx = bh - sy, ty = bw - sx; break;
733      }
734
735    tx *= vp->buffer.scale;
736    ty *= vp->buffer.scale;
737
738    *dx = tx;
739    *dy = ty;
740 }
741
742 static void
743 _e_comp_object_map_transform_rect(E_Client *ec, int sx, int sy, int sw, int sh, int *dx, int *dy, int *dw, int *dh)
744 {
745    int x1 = sx;
746    int y1 = sy;
747    int x2 = sx + sw;
748    int y2 = sy + sh;
749    int mx, my;
750
751    _e_comp_object_map_transform_pos(ec, x1, y1, &x1, &y1);
752    _e_comp_object_map_transform_pos(ec, x2, y2, &x2, &y2);
753
754    mx = MIN(x1, x2);
755    my = MIN(y1, y2);
756
757    if (dx) *dx = mx;
758    if (dy) *dy = my;
759    if (dw) *dw = MAX(x1, x2) - mx;
760    if (dh) *dh = MAX(y1, y2) - my;
761 }
762
763 static void
764 _e_comp_object_map_damage_transform_rect(E_Client *ec, E_Map *m, int sx, int sy, int sw, int sh,
765                                          int *dx, int *dy, int *dw, int *dh)
766 {
767    E_Util_Transform_Rect rect = {sx, sy, sw, sh};
768    E_Util_Transform_Rect_Vertex sv, dv;
769    int bw, bh;
770    int i;
771
772    e_pixmap_size_get(ec->pixmap, &bw, &bh);
773
774    sv = e_util_transform_rect_to_vertices(&rect);
775
776    for (i = 0; i < 4; i++)
777      {
778         double x = 0.0, y = 0.0;
779
780         e_map_coords_get(m, sv.vertices[i].vertex[0], sv.vertices[i].vertex[1], &x, &y, 0);
781
782         /* if evas decide coordinate is outside of map, it returns (0, 0)
783            in this case, full damage is added.
784          */
785         if ((i != 0) && (x == 0.0) && (y == 0.0))
786           goto full;
787
788         dv.vertices[i].vertex[0] = x;
789         dv.vertices[i].vertex[1] = y;
790         dv.vertices[i].vertex[2] = 1.0;
791         dv.vertices[i].vertex[3] = 1.0;
792      }
793
794    rect = e_util_transform_vertices_to_rect(&dv);
795
796    if (dx) *dx = rect.x;
797    if (dy) *dy = rect.y;
798    if (dw) *dw = rect.w;
799    if (dh) *dh = rect.h;
800
801    return;
802
803 full:
804    if (dx) *dx = 0;
805    if (dy) *dy = 0;
806    if (dw) *dw = bw;
807    if (dh) *dh = bh;
808
809    return;
810 }
811
812 static E_Map *
813 _e_comp_object_map_damage_transform_get(E_Client *ec)
814 {
815    E_Map *m;
816    E_Map *m2 = NULL;
817    int bw, bh;
818    int i;
819
820    if (!e_client_transform_core_enable_get(ec))
821      return NULL;
822
823    m = e_client_map_get(ec);
824    if (!m)
825      return NULL;
826
827    e_pixmap_size_get(ec->pixmap, &bw, &bh);
828    if ((bw == 0) || (bh == 0))
829      {
830         e_map_free(m);
831         return NULL;
832      }
833
834    m2 = e_map_new();
835    if (!m2)
836      {
837         e_map_free(m);
838         return NULL;
839      }
840
841    e_map_point_coord_set(m2, 0, 0, 0, 0);
842    e_map_point_coord_set(m2, 1, bw, 0, 0);
843    e_map_point_coord_set(m2, 2, bw, bh, 0);
844    e_map_point_coord_set(m2, 3, 0, bh, 0);
845
846    for (i = 0; i < 4; i++)
847      {
848         int map_x, map_y;
849
850         e_map_point_coord_get(m, i, &map_x, &map_y, NULL);
851         e_map_point_image_uv_set(m2, i, map_x, map_y);
852      }
853
854    e_map_free(m);
855    return m2;
856 }
857
858 /////////////////////////////////////
859
860 /* handle evas mouse-in events on client object */
861 static void
862 _e_comp_object_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
863 {
864    Evas_Event_Mouse_In *ev = event_info;
865    E_Comp_Object *cw = data;
866
867    e_client_mouse_in(cw->ec, ev->output.x, ev->output.y);
868 }
869
870 /* handle evas mouse-out events on client object */
871 static void
872 _e_comp_object_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
873 {
874    Evas_Event_Mouse_Out *ev = event_info;
875    E_Comp_Object *cw = data;
876
877    e_client_mouse_out(cw->ec, ev->output.x, ev->output.y);
878 }
879
880 /* handle evas mouse wheel events on client object */
881 static void
882 _e_comp_object_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
883 {
884    Evas_Event_Mouse_Wheel *ev = event_info;
885    E_Comp_Object *cw = data;
886    E_Binding_Event_Wheel ev2;
887
888    if (!cw->ec) return;
889    if (e_client_action_get()) return;
890    e_bindings_evas_event_mouse_wheel_convert(ev, &ev2);
891    e_client_mouse_wheel(cw->ec, &ev->output, &ev2);
892 }
893
894 /* handle evas mouse down events on client object */
895 static void
896 _e_comp_object_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
897 {
898    Evas_Event_Mouse_Down *ev = event_info;
899    E_Comp_Object *cw = data;
900    E_Binding_Event_Mouse_Button ev2;
901
902    if (!cw->ec) return;
903    if (e_client_action_get()) return;
904    e_bindings_evas_event_mouse_down_button_convert(ev, &ev2);
905    e_client_mouse_down(cw->ec, ev->button, &ev->output, &ev2);
906 }
907
908 /* handle evas mouse up events on client object */
909 static void
910 _e_comp_object_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
911 {
912    Evas_Event_Mouse_Up *ev = event_info;
913    E_Comp_Object *cw = data;
914    E_Binding_Event_Mouse_Button ev2;
915
916    if (!cw->ec) return;
917    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
918    e_bindings_evas_event_mouse_up_button_convert(ev, &ev2);
919    e_client_mouse_up(cw->ec, ev->button, &ev->output, &ev2);
920 }
921
922 /* handle evas mouse movement events on client object */
923 static void
924 _e_comp_object_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
925 {
926    Evas_Event_Mouse_Move *ev = event_info;
927    E_Comp_Object *cw = data;
928
929    if (!cw->ec) return;
930    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
931    e_client_mouse_move(cw->ec, &ev->cur.output);
932 }
933 /////////////////////////////////////
934
935 /* helper function for checking compositor themes based on user-defined matches */
936 static Eina_Bool
937 _e_comp_object_shadow_client_match(const E_Client *ec, E_Comp_Match *m)
938 {
939    if (((m->title) && (!ec->netwm.name)) ||
940        ((ec->netwm.name) && (m->title) && (!e_util_glob_match(ec->netwm.name, m->title))))
941      return EINA_FALSE;
942 #if defined(__cplusplus) || defined(c_plusplus)
943    if (((m->clas) && (!ec->icccm.cpp_class)) ||
944        ((ec->icccm.cpp_class) && (m->clas) && (!e_util_glob_match(ec->icccm.cpp_class, m->clas))))
945      return EINA_FALSE;
946 #else
947    if (((m->clas) && (!ec->icccm.class)) ||
948        ((ec->icccm.class) && (m->clas) && (!e_util_glob_match(ec->icccm.class, m->clas))))
949      return EINA_FALSE;
950 #endif
951
952   if (((m->role) && (!ec->icccm.window_role)) ||
953        ((ec->icccm.window_role) && (m->role) && (!e_util_glob_match(ec->icccm.window_role, m->role))))
954      return EINA_FALSE;
955    if (m->primary_type)
956      {
957         if (ec->netwm.type)
958           {
959              if ((int)ec->netwm.type != m->primary_type)
960                return EINA_FALSE;
961           }
962         else if (m->primary_type != E_WINDOW_TYPE_REAL_UNKNOWN)
963           return EINA_FALSE;
964      }
965   if (m->borderless != 0)
966     {
967        int borderless = 0;
968
969        if (e_client_util_borderless(ec))
970          borderless = 1;
971        if (!(((m->borderless == -1) && (!borderless)) ||
972              ((m->borderless == 1) && (borderless))))
973          return EINA_FALSE;
974     }
975   if (m->dialog != 0)
976     {
977        int dialog = 0;
978
979        if (((ec->icccm.transient_for != 0) ||
980             (ec->dialog)))
981          dialog = 1;
982        if (!(((m->dialog == -1) && (!dialog)) ||
983              ((m->dialog == 1) && (dialog))))
984          return EINA_FALSE;
985     }
986   if (m->accepts_focus != 0)
987     {
988        int accepts_focus = 0;
989
990        if (ec->icccm.accepts_focus)
991          accepts_focus = 1;
992        if (!(((m->accepts_focus == -1) && (!accepts_focus)) ||
993              ((m->accepts_focus == 1) && (accepts_focus))))
994          return EINA_FALSE;
995     }
996   if (m->vkbd != 0)
997     {
998        int vkbd = 0;
999
1000        if (ec->vkbd.vkbd)
1001          vkbd = 1;
1002        if (!(((m->vkbd == -1) && (!vkbd)) ||
1003              ((m->vkbd == 1) && (vkbd))))
1004          return EINA_FALSE;
1005     }
1006   if (m->argb != 0)
1007     {
1008        if (!(((m->argb == -1) && (!ec->argb)) ||
1009              ((m->argb == 1) && (ec->argb))))
1010          return EINA_FALSE;
1011     }
1012   if (m->fullscreen != 0)
1013     {
1014        int fullscreen = ec->fullscreen;
1015
1016        if (!(((m->fullscreen == -1) && (!fullscreen)) ||
1017              ((m->fullscreen == 1) && (fullscreen))))
1018          return EINA_FALSE;
1019     }
1020   if (m->modal != 0)
1021     {
1022        if (!(m->modal == -1))
1023          return EINA_FALSE;
1024     }
1025   return EINA_TRUE;
1026 }
1027
1028 /* function for setting up a client's compositor frame theme (cw->shobj) */
1029 static Eina_Bool
1030 _e_comp_object_shadow_setup(E_Comp_Object *cw)
1031 {
1032    int ok = 0;
1033    char buf[4096];
1034    Eina_List *list = NULL, *l;
1035    E_Input_Rect_Data *input_rect_data;
1036    E_Input_Rect_Smart_Data *input_rect_sd;
1037    E_Comp_Match *m;
1038    Eina_Stringshare *reshadow_group = NULL;
1039    Eina_Bool focus = EINA_FALSE, skip = EINA_FALSE, fast = EINA_FALSE, reshadow = EINA_FALSE, no_shadow = EINA_FALSE, pass_event_flag = EINA_FALSE;
1040    Eina_Stringshare *name, *title;
1041    E_Comp_Config *conf = e_comp_config_get();
1042
1043    edje_object_file_get(cw->shobj, NULL, &reshadow_group);
1044    /* match correct client type */
1045    list = cw->ec->override ? conf->match.overrides : conf->match.borders;
1046    name = cw->ec->icccm.name;
1047    title = cw->ec->icccm.title;
1048    skip = (cw->ec->override ? conf->match.disable_overrides : conf->match.disable_borders) || (title && (!strncmp(title, "noshadow", 8)));
1049    fast = cw->ec->override ? conf->fast_overrides : conf->fast_borders;
1050
1051    /* skipping here is mostly a hack for systray because I hate it */
1052    if (!skip)
1053      {
1054         EINA_LIST_FOREACH(list, l, m)
1055           {
1056              if (((m->name) && (!name)) ||
1057                  ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
1058                continue;
1059              if (!_e_comp_object_shadow_client_match(cw->ec, m)) continue;
1060
1061              focus = m->focus;
1062              no_shadow = m->no_shadow;
1063              if (m->shadow_style)
1064                {
1065                   /* fast effects are just themes with "/fast" appended and shorter effect times */
1066                   if (fast)
1067                     {
1068                        snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", m->shadow_style);
1069                        reshadow = ok = !e_util_strcmp(reshadow_group, buf);
1070                        if (!ok)
1071                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
1072                     }
1073                   /* default to non-fast style if fast not available */
1074                   if (!ok)
1075                     {
1076                        snprintf(buf, sizeof(buf), "e/comp/frame/%s", m->shadow_style);
1077                        reshadow = ok = !e_util_strcmp(reshadow_group, buf);
1078                        if (!ok)
1079                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
1080                     }
1081                   if (ok && m->visibility_effect)
1082                     eina_stringshare_refplace(&cw->visibility_effect, m->visibility_effect);
1083                   if (ok) break;
1084                }
1085           }
1086      }
1087    while (!ok)
1088      {
1089         if (skip || (cw->ec->e.state.video))
1090           {
1091              reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/none");
1092              if (!ok)
1093                ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/none");
1094           }
1095         if (ok) break;
1096         if (conf->shadow_style)
1097           {
1098              if (fast)
1099                {
1100                   snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", conf->shadow_style);
1101                   reshadow = ok = !e_util_strcmp(reshadow_group, buf);
1102                   if (!ok)
1103                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
1104                }
1105              if (!ok)
1106                {
1107                   snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
1108                   reshadow = ok = !e_util_strcmp(reshadow_group, buf);
1109                   if (!ok)
1110                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
1111                }
1112           }
1113         if (!ok)
1114           {
1115              if (fast)
1116                {
1117                   reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/default/fast");
1118                   if (!ok)
1119                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/default/fast");
1120                }
1121              if (!ok)
1122                {
1123                   reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/default");
1124                   if (!ok)
1125                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/default");
1126                }
1127           }
1128         break;
1129      }
1130    /* reshadow means this entire function call has been a no-op since we're re-setting the current style */
1131    if (reshadow)
1132      {
1133         ;
1134      }
1135    if (cw->ec->override)
1136      {
1137         if ((!cw->ec->shaped) && (!no_shadow) && (!cw->ec->argb))
1138           edje_object_signal_emit(cw->shobj, "e,state,shadow,on", "e");
1139         else
1140           edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1141         evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
1142      }
1143    else
1144      {
1145         if (no_shadow)
1146           {
1147              edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1148              evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
1149           }
1150         else
1151           _e_comp_object_shadow(cw);
1152      }
1153
1154    if (focus || cw->ec->focused || cw->ec->override)
1155      e_comp_object_signal_emit(cw->smart_obj, "e,state,focused", "e");
1156    else
1157      e_comp_object_signal_emit(cw->smart_obj, "e,state,unfocused", "e");
1158    if (cw->ec->sticky)
1159      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
1160    if (cw->ec->hung)
1161      e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
1162    /* visibility must always be enabled for re_manage clients to prevent
1163     * pop-in animations every time the user sees a persistent client again;
1164     * applying visibility for iconic clients prevents the client from getting
1165     * stuck as hidden
1166     */
1167    if (cw->visible || cw->ec->re_manage)
1168      e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
1169    else
1170      e_comp_object_signal_emit(cw->smart_obj, "e,state,hidden", "e");
1171
1172    /* breaks animation counter */
1173    if (cw->frame_object)
1174      {
1175         edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
1176         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1177         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1178         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1179         no_shadow = 1;
1180      }
1181    else
1182      {
1183         no_shadow = 1;
1184         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->obj);
1185      }
1186    if (cw->input_obj)
1187      {
1188         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
1189         if (input_rect_sd)
1190           {
1191              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
1192                {
1193                   if (input_rect_data->obj)
1194                     {
1195                        pass_event_flag = EINA_TRUE;
1196                        break;
1197                     }
1198                }
1199           }
1200      }
1201    if (cw->indicator.obj)
1202      {
1203         Evas_Object *indicator;
1204         indicator = edje_object_part_swallow_get(cw->shobj, "e.swallow.indicator");
1205         if (indicator != cw->indicator.obj)
1206           {
1207              edje_object_part_unswallow(cw->shobj, indicator);
1208              edje_object_part_swallow(cw->shobj, "e.swallow.indicator", cw->indicator.obj);
1209              e_comp_object_indicator_size_set(cw->smart_obj, cw->indicator.w, cw->indicator.h);
1210           }
1211      }
1212
1213    evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
1214    evas_object_pass_events_set(cw->obj, pass_event_flag);
1215
1216    return EINA_TRUE;
1217 }
1218
1219 /////////////////////////////////////////////
1220
1221 static void
1222 _e_comp_object_animating_begin(E_Comp_Object *cw)
1223 {
1224    cw->animating++;
1225    if (cw->animating == 1)
1226      {
1227         e_comp->animating++;
1228         REFD(cw->ec, 2);
1229         e_object_ref(E_OBJECT(cw->ec));
1230      }
1231 }
1232
1233 static Eina_Bool
1234 _e_comp_object_animating_end(E_Comp_Object *cw)
1235 {
1236    if (cw->animating)
1237      {
1238         cw->animating--;
1239         if (!cw->animating)
1240           {
1241              if (cw->ec)
1242                {
1243                   if (cw->ec->launching)
1244                     {
1245                        if (!cw->ec->extra_animating)
1246                          {
1247                             ELOGF("COMP", "Un-Set launching flag..", cw->ec);
1248                             cw->ec->launching = EINA_FALSE;
1249                             if (cw->ec->first_mapped)
1250                               {
1251                                  ELOGF("LAUNCH", "SHOW real win", cw->ec);
1252                                  e_comp_object_signal_emit(cw->ec->frame, "e,action,launch_real,done", "e");
1253                               }
1254
1255                             e_comp_object_signal_emit(cw->ec->frame, "e,action,launch,done", "e");
1256                          }
1257                     }
1258                }
1259              e_comp->animating--;
1260              cw->showing = cw->hiding = 0;
1261              UNREFD(cw->ec, 2);
1262              if (e_comp->animating == 0)
1263                e_comp_visibility_calculation_set(EINA_TRUE);
1264              /* remove ref from animation start, account for possibility of deletion from unref */
1265              return !!e_object_unref(E_OBJECT(cw->ec));
1266           }
1267      }
1268    return EINA_TRUE;
1269 }
1270
1271 /* handle the end of a compositor animation */
1272 static void
1273 _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED)
1274 {
1275    E_Comp_Object *cw = data;
1276
1277    /* visible clients which have never been sized are a bug */
1278    if ((!cw->ec->new_client) && (!cw->ec->changes.size) && ((cw->w < 0) || (cw->h < 0)) && (!strcmp(emission, "e,action,show,done")))
1279      CRI("ACK! ec:%p", cw->ec);
1280    if (!_e_comp_object_animating_end(cw)) return;
1281    if (cw->animating) return;
1282    /* hide only after animation finishes to guarantee a full run of the animation */
1283    if (!cw->defer_hide) return;
1284    if ((!strcmp(emission, "e,action,hide,done")) ||
1285        (!strcmp(emission, "e,action,done")) ||
1286        ((cw->ec->iconic) && (!strcmp(emission, "e,action,show,done"))))
1287      {
1288         ELOGF("COMP", "defer hide emission:%s", cw->ec, emission);
1289         evas_object_hide(cw->smart_obj);
1290      }
1291 }
1292
1293 /* run a visibility compositor effect if available, return false if object is dead */
1294 static Eina_Bool
1295 _e_comp_object_effect_visibility_start(E_Comp_Object *cw, Eina_Bool state)
1296 {
1297    E_Zone *zone;
1298    int x, y;
1299    int zw = 0, zh = 0;
1300
1301    if ((!cw->visibility_effect) || (!e_comp_object_effect_allowed_get(cw->smart_obj))) return EINA_TRUE;;
1302    if (!cw->effect_running)
1303      _e_comp_object_animating_begin(cw);
1304    if (!e_comp_object_effect_stop(cw->smart_obj, _e_comp_object_done_defer))
1305      return _e_comp_object_animating_end(cw);
1306    if (!e_comp_object_effect_set(cw->smart_obj, cw->visibility_effect))
1307      return _e_comp_object_animating_end(cw);
1308
1309    evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
1310    x -= cw->x;
1311    y -= cw->y;
1312    zone = e_comp_zone_find_by_ec(cw->ec);
1313    if (zone)
1314      zw = zone->w, zh = zone->h;
1315    else
1316      {
1317         E_Zone *zone;
1318
1319         zone = e_comp_object_util_zone_get(cw->smart_obj);
1320         if (!zone) zone = e_zone_current_get();
1321         if (zone)
1322           {
1323              zw = zone->w;
1324              zh = zone->h;
1325           }
1326      }
1327    e_comp_object_effect_params_set(cw->smart_obj, 1, (int[]){cw->x, cw->y,
1328       cw->w, cw->h, zw, zh, x, y}, 8);
1329    e_comp_object_effect_params_set(cw->smart_obj, 0, (int[]){state}, 1);
1330    e_comp_object_effect_start(cw->smart_obj, _e_comp_object_done_defer, cw);
1331    return EINA_TRUE;
1332 }
1333 /////////////////////////////////////////////
1334
1335 /* create necessary objects for clients that e manages */
1336 static void
1337 _e_comp_object_mouse_event_callback_set(E_Comp_Object *cw)
1338 {
1339    if (cw->set_mouse_callbacks) return;
1340    if (!cw->smart_obj) return;
1341
1342    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_cb_mouse_in, cw);
1343    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_cb_mouse_out, cw);
1344    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_comp_object_cb_mouse_down, cw);
1345    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_cb_mouse_up, cw);
1346    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_comp_object_cb_mouse_move, cw);
1347    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_comp_object_cb_mouse_wheel, cw);
1348
1349    cw->set_mouse_callbacks = EINA_TRUE;
1350 }
1351
1352 static void
1353 _e_comp_object_mouse_event_callback_unset(E_Comp_Object *cw)
1354 {
1355    if (!cw->set_mouse_callbacks) return;
1356    if (!cw->smart_obj) return;
1357
1358    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_cb_mouse_in);
1359    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_cb_mouse_out);
1360    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_comp_object_cb_mouse_down);
1361    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_cb_mouse_up);
1362    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_comp_object_cb_mouse_move);
1363    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_comp_object_cb_mouse_wheel);
1364
1365    cw->set_mouse_callbacks = EINA_FALSE;
1366 }
1367
1368 static void
1369 _e_comp_object_setup(E_Comp_Object *cw)
1370 {
1371    cw->clip = evas_object_rectangle_add(e_comp->evas);
1372    evas_object_move(cw->clip, -9999, -9999);
1373    evas_object_resize(cw->clip, 999999, 999999);
1374    evas_object_smart_member_add(cw->clip, cw->smart_obj);
1375    cw->effect_obj = edje_object_add(e_comp->evas);
1376    evas_object_move(cw->effect_obj, cw->x, cw->y);
1377    evas_object_clip_set(cw->effect_obj, cw->clip);
1378    evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
1379    e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none");
1380    cw->shobj = edje_object_add(e_comp->evas);
1381    evas_object_data_set(cw->shobj, "comp_smart_obj", cw->smart_obj);
1382    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
1383    edje_object_signal_callback_add(cw->shobj, "e,action,*,done", "e", _e_comp_object_done_defer, cw);
1384
1385    /* name objects appropriately for nicer printing when using e_comp_util_wins_print() */
1386    if (cw->ec->override)
1387      {
1388         evas_object_name_set(cw->shobj, "cw->shobj::WINDOW");
1389         evas_object_name_set(cw->effect_obj, "cw->effect_obj::WINDOW");
1390         evas_object_name_set(cw->clip, "cw->clip::WINDOW");
1391      }
1392    else if (!cw->ec->input_only)
1393      {
1394         evas_object_name_set(cw->shobj, "cw->shobj::CLIENT");
1395         evas_object_name_set(cw->effect_obj, "cw->effect_obj::CLIENT");
1396         evas_object_name_set(cw->clip, "cw->clip::CLIENT");
1397      }
1398    cw->real_hid = !cw->ec->input_only;
1399    if (!cw->ec->input_only)
1400      {
1401         e_util_size_debug_set(cw->effect_obj, 1);
1402         _e_comp_object_mouse_event_callback_set(cw);
1403      }
1404
1405    cw->default_input_obj = evas_object_rectangle_add(e_comp->evas);
1406    evas_object_name_set(cw->default_input_obj, "cw->default_input_obj");
1407    evas_object_move(cw->default_input_obj, cw->x, cw->y);
1408    evas_object_resize(cw->default_input_obj, cw->w, cw->h);
1409    evas_object_color_set(cw->default_input_obj, 0, 0, 0, 0);
1410    evas_object_smart_member_add(cw->default_input_obj, cw->smart_obj);
1411
1412    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_OBJECT_SETUP, cw->ec);
1413 }
1414
1415 /////////////////////////////////////////////
1416
1417 /* for fast path evas rendering; only called during render */
1418 static void
1419 _e_comp_object_pixels_get(void *data, Evas_Object *obj EINA_UNUSED)
1420 {
1421    E_Comp_Object *cw = data;
1422    E_Client *ec = cw->ec;
1423    int pw, ph;
1424    int bx, by, bxx, byy;
1425
1426    if (e_object_is_del(E_OBJECT(ec))) return;
1427    if (cw->external_content) return;
1428    if (!e_pixmap_size_get(ec->pixmap, &pw, &ph)) return;
1429    e_pixmap_image_opaque_get(cw->ec->pixmap, &bx, &by, &bxx, &byy);
1430    if (bxx && byy)
1431      {
1432         bxx = pw - (bx + bxx), byy = ph - (by + byy);
1433         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
1434      }
1435    else if (cw->client_inset.calc && (!cw->frame_object)) //CSD
1436      {
1437         bx = -cw->client_inset.l + 4, by = -cw->client_inset.t + 4;
1438         bxx = -cw->client_inset.r, byy = -cw->client_inset.b;
1439      }
1440    else
1441      {
1442         bx = by = bxx = byy = 0;
1443         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
1444      }
1445    {
1446       Edje_Message_Int_Set *msg;
1447       Edje_Message_Int msg2;
1448       Eina_Bool id = (bx || by || bxx || byy);
1449
1450       msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int) * 3));
1451       msg->count = 4;
1452       msg->val[0] = bx;
1453       msg->val[1] = by;
1454       msg->val[2] = bxx;
1455       msg->val[3] = byy;
1456       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 1, msg);
1457       msg2.val = id;
1458       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT, 0, &msg2);
1459    }
1460    if (cw->native)
1461      {
1462         E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
1463         e_comp_client_post_update_add(cw->ec);
1464      }
1465    else if (e_comp_object_render(ec->frame))
1466      {
1467         /* apply shape mask if necessary */
1468         if ((!cw->native) && (ec->shaped))
1469           e_comp_object_shape_apply(ec->frame);
1470      }
1471    /* shaped clients get precise mouse events to handle transparent pixels */
1472    evas_object_precise_is_inside_set(cw->obj, ec->shaped);
1473
1474    /* queue another render if client is still dirty; cannot refresh here. */
1475    if (e_pixmap_dirty_get(ec->pixmap) && e_pixmap_size_get(ec->pixmap, &pw, &ph))
1476      e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1477
1478    if (cw->render_trace)
1479      {
1480         _e_comp_object_event_simple(ec->frame, E_EVENT_COMP_OBJECT_IMG_RENDER);
1481      }
1482 }
1483
1484
1485 static void
1486 _e_comp_object_pixels_noti(void *data, Evas_Object *obj EINA_UNUSED)
1487 {
1488    E_Comp_Object *cw = data;
1489    E_Client *ec = cw->ec;
1490
1491    if (e_object_is_del(E_OBJECT(ec))) return;
1492    if (cw->external_content) return;
1493    if (!e_comp->hwc) return;
1494
1495    e_comp_client_render_list_add(cw->ec);
1496
1497    if (!ec->hwc_window) return;
1498
1499    e_hwc_windows_rendered_window_add(ec->hwc_window);
1500 }
1501
1502 /////////////////////////////////////////////
1503
1504 static void
1505 _e_comp_intercept_move(void *data, Evas_Object *obj, int x, int y)
1506 {
1507    E_Comp_Object *cw = data;
1508    int ix, iy, fx, fy;
1509
1510    if (cw->render_update_lock.lock)
1511      {
1512         cw->render_update_lock.pending_move_x = x;
1513         cw->render_update_lock.pending_move_y = y;
1514         cw->render_update_lock.pending_move_set = EINA_TRUE;
1515         return;
1516      }
1517
1518    if ((e_pixmap_type_get(cw->ec->pixmap) != E_PIXMAP_TYPE_EXT_OBJECT) &&
1519        (e_pixmap_usable_get(cw->ec->pixmap)) &&
1520        (cw->external_content))
1521      {
1522         /* delay to move until the external content is unset */
1523         cw->ec->changes.pos = 1;
1524         EC_CHANGED(cw->ec);
1525         return;
1526      }
1527
1528    if (cw->ec->move_after_resize)
1529      {
1530         if ((x != cw->ec->x) || (y != cw->ec->y))
1531           {
1532              if (!cw->ec->is_cursor)
1533                ELOGF("COMP", "Set Pos to (%d,%d). current ec_pos(%d,%d)", cw->ec, x, y, cw->ec->x, cw->ec->y);
1534              e_client_pos_set(cw->ec, x, y);
1535              cw->ec->changes.pos = 1;
1536              EC_CHANGED(cw->ec);
1537           }
1538         return;
1539      }
1540
1541    if ((cw->ec->resize_mode == E_POINTER_RESIZE_NONE) &&
1542        (cw->ec->manage_resize.resize_obj))
1543      {
1544         e_client_pos_set(cw->ec, x, y);
1545         cw->ec->client.x = x + cw->client_inset.l;
1546         cw->ec->client.y = y + cw->client_inset.t;
1547         e_policy_visibility_client_defer_move(cw->ec);
1548         return;
1549      }
1550
1551    /* if frame_object does not exist, client_inset indicates CSD.
1552     * this means that ec->client matches cw->x/y, the opposite
1553     * of SSD.
1554     */
1555    fx = (!cw->frame_object) * cw->client_inset.l;
1556    fy = (!cw->frame_object) * cw->client_inset.t;
1557    if ((cw->x == x + fx) && (cw->y == y + fy))
1558      {
1559         if ((cw->ec->x != x) || (cw->ec->y != y))
1560           {
1561              /* handle case where client tries to move to position and back very quickly */
1562              e_client_pos_set(cw->ec, x, y);
1563              cw->ec->client.x = x + cw->client_inset.l;
1564              cw->ec->client.y = y + cw->client_inset.t;
1565           }
1566         return;
1567      }
1568    if (!cw->ec->maximize_override)
1569      {
1570         /* prevent moving in some directions while directionally maximized */
1571         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1572           y = cw->y;
1573         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1574           x = cw->x;
1575      }
1576    ix = x + cw->client_inset.l;
1577    iy = y + cw->client_inset.t;
1578    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->x != x) || (cw->ec->y != y)) &&
1579        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_VERTICAL) &&
1580        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_HORIZONTAL))
1581      {
1582         /* prevent moving at all if move isn't allowed in current maximize state */
1583         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1584         /* queue unmaximize if we are allowing move and update unmaximize geometry */
1585
1586         E_Zone *zone;
1587         zone = e_comp_zone_find_by_ec(cw->ec);
1588         if (!zone) return;
1589
1590         cw->ec->changes.need_unmaximize = 1;
1591         cw->ec->saved.x = ix - zone->x;
1592         cw->ec->saved.y = iy - zone->y;
1593         cw->ec->saved.w = cw->ec->client.w;
1594         cw->ec->saved.h = cw->ec->client.h;
1595         EC_CHANGED(cw->ec);
1596         return;
1597      }
1598    /* only update during resize if triggered by resize */
1599    if (e_client_util_resizing_get(cw->ec) && (!cw->force_move)) return;
1600    /* delay to move while surface waits paired commit serial*/
1601    if (e_client_pending_geometry_has(cw->ec))
1602      {
1603         /* do nothing while waiting paired commit serial*/
1604         return;
1605      }
1606
1607    e_client_pos_set(cw->ec, x, y);
1608    if (cw->ec->new_client)
1609      {
1610         /* don't actually do anything until first client idler loop */
1611         cw->ec->placed = ((!cw->ec->dialog) && (!cw->ec->parent));
1612         cw->ec->changes.pos = 1;
1613         EC_CHANGED(cw->ec);
1614      }
1615    else
1616      {
1617         /* only update xy position of client to avoid invalid
1618          * first damage region if it is not a new_client. */
1619         cw->ec->client.x = ix;
1620         cw->ec->client.y = iy;
1621
1622         /* flip SSD->CSD */
1623         if (!cw->frame_object)
1624           x = ix, y = iy;
1625         evas_object_move(obj, x, y);
1626      }
1627 }
1628
1629 static void
1630 _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
1631 {
1632    E_Comp_Object *cw = data;
1633    int pw = 0, ph = 0, fw, fh, iw, ih, prev_w, prev_h, x, y;
1634    E_Zone *zone;
1635
1636    if (cw->render_update_lock.lock)
1637      {
1638         cw->render_update_lock.pending_resize_w = w;
1639         cw->render_update_lock.pending_resize_h = h;
1640         cw->render_update_lock.pending_resize_set = EINA_TRUE;
1641         return;
1642      }
1643
1644    if (!e_util_strcmp("input_panel_surface", cw->ec->icccm.window_role))
1645      {
1646         e_client_size_set(cw->ec, w, h);
1647         evas_object_resize(obj, w, h);
1648         return;
1649      }
1650
1651    /* if frame_object does not exist, client_inset indicates CSD.
1652     * this means that ec->client matches cw->w/h, the opposite
1653     * of SSD.
1654     */
1655    fw = (!cw->frame_object) * (-cw->client_inset.l - cw->client_inset.r);
1656    fh = (!cw->frame_object) * (-cw->client_inset.t - cw->client_inset.b);
1657    if ((cw->w == w + fw) && (cw->h == h + fh))
1658      {
1659         if (((cw->ec->w != w) || (cw->ec->h != h)) ||
1660             (cw->ec->client.w != w - cw->client_inset.l - cw->client_inset.r) ||
1661             (cw->ec->client.h != h - cw->client_inset.t - cw->client_inset.b))
1662           {
1663              /* handle case where client tries to resize itself and back very quickly */
1664              e_client_size_set(cw->ec, w, h);
1665              cw->ec->client.w = w - cw->client_inset.l - cw->client_inset.r;
1666              cw->ec->client.h = h - cw->client_inset.t - cw->client_inset.b;
1667              evas_object_smart_callback_call(obj, "client_resize", NULL);
1668           }
1669         return;
1670      }
1671    /* guarantee that fullscreen is fullscreen */
1672    zone = e_comp_zone_find_by_ec(cw->ec);
1673    if (!zone) return;
1674    if (cw->ec->fullscreen && ((w != zone->w) || (h != zone->h)))
1675      {
1676         if (!e_client_transform_core_enable_get(cw->ec))
1677           return;
1678      }
1679    /* calculate client size */
1680    iw = w - cw->client_inset.l - cw->client_inset.r;
1681    ih = h - cw->client_inset.t - cw->client_inset.b;
1682    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->w != w) || (cw->ec->h != h)))
1683      {
1684         /* prevent resizing while maximized depending on direction and config */
1685         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1686
1687         Eina_Bool reject = EINA_FALSE;
1688         if (cw->ec->maximized & E_MAXIMIZE_VERTICAL)
1689           {
1690              if (cw->ec->client.h != ih)
1691                {
1692                   cw->ec->saved.h = ih;
1693                   cw->ec->saved.y = cw->ec->client.y - zone->y;
1694                   reject = cw->ec->changes.need_unmaximize = 1;
1695                }
1696           }
1697         if (cw->ec->maximized & E_MAXIMIZE_HORIZONTAL)
1698           {
1699              if (cw->ec->client.w != iw)
1700                {
1701                   cw->ec->saved.w = iw;
1702                   cw->ec->saved.x = cw->ec->client.x - zone->x;
1703                   reject = cw->ec->changes.need_unmaximize = 1;
1704                }
1705           }
1706         if (reject)
1707           {
1708              EC_CHANGED(cw->ec);
1709              return;
1710           }
1711      }
1712    if (cw->ec->new_client || (!cw->ec->visible) || (!cw->effect_obj))
1713      {
1714         /* do nothing until client idler loops */
1715         if ((cw->ec->w != w) || (cw->ec->h != h))
1716           {
1717              e_client_size_set(cw->ec, w, h);
1718              cw->ec->changes.size = 1;
1719              EC_CHANGED(cw->ec);
1720           }
1721         return;
1722      }
1723    if (e_client_pending_geometry_has(cw->ec))
1724      {
1725         /* do nothing while waiting paired commit serial*/
1726         return;
1727      }
1728
1729    e_client_size_set(cw->ec, w, h);
1730
1731    cw->ec->client.w = iw;
1732    cw->ec->client.h = ih;
1733    if ((cw->ec->client.w < 0) || (cw->ec->client.h < 0)) CRI("WTF. ec:%p", cw->ec);
1734
1735    /* The size of non-compositing window can be changed, so there is a
1736     * need to check that cw is H/W composited if cw is not redirected.
1737     * And of course we have to change size of evas object of H/W composited cw,
1738     * otherwise cw can't receive input events even if it is shown on the screen.
1739     */
1740    Eina_Bool redirected = cw->redirected;
1741    if (!redirected)
1742      redirected = e_comp_is_on_overlay(cw->ec);
1743
1744    if ((!cw->ec->input_only) && (redirected) &&
1745        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
1746        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE) &&
1747        (e_pixmap_dirty_get(cw->ec->pixmap) ||
1748        (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))))
1749      return;
1750
1751    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
1752        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
1753      pw = w, ph = h;
1754    prev_w = cw->w, prev_h = cw->h;
1755    e_comp_object_frame_wh_adjust(obj, 0, 0, &fw, &fh);
1756    /* check shading and clamp to pixmap size for regular clients */
1757    if ((!cw->ec->input_only) && (!cw->ec->override) &&
1758        (((w - fw != pw) || (h - fh != ph))))
1759      {
1760         //INF("CALLBACK: REQ(%dx%d) != CUR(%dx%d)", w - fw, h - fh, pw, ph);
1761         evas_object_smart_callback_call(obj, "client_resize", NULL);
1762         /* flip for CSD */
1763         if (cw->frame_object || cw->ec->input_only)
1764           e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
1765         else
1766           w = pw, h = ph;
1767         if ((cw->w == w) && (cw->h == h))
1768           {
1769              /* going to be a noop resize which won't trigger smart resize */
1770              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
1771              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
1772           }
1773         evas_object_resize(obj, w, h);
1774      }
1775    else
1776      {
1777         evas_object_smart_callback_call(obj, "client_resize", NULL);
1778
1779         /* flip for CSD */
1780         if ((!cw->frame_object) && (!cw->ec->input_only))
1781           w = pw, h = ph;
1782         /* "just do it" for overrides */
1783         evas_object_resize(obj, w, h);
1784      }
1785    if (!cw->ec->override)
1786      {
1787         /* shape probably changed for non-overrides */
1788         if (cw->ec->shaped)
1789           EC_CHANGED(cw->ec);
1790      }
1791
1792    /* this fixes positioning jiggles when using a resize mode
1793     * which also changes the client's position
1794     */
1795    cw->force_move = 1;
1796    if (cw->frame_object)
1797      x = cw->x, y = cw->y;
1798    else
1799      x = cw->ec->x, y = cw->ec->y;
1800    switch (cw->ec->resize_mode)
1801      {
1802       case E_POINTER_RESIZE_BL:
1803       case E_POINTER_RESIZE_L:
1804         evas_object_move(obj, x + prev_w - cw->w, y);
1805         break;
1806       case E_POINTER_RESIZE_TL:
1807         evas_object_move(obj, x + prev_w - cw->w, y + prev_h - cw->h);
1808         break;
1809       case E_POINTER_RESIZE_T:
1810       case E_POINTER_RESIZE_TR:
1811         evas_object_move(obj, x, y + prev_h - cw->h);
1812         break;
1813       default:
1814         break;
1815      }
1816    cw->force_move = 0;
1817 }
1818
1819 static void
1820 _e_comp_intercept_layer_set(void *data, Evas_Object *obj, int layer)
1821 {
1822 #ifdef REFACTOR_DESK_AREA
1823    E_Comp_Object *cw = data;
1824    E_Comp_Object_Data_Set_Layer layer_set_data;
1825
1826    layer_set_data.cw = cw;
1827    layer_set_data.layer = layer;
1828
1829    wl_signal_emit_mutable(&cw->events.set_layer, &layer_set_data);
1830
1831    if (cw->visible)
1832      {
1833         e_comp_render_queue();
1834         _e_comp_object_transform_obj_stack_update(obj);
1835      }
1836
1837 #else
1838    E_Comp_Object *cw = data;
1839    E_Comp_Wl_Client_Data *child_cdata;
1840    unsigned int l = e_comp_canvas_layer_map(layer);
1841    int oldraise;
1842
1843    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
1844      {
1845         /* doing a compositor effect, follow directions */
1846         _e_comp_object_layer_set(obj, layer);
1847         if (layer == cw->ec->layer) //trying to put layer back
1848           {
1849              E_Client *ec;
1850
1851              /* if ec->layer and layer are the same but the client is not belong to the given(l)
1852                  that means, layer is changed during layer_pending. in this case, need to update layer inlist*/
1853              if (cw->layer != l) goto layer_set;
1854
1855              if (cw->visible)
1856                {
1857                   e_comp_render_queue();
1858                }
1859              ec = e_client_above_get(cw->ec);
1860              /* skip subsurface: stacking subsurface is handled by e_comp_wl */
1861              while ((ec) && (e_comp_wl_subsurface_check(ec)))
1862                ec = e_client_above_get(ec);
1863              if (ec && (evas_object_layer_get(ec->frame) != evas_object_layer_get(obj)))
1864                {
1865                   ec = e_client_below_get(cw->ec);
1866                   /* skip subsurface: stacking subsurface is handled by e_comp_wl */
1867                   while ((ec) && (e_comp_wl_subsurface_check(ec)))
1868                     ec = e_client_below_get(ec);
1869                   if (ec && (evas_object_layer_get(ec->frame) == evas_object_layer_get(cw->smart_obj)))
1870                     {
1871                        evas_object_stack_above(obj, ec->frame);
1872                        return;
1873                     }
1874                   ec = NULL;
1875                }
1876              if (ec && (cw->ec->parent == ec))
1877                {
1878                   if (e_client_transient_policy_get(cw->ec) == E_TRANSIENT_ABOVE)
1879                     evas_object_stack_above(obj, ec->frame);
1880                   else
1881                     evas_object_stack_below(obj, ec->frame);
1882                }
1883              else
1884                evas_object_stack_below(obj, ec ? ec->frame : e_comp->layers[cw->layer].obj);
1885           }
1886         return;
1887      }
1888
1889 layer_set:
1890    if (cw->layer == l) return;
1891    if (e_comp_canvas_client_layer_map(layer) == 9999)
1892      return; //invalid layer for clients not doing comp effects
1893    if (cw->ec->fullscreen)
1894      {
1895         cw->ec->saved.layer = layer;
1896         return;
1897      }
1898    oldraise = e_config->transient.raise;
1899
1900    /* clamp to valid client layer */
1901    layer = e_comp_canvas_client_layer_map_nearest(layer);
1902    cw->ec->layer = layer;
1903    if (e_config->transient.layer)
1904      {
1905         E_Client *child;
1906         Eina_List *list = eina_list_clone(cw->ec->transients);
1907
1908         /* We need to set raise to one, else the child wont
1909          * follow to the new layer. It should be like this,
1910          * even if the user usually doesn't want to raise
1911          * the transients.
1912          */
1913         e_config->transient.raise = 1;
1914         EINA_LIST_FREE(list, child)
1915           {
1916              child_cdata = e_client_cdata_get(child);
1917              if (child_cdata && !child_cdata->mapped)
1918                {
1919                   ELOGF("COMP", "LAYER_SET CHILD. BUT not mapped. skip. child(ec:%p, win:0x%08zx)", cw->ec, child, e_client_util_win_get(child));
1920                   continue;
1921                }
1922              e_client_layer_set(child, layer);
1923           }
1924      }
1925
1926    e_config->transient.raise = oldraise;
1927
1928    _e_comp_object_layers_remove(cw);
1929    cw->layer = e_comp_canvas_layer_map(layer);
1930    _e_comp_object_layers_add(cw, NULL, NULL, 0);
1931    //if (cw->ec->new_client)
1932      //INF("CLIENT STACKED %p: %u", cw->ec, layer);
1933    _e_comp_object_layer_set(obj, layer);
1934    if (!e_comp->layers[cw->layer].obj) return; //this is a layer marker
1935    evas_object_stack_below(obj, e_comp->layers[cw->layer].obj);
1936    if (evas_object_below_get(obj) == e_comp->layers[cw->layer].obj)
1937      {
1938         /* can't stack a client above its own layer marker */
1939         CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
1940      }
1941    if (!cw->visible) return;
1942    e_comp_render_queue();
1943    _e_comp_object_transform_obj_stack_update(obj);
1944 #endif
1945 }
1946
1947 #ifdef REFACTOR_DESK_AREA
1948 #else
1949 typedef void (*E_Comp_Object_Stack_Func)(Evas_Object *obj, Evas_Object *stack);
1950 #endif
1951
1952 #ifdef REFACTOR_DESK_AREA
1953 EINTERN void
1954 _e_comp_object_raise(Evas_Object *obj)
1955 #else
1956 static void
1957 _e_comp_object_raise(Evas_Object *obj)
1958 #endif
1959 {
1960    evas_object_raise(obj);
1961
1962    if (evas_object_smart_smart_get(obj))
1963      {
1964         E_Client *ec = e_comp_object_client_get(obj);
1965         if (ec)
1966           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1967      }
1968 }
1969
1970 #ifdef REFACTOR_DESK_AREA
1971 EINTERN void
1972 _e_comp_object_lower(E_Comp_Object *cw, Evas_Object *obj)
1973 #else
1974 static void
1975 _e_comp_object_lower(E_Comp_Object *cw, Evas_Object *obj)
1976 #endif
1977 {
1978    evas_object_lower(obj);
1979
1980    if (evas_object_smart_smart_get(obj))
1981      {
1982         E_Client *ec = e_comp_object_client_get(obj);
1983         if (ec)
1984           {
1985              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1986 #ifdef REFACTOR_DESK_AREA
1987              wl_signal_emit_mutable(&cw->events.lower_done, NULL);
1988 #else
1989              wl_signal_emit_mutable(&cw->events.lower, NULL);
1990 #endif
1991           }
1992      }
1993 }
1994
1995 #ifdef REFACTOR_DESK_AREA
1996 EINTERN void
1997 _e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target)
1998 #else
1999 static void
2000 _e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target)
2001 #endif
2002 {
2003    evas_object_stack_above(obj, target);
2004
2005    if (evas_object_smart_smart_get(obj))
2006      {
2007         E_Client *ec = e_comp_object_client_get(obj);
2008         if (ec)
2009           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
2010      }
2011 }
2012
2013 #ifdef REFACTOR_DESK_AREA
2014 EINTERN void
2015 _e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target)
2016 #else
2017 static void
2018 _e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target)
2019 #endif
2020 {
2021    evas_object_stack_below(obj, target);
2022
2023    if (evas_object_smart_smart_get(obj))
2024      {
2025         E_Client *ec = e_comp_object_client_get(obj);
2026         if (ec)
2027           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
2028      }
2029 }
2030
2031 #ifdef REFACTOR_DESK_AREA
2032 EINTERN void
2033 e_comp_object_layer_set(Evas_Object *obj, short layer)
2034 #else
2035 static void
2036 _e_comp_object_layer_set(Evas_Object *obj, short layer)
2037 #endif
2038 {
2039    evas_object_layer_set(obj, layer);
2040
2041    if (evas_object_smart_smart_get(obj))
2042      {
2043         E_Client *ec = e_comp_object_client_get(obj);
2044         if (ec)
2045           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_LAYER_SET, ec);
2046      }
2047 }
2048
2049 #ifdef REFACTOR_DESK_AREA
2050 #else
2051 static Eina_Bool
2052 _e_comp_object_is_pending(E_Client *ec)
2053 {
2054    E_Client *topmost;
2055
2056    if (!ec) return EINA_FALSE;
2057
2058    topmost = e_comp_wl_topmost_parent_get(ec);
2059
2060    return (topmost) ? topmost->layer_pending : EINA_FALSE;
2061 }
2062
2063 static void
2064 _e_comp_intercept_stack_helper(E_Comp_Object *cw, Evas_Object *stack, E_Comp_Object_Stack_Func stack_cb)
2065 {
2066    E_Comp_Object *cw2 = NULL;
2067    E_Client *ecstack;
2068    short layer;
2069    Evas_Object *o = stack;
2070    Eina_Bool raising = stack_cb == _e_comp_object_stack_above;
2071
2072    /* We should consider topmost's layer_pending for subsurface */
2073    if ((cw->ec->layer_block) || _e_comp_object_is_pending(cw->ec))
2074      {
2075         if (_e_comp_object_is_pending(cw->ec))
2076           e_comp_object_layer_update(cw->smart_obj,
2077                                      raising? stack : NULL,
2078                                      raising? NULL : stack);
2079
2080         /* obey compositor effects! */
2081         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
2082           evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
2083         stack_cb(cw->smart_obj, stack);
2084         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
2085           evas_object_data_del(cw->smart_obj, "client_restack");
2086         return;
2087      }
2088
2089    cw2 = evas_object_data_get(o, "comp_obj");
2090
2091    /* assume someone knew what they were doing during client init */
2092    if (cw->ec->new_client)
2093      layer = cw->ec->layer;
2094    else if ((cw2) && _e_comp_object_is_pending(cw2->ec))
2095      layer = cw2->ec->layer;
2096    else
2097      layer = evas_object_layer_get(stack);
2098    ecstack = e_client_below_get(cw->ec);
2099    if (layer != e_comp_canvas_layer_map_to(cw->layer))
2100      {
2101         evas_object_layer_set(cw->smart_obj, layer);
2102         /* we got our layer wrangled, return now! */
2103         if (layer != e_comp_canvas_layer_map_to(cw->layer)) return;
2104      }
2105
2106    /* check if we're stacking below another client */
2107    while (!cw2)
2108      {
2109         /* check for non-client layer object */
2110         if (!e_util_strcmp(evas_object_name_get(o), "layer_obj"))
2111           break;
2112         /* find an existing client to use for layering
2113          * by walking up the object stack
2114          *
2115          * this is guaranteed to be pretty quick since we'll either:
2116          * - run out of client layers
2117          * - find a stacking client
2118          */
2119         o = evas_object_above_get(o);
2120         if ((!o) || (o == cw->smart_obj)) break;
2121         if (evas_object_layer_get(o) != layer)
2122           {
2123              /* reached the top client layer somehow
2124               * use top client object
2125               */
2126              o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR)].obj;
2127           }
2128         if (!o)
2129           /* top client layer window hasn't been stacked yet. this probably shouldn't happen?
2130            * return here since the top client layer window
2131            */
2132           {
2133              E_Client *ec;
2134
2135              ec = e_client_top_get();
2136              if (ec)
2137                o = ec->frame;
2138              //else //wat
2139           }
2140         if (o) cw2 = evas_object_data_get(o, "comp_obj");
2141      }
2142
2143    if (cw2 && cw->layer != cw2->layer)
2144      return;
2145
2146    /* remove existing layers */
2147    _e_comp_object_layers_remove(cw);
2148    if (cw2)
2149      {
2150         if (o == stack) //if stacking above, cw2 is above; else cw2 is below
2151           _e_comp_object_layers_add(cw, raising ? cw2 : NULL, raising ? NULL : cw2, 0);
2152         else if (o == cw->smart_obj) //prepend (lower) if not stacking above
2153           _e_comp_object_layers_add(cw, NULL, NULL, !raising);
2154         else //if no stacking objects found, either raise or lower
2155           _e_comp_object_layers_add(cw, raising ? NULL : cw2, raising ? cw2 : NULL, 0);
2156      }
2157    else
2158      _e_comp_object_layers_add(cw, NULL, NULL, 0);
2159
2160    /* find new object for stacking if cw2 is on state of layer_pending */
2161    if ((cw2) && _e_comp_object_is_pending(cw2->ec))
2162      {
2163         E_Client *new_stack = NULL, *current_ec = NULL;
2164         current_ec = cw2->ec;
2165         if (raising)
2166           {
2167              while ((new_stack = e_client_below_get(current_ec)))
2168                {
2169                   current_ec = new_stack;
2170                   if (new_stack == cw->ec) continue;
2171                   if (new_stack->layer != cw2->ec->layer) break;
2172                   if (!_e_comp_object_is_pending(new_stack)) break;
2173                }
2174              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2175                stack = new_stack->frame;
2176              else
2177                {
2178                   /* stack it above layer object */
2179                   int below_layer;
2180                   below_layer = (cw2->layer <= 0)? 0 : cw2->layer - 1 ;
2181                   stack = e_comp->layers[below_layer].obj;
2182                }
2183           }
2184         else
2185           {
2186              while ((new_stack = e_client_above_get(current_ec)))
2187                {
2188                   current_ec = new_stack;
2189                   if (new_stack == cw->ec) continue;
2190                   if (new_stack->layer != cw2->ec->layer) break;
2191                   if (!_e_comp_object_is_pending(new_stack)) break;
2192                }
2193              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2194                stack = new_stack->frame;
2195              else
2196                stack = e_comp->layers[cw2->layer].obj;
2197           }
2198      }
2199
2200    /* set restack if stacking has changed */
2201    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2202      evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
2203    stack_cb(cw->smart_obj, stack);
2204    if (e_comp->layers[cw->layer].obj)
2205      if (evas_object_below_get(cw->smart_obj) == e_comp->layers[cw->layer].obj)
2206        {
2207           CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
2208        }
2209    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2210      evas_object_data_del(cw->smart_obj, "client_restack");
2211    if (!cw->visible) return;
2212    e_comp_render_queue();
2213 }
2214 #endif
2215
2216 static void
2217 _e_comp_intercept_stack_above(void *data, Evas_Object *obj, Evas_Object *above)
2218 {
2219    EINA_SAFETY_ON_TRUE_RETURN(obj == above);
2220
2221    TRACE_DS_BEGIN(COMP:INTERCEPT STACK ABOVE);
2222
2223 #ifdef REFACTOR_DESK_AREA
2224    E_Comp_Object *cw = data;
2225    E_Comp_Object_Data_Stack_Above stack_above_data;
2226
2227    stack_above_data.cw = cw;
2228    stack_above_data.above_obj = above;
2229
2230    wl_signal_emit_mutable(&cw->events.stack_above, &stack_above_data);
2231 #else
2232    if (evas_object_below_get(obj) == above)
2233      {
2234         e_comp_object_layer_update(obj, above, NULL);
2235         return;
2236      }
2237
2238    _e_comp_intercept_stack_helper(data, above, _e_comp_object_stack_above);
2239
2240    _e_comp_object_transform_obj_stack_update(obj);
2241    _e_comp_object_transform_obj_stack_update(above);
2242 #endif
2243
2244    TRACE_DS_END();
2245 }
2246
2247 static void
2248 _e_comp_intercept_stack_below(void *data, Evas_Object *obj, Evas_Object *below)
2249 {
2250    EINA_SAFETY_ON_TRUE_RETURN(obj == below);
2251
2252    TRACE_DS_BEGIN(COMP:INTERCEPT STACK BELOW);
2253
2254 #ifdef REFACTOR_DESK_AREA
2255    E_Comp_Object *cw = data;
2256    E_Comp_Object_Data_Stack_Below stack_below_data;
2257
2258    stack_below_data.cw = cw;
2259    stack_below_data.below_obj = below;
2260
2261    wl_signal_emit_mutable(&cw->events.stack_below, &stack_below_data);
2262
2263    if (!cw->visible)
2264      e_comp_render_queue();
2265 #else
2266    if (evas_object_above_get(obj) == below)
2267      {
2268         e_comp_object_layer_update(obj, NULL, below);
2269         return;
2270      }
2271
2272    _e_comp_intercept_stack_helper(data, below, _e_comp_object_stack_below);
2273
2274    if (evas_object_smart_smart_get(obj))
2275      _e_comp_object_transform_obj_stack_update(obj);
2276    if (evas_object_smart_smart_get(below))
2277      _e_comp_object_transform_obj_stack_update(below);
2278 #endif
2279
2280    TRACE_DS_END();
2281 }
2282
2283 static void
2284 _e_comp_intercept_lower(void *data, Evas_Object *obj)
2285 {
2286    E_Comp_Object *cw = data;
2287
2288 #ifdef REFACTOR_DESK_AREA
2289 #else
2290    Evas_Object *o;
2291 #endif
2292
2293    TRACE_DS_BEGIN(COMP:INTERCEPT LOWER);
2294
2295 #ifdef REFACTOR_DESK_AREA
2296    wl_signal_emit_mutable(&cw->events.lower, cw);
2297 #else
2298    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2299      {
2300         if (cw->ec->layer_pending)
2301           e_comp_object_layer_update(obj, NULL, obj);
2302
2303         _e_comp_object_lower(cw, obj);
2304         goto end;
2305      }
2306    if (!EINA_INLIST_GET(cw->ec)->prev) goto end; //already lowest on layer
2307    o = evas_object_below_get(obj);
2308    _e_comp_object_layers_remove(cw);
2309    /* prepend to client list since this client should be the first item now */
2310    _e_comp_object_layers_add(cw, NULL, NULL, 1);
2311    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at bottom!
2312    evas_object_data_set(obj, "client_restack", (void*)1);
2313    _e_comp_object_lower(cw, obj);
2314    evas_object_data_del(obj, "client_restack");
2315    if (!cw->visible) goto end;
2316    e_comp_render_queue();
2317    _e_comp_object_transform_obj_stack_update(obj);
2318
2319 end:
2320 #endif
2321    TRACE_DS_END();
2322 }
2323
2324 static void
2325 _e_comp_intercept_raise(void *data, Evas_Object *obj)
2326 {
2327    E_Comp_Object *cw = data;
2328 #ifdef REFACTOR_DESK_AREA
2329 #else
2330    Evas_Object *o;
2331    Evas_Object *op;
2332 #endif
2333
2334    TRACE_DS_BEGIN(COMP:INTERCEPT RAISE);
2335
2336 #ifdef REFACTOR_DESK_AREA
2337    wl_signal_emit_mutable(&cw->events.raise, cw);
2338 #else
2339    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2340      {
2341         if (cw->ec->layer_pending)
2342           {
2343              int obj_layer = evas_object_layer_get(obj);
2344              if (cw->ec->layer != obj_layer)
2345                e_comp_object_layer_update(obj, NULL, NULL);
2346           }
2347
2348         _e_comp_object_raise(obj);
2349         goto end;
2350      }
2351    if (!EINA_INLIST_GET(cw->ec)->next) goto end;//already highest on layer
2352    o = evas_object_above_get(obj);
2353    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at top!
2354
2355    /* still stack below override below the layer marker */
2356    for (op = o = e_comp->layers[cw->layer].obj;
2357         o && o != e_comp->layers[cw->layer - 1].obj;
2358         op = o, o = evas_object_below_get(o))
2359      {
2360         if (evas_object_smart_smart_get(o))
2361           {
2362              E_Client *ec;
2363
2364              ec = e_comp_object_client_get(o);
2365              if (ec && (!ec->override)) break;
2366           }
2367      }
2368    _e_comp_object_stack_below(obj, op);
2369    e_client_focus_defer_set(cw->ec);
2370
2371    if (!cw->visible) goto end;
2372    e_comp_render_queue();
2373    _e_comp_object_transform_obj_stack_update(obj);
2374
2375 end:
2376 #endif
2377    TRACE_DS_END();
2378 }
2379
2380 static void
2381 _e_comp_intercept_hide(void *data, Evas_Object *obj)
2382 {
2383    E_Comp_Object *cw = data;
2384
2385 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2386    if( !_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, cw->ec))
2387      {
2388         ELOGF("COMP", "Hide. intercepted", cw->ec);
2389         return;
2390      }
2391 #endif
2392
2393    if (cw->ec->launching == EINA_TRUE)
2394      {
2395         ELOGF("COMP", "Hide. Cancel launching flag", cw->ec);
2396         cw->ec->launching = EINA_FALSE;
2397      }
2398
2399    if (cw->ec->hidden)
2400      {
2401         /* hidden flag = just do it */
2402         ELOGF("COMP", "Hide hidden evas_object:%p", cw->ec, obj);
2403         evas_object_hide(obj);
2404
2405         wl_signal_emit_mutable(&cw->events.hide, NULL);
2406
2407         return;
2408      }
2409
2410    if (cw->ec->input_only)
2411      {
2412         /* input_only = who cares */
2413         ELOGF("COMP", "Hide input_only evas_object:%p", cw->ec, obj);
2414         evas_object_hide(obj);
2415
2416         wl_signal_emit_mutable(&cw->events.hide, NULL);
2417
2418         return;
2419      }
2420    /* already hidden or currently animating */
2421    if ((!cw->visible) || (cw->animating && cw->hiding && (!cw->ec->iconic)))
2422      {
2423         ELOGF("COMP", "Hide. but already hidden or currently animating", cw->ec);
2424         return;
2425      }
2426
2427    /* don't try hiding during shutdown */
2428    cw->defer_hide |= stopping;
2429    if (!cw->defer_hide)
2430      {
2431         if ((!cw->ec->iconic) && (!cw->ec->override))
2432           /* unset delete requested so the client doesn't break */
2433           cw->ec->delete_requested = 0;
2434         if ((!cw->animating) || (!cw->hiding) || cw->ec->iconic)
2435           {
2436              ELOGF("COMP", "Hide. but after iconify or hide animation, cw->animating:%d, cw->hiding:%d, iconic:%d",
2437                    cw->ec, cw->animating, cw->hiding, cw->ec->iconic);
2438
2439              if (cw->ec->iconic)
2440                e_comp_object_signal_emit(obj, "e,action,iconify", "e");
2441              else
2442                {
2443                   e_comp_object_signal_emit(obj, "e,state,hidden", "e");
2444                   if (!cw->showing)
2445                     _e_comp_object_animating_begin(cw);
2446                   if (!_e_comp_object_effect_visibility_start(cw, 0)) return;
2447                }
2448              evas_object_smart_callback_call(obj, "hiding", cw->ec);
2449              cw->defer_hide = !!cw->animating;
2450              if (!cw->animating)
2451                e_comp_object_effect_set(obj, NULL);
2452           }
2453      }
2454    if (cw->animating) return;
2455    /* if we have no animations running, go ahead and hide */
2456    cw->defer_hide = 0;
2457    ELOGF("COMP", "Hide normal object:%p", cw->ec, obj);
2458    evas_object_hide(obj);
2459
2460    wl_signal_emit_mutable(&cw->events.hide, NULL);
2461 }
2462
2463 static void
2464 _e_comp_intercept_show_helper(E_Comp_Object *cw)
2465 {
2466    E_Client *ec = cw->ec;
2467    int w = 0, h = 0;
2468
2469    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
2470
2471    if (ec->show_pending.count > 0)
2472      {
2473         ELOGF("COMP", "show_helper. Show PENDING!!! show_pending:%d", ec, ec->show_pending.count);
2474         ec->show_pending.running = EINA_TRUE;
2475         return;
2476      }
2477
2478 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2479    if (!_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, ec))
2480      {
2481         ELOGF("COMP", "show_helper. intercepted", cw->ec);
2482         return;
2483      }
2484 #endif
2485
2486    ELOGF("COMP", "show_helper. cw(v:%d,a:%d,dh:%d,ct:%d,u:%p,s(%d,%d)), ec(i:%d(%d,%d),o:%d,g:%d,n:%d)", ec,
2487          cw->visible, cw->animating, cw->defer_hide, cw->content_type, cw->updates, cw->w, cw->h,
2488          ec->iconic, ec->exp_iconify.by_client, ec->exp_iconify.type, ec->input_only, ec->ignored, ec->new_client);
2489
2490    if (ec->sticky)
2491      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
2492    if (cw->visible)
2493      {
2494         if (ec->iconic && cw->animating)
2495           {
2496              /* triggered during iconify animation */
2497              e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
2498              cw->defer_hide = 0;
2499           }
2500         ELOGF("COMP", "show_helper. return. already cw->visible", ec);
2501         return;
2502      }
2503    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
2504        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
2505      {
2506         evas_object_move(cw->smart_obj, ec->x, ec->y);
2507         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2508         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2509
2510         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2511           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2512
2513         cw->real_hid = 0;
2514         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2515         evas_object_show(cw->smart_obj);
2516
2517         if (!ec->iconic)
2518           e_client_focus_defer_set(ec);
2519
2520         return;
2521      }
2522    if ((!cw->updates) && (!ec->input_only) && (!ec->ignored))
2523      {
2524         int pw, ph;
2525
2526         pw = ec->client.w, ph = ec->client.h;
2527         if ((!pw) || (!ph))
2528           if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
2529             {
2530                ec->changes.visible = !ec->hidden;
2531                ec->visible = 1;
2532                EC_CHANGED(ec);
2533                ELOGF("COMP", "show_helper. return. no pixmap size", ec);
2534                return;
2535             }
2536
2537         cw->updates = eina_tiler_new(pw, ph);
2538         if (!cw->updates)
2539           {
2540              ec->changes.visible = !ec->hidden;
2541              ec->visible = 1;
2542              EC_CHANGED(ec);
2543              ELOGF("COMP", "show_helper. return. no cw->updates", ec);
2544              return;
2545           }
2546      }
2547    if (cw->updates)
2548      eina_tiler_tile_size_set(cw->updates, 1, 1);
2549    if (ec->new_client)
2550      {
2551         /* ignore until client idler first run */
2552         ec->changes.visible = !ec->hidden;
2553         ec->visible = 1;
2554         EC_CHANGED(ec);
2555         ELOGF("COMP", "show_helper. return. new_client", ec);
2556         return;
2557      }
2558    if (ec->input_only)
2559      {
2560         /* who cares */
2561         cw->real_hid = 0;
2562         evas_object_move(cw->smart_obj, ec->x, ec->y);
2563         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2564         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2565         evas_object_show(cw->smart_obj);
2566         return;
2567      }
2568    if (ec->netwm.type == E_WINDOW_TYPE_DND && !e_comp_wl->drag_client)
2569      {
2570         /* start_drag not received */
2571         ec->changes.visible = 1;
2572         ec->visible = 1;
2573         EC_CHANGED(ec);
2574         ELOGF("COMP", "show_helper. return. start_drag not received yet", ec);
2575         return;
2576      }
2577    /* re-set geometry */
2578    evas_object_move(cw->smart_obj, ec->x, ec->y);
2579    /* force resize in case it hasn't happened yet, or just to update size */
2580    evas_object_resize(cw->smart_obj, ec->w, ec->h);
2581    if ((cw->w < 1) || (cw->h < 1))
2582      {
2583         /* if resize didn't go through, try again */
2584         ec->visible = ec->changes.visible = 1;
2585         EC_CHANGED(ec);
2586         ELOGF("COMP", "show_helper. return. cw_size(%d,%d)", ec, cw->w, cw->h);
2587         return;
2588      }
2589    /* if pixmap not available, clear pixmap since we're going to fetch it again */
2590    if (!e_pixmap_size_get(ec->pixmap, &w, &h))
2591      e_pixmap_clear(ec->pixmap);
2592
2593    if (cw->real_hid && w && h)
2594      {
2595         cw->real_hid = 0;
2596         /* force comp theming in case it didn't happen already */
2597         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2598         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2599           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2600      }
2601
2602    /* only do the show if show is allowed */
2603    if (!cw->real_hid)
2604      {
2605         if (ec->internal) //internal clients render when they feel like it
2606           e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2607
2608         if (!e_client_is_iconified_by_client(ec)||
2609             e_policy_visibility_client_is_uniconic(ec))
2610           {
2611              ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2612              evas_object_show(cw->smart_obj);
2613
2614              /* if comp object is shown in idle enterer before(E_CLIENT_HOOK_EVAL_FETCH),
2615                 it is rendered in idle callback without native surface and
2616                 compositor shows an empty frame if other objects aren't shown
2617                 because job callback of e_comp called at the next loop.
2618                 it causes a visual defect when windows are switched.
2619               */
2620              if (cw->redirected)
2621                {
2622                   e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2623                   e_comp_object_dirty(cw->smart_obj);
2624                   e_comp_object_render(cw->smart_obj);
2625                }
2626           }
2627      }
2628
2629    wl_signal_emit_mutable(&cw->events.show, NULL);
2630 }
2631
2632 static void
2633 _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
2634 {
2635    E_Comp_Object *cw = data;
2636    E_Client *ec = cw->ec;
2637    Eina_List *l;
2638    E_Input_Rect_Data *input_rect_data;
2639    E_Input_Rect_Smart_Data *input_rect_sd;
2640    int tw, th;
2641
2642    if (ec->ignored) return;
2643
2644    if (cw->effect_obj)
2645      {
2646         //INF("SHOW2 %p", ec);
2647         _e_comp_intercept_show_helper(cw);
2648         return;
2649      }
2650    //INF("SHOW %p", ec);
2651    if (ec->input_only)
2652      {
2653         cw->effect_obj = evas_object_rectangle_add(e_comp->evas);
2654         evas_object_color_set(cw->effect_obj, 0, 0, 0, 0);
2655         evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
2656         evas_object_name_set(cw->effect_obj, "cw->effect_obj::input_only");
2657      }
2658    else
2659      {
2660         if ((!cw->obj) && (cw->external_content))
2661           {
2662              ERR("cw->obj for external content is not created! ec:%p", cw->ec);
2663              return;
2664           }
2665
2666         _e_comp_object_setup(cw);
2667         if (!cw->obj)
2668           {
2669              cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
2670              cw->obj = evas_object_image_filled_add(e_comp->evas);
2671              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
2672              e_util_size_debug_set(cw->obj, 1);
2673              evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
2674              evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
2675              evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
2676              evas_object_name_set(cw->obj, "cw->obj");
2677              evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
2678           }
2679         _e_comp_object_alpha_set(cw);
2680
2681         cw->redirected = 1;
2682         evas_object_color_set(cw->clip, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
2683      }
2684
2685    _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
2686    evas_object_geometry_set(cw->effect_obj, cw->x, cw->y, tw, th);
2687    if (cw->input_obj)
2688      {
2689         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2690         if (input_rect_sd)
2691           {
2692              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2693                {
2694                   if (input_rect_data->obj)
2695                     {
2696                        evas_object_geometry_set(input_rect_data->obj,
2697                          cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2698                          cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2699                          input_rect_data->rect.w, input_rect_data->rect.h);
2700                     }
2701                }
2702           }
2703      }
2704
2705    if (cw->mask.obj)
2706      evas_object_resize(cw->mask.obj, cw->w, cw->h);
2707
2708    _e_comp_intercept_show_helper(cw);
2709 }
2710
2711 static void
2712 _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
2713 {
2714    E_Comp_Object *cw = data;
2715    E_Client *ec;
2716
2717    ec = cw->ec;
2718    /* note: this is here as it seems there are enough apps that do not even
2719     * expect us to emulate a look of focus but not actually set x input
2720     * focus as we do - so simply abort any focus set on such windows */
2721    /* be strict about accepting focus hint */
2722    /* be strict about accepting focus hint */
2723    if ((!ec->icccm.accepts_focus) &&
2724        (!ec->icccm.take_focus))
2725      {
2726         if (!focus)
2727           {
2728              if (e_client_focused_get() == ec)
2729                 e_client_focused_set(NULL);
2730
2731              ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2732              evas_object_focus_set(obj, focus);
2733           }
2734         return;
2735      }
2736    if (focus && ec->lock_focus_out) return;
2737    if (e_object_is_del(E_OBJECT(ec)) && focus)
2738      CRI("CAN'T FOCUS DELETED CLIENT! ec:%p", ec);
2739
2740    /* filter focus setting based on current state */
2741    if (focus)
2742      {
2743         if (ec->focused)
2744           {
2745              ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2746              evas_object_focus_set(obj, focus);
2747              return;
2748           }
2749         if ((ec->iconic) && (!ec->deskshow))
2750           {
2751              if (!e_policy_visibility_client_is_uniconify_render_running(ec))
2752                {
2753                   /* don't focus an iconified window. that's silly! */
2754                   ELOGF("FOCUS", "Do uniconify to set focus", ec);
2755                   e_client_uniconify(ec);
2756                   e_client_focus_latest_set(ec);
2757                   return;
2758                }
2759           }
2760         if (!ec->visible)
2761           {
2762              return;
2763           }
2764      }
2765
2766    if (focus)
2767      {
2768         if (!cw->visible)
2769           {
2770              /* not yet visible, wait till the next time... */
2771              ec->want_focus = !ec->hidden;
2772              if (ec->want_focus)
2773                EC_CHANGED(ec);
2774              return;
2775           }
2776         e_client_focused_set(ec);
2777      }
2778    else
2779      {
2780         if (e_client_focused_get() == ec)
2781           e_client_focused_set(NULL);
2782      }
2783
2784    if (focus)
2785      ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2786    else
2787      ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2788
2789    evas_object_focus_set(obj, focus);
2790 }
2791
2792 static void
2793 _e_comp_intercept_color_set(void *data, Evas_Object *obj, int r, int g, int b, int a)
2794 {
2795    E_Comp_Object *cw = data;
2796
2797    if (cw->transparent.set)
2798      {
2799         cw->transparent.user_r = r;
2800         cw->transparent.user_g = g;
2801         cw->transparent.user_b = b;
2802         cw->transparent.user_a = a;
2803
2804         ELOGF("COMP", "Transparent user_color(%d,%d,%d,%d)",
2805               cw->ec,
2806               cw->transparent.user_r,
2807               cw->transparent.user_g,
2808               cw->transparent.user_b,
2809               cw->transparent.user_a);
2810      }
2811    else
2812      {
2813         evas_object_color_set(obj, r, g, b, a);
2814      }
2815 }
2816 ////////////////////////////////////////////////////
2817
2818 static void
2819 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2820 {
2821    int w, h, ox, oy, ow, oh;
2822    Eina_List *l;
2823    Eina_Bool pass_event_flag = EINA_FALSE;
2824    E_Input_Rect_Data *input_rect_data;
2825    E_Input_Rect_Smart_Data *input_rect_sd;
2826
2827    if (cw->frame_object)
2828      {
2829         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2830         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2831         /* set a fixed size, force edje calc, check size difference */
2832         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2833         edje_object_message_signal_process(cw->frame_object);
2834         edje_object_calc_force(cw->frame_object);
2835         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2836         cw->client_inset.l = ox;
2837         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2838         cw->client_inset.t = oy;
2839         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2840         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2841         evas_object_resize(cw->frame_object, w, h);
2842
2843         if (cw->input_obj)
2844           {
2845              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2846              if (input_rect_sd)
2847                {
2848                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2849                     {
2850                        if (input_rect_data->obj)
2851                          {
2852                             pass_event_flag = EINA_TRUE;
2853                             break;
2854                          }
2855                     }
2856                }
2857           }
2858         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2859         evas_object_pass_events_set(cw->obj, pass_event_flag);
2860      }
2861    else
2862      {
2863         cw->client_inset.l = 0;
2864         cw->client_inset.r = 0;
2865         cw->client_inset.t = 0;
2866         cw->client_inset.b = 0;
2867      }
2868    cw->client_inset.calc = !!cw->frame_object;
2869 }
2870
2871 static void
2872 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2873 {
2874    E_Comp_Object *cw = data;
2875    E_Zone *zone;
2876    int w, h, pw, ph;
2877
2878    /* - get current size
2879     * - calc new size
2880     * - readjust for new frame size
2881     */
2882
2883    w = cw->ec->w, h = cw->ec->h;
2884    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2885
2886    _e_comp_object_frame_recalc(cw);
2887
2888    if (!cw->ec->fullscreen)
2889      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2890
2891    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2892    if (cw->ec->fullscreen)
2893      {
2894         zone = e_comp_zone_find_by_ec(cw->ec);
2895         if (!zone) return;
2896         evas_object_resize(cw->ec->frame, zone->w, zone->h);
2897      }
2898    else if (cw->ec->new_client)
2899      {
2900         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2901         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2902         evas_object_resize(cw->ec->frame, w, h);
2903      }
2904    else if ((w != cw->ec->w) || (h != cw->ec->h))
2905      evas_object_resize(cw->ec->frame, w, h);
2906 }
2907
2908 static void
2909 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2910 {
2911    E_Comp_Object *cw = data;
2912
2913    _e_comp_object_shadow_setup(cw);
2914    if (cw->frame_object)
2915      {
2916         _e_comp_object_shadow(cw);
2917         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2918         _e_comp_object_frame_recalc(cw);
2919         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2920      }
2921 }
2922
2923 static void
2924 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2925 {
2926    E_Comp_Object *cw = data;
2927
2928    if (_e_comp_object_shadow_setup(cw))
2929      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2930    if (cw->frame_object)
2931      {
2932         _e_comp_object_shadow(cw);
2933         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2934         _e_comp_object_frame_recalc(cw);
2935         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2936      }
2937 }
2938
2939 static void
2940 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2941 {
2942    E_Comp_Object *cw = data;
2943
2944    if (cw->frame_object)
2945      {
2946         _e_comp_object_shadow(cw);
2947         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2948         _e_comp_object_frame_recalc(cw);
2949         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2950      }
2951 }
2952
2953 static void
2954 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2955 {
2956    E_Comp_Object *cw = data;
2957
2958    if (_e_comp_object_shadow_setup(cw))
2959      {
2960         EC_CHANGED(cw->ec);
2961         cw->ec->changes.size = 1;
2962      }
2963    if (cw->frame_object)
2964      {
2965         _e_comp_object_shadow(cw);
2966         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2967         _e_comp_object_frame_recalc(cw);
2968         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2969      }
2970 }
2971
2972 static void
2973 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2974 {
2975    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
2976 }
2977
2978 static void
2979 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2980 {
2981    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
2982 }
2983
2984 static void
2985 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2986 {
2987    E_Comp_Object *cw = data;
2988
2989    if (!cw->ec) return; //NYI
2990    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
2991 }
2992
2993 static void
2994 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2995 {
2996    E_Comp_Object *cw = data;
2997
2998    if (!cw->ec) return; //NYI
2999    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
3000 }
3001
3002 static void
3003 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3004 {
3005    e_comp_object_signal_emit(obj, "e,state,focused", "e");
3006 }
3007
3008 static void
3009 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3010 {
3011    E_Comp_Object *cw = data;
3012
3013    if (!e_object_is_del(E_OBJECT(cw->ec)))
3014      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
3015 }
3016
3017 static void
3018 _e_comp_input_obj_smart_add(Evas_Object *obj)
3019 {
3020    E_Input_Rect_Smart_Data *input_rect_sd;
3021    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
3022
3023    if (!input_rect_sd) return;
3024    evas_object_smart_data_set(obj, input_rect_sd);
3025 }
3026
3027 static void
3028 _e_comp_input_obj_smart_del(Evas_Object *obj)
3029 {
3030    E_Input_Rect_Smart_Data *input_rect_sd;
3031    E_Input_Rect_Data *input_rect_data;
3032
3033    input_rect_sd = evas_object_smart_data_get(obj);
3034    if (!input_rect_sd) return;
3035
3036    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3037      {
3038         if (input_rect_data->obj)
3039           {
3040              evas_object_smart_member_del(input_rect_data->obj);
3041              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3042           }
3043         E_FREE(input_rect_data);
3044      }
3045    E_FREE(input_rect_sd);
3046 }
3047
3048 static void
3049 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
3050 {
3051    E_Input_Rect_Smart_Data *input_rect_sd;
3052    E_Input_Rect_Data *input_rect_data;
3053    Eina_List *l;
3054    E_Comp_Object *cw;
3055
3056    input_rect_sd = evas_object_smart_data_get(obj);
3057    if (!input_rect_sd) return;
3058
3059    cw = input_rect_sd->cw;
3060    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3061      {
3062         if (input_rect_data->obj)
3063           {
3064              evas_object_geometry_set(input_rect_data->obj,
3065                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3066                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3067                input_rect_data->rect.w, input_rect_data->rect.h);
3068           }
3069      }
3070 }
3071
3072 static void
3073 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
3074 {
3075    E_Input_Rect_Smart_Data *input_rect_sd;
3076    E_Input_Rect_Data *input_rect_data;
3077    Eina_List *l;
3078    E_Comp_Object *cw;
3079
3080    input_rect_sd = evas_object_smart_data_get(obj);
3081    if (!input_rect_sd) return;
3082
3083    cw = input_rect_sd->cw;
3084    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3085      {
3086         if (input_rect_data->obj)
3087           {
3088              evas_object_geometry_set(input_rect_data->obj,
3089                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3090                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3091                input_rect_data->rect.w, input_rect_data->rect.h);
3092           }
3093      }
3094 }
3095
3096 static void
3097 _e_comp_input_obj_smart_show(Evas_Object *obj)
3098 {
3099    E_Input_Rect_Smart_Data *input_rect_sd;
3100    E_Input_Rect_Data *input_rect_data;
3101    Eina_List *l;
3102
3103    input_rect_sd = evas_object_smart_data_get(obj);
3104    if (!input_rect_sd) return;
3105
3106    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3107      {
3108         if (input_rect_data->obj)
3109           {
3110              evas_object_show(input_rect_data->obj);
3111           }
3112      }
3113 }
3114
3115 static void
3116 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3117 {
3118    E_Input_Rect_Smart_Data *input_rect_sd;
3119    E_Input_Rect_Data *input_rect_data;
3120    Eina_List *l;
3121
3122    input_rect_sd = evas_object_smart_data_get(obj);
3123    if (!input_rect_sd) return;
3124
3125    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3126      {
3127         if (input_rect_data->obj)
3128           {
3129              evas_object_hide(input_rect_data->obj);
3130           }
3131      }
3132 }
3133
3134 static void
3135 _e_comp_input_obj_smart_init(void)
3136 {
3137    if (_e_comp_input_obj_smart) return;
3138    {
3139       static const Evas_Smart_Class sc =
3140       {
3141          INPUT_OBJ_SMART_NAME,
3142          EVAS_SMART_CLASS_VERSION,
3143          _e_comp_input_obj_smart_add,
3144          _e_comp_input_obj_smart_del,
3145          _e_comp_input_obj_smart_move,
3146          _e_comp_input_obj_smart_resize,
3147          _e_comp_input_obj_smart_show,
3148          _e_comp_input_obj_smart_hide,
3149          NULL,
3150          NULL,
3151          NULL,
3152          NULL,
3153          NULL,
3154          NULL,
3155
3156          NULL,
3157          NULL,
3158          NULL,
3159          NULL
3160       };
3161       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3162    }
3163 }
3164
3165
3166 static void
3167 _e_comp_smart_add(Evas_Object *obj)
3168 {
3169    E_Comp_Object *cw;
3170
3171    cw = E_NEW(E_Comp_Object, 1);
3172    EINA_SAFETY_ON_NULL_RETURN(cw);
3173
3174    wl_signal_init(&cw->events.lower);
3175 #ifdef REFACTOR_DESK_AREA
3176    wl_signal_init(&cw->events.lower_done);
3177    wl_signal_init(&cw->events.raise);
3178 #endif
3179    wl_signal_init(&cw->events.show);
3180    wl_signal_init(&cw->events.hide);
3181 #ifdef REFACTOR_DESK_AREA
3182    wl_signal_init(&cw->events.set_layer);
3183    wl_signal_init(&cw->events.stack_above);
3184    wl_signal_init(&cw->events.stack_below);
3185 #endif
3186
3187    cw->smart_obj = obj;
3188    cw->x = cw->y = cw->w = cw->h = -1;
3189    evas_object_smart_data_set(obj, cw);
3190    cw->opacity = 255.0;
3191    cw->external_content = 0;
3192    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3193    cw->transform_bg_color.r = 0;
3194    cw->transform_bg_color.g = 0;
3195    cw->transform_bg_color.b = 0;
3196    cw->transform_bg_color.a = 255;
3197    evas_object_data_set(obj, "comp_obj", cw);
3198    evas_object_move(obj, -1, -1);
3199    /* intercept ALL the callbacks! */
3200    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3201    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3202    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3203    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3204    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3205    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3206    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3207    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3208    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3209    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3210    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3211
3212    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3213    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3214    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3215    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3216
3217    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
3218    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
3219
3220    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
3221    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
3222
3223    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3224
3225    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3226    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3227 }
3228
3229 static void
3230 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3231 {
3232    INTERNAL_ENTRY;
3233    evas_object_color_set(cw->clip, r, g, b, a);
3234    evas_object_smart_callback_call(obj, "color_set", NULL);
3235 }
3236
3237
3238 static void
3239 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3240 {
3241    INTERNAL_ENTRY;
3242    evas_object_clip_set(cw->clip, clip);
3243 }
3244
3245 static void
3246 _e_comp_smart_clip_unset(Evas_Object *obj)
3247 {
3248    INTERNAL_ENTRY;
3249    evas_object_clip_unset(cw->clip);
3250 }
3251
3252 static void
3253 _e_comp_smart_hide(Evas_Object *obj)
3254 {
3255    TRACE_DS_BEGIN(COMP:SMART HIDE);
3256
3257    INTERNAL_ENTRY;
3258    cw->visible = 0;
3259    cw->hiding = 0;
3260    evas_object_hide(cw->clip);
3261    if (cw->input_obj) evas_object_hide(cw->input_obj);
3262    evas_object_hide(cw->effect_obj);
3263    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3264    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3265    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3266    if (stopping)
3267      {
3268         TRACE_DS_END();
3269         return;
3270      }
3271
3272    /* unset native surface if current displaying buffer was destroied */
3273    if (!cw->buffer_destroy_listener.notify)
3274      {
3275         Evas_Native_Surface *ns;
3276         ns = evas_object_image_native_surface_get(cw->obj);
3277         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3278           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3279      }
3280
3281    if (!cw->ec->input_only)
3282      {
3283         edje_object_freeze(cw->effect_obj);
3284         edje_object_freeze(cw->shobj);
3285         edje_object_play_set(cw->shobj, 0);
3286         if (cw->frame_object)
3287           edje_object_play_set(cw->frame_object, 0);
3288      }
3289
3290    e_comp_render_queue(); //force nocomp recheck
3291
3292    TRACE_DS_END();
3293 }
3294
3295 static void
3296 _e_comp_smart_show(Evas_Object *obj)
3297 {
3298    E_Client *tmp;
3299    Eina_List *l;
3300
3301    INTERNAL_ENTRY;
3302    cw->defer_hide = 0;
3303    cw->visible = 1;
3304    if ((cw->w < 0) || (cw->h < 0))
3305      CRI("ACK! ec:%p", cw->ec);
3306
3307    TRACE_DS_BEGIN(COMP:SMART SHOW);
3308
3309    e_comp_object_map_update(obj);
3310
3311    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3312      evas_object_show(tmp->frame);
3313
3314    evas_object_show(cw->clip);
3315    if (cw->input_obj) evas_object_show(cw->input_obj);
3316    if (!cw->ec->input_only)
3317      {
3318         edje_object_thaw(cw->effect_obj);
3319         edje_object_thaw(cw->shobj);
3320         edje_object_play_set(cw->shobj, 1);
3321         if (cw->frame_object)
3322           edje_object_play_set(cw->frame_object, 1);
3323      }
3324    evas_object_show(cw->effect_obj);
3325    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3326    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3327    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3328    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3329    e_comp_render_queue();
3330    if (cw->ec->input_only)
3331      {
3332         TRACE_DS_END();
3333         return;
3334      }
3335    if (cw->ec->iconic && (!cw->ec->new_client))
3336      {
3337         if (e_client_is_iconified_by_client(cw->ec))
3338           {
3339              ELOGF("COMP", "Set launching flag..", cw->ec);
3340              cw->ec->launching = EINA_TRUE;
3341           }
3342
3343         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3344      }
3345    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3346      {
3347         cw->showing = 1;
3348         ELOGF("COMP", "Set launching flag..", cw->ec);
3349         cw->ec->launching = EINA_TRUE;
3350
3351         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3352         _e_comp_object_animating_begin(cw);
3353         if (!_e_comp_object_effect_visibility_start(cw, 1))
3354           {
3355              TRACE_DS_END();
3356              return;
3357           }
3358      }
3359    /* ensure some random effect doesn't lock the client offscreen */
3360    if (!cw->animating)
3361      {
3362         cw->showing = 0;
3363         e_comp_object_effect_set(obj, NULL);
3364      }
3365
3366    _e_comp_object_dim_update(cw);
3367
3368    TRACE_DS_END();
3369 }
3370
3371 static void
3372 _e_comp_smart_del(Evas_Object *obj)
3373 {
3374    Eina_List *l;
3375
3376    INTERNAL_ENTRY;
3377
3378    if (cw->buffer_destroy_listener.notify)
3379      {
3380         wl_list_remove(&cw->buffer_destroy_listener.link);
3381         cw->buffer_destroy_listener.notify = NULL;
3382      }
3383
3384    if (cw->tbm_surface)
3385      {
3386         tbm_surface_internal_unref(cw->tbm_surface);
3387         cw->tbm_surface = NULL;
3388      }
3389
3390    if (cw->render_update_lock.buffer_ref.buffer)
3391      {
3392         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3393               cw->ec, cw->render_update_lock.lock);
3394         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3395      }
3396
3397    e_comp_object_render_update_del(cw->smart_obj);
3398    E_FREE_FUNC(cw->updates, eina_tiler_free);
3399    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3400    free(cw->ns);
3401
3402    if (cw->obj_mirror)
3403      {
3404         Evas_Object *o;
3405
3406         EINA_LIST_FREE(cw->obj_mirror, o)
3407           {
3408              evas_object_image_data_set(o, NULL);
3409              evas_object_freeze_events_set(o, 1);
3410              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3411              evas_object_del(o);
3412           }
3413      }
3414 #ifdef REFACTOR_DESK_AREA
3415 #else
3416    _e_comp_object_layers_remove(cw);
3417 #endif
3418    l = evas_object_data_get(obj, "comp_object-to_del");
3419    E_FREE_LIST(l, evas_object_del);
3420    _e_comp_object_mouse_event_callback_unset(cw);
3421    evas_object_del(cw->clip);
3422    evas_object_del(cw->obj);
3423    evas_object_del(cw->shobj);
3424    evas_object_del(cw->effect_obj);
3425    evas_object_del(cw->frame_object);
3426    evas_object_del(cw->input_obj);
3427    evas_object_del(cw->mask.obj);
3428    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3429    evas_object_del(cw->transform_bg_obj);
3430    evas_object_del(cw->transform_tranp_obj);
3431    evas_object_del(cw->default_input_obj);
3432    eina_stringshare_del(cw->frame_theme);
3433    eina_stringshare_del(cw->frame_name);
3434    if (cw->animating)
3435      {
3436         cw->animating = 0;
3437         e_comp->animating--;
3438         UNREFD(cw->ec, 2);
3439         e_object_unref(E_OBJECT(cw->ec));
3440      }
3441    cw->ec->frame = NULL;
3442    free(cw);
3443 }
3444
3445 static void
3446 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3447 {
3448    INTERNAL_ENTRY;
3449
3450    cw->x = x, cw->y = y;
3451    evas_object_move(cw->effect_obj, x, y);
3452    evas_object_move(cw->default_input_obj, x, y);
3453    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3454
3455    e_comp_object_map_update(obj);
3456 }
3457
3458 static void
3459 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3460 {
3461    Eina_Bool first = EINA_FALSE;
3462    int tw, th;
3463
3464    INTERNAL_ENTRY;
3465
3466    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3467
3468    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3469
3470    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3471
3472    if (cw->w != w || cw->h != h)
3473      e_comp_object_map_update(obj);
3474
3475    first = ((cw->w < 1) || (cw->h < 1));
3476    cw->w = w, cw->h = h;
3477
3478    int ww, hh, pw, ph;
3479
3480    if (cw->frame_object)
3481      e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3482    else
3483      ww = w, hh = h;
3484    /* verify pixmap:object size */
3485    if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3486      {
3487         if ((ww != pw) || (hh != ph))
3488           ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3489      }
3490    evas_object_resize(cw->effect_obj, tw, th);
3491    evas_object_resize(cw->default_input_obj, w, h);
3492    if (cw->input_obj)
3493      evas_object_resize(cw->input_obj, w, h);
3494    if (cw->mask.obj)
3495      evas_object_resize(cw->mask.obj, w, h);
3496    /* resize render update tiler */
3497    if (!first)
3498      {
3499         RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3500         cw->updates_full = 0;
3501         if (cw->updates) eina_tiler_clear(cw->updates);
3502      }
3503    else
3504      {
3505         RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3506         if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3507      }
3508
3509    if (!cw->visible)
3510      {
3511         TRACE_DS_END();
3512         return;
3513      }
3514    e_comp_render_queue();
3515
3516    TRACE_DS_END();
3517 }
3518
3519 static void
3520 _e_comp_smart_init(void)
3521 {
3522    if (_e_comp_smart) return;
3523    {
3524       static const Evas_Smart_Class sc =
3525       {
3526          SMART_NAME,
3527          EVAS_SMART_CLASS_VERSION,
3528          _e_comp_smart_add,
3529          _e_comp_smart_del,
3530          _e_comp_smart_move,
3531          _e_comp_smart_resize,
3532          _e_comp_smart_show,
3533          _e_comp_smart_hide,
3534          _e_comp_smart_color_set,
3535          _e_comp_smart_clip_set,
3536          _e_comp_smart_clip_unset,
3537          NULL,
3538          NULL,
3539          NULL,
3540
3541          NULL,
3542          NULL,
3543          NULL,
3544          NULL
3545       };
3546       _e_comp_smart = evas_smart_class_new(&sc);
3547    }
3548 }
3549
3550 EINTERN void
3551 e_comp_object_init(void)
3552 {
3553    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3554    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3555    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3556    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3557 }
3558
3559 EINTERN void
3560 e_comp_object_shutdown(void)
3561 {
3562
3563 }
3564
3565 EINTERN Eina_Bool
3566 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3567 {
3568    API_ENTRY EINA_FALSE;
3569    return !!cw->force_visible;
3570 }
3571 /////////////////////////////////////////////////////////
3572
3573 static void
3574 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3575 {
3576    Eina_List *l;
3577    Eina_Bool comp_object;
3578
3579    comp_object = !!evas_object_data_get(obj, "comp_object");
3580    if (comp_object)
3581      {
3582         Evas_Object *o;
3583
3584         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3585         evas_object_del(o);
3586         e_comp_render_queue();
3587      }
3588    l = evas_object_data_get(obj, "comp_object-to_del");
3589    E_FREE_LIST(l, evas_object_del);
3590 }
3591
3592 static void
3593 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3594 {
3595    if (e_comp_util_object_is_above_nocomp(obj) &&
3596        (!evas_object_data_get(obj, "comp_override")))
3597      {
3598         evas_object_data_set(obj, "comp_override", (void*)1);
3599         e_comp_override_add();
3600      }
3601 }
3602
3603 static void
3604 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3605 {
3606    Eina_Bool ref = EINA_TRUE;
3607    if (evas_object_visible_get(obj))
3608      {
3609         void *d;
3610
3611         d = evas_object_data_del(obj, "comp_hiding");
3612         if (d)
3613           /* currently trying to hide */
3614           ref = EINA_FALSE;
3615         else
3616           /* already visible */
3617           return;
3618      }
3619
3620    evas_object_show(obj);
3621    if (ref)
3622      {
3623         evas_object_ref(obj);
3624         evas_object_data_set(obj, "comp_ref", (void*)1);
3625      }
3626    edje_object_signal_emit(obj, "e,state,visible", "e");
3627    evas_object_data_set(obj, "comp_showing", (void*)1);
3628    if (e_comp_util_object_is_above_nocomp(obj))
3629      {
3630         evas_object_data_set(obj, "comp_override", (void*)1);
3631         e_comp_override_add();
3632      }
3633 }
3634
3635 static void
3636 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3637 {
3638    if (!evas_object_visible_get(obj)) return;
3639    /* already hiding */
3640    if (evas_object_data_get(obj, "comp_hiding")) return;
3641    if (!evas_object_data_del(obj, "comp_showing"))
3642      {
3643         evas_object_ref(obj);
3644         evas_object_data_set(obj, "comp_ref", (void*)1);
3645      }
3646    edje_object_signal_emit(obj, "e,state,hidden", "e");
3647    evas_object_data_set(obj, "comp_hiding", (void*)1);
3648
3649    if (evas_object_data_del(obj, "comp_override"))
3650      e_comp_override_timed_pop();
3651 }
3652
3653 static void
3654 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3655 {
3656    if (!e_util_strcmp(emission, "e,action,hide,done"))
3657      {
3658         if (!evas_object_data_del(obj, "comp_hiding")) return;
3659         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3660         evas_object_hide(obj);
3661         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3662      }
3663    else
3664      evas_object_data_del(obj, "comp_showing");
3665    if (evas_object_data_del(obj, "comp_ref"))
3666      evas_object_unref(obj);
3667 }
3668
3669 static void
3670 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3671 {
3672    if (data)
3673      {
3674         int w, h;
3675
3676         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3677      }
3678 }
3679
3680 E_API E_Comp_Object_Hook *
3681 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3682 {
3683    E_Comp_Object_Hook *ch;
3684
3685    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3686    ch = E_NEW(E_Comp_Object_Hook, 1);
3687    if (!ch) return NULL;
3688    ch->hookpoint = hookpoint;
3689    ch->func = func;
3690    ch->data = (void*)data;
3691    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3692    return ch;
3693 }
3694
3695 E_API void
3696 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3697 {
3698    ch->delete_me = 1;
3699    if (_e_comp_object_hooks_walking == 0)
3700      {
3701         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3702         free(ch);
3703      }
3704    else
3705      _e_comp_object_hooks_delete++;
3706 }
3707
3708 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3709 E_API E_Comp_Object_Intercept_Hook *
3710 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3711 {
3712    E_Comp_Object_Intercept_Hook *ch;
3713
3714    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3715    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3716    if (!ch) return NULL;
3717    ch->hookpoint = hookpoint;
3718    ch->func = func;
3719    ch->data = (void*)data;
3720    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3721    return ch;
3722 }
3723
3724 E_API void
3725 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3726 {
3727    ch->delete_me = 1;
3728    if (_e_comp_object_intercept_hooks_walking == 0)
3729      {
3730         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3731         free(ch);
3732      }
3733    else
3734      _e_comp_object_intercept_hooks_delete++;
3735 }
3736 #endif
3737
3738 E_API Evas_Object *
3739 e_comp_object_util_add(Evas_Object *obj)
3740 {
3741    Evas_Object *o;
3742    const char *name;
3743    E_Comp_Config *conf = e_comp_config_get();
3744    Eina_Bool skip = EINA_FALSE;
3745    char buf[1024];
3746    int ok = 0;
3747    int x, y, w, h;
3748    Eina_Bool vis;
3749
3750    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3751
3752    name = evas_object_name_get(obj);
3753    vis = evas_object_visible_get(obj);
3754    o = edje_object_add(e_comp->evas);
3755    evas_object_data_set(o, "comp_object", (void*)1);
3756    if (name)
3757      skip = (!strncmp(name, "noshadow", 8));
3758    if (skip)
3759      evas_object_data_set(o, "comp_object_skip", (void*)1);
3760
3761    if (conf->shadow_style)
3762      {
3763         snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3764         ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3765      }
3766    if (!ok)
3767      e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3768    if (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow")))
3769      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3770    else
3771      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3772
3773    evas_object_geometry_get(obj, &x, &y, &w, &h);
3774    evas_object_geometry_set(o, x, y, w, h);
3775    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3776
3777    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, NULL);
3778
3779    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, NULL);
3780    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, NULL);
3781    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, NULL);
3782    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3783    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, NULL);
3784    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, NULL);
3785
3786    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3787
3788    edje_object_part_swallow(o, "e.swallow.content", obj);
3789
3790    _e_comp_object_event_add(o);
3791
3792    if (vis)
3793      evas_object_show(o);
3794
3795    return o;
3796 }
3797
3798 /* utility functions for deleting objects when their "owner" is deleted */
3799 EINTERN void
3800 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3801 {
3802    Eina_List *l;
3803
3804    SOFT_ENTRY();
3805    EINA_SAFETY_ON_NULL_RETURN(to_del);
3806    l = evas_object_data_get(obj, "comp_object-to_del");
3807    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3808    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3809    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3810 }
3811
3812 EINTERN void
3813 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3814 {
3815    Eina_List *l;
3816
3817    SOFT_ENTRY();
3818    EINA_SAFETY_ON_NULL_RETURN(to_del);
3819    l = evas_object_data_get(obj, "comp_object-to_del");
3820    if (l)
3821      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3822 }
3823
3824 /////////////////////////////////////////////////////////
3825
3826 EINTERN Evas_Object *
3827 e_comp_object_client_add(E_Client *ec)
3828 {
3829    Evas_Object *o;
3830    E_Comp_Object *cw;
3831
3832    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3833    if (ec->frame) return NULL;
3834    _e_comp_smart_init();
3835    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3836    cw = evas_object_smart_data_get(o);
3837    if (!cw) return NULL;
3838    evas_object_data_set(o, "E_Client", ec);
3839    cw->ec = ec;
3840    ec->frame = o;
3841    evas_object_data_set(o, "comp_object", (void*)1);
3842
3843    _e_comp_object_event_add(o);
3844
3845    return o;
3846 }
3847
3848 /* utility functions for getting client inset */
3849 E_API void
3850 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3851 {
3852    API_ENTRY;
3853    if (!cw->client_inset.calc)
3854      {
3855         if (ax) *ax = x;
3856         if (ay) *ay = y;
3857         return;
3858      }
3859    if (ax) *ax = x - cw->client_inset.l;
3860    if (ay) *ay = y - cw->client_inset.t;
3861 }
3862
3863 E_API void
3864 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3865 {
3866    API_ENTRY;
3867    if (!cw->client_inset.calc)
3868      {
3869         if (ax) *ax = x;
3870         if (ay) *ay = y;
3871         return;
3872      }
3873    if (ax) *ax = x + cw->client_inset.l;
3874    if (ay) *ay = y + cw->client_inset.t;
3875 }
3876
3877 E_API void
3878 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3879 {
3880    API_ENTRY;
3881    if (!cw->client_inset.calc)
3882      {
3883         if (aw) *aw = w;
3884         if (ah) *ah = h;
3885         return;
3886      }
3887    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3888    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3889 }
3890
3891 E_API void
3892 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3893 {
3894    API_ENTRY;
3895    if (!cw->client_inset.calc)
3896      {
3897         if (aw) *aw = w;
3898         if (ah) *ah = h;
3899         return;
3900      }
3901    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3902    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3903 }
3904
3905 E_API E_Client *
3906 e_comp_object_client_get(Evas_Object *obj)
3907 {
3908    Evas_Object *o;
3909
3910    SOFT_ENTRY(NULL);
3911    /* FIXME: remove this when eo is used */
3912    o = evas_object_data_get(obj, "comp_smart_obj");
3913    if (o)
3914      return e_comp_object_client_get(o);
3915    return cw ? cw->ec : NULL;
3916 }
3917
3918 EINTERN void
3919 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3920 {
3921    API_ENTRY;
3922    if (cw->frame_extends)
3923      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3924    else
3925      {
3926         if (x) *x = 0;
3927         if (y) *y = 0;
3928         if (w) *w  = cw->ec->w;
3929         if (h) *h  = cw->ec->h;
3930      }
3931 }
3932
3933 EINTERN E_Zone *
3934 e_comp_object_util_zone_get(Evas_Object *obj)
3935 {
3936    E_Zone *zone = NULL;
3937
3938    SOFT_ENTRY(NULL);
3939    if (cw)
3940      zone = e_comp_zone_find_by_ec(cw->ec);
3941    if (!zone)
3942      {
3943         int x, y;
3944
3945         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3946         zone = e_comp_zone_xy_get(x, y);
3947      }
3948    return zone;
3949 }
3950
3951 EINTERN void
3952 e_comp_object_util_center(Evas_Object *obj)
3953 {
3954    int x, y, w, h, ow, oh;
3955    E_Zone *zone;
3956
3957    SOFT_ENTRY();
3958
3959    zone = e_comp_object_util_zone_get(obj);
3960    EINA_SAFETY_ON_NULL_RETURN(zone);
3961    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3962    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3963      ow = cw->ec->w, oh = cw->ec->h;
3964    else
3965      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3966    x = x + (w - ow) / 2;
3967    y = y + (h - oh) / 2;
3968    evas_object_move(obj, x, y);
3969 }
3970
3971 EINTERN void
3972 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3973 {
3974    int x, y, w, h, ow, oh;
3975
3976    SOFT_ENTRY();
3977    EINA_SAFETY_ON_NULL_RETURN(on);
3978    evas_object_geometry_get(on, &x, &y, &w, &h);
3979    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3980      ow = cw->ec->w, oh = cw->ec->h;
3981    else
3982      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3983    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3984 }
3985
3986 EINTERN void
3987 e_comp_object_util_fullscreen(Evas_Object *obj)
3988 {
3989    SOFT_ENTRY();
3990
3991    if (cw)
3992      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
3993    else
3994      {
3995         evas_object_move(obj, 0, 0);
3996         evas_object_resize(obj, e_comp->w, e_comp->h);
3997      }
3998 }
3999
4000 EINTERN void
4001 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
4002 {
4003    E_Zone *zone;
4004    int zx, zy, zw, zh;
4005    int ow, oh;
4006    SOFT_ENTRY();
4007
4008    if (cw)
4009      ow = cw->w, oh = cw->h;
4010    else
4011      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4012    zone = e_comp_object_util_zone_get(obj);
4013    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4014    if (x) *x = zx + (zw - ow) / 2;
4015    if (y) *y = zy + (zh - oh) / 2;
4016 }
4017
4018 EINTERN void
4019 e_comp_object_input_objs_del(Evas_Object *obj)
4020 {
4021    API_ENTRY;
4022    E_Input_Rect_Data *input_rect_data;
4023    E_Input_Rect_Smart_Data *input_rect_sd;
4024
4025    if (!cw->input_obj)
4026      return;
4027
4028    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4029    if (!input_rect_sd) return;
4030
4031    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
4032      {
4033         if (input_rect_data->obj)
4034           {
4035              evas_object_smart_member_del(input_rect_data->obj);
4036              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
4037           }
4038         E_FREE(input_rect_data);
4039      }
4040 }
4041
4042 E_API void
4043 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
4044 {
4045    API_ENTRY;
4046    E_Input_Rect_Data *input_rect_data = NULL;
4047    E_Input_Rect_Smart_Data *input_rect_sd;
4048    int client_w, client_h;
4049
4050    if (cw->ec->client.w)
4051      client_w = cw->ec->client.w;
4052    else
4053      client_w = cw->ec->w;
4054
4055    if (cw->ec->client.h)
4056      client_h = cw->ec->client.h;
4057    else
4058      client_h = cw->ec->h;
4059
4060    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
4061
4062    if (!cw->input_obj)
4063      {
4064         _e_comp_input_obj_smart_init();
4065         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
4066         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
4067         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4068
4069         if (input_rect_sd)
4070           input_rect_sd->cw = cw;
4071      }
4072
4073    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4074    if (input_rect_sd)
4075      {
4076         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
4077         if (input_rect_data)
4078           {
4079              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
4080              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
4081           }
4082      }
4083
4084    if ((input_rect_data) &&
4085        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
4086      {
4087         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
4088         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
4089         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
4090         evas_object_clip_set(input_rect_data->obj, cw->clip);
4091         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
4092         evas_object_geometry_set(input_rect_data->obj,
4093           cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l) + x,
4094           cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t) + y, w, h);
4095         evas_object_pass_events_set(cw->default_input_obj, 1);
4096         evas_object_pass_events_set(cw->obj, 1);
4097         if (cw->visible)
4098           {
4099              evas_object_show(input_rect_data->obj);
4100              evas_object_show(cw->input_obj);
4101           }
4102      }
4103    else
4104      {
4105         evas_object_smart_member_del(cw->input_obj);
4106         E_FREE_FUNC(cw->input_obj, evas_object_del);
4107         evas_object_pass_events_set(cw->default_input_obj, 0);
4108         evas_object_pass_events_set(cw->obj, 0);
4109      }
4110 }
4111
4112 E_API void
4113 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4114 {
4115    API_ENTRY;
4116    E_Input_Rect_Smart_Data *input_rect_sd;
4117    E_Input_Rect_Data *input_rect_data;
4118    Eina_List *l;
4119
4120    if (!cw->input_obj) return;
4121
4122    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4123    if (input_rect_sd)
4124      {
4125         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4126           {
4127              *list = eina_list_append(*list, &input_rect_data->rect);
4128           }
4129      }
4130 }
4131
4132 EINTERN void
4133 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4134 {
4135    API_ENTRY;
4136    if (l) *l = cw->client_inset.l;
4137    if (r) *r = cw->client_inset.r;
4138    if (t) *t = cw->client_inset.t;
4139    if (b) *b = cw->client_inset.b;
4140 }
4141
4142 /* set geometry for CSD */
4143 EINTERN void
4144 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4145 {
4146    Eina_Bool calc;
4147    int tx, ty, tw, th;
4148
4149    API_ENTRY;
4150    if (cw->frame_object)
4151      CRI("ACK! ec:%p", cw->ec);
4152    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4153        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4154    calc = cw->client_inset.calc;
4155    cw->client_inset.calc = l || r || t || b;
4156    eina_stringshare_replace(&cw->frame_theme, "borderless");
4157    if (cw->client_inset.calc)
4158      {
4159         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4160         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4161         e_client_size_set(cw->ec, tw, th);
4162      }
4163    else if (cw->ec->maximized || cw->ec->fullscreen)
4164      {
4165         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4166         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4167      }
4168    if (!cw->ec->new_client)
4169      {
4170         if (calc && cw->client_inset.calc)
4171           {
4172              tx = cw->ec->x - (l - cw->client_inset.l);
4173              ty = cw->ec->y - (t - cw->client_inset.t);
4174              e_client_pos_set(cw->ec, tx, ty);
4175           }
4176         cw->ec->changes.pos = cw->ec->changes.size = 1;
4177         EC_CHANGED(cw->ec);
4178      }
4179    cw->client_inset.l = l;
4180    cw->client_inset.r = r;
4181    cw->client_inset.t = t;
4182    cw->client_inset.b = b;
4183 }
4184
4185 EINTERN Eina_Bool
4186 e_comp_object_frame_allowed(Evas_Object *obj)
4187 {
4188    API_ENTRY EINA_FALSE;
4189    return (cw->frame_object || (!cw->client_inset.calc));
4190 }
4191
4192 EINTERN Eina_Bool
4193 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4194 {
4195    API_ENTRY EINA_FALSE;
4196    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4197    eina_stringshare_replace(&cw->frame_name, name);
4198    if (cw->frame_object)
4199      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4200    return EINA_TRUE;
4201 }
4202
4203 EINTERN Eina_Bool
4204 e_comp_object_frame_exists(Evas_Object *obj)
4205 {
4206    API_ENTRY EINA_FALSE;
4207    return !!cw->frame_object;
4208 }
4209
4210 EINTERN Eina_Bool
4211 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4212 {
4213    Evas_Object *o, *pbg;
4214    char buf[4096];
4215    int ok;
4216    Eina_Stringshare *theme;
4217
4218    API_ENTRY EINA_FALSE;
4219
4220    if (!e_util_strcmp(cw->frame_theme, name))
4221     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4222    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4223      return _e_comp_object_shadow_setup(cw);
4224    pbg = cw->frame_object;
4225    theme = eina_stringshare_add(name);
4226
4227    if (cw->frame_object)
4228      {
4229         int w, h;
4230
4231         w = cw->ec->w, h = cw->ec->h;
4232         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4233         if ((cw->ec->w != w) || (cw->ec->h != h))
4234           {
4235              cw->ec->changes.size = 1;
4236              EC_CHANGED(cw->ec);
4237           }
4238         E_FREE_FUNC(cw->frame_object, evas_object_del);
4239         if (!name) goto reshadow;
4240      }
4241    o = edje_object_add(e_comp->evas);
4242    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4243    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4244    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4245      {
4246         cw->frame_object = NULL;
4247         evas_object_del(o);
4248         eina_stringshare_del(cw->frame_theme);
4249         cw->frame_theme = theme;
4250         goto reshadow;
4251      }
4252    if (!ok)
4253      {
4254         if (theme != e_config->theme_default_border_style)
4255           {
4256              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4257              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4258           }
4259         if (!ok)
4260           {
4261              ok = e_theme_edje_object_set(o, "base/theme/border",
4262                                           "e/widgets/border/default/border");
4263              if (ok && (theme == e_config->theme_default_border_style))
4264                {
4265                   /* Reset default border style to default */
4266                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4267                   e_config_save_queue();
4268                }
4269           }
4270      }
4271
4272    if (ok)
4273      {
4274         cw->frame_object = o;
4275         eina_stringshare_del(cw->frame_theme);
4276         cw->frame_theme = theme;
4277         evas_object_name_set(o, "cw->frame_object");
4278
4279         if (cw->frame_name)
4280           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4281
4282         if (!pbg)
4283           {
4284              cw->ec->changes.icon = 1;
4285              EC_CHANGED(cw->ec);
4286           }
4287      }
4288    else
4289      {
4290         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4291         evas_object_del(o);
4292      }
4293 reshadow:
4294    if (cw->shobj)
4295      _e_comp_object_shadow_setup(cw);
4296    do
4297      {
4298         int old_x, old_y, new_x = 0, new_y = 0;
4299
4300         old_x = cw->x, old_y = cw->y;
4301
4302         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4303         if (pbg)
4304           new_x = cw->ec->x, new_y = cw->ec->y;
4305         else if (cw->ec->placed || (!cw->ec->new_client))
4306           {
4307              /* if no previous frame:
4308               * - reapply client_inset
4309               * - clamp to zone
4310               */
4311              int x, y;
4312
4313              if (cw->ec->changes.size)
4314                {
4315                   x = cw->ec->x;
4316                   y = cw->ec->y;
4317                }
4318              else
4319                {
4320                   E_Zone *zone;
4321                   zone = e_comp_zone_find_by_ec(cw->ec);
4322                   if (!zone) break;
4323
4324                   x = cw->ec->client.x, y = cw->ec->client.y;
4325                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4326                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4327                }
4328              new_x = x, new_y = y;
4329           }
4330
4331         if (old_x != new_x || old_y != new_y)
4332           {
4333              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4334              cw->y = cw->x = -99999;
4335              evas_object_move(obj, new_x, new_y);
4336           }
4337      } while (0);
4338
4339    if (cw->ec->maximized)
4340      {
4341         cw->ec->changes.need_maximize = 1;
4342         EC_CHANGED(cw->ec);
4343      }
4344    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4345    if (cw->frame_object)
4346      {
4347         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4348      }
4349    else
4350      cw->frame_extends = 0;
4351    evas_object_del(pbg);
4352    return EINA_TRUE;
4353 }
4354
4355 E_API void
4356 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4357 {
4358    E_Comp_Object_Mover *prov;
4359
4360    API_ENTRY;
4361    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4362    edje_object_signal_emit(cw->shobj, sig, src);
4363    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4364    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4365        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4366      return;
4367    /* start with highest priority callback first */
4368    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4369      {
4370         if (!e_util_glob_match(sig, prov->sig)) continue;
4371         if (prov->func(prov->data, obj, sig)) break;
4372      }
4373 }
4374
4375 E_API void
4376 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4377 {
4378    /* FIXME: at some point I guess this should use eo to inherit
4379     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4380     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4381     */
4382    API_ENTRY;
4383    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4384 }
4385
4386 E_API void
4387 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4388 {
4389    API_ENTRY;
4390    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4391 }
4392
4393 E_API void
4394 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4395 {
4396    API_ENTRY;
4397    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4398 }
4399
4400 E_API void
4401 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4402 {
4403    int tw, th;
4404    Eina_Rectangle rect;
4405    API_ENTRY;
4406
4407    if (cw->ec->input_only || (!cw->updates)) return;
4408    if (cw->nocomp) return;
4409    rect.x = x, rect.y = y;
4410    rect.w = w, rect.h = h;
4411    evas_object_smart_callback_call(obj, "damage", &rect);
4412
4413    if (e_comp_is_on_overlay(cw->ec))
4414      {
4415         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4416         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4417         * E module attempts to block screen update due to the particular policy.
4418         */
4419         if (e_pixmap_resource_get(cw->ec->pixmap))
4420           cw->hwc_need_update = EINA_TRUE;
4421      }
4422
4423    /* ignore overdraw */
4424    if (cw->updates_full)
4425      {
4426         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4427         e_comp_object_render_update_add(obj);
4428
4429         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4430           evas_object_show(cw->smart_obj);
4431
4432         return;
4433      }
4434    /* clip rect to client surface */
4435    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4436    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4437    /* if rect is the total size of the client after clip, clear the updates
4438     * since this is guaranteed to be the whole region anyway
4439     */
4440    eina_tiler_area_size_get(cw->updates, &tw, &th);
4441    if ((w > tw) || (h > th))
4442      {
4443         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4444         eina_tiler_clear(cw->updates);
4445         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4446         x = 0, y = 0;
4447         tw = cw->ec->client.w, th = cw->ec->client.h;
4448      }
4449    if ((!x) && (!y) && (w == tw) && (h == th))
4450      {
4451         eina_tiler_clear(cw->updates);
4452         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4453         cw->updates_full = 1;
4454         cw->update_count = 0;
4455      }
4456    cw->update_count++;
4457    if (cw->update_count > UPDATE_MAX)
4458      {
4459         /* this is going to get really dumb, so just update the whole thing */
4460         eina_tiler_clear(cw->updates);
4461         cw->update_count = cw->updates_full = 1;
4462         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4463         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4464      }
4465    else
4466      {
4467         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4468         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4469      }
4470    cw->updates_exist = 1;
4471    e_comp_object_render_update_add(obj);
4472
4473    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4474      evas_object_show(cw->smart_obj);
4475 }
4476
4477 EINTERN Eina_Bool
4478 e_comp_object_damage_exists(Evas_Object *obj)
4479 {
4480    API_ENTRY EINA_FALSE;
4481    return cw->updates_exist;
4482 }
4483
4484 EINTERN void
4485 e_comp_object_render_update_add(Evas_Object *obj)
4486 {
4487    API_ENTRY;
4488
4489    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4490    if (cw->render_update_lock.lock) return;
4491    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4492    if (!cw->update)
4493      {
4494         cw->update = 1;
4495         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4496      }
4497    e_comp_render_queue();
4498 }
4499
4500 EINTERN void
4501 e_comp_object_render_update_del(Evas_Object *obj)
4502 {
4503    API_ENTRY;
4504
4505    if (cw->ec->input_only || (!cw->updates)) return;
4506    if (!cw->update) return;
4507    cw->update = 0;
4508    /* this gets called during comp animating to clear the update flag */
4509    if (e_comp->grabbed) return;
4510    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4511    if (!e_comp->updates)
4512      {
4513         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4514         if (e_comp->render_animator)
4515           ecore_animator_freeze(e_comp->render_animator);
4516      }
4517 }
4518
4519 EINTERN void
4520 e_comp_object_shape_apply(Evas_Object *obj)
4521 {
4522    Eina_List *l;
4523    Evas_Object *o;
4524    unsigned int i, *pix, *p;
4525    int w, h, px, py;
4526
4527    API_ENTRY;
4528    if (!cw->ec) return; //NYI
4529    if (cw->external_content) return;
4530    if (cw->ec->shaped)
4531      {
4532         if ((cw->ec->shape_rects_num >= 1) &&
4533             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4534            return;
4535      }
4536    if (cw->native)
4537      {
4538         ERR("BUGGER: shape with native surface? cw=%p", cw);
4539         return;
4540      }
4541    evas_object_image_size_get(cw->obj, &w, &h);
4542    if ((w < 1) || (h < 1)) return;
4543
4544    if (cw->ec->shaped)
4545      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4546    _e_comp_object_alpha_set(cw);
4547    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4548       evas_object_image_alpha_set(o, 1);
4549
4550    p = pix = evas_object_image_data_get(cw->obj, 1);
4551    if (!pix)
4552      {
4553         evas_object_image_data_set(cw->obj, pix);
4554         return;
4555      }
4556    if (cw->ec->shaped)
4557      {
4558         unsigned char *spix, *sp;
4559
4560         spix = calloc(w * h, sizeof(unsigned char));
4561         if (!spix) return;
4562         for (i = 0; i < cw->ec->shape_rects_num; i++)
4563           {
4564              int rx, ry, rw, rh;
4565
4566              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4567              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4568              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4569              sp = spix + (w * ry) + rx;
4570              for (py = 0; py < rh; py++)
4571                {
4572                   for (px = 0; px < rw; px++)
4573                     {
4574                        *sp = 0xff; sp++;
4575                     }
4576                   sp += w - rw;
4577                }
4578           }
4579         sp = spix;
4580         for (py = 0; py < h; py++)
4581           {
4582              for (px = 0; px < w; px++)
4583                {
4584                   unsigned int mask, imask;
4585
4586                   mask = ((unsigned int)(*sp)) << 24;
4587                   imask = mask >> 8;
4588                   imask |= imask >> 8;
4589                   imask |= imask >> 8;
4590                   *p = mask | (*p & imask);
4591                   //if (*sp) *p = 0xff000000 | *p;
4592                   //else *p = 0x00000000;
4593                   sp++;
4594                   p++;
4595                }
4596           }
4597         free(spix);
4598      }
4599    else
4600       {
4601          for (py = 0; py < h; py++)
4602            {
4603               for (px = 0; px < w; px++)
4604                 *p |= 0xff000000;
4605            }
4606       }
4607    evas_object_image_data_set(cw->obj, pix);
4608    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4609    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4610      {
4611         evas_object_image_data_set(o, pix);
4612         evas_object_image_data_update_add(o, 0, 0, w, h);
4613      }
4614 // don't need to fix alpha chanel as blending
4615 // should be totally off here regardless of
4616 // alpha channel content
4617 }
4618
4619 static void
4620 _e_comp_object_clear(E_Comp_Object *cw)
4621 {
4622    Eina_List *l;
4623    Evas_Object *o;
4624
4625    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4626
4627    if (cw->render_update_lock.lock) return;
4628
4629    if (cw->ec->pixmap)
4630      e_pixmap_clear(cw->ec->pixmap);
4631    if (cw->native)
4632      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4633    evas_object_image_size_set(cw->obj, 1, 1);
4634    evas_object_image_data_set(cw->obj, NULL);
4635    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4636      {
4637         evas_object_image_size_set(o, 1, 1);
4638         evas_object_image_data_set(o, NULL);
4639      }
4640    cw->native = 0;
4641    e_comp_object_render_update_del(cw->smart_obj);
4642 }
4643
4644 static Eina_Bool
4645 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4646 {
4647     int r, g, b, a;
4648
4649     API_ENTRY EINA_FALSE;
4650
4651     if (cw->transparent.set == set)
4652        return EINA_TRUE;
4653
4654     if (set)
4655       {
4656          evas_object_color_get(obj, &r, &g, &b, &a);
4657          evas_object_color_set(obj, 0, 0, 0, 0);
4658
4659          cw->transparent.user_r = r;
4660          cw->transparent.user_g = g;
4661          cw->transparent.user_b = b;
4662          cw->transparent.user_a = a;
4663
4664          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4665                cw->ec,
4666                cw->transparent.user_r,
4667                cw->transparent.user_g,
4668                cw->transparent.user_b,
4669                cw->transparent.user_a);
4670
4671          cw->transparent.set = EINA_TRUE;
4672       }
4673     else
4674       {
4675          cw->transparent.set = EINA_FALSE;
4676
4677          evas_object_color_set(obj,
4678                                cw->transparent.user_r,
4679                                cw->transparent.user_g,
4680                                cw->transparent.user_b,
4681                                cw->transparent.user_a);
4682
4683          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4684                cw->ec,
4685                cw->transparent.user_r,
4686                cw->transparent.user_g,
4687                cw->transparent.user_b,
4688                cw->transparent.user_a);
4689       }
4690
4691    return EINA_TRUE;
4692 }
4693
4694 /* helper function to simplify toggling of redirection for display servers which support it */
4695 EINTERN void
4696 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4697 {
4698    API_ENTRY;
4699
4700    set = !!set;
4701    if (cw->redirected == set) return;
4702    cw->redirected = set;
4703    if (cw->external_content) return;
4704
4705    e_comp_object_map_update(obj);
4706
4707    if (set)
4708      {
4709         if (cw->updates_exist)
4710           e_comp_object_render_update_add(obj);
4711         else
4712           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4713
4714         _e_comp_object_transparent_set(obj, EINA_FALSE);
4715         evas_object_smart_callback_call(obj, "redirected", NULL);
4716      }
4717    else
4718      {
4719         _e_comp_object_clear(cw);
4720         _e_comp_object_transparent_set(obj, EINA_TRUE);
4721         evas_object_smart_callback_call(obj, "unredirected", NULL);
4722      }
4723 }
4724
4725 static void
4726 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4727 {
4728    E_Comp_Object *cw;
4729    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4730
4731    if (cw->buffer_destroy_listener.notify)
4732      {
4733         cw->buffer_destroy_listener.notify = NULL;
4734         wl_list_remove(&cw->buffer_destroy_listener.link);
4735      }
4736
4737    if (e_object_is_del(E_OBJECT(cw->ec)))
4738      {
4739         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4740           return;
4741      }
4742    else
4743      {
4744         /* if it's current displaying buffer, do not remove its content */
4745         if (!evas_object_visible_get(cw->ec->frame))
4746           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4747      }
4748 }
4749
4750 static void
4751 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4752 {
4753    Eina_List *l;
4754    Evas_Object *o;
4755
4756    if (cw->buffer_destroy_listener.notify)
4757      {
4758         wl_list_remove(&cw->buffer_destroy_listener.link);
4759         cw->buffer_destroy_listener.notify = NULL;
4760      }
4761
4762    if (cw->tbm_surface)
4763      {
4764         tbm_surface_internal_unref(cw->tbm_surface);
4765         cw->tbm_surface = NULL;
4766      }
4767
4768    if (ns)
4769      {
4770         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4771           {
4772              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4773              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4774           }
4775         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4776           {
4777              tbm_surface_internal_ref(ns->data.tbm.buffer);
4778              cw->tbm_surface = ns->data.tbm.buffer;
4779           }
4780      }
4781
4782    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4783    evas_object_image_native_surface_set(cw->obj, ns);
4784    TRACE_DS_END();
4785    if (with_mirror)
4786      {
4787         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4788           {
4789              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4790              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4791              evas_object_image_native_surface_set(o, ns);
4792              TRACE_DS_END();
4793           }
4794      }
4795 }
4796
4797 EINTERN void
4798 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4799 {
4800    Evas_Native_Surface ns;
4801
4802    API_ENTRY;
4803    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4804    if (cw->ec->input_only) return;
4805    if (cw->external_content) return;
4806    if (cw->render_update_lock.lock) return;
4807    set = !!set;
4808
4809    memset(&ns, 0, sizeof(Evas_Native_Surface));
4810
4811    if (set)
4812      {
4813         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4814         set = (!cw->ec->shaped);
4815         if (set)
4816           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4817      }
4818    cw->native = set;
4819
4820    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4821 }
4822
4823 EINTERN void
4824 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4825 {
4826    API_ENTRY;
4827    if (cw->ec->input_only) return;
4828    E_FREE(cw->ns);
4829    if (ns)
4830      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4831    _e_comp_object_alpha_set(cw);
4832    if (cw->native)
4833      e_comp_object_native_surface_set(obj, cw->native);
4834    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4835 }
4836
4837 EINTERN void
4838 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4839 {
4840    API_ENTRY;
4841
4842    set = !!set;
4843
4844    if (cw->blanked == set) return;
4845    cw->blanked = set;
4846    _e_comp_object_alpha_set(cw);
4847    if (set)
4848      {
4849         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4850         evas_object_image_data_set(cw->obj, NULL);
4851         return;
4852      }
4853    if (cw->native)
4854      e_comp_object_native_surface_set(obj, 1);
4855    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4856 }
4857
4858 static void
4859 _e_comp_object_damage_trace_rect_set(Evas_Object *obj, Eina_Rectangle *origin, int dmg_x, int dmg_y, int dmg_w, int dmg_h)
4860 {
4861    Evas_Object *o;
4862    int obj_x, obj_y;
4863
4864    if (!_damage_trace) return;
4865
4866    API_ENTRY;
4867
4868    if (!evas_object_visible_get(cw->obj)) return;
4869
4870    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4871
4872    o = evas_object_rectangle_add(e_comp->evas);
4873    evas_object_layer_set(o, E_LAYER_MAX);
4874    evas_object_name_set(o, "damage_trace");
4875    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4876    evas_object_resize(o, dmg_w, dmg_h);
4877    evas_object_color_set(o, 0, 128, 0, 128);
4878    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4879    evas_object_pass_events_set(o, EINA_TRUE);
4880    evas_object_show(o);
4881
4882    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4883          cw->ec,
4884          dmg_w, dmg_h, dmg_x, dmg_y,
4885          origin->w, origin->h, origin->x, origin->y);
4886
4887    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4888 }
4889
4890 /* mark an object as dirty and setup damages */
4891 E_API void
4892 e_comp_object_dirty(Evas_Object *obj)
4893 {
4894    Eina_Iterator *it;
4895    Eina_Rectangle *rect;
4896    Eina_List *ll;
4897    Evas_Object *o;
4898    int w, h, tw, th;
4899    Eina_Bool dirty, visible;
4900    E_Map *m = NULL;
4901
4902    API_ENTRY;
4903    if (cw->external_content) return;
4904    if (!cw->redirected) return;
4905    if (cw->render_update_lock.lock)
4906      {
4907         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4908         return;
4909      }
4910    /* only actually dirty if pixmap is available */
4911    if (!e_pixmap_resource_get(cw->ec->pixmap))
4912      {
4913         // e_pixmap_size_get returns last attached buffer size
4914         // eventhough it is destroyed
4915         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4916         return;
4917      }
4918    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4919    visible = cw->visible;
4920    if (!dirty) w = h = 1;
4921    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4922    if (!dirty)
4923      evas_object_image_data_set(cw->obj, NULL);
4924    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4925    evas_object_image_size_set(cw->obj, tw, th);
4926    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4927    if (cw->pending_updates)
4928      eina_tiler_area_size_set(cw->pending_updates, w, h);
4929    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4930      {
4931         evas_object_image_pixels_dirty_set(o, dirty);
4932         if (!dirty)
4933           evas_object_image_data_set(o, NULL);
4934         evas_object_image_size_set(o, tw, th);
4935         visible |= evas_object_visible_get(o);
4936      }
4937    if (!dirty)
4938      {
4939         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4940         return;
4941      }
4942
4943    e_comp_object_native_surface_set(obj, 1);
4944
4945    m = _e_comp_object_map_damage_transform_get(cw->ec);
4946    it = eina_tiler_iterator_new(cw->updates);
4947    EINA_ITERATOR_FOREACH(it, rect)
4948      {
4949         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4950          * of evas engine and doesn't convert damage according to evas_map.
4951          * so damage of evas_object_image use surface coordinate.
4952          */
4953         if (m)
4954           {
4955              int damage_x, damage_y, damage_w, damage_h;
4956
4957              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4958                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4959              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4960              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4961           }
4962         else
4963           {
4964              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4965              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4966           }
4967
4968         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4969           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4970         if (cw->pending_updates)
4971           eina_tiler_rect_add(cw->pending_updates, rect);
4972      }
4973    eina_iterator_free(it);
4974    if (m) e_map_free(m);
4975    if (cw->pending_updates)
4976      eina_tiler_clear(cw->updates);
4977    else
4978      {
4979         cw->pending_updates = cw->updates;
4980         cw->updates = eina_tiler_new(w, h);
4981         eina_tiler_tile_size_set(cw->updates, 1, 1);
4982      }
4983    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4984    evas_object_smart_callback_call(obj, "dirty", NULL);
4985    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4986    /* force render if main object is hidden but mirrors are visible */
4987    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4988    e_comp_object_render(obj);
4989 }
4990
4991 E_API Eina_Bool
4992 e_comp_object_render(Evas_Object *obj)
4993 {
4994    Eina_List *l;
4995    Evas_Object *o;
4996    int pw, ph;
4997    unsigned int *pix;
4998
4999    API_ENTRY EINA_FALSE;
5000
5001    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5002    if (cw->ec->input_only) return EINA_TRUE;
5003    if (cw->external_content) return EINA_TRUE;
5004    if (cw->native) return EINA_FALSE;
5005    /* if comp object is not redirected state, comp object should not be set by newly committed data
5006       because image size of comp object is 1x1 and it should not be shown on canvas */
5007    if (!cw->redirected) return EINA_TRUE;
5008    if (cw->render_update_lock.lock)
5009      {
5010         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5011         return EINA_TRUE;
5012      }
5013    e_comp_object_render_update_del(obj);
5014    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5015
5016    if (!cw->pending_updates)
5017      {
5018         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5019         evas_object_image_data_set(cw->obj, NULL);
5020         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5021           evas_object_image_data_set(o, NULL);
5022         return EINA_FALSE;
5023      }
5024
5025    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5026
5027    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5028
5029    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5030    if (!pix)
5031      {
5032         e_pixmap_image_refresh(cw->ec->pixmap);
5033         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5034      }
5035
5036    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5037      e_pixmap_image_data_ref(cw->ec->pixmap);
5038
5039    /* set pixel data */
5040    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5041    _e_comp_object_alpha_set(cw);
5042    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5043      {
5044         evas_object_image_data_set(o, pix);
5045         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5046         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5047      }
5048
5049    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5050
5051    e_comp_client_post_update_add(cw->ec);
5052
5053    return EINA_TRUE;
5054 }
5055
5056 /* create a duplicate of an evas object */
5057 E_API Evas_Object *
5058 e_comp_object_util_mirror_add(Evas_Object *obj)
5059 {
5060    Evas_Object *o;
5061    int w, h, tw, th;
5062    unsigned int *pix = NULL;
5063    Eina_Bool argb = EINA_FALSE;
5064
5065    SOFT_ENTRY(NULL);
5066
5067    if (!cw)
5068      cw = evas_object_data_get(obj, "comp_mirror");
5069    if (!cw)
5070      {
5071         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5072         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5073         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5074         evas_object_image_alpha_set(o, 1);
5075         evas_object_image_source_set(o, obj);
5076         return o;
5077      }
5078    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5079    if (cw->external_content)
5080      {
5081         ERR("%p of client %p is external content.", obj, cw->ec);
5082         return NULL;
5083      }
5084    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5085    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5086    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5087    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5088    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5089    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5090    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5091    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5092    evas_object_data_set(o, "comp_mirror", cw);
5093
5094    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5095    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5096
5097    evas_object_image_size_set(o, tw, th);
5098
5099    if (cw->ec->shaped)
5100      pix = evas_object_image_data_get(cw->obj, 0);
5101    else
5102      {
5103         if (cw->native)
5104           {
5105              if (cw->ns)
5106                evas_object_image_native_surface_set(o, cw->ns);
5107              else
5108                {
5109                   Evas_Native_Surface ns;
5110                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5111                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5112                     evas_object_image_native_surface_set(o, &ns);
5113                }
5114           }
5115         else
5116           {
5117              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5118              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5119              if ((argb) &&
5120                  (e_pixmap_image_exists(cw->ec->pixmap)))
5121                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5122              else
5123                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5124           }
5125      }
5126    if (pix)
5127      {
5128       Eina_Bool dirty;
5129
5130       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5131       evas_object_image_pixels_dirty_set(o, dirty);
5132       evas_object_image_data_set(o, pix);
5133       evas_object_image_data_set(cw->obj, pix);
5134       if (dirty)
5135         evas_object_image_data_update_add(o, 0, 0, tw, th);
5136    }
5137    return o;
5138 }
5139
5140 //////////////////////////////////////////////////////
5141
5142 EINTERN Eina_Bool
5143 e_comp_object_effect_allowed_get(Evas_Object *obj)
5144 {
5145    API_ENTRY EINA_FALSE;
5146
5147    if (!cw->shobj) return EINA_FALSE;
5148    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5149    return !e_comp_config_get()->match.disable_borders;
5150 }
5151
5152 /* setup an api effect for a client */
5153 E_API Eina_Bool
5154 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5155 {
5156    char buf[4096];
5157    Eina_Stringshare *grp;
5158    E_Comp_Config *config;
5159    Eina_Bool loaded = EINA_FALSE;
5160
5161    API_ENTRY EINA_FALSE;
5162    if (!cw->shobj) return EINA_FALSE; //input window
5163
5164    if (!effect) effect = "none";
5165    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5166
5167    config = e_comp_config_get();
5168    if ((config) && (config->effect_file))
5169      {
5170         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5171           {
5172              cw->effect_set = EINA_TRUE;
5173              loaded = EINA_TRUE;
5174           }
5175      }
5176
5177    if (!loaded)
5178      {
5179         edje_object_file_get(cw->effect_obj, NULL, &grp);
5180         cw->effect_set = !eina_streq(effect, "none");
5181         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5182         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5183           {
5184              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5185              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5186                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5187                  {
5188                     if (cw->effect_running)
5189                       {
5190                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5191                            return EINA_FALSE;
5192                       }
5193                     cw->effect_set = EINA_FALSE;
5194                     return cw->effect_set;
5195                  }
5196           }
5197      }
5198    if (cw->effect_running)
5199      {
5200         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5201           return EINA_FALSE;
5202      }
5203    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5204    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5205    if (cw->effect_clip)
5206      {
5207         evas_object_clip_unset(cw->clip);
5208         cw->effect_clip = 0;
5209      }
5210    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5211
5212    _e_comp_object_dim_update(cw);
5213
5214    return cw->effect_set;
5215 }
5216
5217 /* set params for embryo scripts in effect */
5218 E_API void
5219 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5220 {
5221    Edje_Message_Int_Set *msg;
5222    unsigned int x;
5223
5224    API_ENTRY;
5225    EINA_SAFETY_ON_NULL_RETURN(params);
5226    EINA_SAFETY_ON_FALSE_RETURN(count);
5227    if (!cw->effect_set) return;
5228
5229    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5230    msg->count = (int)count;
5231    for (x = 0; x < count; x++)
5232       msg->val[x] = params[x];
5233    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5234    edje_object_message_signal_process(cw->effect_obj);
5235 }
5236
5237 static void
5238 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5239 {
5240    Edje_Signal_Cb end_cb;
5241    void *end_data;
5242    E_Comp_Object *cw = data;
5243
5244    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5245    cw->effect_running = 0;
5246    if (!_e_comp_object_animating_end(cw)) return;
5247
5248    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5249      {
5250         evas_object_data_del(cw->smart_obj, "effect_running");
5251         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5252         e_comp_visibility_calculation_set(EINA_TRUE);
5253      }
5254
5255    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5256    if (!end_cb) return;
5257    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5258    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5259    end_cb(end_data, cw->smart_obj, emission, source);
5260 }
5261
5262 /* clip effect to client's zone */
5263 EINTERN void
5264 e_comp_object_effect_clip(Evas_Object *obj)
5265 {
5266    API_ENTRY;
5267    E_Zone *zone;
5268    zone = e_comp_zone_find_by_ec(cw->ec);
5269    if (!zone) return;
5270    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5271    if (!cw->effect_clip_able) return;
5272    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5273    cw->effect_clip = 1;
5274 }
5275
5276 /* unclip effect from client's zone */
5277 EINTERN void
5278 e_comp_object_effect_unclip(Evas_Object *obj)
5279 {
5280    API_ENTRY;
5281    if (!cw->effect_clip) return;
5282    evas_object_clip_unset(cw->smart_obj);
5283    cw->effect_clip = 0;
5284 }
5285
5286 /* start effect, running end_cb after */
5287 E_API Eina_Bool
5288 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5289 {
5290    API_ENTRY EINA_FALSE;
5291    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5292    if (!cw->effect_set) return EINA_FALSE;
5293
5294    if (cw->effect_running)
5295      {
5296         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5297      }
5298
5299    e_comp_object_effect_clip(obj);
5300    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5301
5302    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5303    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5304    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5305    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5306
5307    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5308    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5309
5310    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5311    _e_comp_object_animating_begin(cw);
5312    cw->effect_running = 1;
5313    return EINA_TRUE;
5314 }
5315
5316 /* stop a currently-running effect immediately */
5317 E_API Eina_Bool
5318 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5319 {
5320    int ret = 0;
5321    Edje_Signal_Cb end_cb_before = NULL;
5322    void *end_data_before = NULL;
5323    API_ENTRY EINA_FALSE;
5324
5325    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5326    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5327
5328    if (end_cb_before != end_cb) return EINA_TRUE;
5329    e_comp_object_effect_unclip(obj);
5330    if (cw->effect_clip)
5331      {
5332         evas_object_clip_unset(cw->effect_obj);
5333         cw->effect_clip = 0;
5334      }
5335    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5336    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5337
5338    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5339      {
5340         evas_object_data_del(cw->smart_obj, "effect_running");
5341         e_comp_visibility_calculation_set(EINA_TRUE);
5342      }
5343
5344    cw->effect_running = 0;
5345    ret = _e_comp_object_animating_end(cw);
5346
5347    if ((ret) && (end_cb_before))
5348      {
5349         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5350         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5351      }
5352
5353    return ret;
5354 }
5355
5356 static int
5357 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5358 {
5359    return a->pri - b->pri;
5360 }
5361
5362 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5363 E_API E_Comp_Object_Mover *
5364 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5365 {
5366    E_Comp_Object_Mover *prov;
5367
5368    prov = E_NEW(E_Comp_Object_Mover, 1);
5369    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5370    prov->func = provider;
5371    prov->data = (void*)data;
5372    prov->pri = pri;
5373    prov->sig = sig;
5374    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5375      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5376    return prov;
5377 }
5378
5379 E_API void
5380 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5381 {
5382    EINA_SAFETY_ON_NULL_RETURN(prov);
5383    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5384    free(prov);
5385 }
5386
5387 E_API Evas_Object *
5388 e_comp_object_effect_object_get(Evas_Object *obj)
5389 {
5390    API_ENTRY NULL;
5391
5392    return cw->effect_obj;
5393 }
5394
5395 E_API Eina_Bool
5396 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5397 {
5398    API_ENTRY EINA_FALSE;
5399    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5400    if (!cw->effect_set) return EINA_FALSE;
5401
5402    cw->hiding = set;
5403
5404    return EINA_TRUE;
5405 }
5406
5407 ////////////////////////////////////
5408
5409 static void
5410 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5411 {
5412    if (e_comp->autoclose.obj)
5413      {
5414         e_comp_ungrab_input(0, 1);
5415         if (e_comp->autoclose.del_cb)
5416           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5417         else if (!already_del)
5418           {
5419              evas_object_hide(e_comp->autoclose.obj);
5420              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5421           }
5422         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5423      }
5424    e_comp->autoclose.obj = NULL;
5425    e_comp->autoclose.data = NULL;
5426    e_comp->autoclose.del_cb = NULL;
5427    e_comp->autoclose.key_cb = NULL;
5428    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5429 }
5430
5431 static void
5432 _e_comp_object_autoclose_mouse_up_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
5433 {
5434    _e_comp_object_autoclose_cleanup(0);
5435 }
5436
5437 static void
5438 _e_comp_object_autoclose_setup(Evas_Object *obj)
5439 {
5440    if (!e_comp->autoclose.rect)
5441      {
5442         /* create rect just below autoclose object to catch mouse events */
5443         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5444         evas_object_move(e_comp->autoclose.rect, 0, 0);
5445         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5446         evas_object_show(e_comp->autoclose.rect);
5447         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5448         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5449         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5450         e_comp_grab_input(0, 1);
5451      }
5452    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5453    evas_object_focus_set(obj, 1);
5454 }
5455
5456 static void
5457 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5458 {
5459    _e_comp_object_autoclose_setup(obj);
5460    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5461 }
5462
5463 static void
5464 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5465 {
5466    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5467    _e_comp_object_autoclose_cleanup(1);
5468    if (e_client_focused_get()) return;
5469
5470    E_Zone *zone = e_zone_current_get();
5471    if (!zone) return;
5472
5473    e_zone_focus_reset(zone);
5474 }
5475
5476 EINTERN void
5477 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5478 {
5479    SOFT_ENTRY();
5480
5481    if (e_comp->autoclose.obj)
5482      {
5483         if (e_comp->autoclose.obj == obj) return;
5484         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5485         e_comp->autoclose.obj = obj;
5486         e_comp->autoclose.del_cb = del_cb;
5487         e_comp->autoclose.key_cb = cb;
5488         e_comp->autoclose.data = (void*)data;
5489         if (evas_object_visible_get(obj))
5490           _e_comp_object_autoclose_setup(obj);
5491         else
5492           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5493         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5494         return;
5495      }
5496    e_comp->autoclose.obj = obj;
5497    e_comp->autoclose.del_cb = del_cb;
5498    e_comp->autoclose.key_cb = cb;
5499    e_comp->autoclose.data = (void*)data;
5500    if (evas_object_visible_get(obj))
5501      _e_comp_object_autoclose_setup(obj);
5502    else
5503      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5504    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5505 }
5506
5507 E_API unsigned int
5508 e_comp_object_is_animating(Evas_Object *obj)
5509 {
5510    API_ENTRY 0;
5511
5512    return cw->animating;
5513 }
5514
5515 E_API void
5516 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5517 {
5518    API_ENTRY;
5519
5520    if ((cw->external_content) &&
5521        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5522      {
5523         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5524             "But current external content is %d object for %p.",
5525             cw->content_type, cw->ec);
5526         return;
5527      }
5528
5529    cw->user_alpha_set = EINA_TRUE;
5530    cw->user_alpha = alpha;
5531
5532    if (!cw->obj) return;
5533
5534    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5535
5536    evas_object_image_alpha_set(cw->obj, alpha);
5537
5538    if ((!cw->native) && (!cw->external_content))
5539      evas_object_image_data_set(cw->obj, NULL);
5540 }
5541
5542 EINTERN Eina_Bool
5543 e_comp_object_alpha_get(Evas_Object *obj)
5544 {
5545    API_ENTRY EINA_FALSE;
5546
5547    return evas_object_image_alpha_get(cw->obj);
5548 }
5549
5550 E_API void
5551 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5552 {
5553    Eina_Bool mask_set = EINA_FALSE;
5554    Evas_Object *o;
5555
5556    API_ENTRY;
5557    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5558    if (cw->ec->input_only) return;
5559    mask_set = !!set;
5560
5561    if (mask_set)
5562      {
5563         if (!cw->mask.obj)
5564           {
5565              o = evas_object_rectangle_add(e_comp->evas);
5566              evas_object_color_set(o, 0, 0, 0, 0);
5567              evas_object_clip_set(o, cw->clip);
5568              evas_object_smart_member_add(o, obj);
5569              evas_object_move(o, 0, 0);
5570              evas_object_resize(o, cw->w, cw->h);
5571              /* save render op value to restore when clear a mask.
5572               *
5573               * NOTE: DO NOT change the render op on ec->frame while mask object
5574               * is set. it will overwrite the changed op value. */
5575              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5576              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5577              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5578              if (cw->visible) evas_object_show(o);
5579
5580              cw->mask.obj = o;
5581              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5582              ELOGF("COMP", "         |mask_obj", cw->ec);
5583              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5584           }
5585      }
5586    else
5587      {
5588         if (cw->mask.obj)
5589           {
5590              evas_object_smart_member_del(cw->mask.obj);
5591              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5592
5593              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5594              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5595           }
5596      }
5597 }
5598
5599 E_API Eina_Bool
5600 e_comp_object_mask_has(Evas_Object *obj)
5601 {
5602    API_ENTRY EINA_FALSE;
5603
5604    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5605 }
5606
5607 EINTERN void
5608 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5609 {
5610    int tw, th;
5611    API_ENTRY;
5612
5613    if ((cw->external_content) &&
5614        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5615      {
5616         WRN("Can set up size to ONLY evas \"image\" object. "
5617             "But current external content is %d object for %p.",
5618             cw->content_type, cw->ec);
5619         return;
5620      }
5621
5622    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5623
5624    evas_object_image_size_set(cw->obj, tw, th);
5625 }
5626
5627 E_API void
5628 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5629 {
5630    Eina_Bool transform_set = EINA_FALSE;
5631    API_ENTRY;
5632    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5633    if (cw->ec->input_only) return;
5634
5635    transform_set = !!set;
5636
5637    if (transform_set)
5638      {
5639         if (!cw->transform_bg_obj)
5640           {
5641              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5642              evas_object_move(o, 0, 0);
5643              evas_object_resize(o, 1, 1);
5644              if (cw->transform_bg_color.a >= 255)
5645                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5646              else
5647                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5648              evas_object_color_set(o,
5649                                    cw->transform_bg_color.r,
5650                                    cw->transform_bg_color.g,
5651                                    cw->transform_bg_color.b,
5652                                    cw->transform_bg_color.a);
5653              if (cw->visible) evas_object_show(o);
5654
5655              cw->transform_bg_obj = o;
5656              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5657           }
5658         _e_comp_object_transform_obj_stack_update(obj);
5659      }
5660    else
5661      {
5662         if (cw->transform_bg_obj)
5663           {
5664              evas_object_smart_member_del(cw->transform_bg_obj);
5665              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5666           }
5667      }
5668 }
5669
5670 E_API void
5671 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5672 {
5673    API_ENTRY;
5674
5675    cw->transform_bg_color.r = r;
5676    cw->transform_bg_color.g = g;
5677    cw->transform_bg_color.b = b;
5678    cw->transform_bg_color.a = a;
5679
5680    if (cw->transform_bg_obj)
5681      {
5682         evas_object_color_set(cw->transform_bg_obj,
5683                               cw->transform_bg_color.r,
5684                               cw->transform_bg_color.g,
5685                               cw->transform_bg_color.b,
5686                               cw->transform_bg_color.a);
5687      }
5688 }
5689
5690 EINTERN void
5691 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5692 {
5693    API_ENTRY;
5694    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5695    if (cw->ec->input_only) return;
5696    if (!cw->transform_bg_obj) return;
5697
5698    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5699 }
5700
5701 EINTERN void
5702 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5703 {
5704    API_ENTRY;
5705    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5706    if (cw->ec->input_only) return;
5707    if (!cw->transform_bg_obj) return;
5708
5709    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5710 }
5711
5712 E_API void
5713 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5714 {
5715    Eina_Bool transform_set = EINA_FALSE;
5716    API_ENTRY;
5717    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5718    if (cw->ec->input_only) return;
5719
5720    transform_set = !!set;
5721
5722    if (transform_set)
5723      {
5724         if (!cw->transform_tranp_obj)
5725           {
5726              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5727              evas_object_move(o, 0, 0);
5728              evas_object_resize(o, 1, 1);
5729              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5730              evas_object_color_set(o, 0, 0, 0, 0);
5731              if (cw->visible) evas_object_show(o);
5732
5733              cw->transform_tranp_obj = o;
5734              evas_object_pass_events_set(cw->transform_tranp_obj, EINA_TRUE);
5735              ELOGF("TRANSFORM","transform set: TRUE", cw->ec);
5736              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5737           }
5738         _e_comp_object_transform_obj_stack_update(obj);
5739      }
5740    else
5741      {
5742         if (cw->transform_tranp_obj)
5743           {
5744              ELOGF("TRANSFORM","transform set: FALSE", cw->ec);
5745              evas_object_smart_member_del(cw->transform_tranp_obj);
5746              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5747           }
5748      }
5749 }
5750
5751 EINTERN void
5752 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5753 {
5754    API_ENTRY;
5755    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5756    if (cw->ec->input_only) return;
5757    if (!cw->transform_tranp_obj) return;
5758
5759    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5760 }
5761
5762 EINTERN void
5763 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5764 {
5765    API_ENTRY;
5766    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5767    if (cw->ec->input_only) return;
5768    if (!cw->transform_tranp_obj) return;
5769
5770    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5771 }
5772
5773 #ifdef REFACTOR_DESK_AREA
5774 #else
5775 EINTERN void
5776 e_comp_object_layer_update(Evas_Object *obj,
5777                            Evas_Object *above, Evas_Object *below)
5778 {
5779    E_Comp_Object *cw2 = NULL;
5780    Evas_Object *o = NULL;
5781    short layer;
5782
5783    API_ENTRY;
5784
5785    if (cw->ec->layer_block) return;
5786    if ((above) && (below))
5787      {
5788         ERR("Invalid layer update request! cw=%p", cw);
5789         return;
5790      }
5791
5792    o = above?:below;
5793
5794    if (o)
5795      {
5796         layer = evas_object_layer_get(o);
5797         cw2 = evas_object_data_get(o, "comp_obj");
5798         while (!cw2)
5799           {
5800              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5801
5802              o = evas_object_above_get(o);
5803              if ((!o) || (o == cw->smart_obj)) break;
5804              if (evas_object_layer_get(o) != layer)
5805                {
5806                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5807                }
5808              if (!o)
5809                {
5810                   E_Client *ec;
5811                   ec = e_client_top_get();
5812                   if (ec) o = ec->frame;
5813                }
5814
5815              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5816           }
5817      }
5818
5819    _e_comp_object_layers_remove(cw);
5820    if (cw2)
5821      {
5822         if (cw2->layer > cw->layer)
5823           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5824         else if (cw2->layer == cw->layer)
5825           {
5826              if (above)
5827                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5828              else if (o == obj)
5829                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5830              else if (below)
5831                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5832           }
5833         else
5834           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5835      }
5836    else
5837      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5838 }
5839 #endif
5840
5841 EINTERN int
5842 e_comp_object_layer_get(Evas_Object *obj)
5843 {
5844    API_ENTRY -1;
5845    return cw->layer;
5846 }
5847
5848 E_API Eina_Bool
5849 e_comp_object_content_set(Evas_Object *obj,
5850                           Evas_Object *content,
5851                           E_Comp_Object_Content_Type type)
5852 {
5853    API_ENTRY EINA_FALSE;
5854
5855    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5856    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5857    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5858
5859    if (cw->obj)
5860      {
5861         ERR("Can't set e.swallow.content to requested content. "
5862             "Previous comp object should not be changed at all.");
5863         return EINA_FALSE;
5864      }
5865
5866    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5867
5868    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5869        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5870      {
5871         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5872             type, content, cw->ec, cw->ec->pixmap);
5873         return EINA_FALSE;
5874      }
5875
5876    cw->external_content = EINA_TRUE;
5877
5878    cw->obj = content;
5879    cw->content_type = type;
5880    e_util_size_debug_set(cw->obj, 1);
5881    evas_object_name_set(cw->obj, "cw->obj");
5882    _e_comp_object_alpha_set(cw);
5883
5884    if (cw->shobj)
5885      _e_comp_object_shadow_setup(cw);
5886
5887    return EINA_TRUE;
5888 }
5889
5890 EINTERN Eina_Bool
5891 e_comp_object_content_unset(Evas_Object *obj)
5892 {
5893    API_ENTRY EINA_FALSE;
5894
5895    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5896    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5897
5898    if (!cw->obj && !cw->ec->visible)
5899      {
5900         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5901         return EINA_TRUE;
5902      }
5903
5904    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5905      {
5906         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5907         return EINA_TRUE;
5908      }
5909
5910    if (cw->obj)
5911      {
5912         if (cw->frame_object)
5913           edje_object_part_unswallow(cw->frame_object, cw->obj);
5914         else if (cw->shobj)
5915           edje_object_part_unswallow(cw->shobj, cw->obj);
5916
5917         evas_object_del(cw->obj);
5918         evas_object_hide(cw->obj);
5919         cw->obj = NULL;
5920      }
5921
5922    cw->external_content = EINA_FALSE;
5923    if (cw->ec->is_cursor)
5924      {
5925         int pw, ph;
5926         DBG("%p is cursor surface..", cw->ec);
5927         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5928           pw = ph = 1;
5929         evas_object_resize(cw->ec->frame, pw, ph);
5930         evas_object_hide(cw->ec->frame);
5931         return EINA_TRUE;
5932      }
5933
5934
5935    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5936    cw->obj = evas_object_image_filled_add(e_comp->evas);
5937    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5938    e_util_size_debug_set(cw->obj, 1);
5939    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5940    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5941    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5942    evas_object_name_set(cw->obj, "cw->obj");
5943    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5944    _e_comp_object_alpha_set(cw);
5945
5946    if (cw->shobj)
5947      _e_comp_object_shadow_setup(cw);
5948
5949    if (cw->visible)
5950      {
5951         cw->visible = 0;
5952         _e_comp_intercept_show_helper(cw);
5953         cw->visible = 1;
5954      }
5955
5956    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5957    e_comp_object_dirty(cw->smart_obj);
5958    e_comp_object_render(cw->smart_obj);
5959    e_comp_object_render_update_add(obj);
5960
5961    return EINA_TRUE;
5962 }
5963
5964 EINTERN Evas_Object *
5965 e_comp_object_content_get(Evas_Object *obj)
5966 {
5967    API_ENTRY NULL;
5968
5969    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5970
5971    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5972      {
5973         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5974         return NULL;
5975      }
5976
5977    return cw->obj;
5978 }
5979
5980 E_API E_Comp_Object_Content_Type
5981 e_comp_object_content_type_get(Evas_Object *obj)
5982 {
5983    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
5984
5985    return cw->content_type;
5986 }
5987
5988 E_API void
5989 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
5990 {
5991    API_ENTRY;
5992    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5993    E_Comp_Config *conf = e_comp_config_get();
5994    if (cw->ec->input_only) return;
5995    if (!conf->dim_rect_enable) return;
5996
5997    cw->dim.mask_set = mask_set;
5998    cw->dim.mask_x = x;
5999    cw->dim.mask_y = y;
6000    cw->dim.mask_w = w;
6001    cw->dim.mask_h = h;
6002
6003    if (!cw->dim.enable) return;
6004    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
6005 }
6006
6007 EINTERN void
6008 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6009 {
6010    Eina_Bool mask_set = EINA_FALSE;
6011    Evas_Object *o;
6012
6013    API_ENTRY;
6014    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6015    E_Comp_Config *conf = e_comp_config_get();
6016    if (cw->ec->input_only) return;
6017    if (!conf->dim_rect_enable) return;
6018
6019    mask_set = !!set;
6020
6021    if (mask_set)
6022      {
6023         if (cw->dim.mask_obj)
6024           {
6025              evas_object_smart_member_del(cw->dim.mask_obj);
6026              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6027           }
6028
6029         ELOGF("COMP", "DIM  |Mask applied on Dim rect mask_rect[%d %d %d %d]", cw->ec, cw->dim.mask_x, cw->dim.mask_y, cw->dim.mask_w, cw->dim.mask_h);
6030         o = evas_object_rectangle_add(e_comp->evas);
6031         evas_object_color_set(o, 0, 0, 0, 0);
6032         evas_object_smart_member_add(o, obj);
6033         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6034         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6035
6036         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6037         if (cw->visible) evas_object_show(o);
6038
6039         cw->dim.mask_obj = o;
6040         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6041
6042         evas_object_layer_set(cw->dim.mask_obj, 9998);
6043      }
6044    else
6045      {
6046         if (cw->dim.mask_obj)
6047           {
6048              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6049              evas_object_smart_member_del(cw->dim.mask_obj);
6050              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6051           }
6052      }
6053 }
6054
6055 E_API void
6056 e_comp_object_dim_client_set(E_Client *ec)
6057 {
6058    E_Comp_Config *conf = e_comp_config_get();
6059
6060    if (!conf->dim_rect_enable) return ;
6061    if (dim_client == ec) return;
6062
6063    Eina_Bool prev_dim = EINA_FALSE;
6064    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6065
6066    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6067       prev_dim = EINA_TRUE;
6068
6069    if (prev_dim && dim_client->visible && ec)
6070      {
6071         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6072         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6073      }
6074    else
6075      {
6076         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6077         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6078      }
6079    dim_client = ec;
6080 }
6081
6082 EINTERN E_Client *
6083 e_comp_object_dim_client_get(void)
6084 {
6085    E_Comp_Config *conf = e_comp_config_get();
6086
6087    if (!conf->dim_rect_enable ) return NULL;
6088
6089    return dim_client;
6090 }
6091
6092 static void
6093 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6094 {
6095    API_ENTRY;
6096    char emit[32] = "\0";
6097    E_Comp_Config *conf = e_comp_config_get();
6098
6099    if (!ec) return;
6100    if (!conf->dim_rect_enable) return;
6101    if (!cw->effect_obj) return;
6102    if (enable == cw->dim.enable) return;
6103
6104    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6105    if (noeffect || !conf->dim_rect_effect)
6106      {
6107         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6108      }
6109    else
6110      {
6111         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6112      }
6113
6114    cw->dim.enable = enable;
6115
6116    if (cw->dim.mask_set && !enable)
6117      {
6118         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6119         edje_object_signal_emit(cw->effect_obj, emit, "e");
6120      }
6121    else if (cw->dim.mask_set && enable)
6122      {
6123         edje_object_signal_emit(cw->effect_obj, emit, "e");
6124         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6125      }
6126    else
6127      {
6128         edje_object_signal_emit(cw->effect_obj, emit, "e");
6129      }
6130 }
6131
6132 static Eina_Bool
6133 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6134 {
6135    API_ENTRY EINA_FALSE;
6136    E_Comp_Config *conf = e_comp_config_get();
6137
6138    if (!ec) return EINA_FALSE;
6139    if (!conf->dim_rect_enable) return EINA_FALSE;
6140
6141    if (cw->dim.enable) return EINA_TRUE;
6142
6143    return EINA_FALSE;
6144 }
6145
6146 static void
6147 _e_comp_object_dim_update(E_Comp_Object *cw)
6148 {
6149    E_Comp_Config *conf = e_comp_config_get();
6150
6151    if (!cw) return;
6152    if (!conf->dim_rect_enable) return;
6153    if (!cw->effect_obj) return;
6154    if (cw->dim.enable)
6155      {
6156         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6157         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6158
6159         if (cw->dim.mask_set)
6160           {
6161              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6162           }
6163      }
6164 }
6165
6166 EINTERN void
6167 e_comp_object_clear(Evas_Object *obj)
6168 {
6169    API_ENTRY;
6170
6171    _e_comp_object_clear(cw);
6172 }
6173
6174 EINTERN Eina_Bool
6175 e_comp_object_hwc_update_exists(Evas_Object *obj)
6176 {
6177    API_ENTRY EINA_FALSE;
6178    return cw->hwc_need_update;
6179 }
6180
6181 // will remove out
6182 E_API void
6183 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6184 {
6185    API_ENTRY;
6186    cw->hwc_need_update = set;
6187 }
6188
6189 E_API Eina_Bool
6190 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6191 {
6192    API_ENTRY EINA_FALSE;
6193    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6194 }
6195
6196 EINTERN void
6197 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6198 {
6199    API_ENTRY;
6200    if (cw->indicator.obj != indicator)
6201      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6202    cw->indicator.obj = indicator;
6203    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6204 }
6205
6206 EINTERN void
6207 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6208 {
6209    API_ENTRY;
6210    if (cw->indicator.obj != indicator) return;
6211    cw->indicator.obj = NULL;
6212    edje_object_part_unswallow(cw->shobj, indicator);
6213 }
6214
6215 EINTERN void
6216 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6217 {
6218    API_ENTRY;
6219    Edje_Message_Int_Set *msg;
6220
6221    if (!cw->indicator.obj) return;
6222
6223    cw->indicator.w = w;
6224    cw->indicator.h = h;
6225
6226    if (!cw->shobj) return;
6227
6228    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6229    msg->count = 2;
6230    msg->val[0] = w;
6231    msg->val[1] = h;
6232    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6233    edje_object_message_signal_process(cw->shobj);
6234 }
6235
6236 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6237 EINTERN void
6238 e_comp_object_map_update(Evas_Object *obj)
6239 {
6240    API_ENTRY;
6241    E_Client *ec = cw->ec;
6242    E_Comp_Wl_Client_Data *cdata;
6243    E_Map *map;
6244    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6245    char buffer[128];
6246    char *p = buffer;
6247    int l, remain = sizeof buffer;
6248
6249    if (!ec) return;
6250    if (e_object_is_del(E_OBJECT(ec))) return;
6251    cdata = e_client_cdata_get(ec);
6252    if (!cdata) return;
6253
6254    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6255     * when new buffer is attached.
6256     */
6257    if (!cdata->buffer_ref.buffer) return;
6258
6259    if ((!cw->redirected) ||
6260        (e_client_video_hw_composition_check(ec)) ||
6261        (!e_comp_wl_output_buffer_transform_get(ec) &&
6262         cdata->scaler.buffer_viewport.buffer.scale == 1))
6263      {
6264         if (evas_object_map_enable_get(cw->effect_obj))
6265           {
6266              ELOGF("TRANSFORM", "map: disable", cw->ec);
6267              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6268              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6269              evas_object_resize(cw->effect_obj, tw, th);
6270           }
6271
6272         return;
6273      }
6274
6275    map = e_map_new();
6276    EINA_SAFETY_ON_NULL_RETURN(map);
6277
6278    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6279
6280    x1 = y1 = 0;
6281    x2 = bw;
6282    y2 = bh;
6283
6284    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6285
6286    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6287    e_map_point_image_uv_set(map, 0, x, y);
6288    l = snprintf(p, remain, "%d,%d", x, y);
6289    p += l, remain -= l;
6290
6291    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6292    e_map_point_image_uv_set(map, 1, x, y);
6293    l = snprintf(p, remain, " %d,%d", x, y);
6294    p += l, remain -= l;
6295
6296    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6297    e_map_point_image_uv_set(map, 2, x, y);
6298    l = snprintf(p, remain, " %d,%d", x, y);
6299    p += l, remain -= l;
6300
6301    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6302    e_map_point_image_uv_set(map, 3, x, y);
6303    l = snprintf(p, remain, " %d,%d", x, y);
6304    p += l, remain -= l;
6305
6306    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6307          cw->ec,
6308          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6309
6310    e_comp_object_map_set(cw->effect_obj, map);
6311    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6312
6313    e_map_free(map);
6314
6315    /* if there's screen rotation with comp mode, then ec->effect_obj and
6316     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6317     */
6318    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6319    evas_object_resize(cw->effect_obj, tw, th);
6320 }
6321
6322 EINTERN Eina_Bool
6323 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6324 {
6325    API_ENTRY EINA_FALSE;
6326
6327    cw->render_trace = set;
6328
6329    return EINA_TRUE;
6330 }
6331
6332 E_API Eina_Bool
6333 e_comp_object_native_usable_get(Evas_Object *obj)
6334 {
6335    API_ENTRY EINA_FALSE;
6336    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6337
6338    if (cw->ec->input_only) return EINA_FALSE;
6339    if (cw->external_content) return EINA_FALSE;
6340    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6341
6342    /* just return true value, if it is normal case */
6343    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6344
6345    /* abnormal case */
6346    Evas_Native_Surface *ns;
6347    ns = evas_object_image_native_surface_get(cw->obj);
6348
6349    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6350    if (ns)
6351      {
6352         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6353         return EINA_TRUE;
6354      }
6355
6356    return EINA_FALSE;
6357 }
6358
6359 EINTERN Eina_Bool
6360 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6361 {
6362    API_ENTRY EINA_FALSE;
6363    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6364    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6365    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6366
6367    switch (filter)
6368      {
6369       case E_COMP_IMAGE_FILTER_BLUR:
6370          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6371          break;
6372       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6373          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6374          break;
6375       case E_COMP_IMAGE_FILTER_INVERSE:
6376          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6377          break;
6378       case E_COMP_IMAGE_FILTER_NONE:
6379       default:
6380          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6381          break;
6382      }
6383
6384    cw->image_filter = filter;
6385
6386    return EINA_TRUE;
6387 }
6388
6389 EINTERN E_Comp_Image_Filter
6390 e_comp_object_image_filter_get(Evas_Object *obj)
6391 {
6392    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6393    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6394    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6395    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6396
6397    return cw->image_filter;
6398 }
6399
6400 static void
6401 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6402 {
6403    Evas_Object *obj;
6404
6405    if (!_damage_trace) return;
6406
6407    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6408      evas_object_del(obj);
6409
6410    _damage_trace_post_objs = NULL;
6411 }
6412
6413 static void
6414 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6415 {
6416    if (!_damage_trace) return;
6417
6418    _damage_trace_post_objs = _damage_trace_objs;
6419    _damage_trace_objs = NULL;
6420 }
6421
6422 EINTERN void
6423 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6424 {
6425    if (_damage_trace == onoff) return;
6426
6427    if (onoff)
6428      {
6429         evas_event_callback_add(e_comp->evas,
6430                                 EVAS_CALLBACK_RENDER_PRE,
6431                                 _e_comp_object_damage_trace_render_pre_cb,
6432                                 NULL);
6433
6434         evas_event_callback_add(e_comp->evas,
6435                                 EVAS_CALLBACK_RENDER_POST,
6436                                 _e_comp_object_damage_trace_render_post_cb,
6437                                 NULL);
6438      }
6439    else
6440      {
6441         Evas_Object *obj;
6442
6443         EINA_LIST_FREE(_damage_trace_objs, obj)
6444           evas_object_del(obj);
6445
6446         _damage_trace_objs = NULL;
6447
6448         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6449           evas_object_del(obj);
6450
6451         _damage_trace_post_objs = NULL;
6452
6453         evas_event_callback_del(e_comp->evas,
6454                                 EVAS_CALLBACK_RENDER_PRE,
6455                                 _e_comp_object_damage_trace_render_pre_cb);
6456
6457         evas_event_callback_del(e_comp->evas,
6458                                 EVAS_CALLBACK_RENDER_POST,
6459                                 _e_comp_object_damage_trace_render_post_cb);
6460      }
6461
6462    _damage_trace = onoff;
6463 }
6464
6465 EINTERN Eina_Bool
6466 e_comp_object_redirected_get(Evas_Object *obj)
6467 {
6468    API_ENTRY EINA_FALSE;
6469    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6470
6471    return cw->redirected;
6472 }
6473
6474 EINTERN Eina_Bool
6475 e_comp_object_color_visible_get(Evas_Object *obj)
6476 {
6477    API_ENTRY EINA_FALSE;
6478    int a;
6479
6480    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6481
6482    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6483    if (a <= 0)
6484      return EINA_FALSE;
6485
6486    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6487    if (a <= 0)
6488      return EINA_FALSE;
6489
6490    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6491    if (a <= 0)
6492      return EINA_FALSE;
6493
6494    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6495    if (a <= 0)
6496      return EINA_FALSE;
6497
6498    return EINA_TRUE;
6499 }
6500
6501 E_API Eina_Bool
6502 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6503 {
6504    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6505
6506    return e_map_set_to_comp_object(em, obj);
6507 }
6508
6509 EINTERN E_Map *
6510 e_comp_object_map_get(const Evas_Object *obj)
6511 {
6512    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6513
6514    return e_map_get_from_comp_object(obj);
6515 }
6516
6517 E_API Eina_Bool
6518 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6519 {
6520    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6521
6522    evas_object_map_enable_set(obj, enable);
6523
6524    return EINA_TRUE;
6525 }
6526
6527 E_API Eina_Bool
6528 e_comp_object_render_update_lock(Evas_Object *obj)
6529 {
6530    E_Comp_Wl_Buffer *buffer;
6531    struct wayland_tbm_client_queue *cqueue;
6532
6533    API_ENTRY EINA_FALSE;
6534
6535    if (cw->render_update_lock.lock == 0)
6536      {
6537         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6538
6539         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6540         if ((buffer) && (buffer->resource))
6541           {
6542              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6543              if (cqueue)
6544                wayland_tbm_server_client_queue_flush(cqueue);
6545           }
6546
6547         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6548         e_comp_object_render_update_del(obj);
6549
6550         ELOGF("COMP", "Render update lock enabled", cw->ec);
6551      }
6552
6553    cw->render_update_lock.lock++;
6554
6555    return EINA_TRUE;
6556 }
6557
6558 E_API void
6559 e_comp_object_render_update_unlock(Evas_Object *obj)
6560 {
6561    API_ENTRY;
6562
6563    if (cw->render_update_lock.lock == 0)
6564      return;
6565
6566    cw->render_update_lock.lock--;
6567
6568    if (cw->render_update_lock.lock == 0)
6569      {
6570
6571         if (cw->render_update_lock.pending_move_set)
6572           {
6573              evas_object_move(obj,
6574                               cw->render_update_lock.pending_move_x,
6575                               cw->render_update_lock.pending_move_y);
6576              cw->render_update_lock.pending_move_x = 0;
6577              cw->render_update_lock.pending_move_y = 0;
6578              cw->render_update_lock.pending_move_set = EINA_FALSE;
6579           }
6580
6581         if (cw->render_update_lock.pending_resize_set)
6582           {
6583              evas_object_resize(obj,
6584                                 cw->render_update_lock.pending_resize_w,
6585                                 cw->render_update_lock.pending_resize_h);
6586              cw->render_update_lock.pending_resize_w = 0;
6587              cw->render_update_lock.pending_resize_h = 0;
6588              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6589           }
6590
6591         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6592
6593         if ((cw->ec->exp_iconify.buffer_flush) &&
6594             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6595             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6596           e_comp_object_clear(obj);
6597         else
6598           e_comp_object_render_update_add(obj);
6599
6600         ELOGF("COMP", "Render update lock disabled", cw->ec);
6601      }
6602 }
6603
6604 E_API Eina_Bool
6605 e_comp_object_render_update_lock_get(Evas_Object *obj)
6606 {
6607    API_ENTRY EINA_FALSE;
6608
6609    if (cw->render_update_lock.lock > 0)
6610      return EINA_TRUE;
6611
6612    return EINA_FALSE;
6613 }
6614
6615 E_API void
6616 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6617 {
6618    API_ENTRY;
6619
6620    if (cw->transparent.set)
6621      {
6622         if (r) *r = cw->transparent.user_r;
6623         if (g) *g = cw->transparent.user_g;
6624         if (b) *b = cw->transparent.user_b;
6625         if (a) *a = cw->transparent.user_a;
6626      }
6627    else
6628      {
6629         evas_object_color_get(obj, r, g, b, a);
6630      }
6631 }
6632
6633 EINTERN void
6634 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6635 {
6636    API_ENTRY;
6637
6638    evas_object_render_op_set(cw->obj, op);
6639 }
6640
6641 EINTERN Evas_Render_Op
6642 e_comp_object_render_op_get(Evas_Object *obj)
6643 {
6644    API_ENTRY EVAS_RENDER_BLEND;
6645
6646    return evas_object_render_op_get(cw->obj);
6647 }
6648
6649 EINTERN void
6650 e_comp_object_lower_listener_add(Evas_Object *obj, struct wl_listener *listener)
6651 {
6652    API_ENTRY;
6653    wl_signal_add(&cw->events.lower, listener);
6654 }
6655
6656 #ifdef REFACTOR_DESK_AREA
6657 EINTERN void
6658 e_comp_object_lower_done_listener_add(Evas_Object *obj, struct wl_listener *listener)
6659 {
6660    API_ENTRY;
6661    wl_signal_add(&cw->events.lower_done, listener);
6662 }
6663
6664 EINTERN void
6665 e_comp_object_raise_listener_add(Evas_Object *obj, struct wl_listener *listener)
6666 {
6667    API_ENTRY;
6668    wl_signal_add(&cw->events.raise, listener);
6669 }
6670 #endif
6671
6672 EINTERN void
6673 e_comp_object_show_listener_add(Evas_Object *obj, struct wl_listener *listener)
6674 {
6675    API_ENTRY;
6676    wl_signal_add(&cw->events.show, listener);
6677 }
6678
6679 EINTERN void
6680 e_comp_object_hide_listener_add(Evas_Object *obj, struct wl_listener *listener)
6681 {
6682    API_ENTRY;
6683    wl_signal_add(&cw->events.hide, listener);
6684 }
6685
6686 #ifdef REFACTOR_DESK_AREA
6687 EINTERN void
6688 e_comp_object_set_layer_listener_add(Evas_Object *obj, struct wl_listener *listener)
6689 {
6690    API_ENTRY;
6691    wl_signal_add(&cw->events.set_layer, listener);
6692 }
6693
6694 EINTERN void
6695 e_comp_object_stack_above_listener_add(Evas_Object *obj, struct wl_listener *listener)
6696 {
6697    API_ENTRY;
6698    wl_signal_add(&cw->events.stack_above, listener);
6699 }
6700
6701 EINTERN void
6702 e_comp_object_stack_below_listener_add(Evas_Object *obj, struct wl_listener *listener)
6703 {
6704    API_ENTRY;
6705    wl_signal_add(&cw->events.stack_below, listener);
6706 }
6707 #endif