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