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