e_comp_object: fix the comp object is shown even if ec is iconic
[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                   if (e_client_focus_track_enabled())
2700                     e_client_focus_latest_set(ec);
2701                   return;
2702                }
2703           }
2704         if (!ec->visible)
2705           {
2706              return;
2707           }
2708         if ((!ec->sticky) && (ec->desk) && (!ec->desk->visible))
2709           {
2710              if (ec->desk->animate_count) return;
2711              e_desk_show(ec->desk);
2712              if (!ec->desk->visible) return;
2713           }
2714      }
2715
2716    if (focus)
2717      {
2718         if (!cw->visible)
2719           {
2720              /* not yet visible, wait till the next time... */
2721              ec->want_focus = !ec->hidden;
2722              if (ec->want_focus)
2723                EC_CHANGED(ec);
2724              return;
2725           }
2726         e_client_focused_set(ec);
2727      }
2728    else
2729      {
2730         if (e_client_focused_get() == ec)
2731           e_client_focused_set(NULL);
2732      }
2733
2734    if (focus)
2735      ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2736    else
2737      ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2738
2739    evas_object_focus_set(obj, focus);
2740 }
2741
2742 static void
2743 _e_comp_intercept_color_set(void *data, Evas_Object *obj, int r, int g, int b, int a)
2744 {
2745    E_Comp_Object *cw = data;
2746
2747    if (cw->transparent.set)
2748      {
2749         cw->transparent.user_r = r;
2750         cw->transparent.user_g = g;
2751         cw->transparent.user_b = b;
2752         cw->transparent.user_a = a;
2753
2754         ELOGF("COMP", "Transparent user_color(%d,%d,%d,%d)",
2755               cw->ec,
2756               cw->transparent.user_r,
2757               cw->transparent.user_g,
2758               cw->transparent.user_b,
2759               cw->transparent.user_a);
2760      }
2761    else
2762      {
2763         evas_object_color_set(obj, r, g, b, a);
2764      }
2765 }
2766 ////////////////////////////////////////////////////
2767
2768 static void
2769 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2770 {
2771    int w, h, ox, oy, ow, oh;
2772    Eina_List *l;
2773    Eina_Bool pass_event_flag = EINA_FALSE;
2774    E_Input_Rect_Data *input_rect_data;
2775    E_Input_Rect_Smart_Data *input_rect_sd;
2776
2777    if (cw->frame_object)
2778      {
2779         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2780         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2781         /* set a fixed size, force edje calc, check size difference */
2782         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2783         edje_object_message_signal_process(cw->frame_object);
2784         edje_object_calc_force(cw->frame_object);
2785         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2786         cw->client_inset.l = ox;
2787         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2788         cw->client_inset.t = oy;
2789         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2790         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2791         evas_object_resize(cw->frame_object, w, h);
2792
2793         if (cw->input_obj)
2794           {
2795              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2796              if (input_rect_sd)
2797                {
2798                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2799                     {
2800                        if (input_rect_data->obj)
2801                          {
2802                             pass_event_flag = EINA_TRUE;
2803                             break;
2804                          }
2805                     }
2806                }
2807           }
2808         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2809         evas_object_pass_events_set(cw->obj, pass_event_flag);
2810      }
2811    else
2812      {
2813         cw->client_inset.l = 0;
2814         cw->client_inset.r = 0;
2815         cw->client_inset.t = 0;
2816         cw->client_inset.b = 0;
2817      }
2818    cw->client_inset.calc = !!cw->frame_object;
2819 }
2820
2821 static void
2822 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2823 {
2824    E_Comp_Object *cw = data;
2825    E_Zone *zone;
2826    int w, h, pw, ph;
2827
2828    /* - get current size
2829     * - calc new size
2830     * - readjust for new frame size
2831     */
2832
2833    w = cw->ec->w, h = cw->ec->h;
2834    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2835
2836    _e_comp_object_frame_recalc(cw);
2837
2838    if (!cw->ec->fullscreen)
2839      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2840
2841    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2842    if (cw->ec->shading || cw->ec->shaded) return;
2843    if (cw->ec->fullscreen)
2844      {
2845         zone = e_comp_zone_find_by_ec(cw->ec);
2846         if (!zone) return;
2847         evas_object_resize(cw->ec->frame, zone->w, zone->h);
2848      }
2849    else if (cw->ec->new_client)
2850      {
2851         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2852         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2853         evas_object_resize(cw->ec->frame, w, h);
2854      }
2855    else if ((w != cw->ec->w) || (h != cw->ec->h))
2856      evas_object_resize(cw->ec->frame, w, h);
2857 }
2858
2859 static void
2860 _e_comp_smart_cb_shading(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2861 {
2862    E_Comp_Object *cw = data;
2863
2864    if (!cw->ec) return; //NYI
2865    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2866
2867    cw->shade.x = cw->x;
2868    cw->shade.y = cw->y;
2869    e_comp_object_signal_emit(cw->smart_obj, "e,state,shading", "e");
2870 }
2871
2872 static void
2873 _e_comp_smart_cb_shaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2874 {
2875    E_Comp_Object *cw = data;
2876
2877    if (!cw->ec) return; //NYI
2878    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2879
2880    e_comp_object_signal_emit(cw->smart_obj, "e,state,shaded", "e");
2881 }
2882
2883 static void
2884 _e_comp_smart_cb_unshading(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2885 {
2886    E_Comp_Object *cw = data;
2887
2888    if (!cw->ec) return; //NYI
2889    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2890
2891    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshading", "e");
2892 }
2893
2894 static void
2895 _e_comp_smart_cb_unshaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2896 {
2897    E_Comp_Object *cw = data;
2898
2899    if (!cw->ec) return; //NYI
2900    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2901
2902    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshaded", "e");
2903 }
2904
2905 static void
2906 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2907 {
2908    E_Comp_Object *cw = data;
2909
2910    _e_comp_object_shadow_setup(cw);
2911    if (cw->frame_object)
2912      {
2913         _e_comp_object_shadow(cw);
2914         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2915         _e_comp_object_frame_recalc(cw);
2916         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2917      }
2918 }
2919
2920 static void
2921 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2922 {
2923    E_Comp_Object *cw = data;
2924
2925    if (_e_comp_object_shadow_setup(cw))
2926      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2927    if (cw->frame_object)
2928      {
2929         _e_comp_object_shadow(cw);
2930         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2931         _e_comp_object_frame_recalc(cw);
2932         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2933      }
2934 }
2935
2936 static void
2937 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2938 {
2939    E_Comp_Object *cw = data;
2940
2941    if (cw->frame_object)
2942      {
2943         _e_comp_object_shadow(cw);
2944         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2945         _e_comp_object_frame_recalc(cw);
2946         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2947      }
2948 }
2949
2950 static void
2951 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2952 {
2953    E_Comp_Object *cw = data;
2954
2955    if (_e_comp_object_shadow_setup(cw))
2956      {
2957         EC_CHANGED(cw->ec);
2958         cw->ec->changes.size = 1;
2959      }
2960    if (cw->frame_object)
2961      {
2962         _e_comp_object_shadow(cw);
2963         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2964         _e_comp_object_frame_recalc(cw);
2965         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2966      }
2967 }
2968
2969 static void
2970 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2971 {
2972    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
2973 }
2974
2975 static void
2976 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2977 {
2978    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
2979 }
2980
2981 static void
2982 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2983 {
2984    E_Comp_Object *cw = data;
2985
2986    if (!cw->ec) return; //NYI
2987    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
2988 }
2989
2990 static void
2991 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2992 {
2993    E_Comp_Object *cw = data;
2994
2995    if (!cw->ec) return; //NYI
2996    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
2997 }
2998
2999 static void
3000 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3001 {
3002    e_comp_object_signal_emit(obj, "e,state,focused", "e");
3003 }
3004
3005 static void
3006 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3007 {
3008    E_Comp_Object *cw = data;
3009
3010    if (!e_object_is_del(E_OBJECT(cw->ec)))
3011      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
3012 }
3013
3014 static void
3015 _e_comp_input_obj_smart_add(Evas_Object *obj)
3016 {
3017    E_Input_Rect_Smart_Data *input_rect_sd;
3018    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
3019
3020    if (!input_rect_sd) return;
3021    evas_object_smart_data_set(obj, input_rect_sd);
3022 }
3023
3024 static void
3025 _e_comp_input_obj_smart_del(Evas_Object *obj)
3026 {
3027    E_Input_Rect_Smart_Data *input_rect_sd;
3028    E_Input_Rect_Data *input_rect_data;
3029
3030    input_rect_sd = evas_object_smart_data_get(obj);
3031    if (!input_rect_sd) return;
3032
3033    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3034      {
3035         if (input_rect_data->obj)
3036           {
3037              evas_object_smart_member_del(input_rect_data->obj);
3038              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3039           }
3040         E_FREE(input_rect_data);
3041      }
3042    E_FREE(input_rect_sd);
3043 }
3044
3045 static void
3046 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
3047 {
3048    E_Input_Rect_Smart_Data *input_rect_sd;
3049    E_Input_Rect_Data *input_rect_data;
3050    Eina_List *l;
3051    E_Comp_Object *cw;
3052
3053    input_rect_sd = evas_object_smart_data_get(obj);
3054    if (!input_rect_sd) return;
3055
3056    cw = input_rect_sd->cw;
3057    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3058      {
3059         if (input_rect_data->obj)
3060           {
3061              evas_object_geometry_set(input_rect_data->obj,
3062                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3063                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3064                input_rect_data->rect.w, input_rect_data->rect.h);
3065           }
3066      }
3067 }
3068
3069 static void
3070 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
3071 {
3072    E_Input_Rect_Smart_Data *input_rect_sd;
3073    E_Input_Rect_Data *input_rect_data;
3074    Eina_List *l;
3075    E_Comp_Object *cw;
3076
3077    input_rect_sd = evas_object_smart_data_get(obj);
3078    if (!input_rect_sd) return;
3079
3080    cw = input_rect_sd->cw;
3081    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3082      {
3083         if (input_rect_data->obj)
3084           {
3085              evas_object_geometry_set(input_rect_data->obj,
3086                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3087                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3088                input_rect_data->rect.w, input_rect_data->rect.h);
3089           }
3090      }
3091 }
3092
3093 static void
3094 _e_comp_input_obj_smart_show(Evas_Object *obj)
3095 {
3096    E_Input_Rect_Smart_Data *input_rect_sd;
3097    E_Input_Rect_Data *input_rect_data;
3098    Eina_List *l;
3099
3100    input_rect_sd = evas_object_smart_data_get(obj);
3101    if (!input_rect_sd) return;
3102
3103    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3104      {
3105         if (input_rect_data->obj)
3106           {
3107              evas_object_show(input_rect_data->obj);
3108           }
3109      }
3110 }
3111
3112 static void
3113 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3114 {
3115    E_Input_Rect_Smart_Data *input_rect_sd;
3116    E_Input_Rect_Data *input_rect_data;
3117    Eina_List *l;
3118
3119    input_rect_sd = evas_object_smart_data_get(obj);
3120    if (!input_rect_sd) return;
3121
3122    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3123      {
3124         if (input_rect_data->obj)
3125           {
3126              evas_object_hide(input_rect_data->obj);
3127           }
3128      }
3129 }
3130
3131 static void
3132 _e_comp_input_obj_smart_init(void)
3133 {
3134    if (_e_comp_input_obj_smart) return;
3135    {
3136       static const Evas_Smart_Class sc =
3137       {
3138          INPUT_OBJ_SMART_NAME,
3139          EVAS_SMART_CLASS_VERSION,
3140          _e_comp_input_obj_smart_add,
3141          _e_comp_input_obj_smart_del,
3142          _e_comp_input_obj_smart_move,
3143          _e_comp_input_obj_smart_resize,
3144          _e_comp_input_obj_smart_show,
3145          _e_comp_input_obj_smart_hide,
3146          NULL,
3147          NULL,
3148          NULL,
3149          NULL,
3150          NULL,
3151          NULL,
3152
3153          NULL,
3154          NULL,
3155          NULL,
3156          NULL
3157       };
3158       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3159    }
3160 }
3161
3162
3163 static void
3164 _e_comp_smart_add(Evas_Object *obj)
3165 {
3166    E_Comp_Object *cw;
3167
3168    cw = E_NEW(E_Comp_Object, 1);
3169    EINA_SAFETY_ON_NULL_RETURN(cw);
3170
3171    cw->smart_obj = obj;
3172    cw->x = cw->y = cw->w = cw->h = -1;
3173    evas_object_smart_data_set(obj, cw);
3174    cw->opacity = 255.0;
3175    cw->external_content = 0;
3176    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3177    cw->transform_bg_color.r = 0;
3178    cw->transform_bg_color.g = 0;
3179    cw->transform_bg_color.b = 0;
3180    cw->transform_bg_color.a = 255;
3181    evas_object_data_set(obj, "comp_obj", cw);
3182    evas_object_move(obj, -1, -1);
3183    /* intercept ALL the callbacks! */
3184    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3185    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3186    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3187    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3188    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3189    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3190    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3191    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3192    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3193    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3194    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3195
3196    evas_object_smart_callback_add(obj, "shading", _e_comp_smart_cb_shading, cw);
3197    evas_object_smart_callback_add(obj, "shaded", _e_comp_smart_cb_shaded, cw);
3198    evas_object_smart_callback_add(obj, "unshading", _e_comp_smart_cb_unshading, cw);
3199    evas_object_smart_callback_add(obj, "unshaded", _e_comp_smart_cb_unshaded, cw);
3200
3201    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3202    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3203    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3204    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3205
3206    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
3207    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
3208
3209    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
3210    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
3211
3212    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3213
3214    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3215    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3216 }
3217
3218 static void
3219 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3220 {
3221    INTERNAL_ENTRY;
3222    evas_object_color_set(cw->clip, r, g, b, a);
3223    evas_object_smart_callback_call(obj, "color_set", NULL);
3224 }
3225
3226
3227 static void
3228 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3229 {
3230    INTERNAL_ENTRY;
3231    evas_object_clip_set(cw->clip, clip);
3232 }
3233
3234 static void
3235 _e_comp_smart_clip_unset(Evas_Object *obj)
3236 {
3237    INTERNAL_ENTRY;
3238    evas_object_clip_unset(cw->clip);
3239 }
3240
3241 static void
3242 _e_comp_smart_hide(Evas_Object *obj)
3243 {
3244    TRACE_DS_BEGIN(COMP:SMART HIDE);
3245
3246    INTERNAL_ENTRY;
3247    cw->visible = 0;
3248    cw->hiding = 0;
3249    evas_object_hide(cw->clip);
3250    if (cw->input_obj) evas_object_hide(cw->input_obj);
3251    evas_object_hide(cw->effect_obj);
3252    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3253    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3254    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3255    if (stopping)
3256      {
3257         TRACE_DS_END();
3258         return;
3259      }
3260
3261    /* unset native surface if current displaying buffer was destroied */
3262    if (!cw->buffer_destroy_listener.notify)
3263      {
3264         Evas_Native_Surface *ns;
3265         ns = evas_object_image_native_surface_get(cw->obj);
3266         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3267           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3268      }
3269
3270    if (!cw->ec->input_only)
3271      {
3272         edje_object_freeze(cw->effect_obj);
3273         edje_object_freeze(cw->shobj);
3274         edje_object_play_set(cw->shobj, 0);
3275         if (cw->frame_object)
3276           edje_object_play_set(cw->frame_object, 0);
3277      }
3278    /* ensure focus-out */
3279    if (cw->ec->focused &&
3280        (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK))
3281      {
3282         ELOGF("FOCUS", "focus unset | smart_hide", cw->ec);
3283         e_client_frame_focus_set(cw->ec, EINA_FALSE);
3284         e_client_focus_defer_unset(cw->ec);
3285      }
3286    e_comp_render_queue(); //force nocomp recheck
3287
3288    TRACE_DS_END();
3289 }
3290
3291 static void
3292 _e_comp_smart_show(Evas_Object *obj)
3293 {
3294    E_Client *tmp;
3295    Eina_List *l;
3296
3297    INTERNAL_ENTRY;
3298    cw->defer_hide = 0;
3299    cw->visible = 1;
3300    if ((cw->w < 0) || (cw->h < 0))
3301      CRI("ACK! ec:%p", cw->ec);
3302
3303    TRACE_DS_BEGIN(COMP:SMART SHOW);
3304
3305    e_comp_object_map_update(obj);
3306
3307    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3308      evas_object_show(tmp->frame);
3309
3310    evas_object_show(cw->clip);
3311    if (cw->input_obj) evas_object_show(cw->input_obj);
3312    if (!cw->ec->input_only)
3313      {
3314         edje_object_thaw(cw->effect_obj);
3315         edje_object_thaw(cw->shobj);
3316         edje_object_play_set(cw->shobj, 1);
3317         if (cw->frame_object)
3318           edje_object_play_set(cw->frame_object, 1);
3319      }
3320    evas_object_show(cw->effect_obj);
3321    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3322    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3323    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3324    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3325    e_comp_render_queue();
3326    if (cw->ec->input_only)
3327      {
3328         TRACE_DS_END();
3329         return;
3330      }
3331    if (cw->ec->iconic && (!cw->ec->new_client))
3332      {
3333         if (e_client_is_iconified_by_client(cw->ec))
3334           {
3335              ELOGF("COMP", "Set launching flag..", cw->ec);
3336              cw->ec->launching = EINA_TRUE;
3337           }
3338
3339         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3340      }
3341    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3342      {
3343         cw->showing = 1;
3344         ELOGF("COMP", "Set launching flag..", cw->ec);
3345         cw->ec->launching = EINA_TRUE;
3346
3347         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3348         _e_comp_object_animating_begin(cw);
3349         if (!_e_comp_object_effect_visibility_start(cw, 1))
3350           {
3351              TRACE_DS_END();
3352              return;
3353           }
3354      }
3355    /* ensure some random effect doesn't lock the client offscreen */
3356    if (!cw->animating)
3357      {
3358         cw->showing = 0;
3359         e_comp_object_effect_set(obj, NULL);
3360      }
3361
3362    _e_comp_object_dim_update(cw);
3363
3364    TRACE_DS_END();
3365 }
3366
3367 static void
3368 _e_comp_smart_del(Evas_Object *obj)
3369 {
3370    Eina_List *l;
3371
3372    INTERNAL_ENTRY;
3373
3374    if (cw->buffer_destroy_listener.notify)
3375      {
3376         wl_list_remove(&cw->buffer_destroy_listener.link);
3377         cw->buffer_destroy_listener.notify = NULL;
3378      }
3379
3380    if (cw->tbm_surface)
3381      {
3382         tbm_surface_internal_unref(cw->tbm_surface);
3383         cw->tbm_surface = NULL;
3384      }
3385
3386    if (cw->render_update_lock.buffer_ref.buffer)
3387      {
3388         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3389               cw->ec, cw->render_update_lock.lock);
3390         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3391      }
3392
3393    e_comp_object_render_update_del(cw->smart_obj);
3394    E_FREE_FUNC(cw->updates, eina_tiler_free);
3395    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3396    free(cw->ns);
3397
3398    if (cw->obj_mirror)
3399      {
3400         Evas_Object *o;
3401
3402         EINA_LIST_FREE(cw->obj_mirror, o)
3403           {
3404              evas_object_image_data_set(o, NULL);
3405              evas_object_freeze_events_set(o, 1);
3406              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3407              evas_object_del(o);
3408           }
3409      }
3410    _e_comp_object_layers_remove(cw);
3411    l = evas_object_data_get(obj, "comp_object-to_del");
3412    E_FREE_LIST(l, evas_object_del);
3413    _e_comp_object_mouse_event_callback_unset(cw);
3414    evas_object_del(cw->clip);
3415    evas_object_del(cw->effect_obj);
3416    evas_object_del(cw->shobj);
3417    evas_object_del(cw->frame_object);
3418    evas_object_del(cw->input_obj);
3419    evas_object_del(cw->obj);
3420    evas_object_del(cw->mask.obj);
3421    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3422    evas_object_del(cw->transform_bg_obj);
3423    evas_object_del(cw->transform_tranp_obj);
3424    evas_object_del(cw->default_input_obj);
3425    eina_stringshare_del(cw->frame_theme);
3426    eina_stringshare_del(cw->frame_name);
3427    if (cw->animating)
3428      {
3429         cw->animating = 0;
3430         e_comp->animating--;
3431         UNREFD(cw->ec, 2);
3432         e_object_unref(E_OBJECT(cw->ec));
3433      }
3434    cw->ec->frame = NULL;
3435    free(cw);
3436 }
3437
3438 static void
3439 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3440 {
3441    INTERNAL_ENTRY;
3442
3443    cw->x = x, cw->y = y;
3444    evas_object_move(cw->effect_obj, x, y);
3445    evas_object_move(cw->default_input_obj, x, y);
3446    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3447
3448    e_comp_object_map_update(obj);
3449 }
3450
3451 static void
3452 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3453 {
3454    Eina_Bool first = EINA_FALSE;
3455    int tw, th;
3456
3457    INTERNAL_ENTRY;
3458
3459    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3460
3461    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3462
3463    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3464
3465    if (cw->w != w || cw->h != h)
3466      e_comp_object_map_update(obj);
3467
3468    first = ((cw->w < 1) || (cw->h < 1));
3469    cw->w = w, cw->h = h;
3470    if ((!cw->ec->shading) && (!cw->ec->shaded))
3471      {
3472         int ww, hh, pw, ph;
3473
3474         if (cw->frame_object)
3475           e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3476         else
3477           ww = w, hh = h;
3478         /* verify pixmap:object size */
3479         if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3480           {
3481              if ((ww != pw) || (hh != ph))
3482                ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3483           }
3484         evas_object_resize(cw->effect_obj, tw, th);
3485         evas_object_resize(cw->default_input_obj, w, h);
3486         if (cw->input_obj)
3487           evas_object_resize(cw->input_obj, w, h);
3488         if (cw->mask.obj)
3489           evas_object_resize(cw->mask.obj, w, h);
3490         /* resize render update tiler */
3491         if (!first)
3492           {
3493              RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3494              cw->updates_full = 0;
3495              if (cw->updates) eina_tiler_clear(cw->updates);
3496           }
3497         else
3498           {
3499              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3500              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3501           }
3502      }
3503    else
3504      {
3505         evas_object_resize(cw->effect_obj, tw, th);
3506         evas_object_resize(cw->default_input_obj, w, h);
3507      }
3508    if (!cw->visible)
3509      {
3510         TRACE_DS_END();
3511         return;
3512      }
3513    e_comp_render_queue();
3514
3515    TRACE_DS_END();
3516 }
3517
3518 static void
3519 _e_comp_smart_init(void)
3520 {
3521    if (_e_comp_smart) return;
3522    {
3523       static const Evas_Smart_Class sc =
3524       {
3525          SMART_NAME,
3526          EVAS_SMART_CLASS_VERSION,
3527          _e_comp_smart_add,
3528          _e_comp_smart_del,
3529          _e_comp_smart_move,
3530          _e_comp_smart_resize,
3531          _e_comp_smart_show,
3532          _e_comp_smart_hide,
3533          _e_comp_smart_color_set,
3534          _e_comp_smart_clip_set,
3535          _e_comp_smart_clip_unset,
3536          NULL,
3537          NULL,
3538          NULL,
3539
3540          NULL,
3541          NULL,
3542          NULL,
3543          NULL
3544       };
3545       _e_comp_smart = evas_smart_class_new(&sc);
3546    }
3547 }
3548
3549 EINTERN void
3550 e_comp_object_init(void)
3551 {
3552    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3553    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3554    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3555    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3556 }
3557
3558 EINTERN void
3559 e_comp_object_shutdown(void)
3560 {
3561
3562 }
3563
3564 EINTERN Eina_Bool
3565 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3566 {
3567    API_ENTRY EINA_FALSE;
3568    return !!cw->force_visible;
3569 }
3570 /////////////////////////////////////////////////////////
3571
3572 static void
3573 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3574 {
3575    Eina_List *l;
3576    Eina_Bool comp_object;
3577
3578    comp_object = !!evas_object_data_get(obj, "comp_object");
3579    if (comp_object)
3580      {
3581         Evas_Object *o;
3582
3583         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3584         evas_object_del(o);
3585         e_comp_render_queue();
3586      }
3587    l = evas_object_data_get(obj, "comp_object-to_del");
3588    E_FREE_LIST(l, evas_object_del);
3589 }
3590
3591 static void
3592 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3593 {
3594    if (e_comp_util_object_is_above_nocomp(obj) &&
3595        (!evas_object_data_get(obj, "comp_override")))
3596      {
3597         evas_object_data_set(obj, "comp_override", (void*)1);
3598         e_comp_override_add();
3599      }
3600 }
3601
3602 static void
3603 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3604 {
3605    Eina_Bool ref = EINA_TRUE;
3606    if (evas_object_visible_get(obj))
3607      {
3608         void *d;
3609
3610         d = evas_object_data_del(obj, "comp_hiding");
3611         if (d)
3612           /* currently trying to hide */
3613           ref = EINA_FALSE;
3614         else
3615           /* already visible */
3616           return;
3617      }
3618
3619    evas_object_show(obj);
3620    if (ref)
3621      {
3622         evas_object_ref(obj);
3623         evas_object_data_set(obj, "comp_ref", (void*)1);
3624      }
3625    edje_object_signal_emit(obj, "e,state,visible", "e");
3626    evas_object_data_set(obj, "comp_showing", (void*)1);
3627    if (e_comp_util_object_is_above_nocomp(obj))
3628      {
3629         evas_object_data_set(obj, "comp_override", (void*)1);
3630         e_comp_override_add();
3631      }
3632 }
3633
3634 static void
3635 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3636 {
3637    if (!evas_object_visible_get(obj)) return;
3638    /* already hiding */
3639    if (evas_object_data_get(obj, "comp_hiding")) return;
3640    if (!evas_object_data_del(obj, "comp_showing"))
3641      {
3642         evas_object_ref(obj);
3643         evas_object_data_set(obj, "comp_ref", (void*)1);
3644      }
3645    edje_object_signal_emit(obj, "e,state,hidden", "e");
3646    evas_object_data_set(obj, "comp_hiding", (void*)1);
3647
3648    if (evas_object_data_del(obj, "comp_override"))
3649      e_comp_override_timed_pop();
3650 }
3651
3652 static void
3653 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3654 {
3655    if (!e_util_strcmp(emission, "e,action,hide,done"))
3656      {
3657         if (!evas_object_data_del(obj, "comp_hiding")) return;
3658         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3659         evas_object_hide(obj);
3660         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3661      }
3662    else
3663      evas_object_data_del(obj, "comp_showing");
3664    if (evas_object_data_del(obj, "comp_ref"))
3665      evas_object_unref(obj);
3666 }
3667
3668 static void
3669 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3670 {
3671    if (data)
3672      {
3673         int w, h;
3674
3675         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3676      }
3677 }
3678
3679 E_API E_Comp_Object_Hook *
3680 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3681 {
3682    E_Comp_Object_Hook *ch;
3683
3684    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3685    ch = E_NEW(E_Comp_Object_Hook, 1);
3686    if (!ch) return NULL;
3687    ch->hookpoint = hookpoint;
3688    ch->func = func;
3689    ch->data = (void*)data;
3690    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3691    return ch;
3692 }
3693
3694 E_API void
3695 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3696 {
3697    ch->delete_me = 1;
3698    if (_e_comp_object_hooks_walking == 0)
3699      {
3700         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3701         free(ch);
3702      }
3703    else
3704      _e_comp_object_hooks_delete++;
3705 }
3706
3707 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3708 E_API E_Comp_Object_Intercept_Hook *
3709 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3710 {
3711    E_Comp_Object_Intercept_Hook *ch;
3712
3713    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3714    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3715    if (!ch) return NULL;
3716    ch->hookpoint = hookpoint;
3717    ch->func = func;
3718    ch->data = (void*)data;
3719    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3720    return ch;
3721 }
3722
3723 E_API void
3724 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3725 {
3726    ch->delete_me = 1;
3727    if (_e_comp_object_intercept_hooks_walking == 0)
3728      {
3729         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3730         free(ch);
3731      }
3732    else
3733      _e_comp_object_intercept_hooks_delete++;
3734 }
3735 #endif
3736
3737 E_API Evas_Object *
3738 e_comp_object_util_add(Evas_Object *obj)
3739 {
3740    Evas_Object *o;
3741    const char *name;
3742    E_Comp_Config *conf = e_comp_config_get();
3743    Eina_Bool skip = EINA_FALSE;
3744    char buf[1024];
3745    int ok = 0;
3746    int x, y, w, h;
3747    Eina_Bool vis;
3748
3749    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3750
3751    name = evas_object_name_get(obj);
3752    vis = evas_object_visible_get(obj);
3753    o = edje_object_add(e_comp->evas);
3754    evas_object_data_set(o, "comp_object", (void*)1);
3755    if (name)
3756      skip = (!strncmp(name, "noshadow", 8));
3757    if (skip)
3758      evas_object_data_set(o, "comp_object_skip", (void*)1);
3759
3760    if (conf->shadow_style)
3761      {
3762         snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3763         ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3764      }
3765    if (!ok)
3766      e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3767    if (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow")))
3768      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3769    else
3770      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3771
3772    evas_object_geometry_get(obj, &x, &y, &w, &h);
3773    evas_object_geometry_set(o, x, y, w, h);
3774    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3775
3776    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, NULL);
3777
3778    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, NULL);
3779    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, NULL);
3780    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, NULL);
3781    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3782    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, NULL);
3783    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, NULL);
3784
3785    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3786
3787    edje_object_part_swallow(o, "e.swallow.content", obj);
3788
3789    _e_comp_object_event_add(o);
3790
3791    if (vis)
3792      evas_object_show(o);
3793
3794    return o;
3795 }
3796
3797 /* utility functions for deleting objects when their "owner" is deleted */
3798 EINTERN void
3799 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3800 {
3801    Eina_List *l;
3802
3803    SOFT_ENTRY();
3804    EINA_SAFETY_ON_NULL_RETURN(to_del);
3805    l = evas_object_data_get(obj, "comp_object-to_del");
3806    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3807    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3808    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3809 }
3810
3811 EINTERN void
3812 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3813 {
3814    Eina_List *l;
3815
3816    SOFT_ENTRY();
3817    EINA_SAFETY_ON_NULL_RETURN(to_del);
3818    l = evas_object_data_get(obj, "comp_object-to_del");
3819    if (l)
3820      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3821 }
3822
3823 /////////////////////////////////////////////////////////
3824
3825 EINTERN Evas_Object *
3826 e_comp_object_client_add(E_Client *ec)
3827 {
3828    Evas_Object *o;
3829    E_Comp_Object *cw;
3830
3831    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3832    if (ec->frame) return NULL;
3833    _e_comp_smart_init();
3834    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3835    cw = evas_object_smart_data_get(o);
3836    if (!cw) return NULL;
3837    evas_object_data_set(o, "E_Client", ec);
3838    cw->ec = ec;
3839    ec->frame = o;
3840    evas_object_data_set(o, "comp_object", (void*)1);
3841
3842    _e_comp_object_event_add(o);
3843
3844    return o;
3845 }
3846
3847 /* utility functions for getting client inset */
3848 E_API void
3849 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3850 {
3851    API_ENTRY;
3852    if (!cw->client_inset.calc)
3853      {
3854         if (ax) *ax = x;
3855         if (ay) *ay = y;
3856         return;
3857      }
3858    if (ax) *ax = x - cw->client_inset.l;
3859    if (ay) *ay = y - cw->client_inset.t;
3860 }
3861
3862 E_API void
3863 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3864 {
3865    API_ENTRY;
3866    if (!cw->client_inset.calc)
3867      {
3868         if (ax) *ax = x;
3869         if (ay) *ay = y;
3870         return;
3871      }
3872    if (ax) *ax = x + cw->client_inset.l;
3873    if (ay) *ay = y + cw->client_inset.t;
3874 }
3875
3876 E_API void
3877 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3878 {
3879    API_ENTRY;
3880    if (!cw->client_inset.calc)
3881      {
3882         if (aw) *aw = w;
3883         if (ah) *ah = h;
3884         return;
3885      }
3886    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3887    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3888 }
3889
3890 E_API void
3891 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3892 {
3893    API_ENTRY;
3894    if (!cw->client_inset.calc)
3895      {
3896         if (aw) *aw = w;
3897         if (ah) *ah = h;
3898         return;
3899      }
3900    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3901    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3902 }
3903
3904 E_API E_Client *
3905 e_comp_object_client_get(Evas_Object *obj)
3906 {
3907    Evas_Object *o;
3908
3909    SOFT_ENTRY(NULL);
3910    /* FIXME: remove this when eo is used */
3911    o = evas_object_data_get(obj, "comp_smart_obj");
3912    if (o)
3913      return e_comp_object_client_get(o);
3914    return cw ? cw->ec : NULL;
3915 }
3916
3917 EINTERN void
3918 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3919 {
3920    API_ENTRY;
3921    if (cw->frame_extends)
3922      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3923    else
3924      {
3925         if (x) *x = 0;
3926         if (y) *y = 0;
3927         if (w) *w  = cw->ec->w;
3928         if (h) *h  = cw->ec->h;
3929      }
3930 }
3931
3932 EINTERN E_Zone *
3933 e_comp_object_util_zone_get(Evas_Object *obj)
3934 {
3935    E_Zone *zone = NULL;
3936
3937    SOFT_ENTRY(NULL);
3938    if (cw)
3939      zone = e_comp_zone_find_by_ec(cw->ec);
3940    if (!zone)
3941      {
3942         int x, y;
3943
3944         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3945         zone = e_comp_zone_xy_get(x, y);
3946      }
3947    return zone;
3948 }
3949
3950 EINTERN void
3951 e_comp_object_util_center(Evas_Object *obj)
3952 {
3953    int x, y, w, h, ow, oh;
3954    E_Zone *zone;
3955
3956    SOFT_ENTRY();
3957
3958    zone = e_comp_object_util_zone_get(obj);
3959    EINA_SAFETY_ON_NULL_RETURN(zone);
3960    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3961    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3962      ow = cw->ec->w, oh = cw->ec->h;
3963    else
3964      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3965    x = x + (w - ow) / 2;
3966    y = y + (h - oh) / 2;
3967    evas_object_move(obj, x, y);
3968 }
3969
3970 EINTERN void
3971 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3972 {
3973    int x, y, w, h, ow, oh;
3974
3975    SOFT_ENTRY();
3976    EINA_SAFETY_ON_NULL_RETURN(on);
3977    evas_object_geometry_get(on, &x, &y, &w, &h);
3978    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3979      ow = cw->ec->w, oh = cw->ec->h;
3980    else
3981      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3982    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3983 }
3984
3985 EINTERN void
3986 e_comp_object_util_fullscreen(Evas_Object *obj)
3987 {
3988    SOFT_ENTRY();
3989
3990    if (cw)
3991      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
3992    else
3993      {
3994         evas_object_move(obj, 0, 0);
3995         evas_object_resize(obj, e_comp->w, e_comp->h);
3996      }
3997 }
3998
3999 EINTERN void
4000 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
4001 {
4002    E_Zone *zone;
4003    int zx, zy, zw, zh;
4004    int ow, oh;
4005    SOFT_ENTRY();
4006
4007    if (cw)
4008      ow = cw->w, oh = cw->h;
4009    else
4010      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4011    zone = e_comp_object_util_zone_get(obj);
4012    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4013    if (x) *x = zx + (zw - ow) / 2;
4014    if (y) *y = zy + (zh - oh) / 2;
4015 }
4016
4017 EINTERN void
4018 e_comp_object_input_objs_del(Evas_Object *obj)
4019 {
4020    API_ENTRY;
4021    E_Input_Rect_Data *input_rect_data;
4022    E_Input_Rect_Smart_Data *input_rect_sd;
4023
4024    if (!cw->input_obj)
4025      return;
4026
4027    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4028    if (!input_rect_sd) return;
4029
4030    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
4031      {
4032         if (input_rect_data->obj)
4033           {
4034              evas_object_smart_member_del(input_rect_data->obj);
4035              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
4036           }
4037         E_FREE(input_rect_data);
4038      }
4039 }
4040
4041 E_API void
4042 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
4043 {
4044    API_ENTRY;
4045    E_Input_Rect_Data *input_rect_data = NULL;
4046    E_Input_Rect_Smart_Data *input_rect_sd;
4047    int client_w, client_h;
4048
4049    if (cw->ec->client.w)
4050      client_w = cw->ec->client.w;
4051    else
4052      client_w = cw->ec->w;
4053
4054    if (cw->ec->client.h)
4055      client_h = cw->ec->client.h;
4056    else
4057      client_h = cw->ec->h;
4058
4059    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
4060
4061    if (!cw->input_obj)
4062      {
4063         _e_comp_input_obj_smart_init();
4064         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
4065         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
4066         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4067
4068         if (input_rect_sd)
4069           input_rect_sd->cw = cw;
4070      }
4071
4072    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4073    if (input_rect_sd)
4074      {
4075         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
4076         if (input_rect_data)
4077           {
4078              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
4079              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
4080           }
4081      }
4082
4083    if ((input_rect_data) &&
4084        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
4085      {
4086         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
4087         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
4088         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
4089         evas_object_clip_set(input_rect_data->obj, cw->clip);
4090         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
4091         evas_object_geometry_set(input_rect_data->obj,
4092           MAX(cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l), 0) + x,
4093           MAX(cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t), 0) + y, w, h);
4094         evas_object_pass_events_set(cw->default_input_obj, 1);
4095         evas_object_pass_events_set(cw->obj, 1);
4096         if (cw->visible)
4097           {
4098              evas_object_show(input_rect_data->obj);
4099              evas_object_show(cw->input_obj);
4100           }
4101      }
4102    else
4103      {
4104         evas_object_smart_member_del(cw->input_obj);
4105         E_FREE_FUNC(cw->input_obj, evas_object_del);
4106         evas_object_pass_events_set(cw->default_input_obj, 0);
4107         evas_object_pass_events_set(cw->obj, 0);
4108      }
4109 }
4110
4111 E_API void
4112 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4113 {
4114    API_ENTRY;
4115    E_Input_Rect_Smart_Data *input_rect_sd;
4116    E_Input_Rect_Data *input_rect_data;
4117    Eina_List *l;
4118
4119    if (!cw->input_obj) return;
4120
4121    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4122    if (input_rect_sd)
4123      {
4124         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4125           {
4126              *list = eina_list_append(*list, &input_rect_data->rect);
4127           }
4128      }
4129 }
4130
4131 EINTERN void
4132 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4133 {
4134    API_ENTRY;
4135    if (l) *l = cw->client_inset.l;
4136    if (r) *r = cw->client_inset.r;
4137    if (t) *t = cw->client_inset.t;
4138    if (b) *b = cw->client_inset.b;
4139 }
4140
4141 /* set geometry for CSD */
4142 EINTERN void
4143 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4144 {
4145    Eina_Bool calc;
4146    int tx, ty, tw, th;
4147
4148    API_ENTRY;
4149    if (cw->frame_object)
4150      CRI("ACK! ec:%p", cw->ec);
4151    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4152        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4153    calc = cw->client_inset.calc;
4154    cw->client_inset.calc = l || r || t || b;
4155    eina_stringshare_replace(&cw->frame_theme, "borderless");
4156    if (cw->client_inset.calc)
4157      {
4158         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4159         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4160         e_client_size_set(cw->ec, tw, th);
4161      }
4162    else if (cw->ec->maximized || cw->ec->fullscreen)
4163      {
4164         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4165         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4166      }
4167    if (!cw->ec->new_client)
4168      {
4169         if (calc && cw->client_inset.calc)
4170           {
4171              tx = cw->ec->x - (l - cw->client_inset.l);
4172              ty = cw->ec->y - (t - cw->client_inset.t);
4173              e_client_pos_set(cw->ec, tx, ty);
4174           }
4175         cw->ec->changes.pos = cw->ec->changes.size = 1;
4176         EC_CHANGED(cw->ec);
4177      }
4178    cw->client_inset.l = l;
4179    cw->client_inset.r = r;
4180    cw->client_inset.t = t;
4181    cw->client_inset.b = b;
4182 }
4183
4184 EINTERN Eina_Bool
4185 e_comp_object_frame_allowed(Evas_Object *obj)
4186 {
4187    API_ENTRY EINA_FALSE;
4188    return (!cw->ec->mwm.borderless) && (cw->frame_object || (!cw->client_inset.calc));
4189 }
4190
4191 EINTERN Eina_Bool
4192 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4193 {
4194    API_ENTRY EINA_FALSE;
4195    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4196    eina_stringshare_replace(&cw->frame_name, name);
4197    if (cw->frame_object)
4198      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4199    return EINA_TRUE;
4200 }
4201
4202 EINTERN Eina_Bool
4203 e_comp_object_frame_exists(Evas_Object *obj)
4204 {
4205    API_ENTRY EINA_FALSE;
4206    return !!cw->frame_object;
4207 }
4208
4209 EINTERN Eina_Bool
4210 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4211 {
4212    Evas_Object *o, *pbg;
4213    char buf[4096];
4214    int ok;
4215    Eina_Stringshare *theme;
4216
4217    API_ENTRY EINA_FALSE;
4218
4219    if (!e_util_strcmp(cw->frame_theme, name))
4220     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4221    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4222      return _e_comp_object_shadow_setup(cw);
4223    pbg = cw->frame_object;
4224    theme = eina_stringshare_add(name);
4225
4226    if (cw->frame_object)
4227      {
4228         int w, h;
4229
4230         w = cw->ec->w, h = cw->ec->h;
4231         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4232         if ((cw->ec->w != w) || (cw->ec->h != h))
4233           {
4234              cw->ec->changes.size = 1;
4235              EC_CHANGED(cw->ec);
4236           }
4237         E_FREE_FUNC(cw->frame_object, evas_object_del);
4238         if (!name) goto reshadow;
4239      }
4240    o = edje_object_add(e_comp->evas);
4241    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4242    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4243    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4244      {
4245         cw->frame_object = NULL;
4246         evas_object_del(o);
4247         eina_stringshare_del(cw->frame_theme);
4248         cw->frame_theme = theme;
4249         goto reshadow;
4250      }
4251    if (!ok)
4252      {
4253         if (theme != e_config->theme_default_border_style)
4254           {
4255              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4256              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4257           }
4258         if (!ok)
4259           {
4260              ok = e_theme_edje_object_set(o, "base/theme/border",
4261                                           "e/widgets/border/default/border");
4262              if (ok && (theme == e_config->theme_default_border_style))
4263                {
4264                   /* Reset default border style to default */
4265                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4266                   e_config_save_queue();
4267                }
4268           }
4269      }
4270
4271    if (ok)
4272      {
4273         cw->frame_object = o;
4274         eina_stringshare_del(cw->frame_theme);
4275         cw->frame_theme = theme;
4276         evas_object_name_set(o, "cw->frame_object");
4277
4278         if (cw->frame_name)
4279           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4280
4281         if (!pbg)
4282           {
4283              cw->ec->changes.icon = 1;
4284              EC_CHANGED(cw->ec);
4285           }
4286      }
4287    else
4288      {
4289         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4290         evas_object_del(o);
4291      }
4292 reshadow:
4293    if (cw->shobj)
4294      _e_comp_object_shadow_setup(cw);
4295    do
4296      {
4297         int old_x, old_y, new_x = 0, new_y = 0;
4298
4299         old_x = cw->x, old_y = cw->y;
4300
4301         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4302         if (pbg)
4303           new_x = cw->ec->x, new_y = cw->ec->y;
4304         else if (cw->ec->placed || (!cw->ec->new_client))
4305           {
4306              /* if no previous frame:
4307               * - reapply client_inset
4308               * - clamp to zone
4309               */
4310              int x, y;
4311
4312              if (cw->ec->changes.size)
4313                {
4314                   x = cw->ec->x;
4315                   y = cw->ec->y;
4316                }
4317              else
4318                {
4319                   E_Zone *zone;
4320                   zone = e_comp_zone_find_by_ec(cw->ec);
4321                   if (!zone) break;
4322
4323                   x = cw->ec->client.x, y = cw->ec->client.y;
4324                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4325                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4326                }
4327              new_x = x, new_y = y;
4328           }
4329
4330         if (old_x != new_x || old_y != new_y)
4331           {
4332              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4333              cw->y = cw->x = -99999;
4334              evas_object_move(obj, new_x, new_y);
4335           }
4336      } while (0);
4337
4338    if (cw->ec->maximized)
4339      {
4340         cw->ec->changes.need_maximize = 1;
4341         EC_CHANGED(cw->ec);
4342      }
4343    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4344    if (cw->frame_object)
4345      {
4346         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4347      }
4348    else
4349      cw->frame_extends = 0;
4350    evas_object_del(pbg);
4351    return EINA_TRUE;
4352 }
4353
4354 E_API void
4355 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4356 {
4357    E_Comp_Object_Mover *prov;
4358
4359    API_ENTRY;
4360    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4361    edje_object_signal_emit(cw->shobj, sig, src);
4362    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4363    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4364        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4365      return;
4366    /* start with highest priority callback first */
4367    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4368      {
4369         if (!e_util_glob_match(sig, prov->sig)) continue;
4370         if (prov->func(prov->data, obj, sig)) break;
4371      }
4372 }
4373
4374 E_API void
4375 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4376 {
4377    /* FIXME: at some point I guess this should use eo to inherit
4378     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4379     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4380     */
4381    API_ENTRY;
4382    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4383 }
4384
4385 E_API void
4386 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4387 {
4388    API_ENTRY;
4389    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4390 }
4391
4392 E_API void
4393 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4394 {
4395    API_ENTRY;
4396    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4397 }
4398
4399 E_API void
4400 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4401 {
4402    int tw, th;
4403    Eina_Rectangle rect;
4404    API_ENTRY;
4405
4406    if (cw->ec->input_only || (!cw->updates)) return;
4407    if (cw->nocomp) return;
4408    rect.x = x, rect.y = y;
4409    rect.w = w, rect.h = h;
4410    evas_object_smart_callback_call(obj, "damage", &rect);
4411
4412    if (e_comp_is_on_overlay(cw->ec))
4413      {
4414         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4415         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4416         * E module attempts to block screen update due to the particular policy.
4417         */
4418         if (e_pixmap_resource_get(cw->ec->pixmap))
4419           cw->hwc_need_update = EINA_TRUE;
4420      }
4421
4422    /* ignore overdraw */
4423    if (cw->updates_full)
4424      {
4425         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4426         e_comp_object_render_update_add(obj);
4427
4428         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4429           evas_object_show(cw->smart_obj);
4430
4431         return;
4432      }
4433    /* clip rect to client surface */
4434    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4435    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4436    /* if rect is the total size of the client after clip, clear the updates
4437     * since this is guaranteed to be the whole region anyway
4438     */
4439    eina_tiler_area_size_get(cw->updates, &tw, &th);
4440    if ((w > tw) || (h > th))
4441      {
4442         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4443         eina_tiler_clear(cw->updates);
4444         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4445         x = 0, y = 0;
4446         tw = cw->ec->client.w, th = cw->ec->client.h;
4447      }
4448    if ((!x) && (!y) && (w == tw) && (h == th))
4449      {
4450         eina_tiler_clear(cw->updates);
4451         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4452         cw->updates_full = 1;
4453         cw->update_count = 0;
4454      }
4455    cw->update_count++;
4456    if (cw->update_count > UPDATE_MAX)
4457      {
4458         /* this is going to get really dumb, so just update the whole thing */
4459         eina_tiler_clear(cw->updates);
4460         cw->update_count = cw->updates_full = 1;
4461         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4462         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4463      }
4464    else
4465      {
4466         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4467         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4468      }
4469    cw->updates_exist = 1;
4470    e_comp_object_render_update_add(obj);
4471
4472    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4473      evas_object_show(cw->smart_obj);
4474 }
4475
4476 EINTERN Eina_Bool
4477 e_comp_object_damage_exists(Evas_Object *obj)
4478 {
4479    API_ENTRY EINA_FALSE;
4480    return cw->updates_exist;
4481 }
4482
4483 EINTERN void
4484 e_comp_object_render_update_add(Evas_Object *obj)
4485 {
4486    API_ENTRY;
4487
4488    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4489    if (cw->render_update_lock.lock) return;
4490    if (e_object_is_del(E_OBJECT(cw->ec)))
4491      CRI("CAN'T RENDER A DELETED CLIENT!!! ec:%p", cw->ec);
4492    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4493    if (!cw->update)
4494      {
4495         cw->update = 1;
4496         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4497      }
4498    e_comp_render_queue();
4499 }
4500
4501 EINTERN void
4502 e_comp_object_render_update_del(Evas_Object *obj)
4503 {
4504    API_ENTRY;
4505
4506    if (cw->ec->input_only || (!cw->updates)) return;
4507    if (!cw->update) return;
4508    cw->update = 0;
4509    /* this gets called during comp animating to clear the update flag */
4510    if (e_comp->grabbed) return;
4511    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4512    if (!e_comp->updates)
4513      {
4514         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4515         if (e_comp->render_animator)
4516           ecore_animator_freeze(e_comp->render_animator);
4517      }
4518 }
4519
4520 EINTERN void
4521 e_comp_object_shape_apply(Evas_Object *obj)
4522 {
4523    Eina_List *l;
4524    Evas_Object *o;
4525    unsigned int i, *pix, *p;
4526    int w, h, px, py;
4527
4528    API_ENTRY;
4529    if (!cw->ec) return; //NYI
4530    if (cw->external_content) return;
4531    if (cw->ec->shaped)
4532      {
4533         if ((cw->ec->shape_rects_num >= 1) &&
4534             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4535            return;
4536      }
4537    if (cw->native)
4538      {
4539         ERR("BUGGER: shape with native surface? cw=%p", cw);
4540         return;
4541      }
4542    evas_object_image_size_get(cw->obj, &w, &h);
4543    if ((w < 1) || (h < 1)) return;
4544
4545    if (cw->ec->shaped)
4546      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4547    _e_comp_object_alpha_set(cw);
4548    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4549       evas_object_image_alpha_set(o, 1);
4550
4551    p = pix = evas_object_image_data_get(cw->obj, 1);
4552    if (!pix)
4553      {
4554         evas_object_image_data_set(cw->obj, pix);
4555         return;
4556      }
4557    if (cw->ec->shaped)
4558      {
4559         unsigned char *spix, *sp;
4560
4561         spix = calloc(w * h, sizeof(unsigned char));
4562         if (!spix) return;
4563         for (i = 0; i < cw->ec->shape_rects_num; i++)
4564           {
4565              int rx, ry, rw, rh;
4566
4567              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4568              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4569              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4570              sp = spix + (w * ry) + rx;
4571              for (py = 0; py < rh; py++)
4572                {
4573                   for (px = 0; px < rw; px++)
4574                     {
4575                        *sp = 0xff; sp++;
4576                     }
4577                   sp += w - rw;
4578                }
4579           }
4580         sp = spix;
4581         for (py = 0; py < h; py++)
4582           {
4583              for (px = 0; px < w; px++)
4584                {
4585                   unsigned int mask, imask;
4586
4587                   mask = ((unsigned int)(*sp)) << 24;
4588                   imask = mask >> 8;
4589                   imask |= imask >> 8;
4590                   imask |= imask >> 8;
4591                   *p = mask | (*p & imask);
4592                   //if (*sp) *p = 0xff000000 | *p;
4593                   //else *p = 0x00000000;
4594                   sp++;
4595                   p++;
4596                }
4597           }
4598         free(spix);
4599      }
4600    else
4601       {
4602          for (py = 0; py < h; py++)
4603            {
4604               for (px = 0; px < w; px++)
4605                 *p |= 0xff000000;
4606            }
4607       }
4608    evas_object_image_data_set(cw->obj, pix);
4609    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4610    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4611      {
4612         evas_object_image_data_set(o, pix);
4613         evas_object_image_data_update_add(o, 0, 0, w, h);
4614      }
4615 // don't need to fix alpha chanel as blending
4616 // should be totally off here regardless of
4617 // alpha channel content
4618 }
4619
4620 static void
4621 _e_comp_object_clear(E_Comp_Object *cw)
4622 {
4623    Eina_List *l;
4624    Evas_Object *o;
4625
4626    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4627
4628    if (cw->render_update_lock.lock) return;
4629
4630    if (cw->ec->pixmap)
4631      e_pixmap_clear(cw->ec->pixmap);
4632    if (cw->native)
4633      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4634    evas_object_image_size_set(cw->obj, 1, 1);
4635    evas_object_image_data_set(cw->obj, NULL);
4636    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4637      {
4638         evas_object_image_size_set(o, 1, 1);
4639         evas_object_image_data_set(o, NULL);
4640      }
4641    cw->native = 0;
4642    e_comp_object_render_update_del(cw->smart_obj);
4643 }
4644
4645 static Eina_Bool
4646 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4647 {
4648     int r, g, b, a;
4649
4650     API_ENTRY EINA_FALSE;
4651
4652     if (cw->transparent.set == set)
4653        return EINA_TRUE;
4654
4655     if (set)
4656       {
4657          evas_object_color_get(obj, &r, &g, &b, &a);
4658          evas_object_color_set(obj, 0, 0, 0, 0);
4659
4660          cw->transparent.user_r = r;
4661          cw->transparent.user_g = g;
4662          cw->transparent.user_b = b;
4663          cw->transparent.user_a = a;
4664
4665          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4666                cw->ec,
4667                cw->transparent.user_r,
4668                cw->transparent.user_g,
4669                cw->transparent.user_b,
4670                cw->transparent.user_a);
4671
4672          cw->transparent.set = EINA_TRUE;
4673       }
4674     else
4675       {
4676          cw->transparent.set = EINA_FALSE;
4677
4678          evas_object_color_set(obj,
4679                                cw->transparent.user_r,
4680                                cw->transparent.user_g,
4681                                cw->transparent.user_b,
4682                                cw->transparent.user_a);
4683
4684          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4685                cw->ec,
4686                cw->transparent.user_r,
4687                cw->transparent.user_g,
4688                cw->transparent.user_b,
4689                cw->transparent.user_a);
4690       }
4691
4692    return EINA_TRUE;
4693 }
4694
4695 /* helper function to simplify toggling of redirection for display servers which support it */
4696 EINTERN void
4697 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4698 {
4699    API_ENTRY;
4700
4701    set = !!set;
4702    if (cw->redirected == set) return;
4703    cw->redirected = set;
4704    if (cw->external_content) return;
4705
4706    e_comp_object_map_update(obj);
4707
4708    if (set)
4709      {
4710         if (cw->updates_exist)
4711           e_comp_object_render_update_add(obj);
4712         else
4713           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4714
4715         _e_comp_object_transparent_set(obj, EINA_FALSE);
4716         evas_object_smart_callback_call(obj, "redirected", NULL);
4717      }
4718    else
4719      {
4720         _e_comp_object_clear(cw);
4721         _e_comp_object_transparent_set(obj, EINA_TRUE);
4722         evas_object_smart_callback_call(obj, "unredirected", NULL);
4723      }
4724 }
4725
4726 static void
4727 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4728 {
4729    E_Comp_Object *cw;
4730    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4731
4732    if (cw->buffer_destroy_listener.notify)
4733      {
4734         cw->buffer_destroy_listener.notify = NULL;
4735         wl_list_remove(&cw->buffer_destroy_listener.link);
4736      }
4737
4738    if (e_object_is_del(E_OBJECT(cw->ec)))
4739      {
4740         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4741           return;
4742      }
4743    else
4744      {
4745         /* if it's current displaying buffer, do not remove its content */
4746         if (!evas_object_visible_get(cw->ec->frame))
4747           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4748      }
4749 }
4750
4751 static void
4752 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4753 {
4754    Eina_List *l;
4755    Evas_Object *o;
4756
4757    if (cw->buffer_destroy_listener.notify)
4758      {
4759         wl_list_remove(&cw->buffer_destroy_listener.link);
4760         cw->buffer_destroy_listener.notify = NULL;
4761      }
4762
4763    if (cw->tbm_surface)
4764      {
4765         tbm_surface_internal_unref(cw->tbm_surface);
4766         cw->tbm_surface = NULL;
4767      }
4768
4769    if (ns)
4770      {
4771         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4772           {
4773              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4774              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4775           }
4776         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4777           {
4778              tbm_surface_internal_ref(ns->data.tbm.buffer);
4779              cw->tbm_surface = ns->data.tbm.buffer;
4780           }
4781      }
4782
4783    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4784    evas_object_image_native_surface_set(cw->obj, ns);
4785    TRACE_DS_END();
4786    if (with_mirror)
4787      {
4788         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4789           {
4790              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4791              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4792              evas_object_image_native_surface_set(o, ns);
4793              TRACE_DS_END();
4794           }
4795      }
4796 }
4797
4798 EINTERN void
4799 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4800 {
4801    Evas_Native_Surface ns;
4802
4803    API_ENTRY;
4804    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4805    if (cw->ec->input_only) return;
4806    if (cw->external_content) return;
4807    if (cw->render_update_lock.lock) return;
4808    set = !!set;
4809
4810    memset(&ns, 0, sizeof(Evas_Native_Surface));
4811
4812    if (set)
4813      {
4814         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4815         set = (!cw->ec->shaped);
4816         if (set)
4817           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4818      }
4819    cw->native = set;
4820
4821    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4822 }
4823
4824 EINTERN void
4825 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4826 {
4827    API_ENTRY;
4828    if (cw->ec->input_only) return;
4829    E_FREE(cw->ns);
4830    if (ns)
4831      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4832    _e_comp_object_alpha_set(cw);
4833    if (cw->native)
4834      e_comp_object_native_surface_set(obj, cw->native);
4835    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4836 }
4837
4838 EINTERN void
4839 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4840 {
4841    API_ENTRY;
4842
4843    set = !!set;
4844
4845    if (cw->blanked == set) return;
4846    cw->blanked = set;
4847    _e_comp_object_alpha_set(cw);
4848    if (set)
4849      {
4850         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4851         evas_object_image_data_set(cw->obj, NULL);
4852         return;
4853      }
4854    if (cw->native)
4855      e_comp_object_native_surface_set(obj, 1);
4856    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4857 }
4858
4859 static void
4860 _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)
4861 {
4862    Evas_Object *o;
4863    int obj_x, obj_y;
4864
4865    if (!_damage_trace) return;
4866
4867    API_ENTRY;
4868
4869    if (!evas_object_visible_get(cw->obj)) return;
4870
4871    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4872
4873    o = evas_object_rectangle_add(e_comp->evas);
4874    evas_object_layer_set(o, E_LAYER_MAX);
4875    evas_object_name_set(o, "damage_trace");
4876    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4877    evas_object_resize(o, dmg_w, dmg_h);
4878    evas_object_color_set(o, 0, 128, 0, 128);
4879    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4880    evas_object_pass_events_set(o, EINA_TRUE);
4881    evas_object_show(o);
4882
4883    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4884          cw->ec,
4885          dmg_w, dmg_h, dmg_x, dmg_y,
4886          origin->w, origin->h, origin->x, origin->y);
4887
4888    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4889 }
4890
4891 /* mark an object as dirty and setup damages */
4892 E_API void
4893 e_comp_object_dirty(Evas_Object *obj)
4894 {
4895    Eina_Iterator *it;
4896    Eina_Rectangle *rect;
4897    Eina_List *ll;
4898    Evas_Object *o;
4899    int w, h, tw, th;
4900    Eina_Bool dirty, visible;
4901    E_Map *m = NULL;
4902
4903    API_ENTRY;
4904    if (cw->external_content) return;
4905    if (!cw->redirected) return;
4906    if (cw->render_update_lock.lock)
4907      {
4908         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4909         return;
4910      }
4911    /* only actually dirty if pixmap is available */
4912    if (!e_pixmap_resource_get(cw->ec->pixmap))
4913      {
4914         // e_pixmap_size_get returns last attached buffer size
4915         // eventhough it is destroyed
4916         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4917         return;
4918      }
4919    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4920    visible = cw->visible;
4921    if (!dirty) w = h = 1;
4922    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4923    if (!dirty)
4924      evas_object_image_data_set(cw->obj, NULL);
4925    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4926    evas_object_image_size_set(cw->obj, tw, th);
4927    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4928    if (cw->pending_updates)
4929      eina_tiler_area_size_set(cw->pending_updates, w, h);
4930    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4931      {
4932         evas_object_image_pixels_dirty_set(o, dirty);
4933         if (!dirty)
4934           evas_object_image_data_set(o, NULL);
4935         evas_object_image_size_set(o, tw, th);
4936         visible |= evas_object_visible_get(o);
4937      }
4938    if (!dirty)
4939      {
4940         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4941         return;
4942      }
4943
4944    e_comp_object_native_surface_set(obj, 1);
4945
4946    m = _e_comp_object_map_damage_transform_get(cw->ec);
4947    it = eina_tiler_iterator_new(cw->updates);
4948    EINA_ITERATOR_FOREACH(it, rect)
4949      {
4950         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4951          * of evas engine and doesn't convert damage according to evas_map.
4952          * so damage of evas_object_image use surface coordinate.
4953          */
4954         if (m)
4955           {
4956              int damage_x, damage_y, damage_w, damage_h;
4957
4958              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4959                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4960              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4961              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4962           }
4963         else
4964           {
4965              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4966              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4967           }
4968
4969         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4970           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4971         if (cw->pending_updates)
4972           eina_tiler_rect_add(cw->pending_updates, rect);
4973      }
4974    eina_iterator_free(it);
4975    if (m) e_map_free(m);
4976    if (cw->pending_updates)
4977      eina_tiler_clear(cw->updates);
4978    else
4979      {
4980         cw->pending_updates = cw->updates;
4981         cw->updates = eina_tiler_new(w, h);
4982         eina_tiler_tile_size_set(cw->updates, 1, 1);
4983      }
4984    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4985    evas_object_smart_callback_call(obj, "dirty", NULL);
4986    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4987    /* force render if main object is hidden but mirrors are visible */
4988    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4989    e_comp_object_render(obj);
4990 }
4991
4992 E_API Eina_Bool
4993 e_comp_object_render(Evas_Object *obj)
4994 {
4995    Eina_List *l;
4996    Evas_Object *o;
4997    int pw, ph;
4998    unsigned int *pix;
4999
5000    API_ENTRY EINA_FALSE;
5001
5002    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5003    if (cw->ec->input_only) return EINA_TRUE;
5004    if (cw->external_content) return EINA_TRUE;
5005    if (cw->native) return EINA_FALSE;
5006    /* if comp object is not redirected state, comp object should not be set by newly committed data
5007       because image size of comp object is 1x1 and it should not be shown on canvas */
5008    if (!cw->redirected) return EINA_TRUE;
5009    if (cw->render_update_lock.lock)
5010      {
5011         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5012         return EINA_TRUE;
5013      }
5014    e_comp_object_render_update_del(obj);
5015    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5016
5017    if (!cw->pending_updates)
5018      {
5019         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5020         evas_object_image_data_set(cw->obj, NULL);
5021         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5022           evas_object_image_data_set(o, NULL);
5023         return EINA_FALSE;
5024      }
5025
5026    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5027
5028    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5029
5030    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5031    if (!pix)
5032      {
5033         e_pixmap_image_refresh(cw->ec->pixmap);
5034         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5035      }
5036
5037    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5038      e_pixmap_image_data_ref(cw->ec->pixmap);
5039
5040    /* set pixel data */
5041    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5042    _e_comp_object_alpha_set(cw);
5043    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5044      {
5045         evas_object_image_data_set(o, pix);
5046         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5047         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5048      }
5049
5050    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5051
5052    e_comp_client_post_update_add(cw->ec);
5053
5054    return EINA_TRUE;
5055 }
5056
5057 /* create a duplicate of an evas object */
5058 E_API Evas_Object *
5059 e_comp_object_util_mirror_add(Evas_Object *obj)
5060 {
5061    Evas_Object *o;
5062    int w, h, tw, th;
5063    unsigned int *pix = NULL;
5064    Eina_Bool argb = EINA_FALSE;
5065
5066    SOFT_ENTRY(NULL);
5067
5068    if (!cw)
5069      cw = evas_object_data_get(obj, "comp_mirror");
5070    if (!cw)
5071      {
5072         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5073         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5074         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5075         evas_object_image_alpha_set(o, 1);
5076         evas_object_image_source_set(o, obj);
5077         return o;
5078      }
5079    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5080    if (cw->external_content)
5081      {
5082         ERR("%p of client %p is external content.", obj, cw->ec);
5083         return NULL;
5084      }
5085    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5086    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5087    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5088    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5089    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5090    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5091    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5092    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5093    evas_object_data_set(o, "comp_mirror", cw);
5094
5095    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5096    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5097
5098    evas_object_image_size_set(o, tw, th);
5099
5100    if (cw->ec->shaped)
5101      pix = evas_object_image_data_get(cw->obj, 0);
5102    else
5103      {
5104         if (cw->native)
5105           {
5106              if (cw->ns)
5107                evas_object_image_native_surface_set(o, cw->ns);
5108              else
5109                {
5110                   Evas_Native_Surface ns;
5111                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5112                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5113                     evas_object_image_native_surface_set(o, &ns);
5114                }
5115           }
5116         else
5117           {
5118              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5119              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5120              if ((argb) &&
5121                  (e_pixmap_image_exists(cw->ec->pixmap)))
5122                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5123              else
5124                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5125           }
5126      }
5127    if (pix)
5128      {
5129       Eina_Bool dirty;
5130
5131       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5132       evas_object_image_pixels_dirty_set(o, dirty);
5133       evas_object_image_data_set(o, pix);
5134       evas_object_image_data_set(cw->obj, pix);
5135       if (dirty)
5136         evas_object_image_data_update_add(o, 0, 0, tw, th);
5137    }
5138    return o;
5139 }
5140
5141 //////////////////////////////////////////////////////
5142
5143 EINTERN Eina_Bool
5144 e_comp_object_effect_allowed_get(Evas_Object *obj)
5145 {
5146    API_ENTRY EINA_FALSE;
5147
5148    if (!cw->shobj) return EINA_FALSE;
5149    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5150    return !e_comp_config_get()->match.disable_borders;
5151 }
5152
5153 /* setup an api effect for a client */
5154 E_API Eina_Bool
5155 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5156 {
5157    char buf[4096];
5158    Eina_Stringshare *grp;
5159    E_Comp_Config *config;
5160    Eina_Bool loaded = EINA_FALSE;
5161
5162    API_ENTRY EINA_FALSE;
5163    if (!cw->shobj) return EINA_FALSE; //input window
5164
5165    if (!effect) effect = "none";
5166    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5167
5168    config = e_comp_config_get();
5169    if ((config) && (config->effect_file))
5170      {
5171         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5172           {
5173              cw->effect_set = EINA_TRUE;
5174              loaded = EINA_TRUE;
5175           }
5176      }
5177
5178    if (!loaded)
5179      {
5180         edje_object_file_get(cw->effect_obj, NULL, &grp);
5181         cw->effect_set = !eina_streq(effect, "none");
5182         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5183         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5184           {
5185              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5186              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5187                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5188                  {
5189                     if (cw->effect_running)
5190                       {
5191                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5192                            return EINA_FALSE;
5193                       }
5194                     cw->effect_set = EINA_FALSE;
5195                     return cw->effect_set;
5196                  }
5197           }
5198      }
5199    if (cw->effect_running)
5200      {
5201         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5202           return EINA_FALSE;
5203      }
5204    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5205    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5206    if (cw->effect_clip)
5207      {
5208         evas_object_clip_unset(cw->clip);
5209         cw->effect_clip = 0;
5210      }
5211    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5212
5213    _e_comp_object_dim_update(cw);
5214
5215    return cw->effect_set;
5216 }
5217
5218 /* set params for embryo scripts in effect */
5219 E_API void
5220 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5221 {
5222    Edje_Message_Int_Set *msg;
5223    unsigned int x;
5224
5225    API_ENTRY;
5226    EINA_SAFETY_ON_NULL_RETURN(params);
5227    EINA_SAFETY_ON_FALSE_RETURN(count);
5228    if (!cw->effect_set) return;
5229
5230    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5231    msg->count = (int)count;
5232    for (x = 0; x < count; x++)
5233       msg->val[x] = params[x];
5234    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5235    edje_object_message_signal_process(cw->effect_obj);
5236 }
5237
5238 static void
5239 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5240 {
5241    Edje_Signal_Cb end_cb;
5242    void *end_data;
5243    E_Comp_Object *cw = data;
5244
5245    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5246    cw->effect_running = 0;
5247    if (!_e_comp_object_animating_end(cw)) return;
5248
5249    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5250      {
5251         evas_object_data_del(cw->smart_obj, "effect_running");
5252         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5253         e_comp_visibility_calculation_set(EINA_TRUE);
5254      }
5255
5256    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5257    if (!end_cb) return;
5258    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5259    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5260    end_cb(end_data, cw->smart_obj, emission, source);
5261 }
5262
5263 /* clip effect to client's zone */
5264 EINTERN void
5265 e_comp_object_effect_clip(Evas_Object *obj)
5266 {
5267    API_ENTRY;
5268    E_Zone *zone;
5269    zone = e_comp_zone_find_by_ec(cw->ec);
5270    if (!zone) return;
5271    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5272    if (!cw->effect_clip_able) return;
5273    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5274    cw->effect_clip = 1;
5275 }
5276
5277 /* unclip effect from client's zone */
5278 EINTERN void
5279 e_comp_object_effect_unclip(Evas_Object *obj)
5280 {
5281    API_ENTRY;
5282    if (!cw->effect_clip) return;
5283    evas_object_clip_unset(cw->smart_obj);
5284    cw->effect_clip = 0;
5285 }
5286
5287 /* start effect, running end_cb after */
5288 E_API Eina_Bool
5289 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5290 {
5291    API_ENTRY EINA_FALSE;
5292    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5293    if (!cw->effect_set) return EINA_FALSE;
5294
5295    if (cw->effect_running)
5296      {
5297         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5298      }
5299
5300    e_comp_object_effect_clip(obj);
5301    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5302
5303    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5304    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5305    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5306    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5307
5308    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5309    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5310
5311    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5312    _e_comp_object_animating_begin(cw);
5313    cw->effect_running = 1;
5314    return EINA_TRUE;
5315 }
5316
5317 /* stop a currently-running effect immediately */
5318 E_API Eina_Bool
5319 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5320 {
5321    int ret = 0;
5322    Edje_Signal_Cb end_cb_before = NULL;
5323    void *end_data_before = NULL;
5324    API_ENTRY EINA_FALSE;
5325
5326    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5327    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5328
5329    if (end_cb_before != end_cb) return EINA_TRUE;
5330    e_comp_object_effect_unclip(obj);
5331    if (cw->effect_clip)
5332      {
5333         evas_object_clip_unset(cw->effect_obj);
5334         cw->effect_clip = 0;
5335      }
5336    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5337    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5338
5339    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5340      {
5341         evas_object_data_del(cw->smart_obj, "effect_running");
5342         e_comp_visibility_calculation_set(EINA_TRUE);
5343      }
5344
5345    cw->effect_running = 0;
5346    ret = _e_comp_object_animating_end(cw);
5347
5348    if ((ret) && (end_cb_before))
5349      {
5350         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5351         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5352      }
5353
5354    return ret;
5355 }
5356
5357 static int
5358 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5359 {
5360    return a->pri - b->pri;
5361 }
5362
5363 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5364 E_API E_Comp_Object_Mover *
5365 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5366 {
5367    E_Comp_Object_Mover *prov;
5368
5369    prov = E_NEW(E_Comp_Object_Mover, 1);
5370    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5371    prov->func = provider;
5372    prov->data = (void*)data;
5373    prov->pri = pri;
5374    prov->sig = sig;
5375    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5376      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5377    return prov;
5378 }
5379
5380 E_API void
5381 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5382 {
5383    EINA_SAFETY_ON_NULL_RETURN(prov);
5384    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5385    free(prov);
5386 }
5387
5388 E_API Evas_Object *
5389 e_comp_object_effect_object_get(Evas_Object *obj)
5390 {
5391    API_ENTRY NULL;
5392
5393    return cw->effect_obj;
5394 }
5395
5396 E_API Eina_Bool
5397 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5398 {
5399    API_ENTRY EINA_FALSE;
5400    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5401    if (!cw->effect_set) return EINA_FALSE;
5402
5403    cw->hiding = set;
5404
5405    return EINA_TRUE;
5406 }
5407
5408 ////////////////////////////////////
5409
5410 static void
5411 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5412 {
5413    if (e_comp->autoclose.obj)
5414      {
5415         e_comp_ungrab_input(0, 1);
5416         if (e_comp->autoclose.del_cb)
5417           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5418         else if (!already_del)
5419           {
5420              evas_object_hide(e_comp->autoclose.obj);
5421              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5422           }
5423         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5424      }
5425    e_comp->autoclose.obj = NULL;
5426    e_comp->autoclose.data = NULL;
5427    e_comp->autoclose.del_cb = NULL;
5428    e_comp->autoclose.key_cb = NULL;
5429    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5430 }
5431
5432 static void
5433 _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)
5434 {
5435    _e_comp_object_autoclose_cleanup(0);
5436 }
5437
5438 static void
5439 _e_comp_object_autoclose_setup(Evas_Object *obj)
5440 {
5441    if (!e_comp->autoclose.rect)
5442      {
5443         /* create rect just below autoclose object to catch mouse events */
5444         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5445         evas_object_move(e_comp->autoclose.rect, 0, 0);
5446         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5447         evas_object_show(e_comp->autoclose.rect);
5448         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5449         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5450         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5451         e_comp_grab_input(0, 1);
5452      }
5453    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5454    evas_object_focus_set(obj, 1);
5455 }
5456
5457 static void
5458 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5459 {
5460    _e_comp_object_autoclose_setup(obj);
5461    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5462 }
5463
5464 static void
5465 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5466 {
5467    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5468    _e_comp_object_autoclose_cleanup(1);
5469    if (e_client_focused_get()) return;
5470    if (e_config->focus_policy != E_FOCUS_MOUSE)
5471      e_client_refocus();
5472 }
5473
5474 EINTERN void
5475 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5476 {
5477    SOFT_ENTRY();
5478
5479    if (e_comp->autoclose.obj)
5480      {
5481         if (e_comp->autoclose.obj == obj) return;
5482         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5483         e_comp->autoclose.obj = obj;
5484         e_comp->autoclose.del_cb = del_cb;
5485         e_comp->autoclose.key_cb = cb;
5486         e_comp->autoclose.data = (void*)data;
5487         if (evas_object_visible_get(obj))
5488           _e_comp_object_autoclose_setup(obj);
5489         else
5490           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5491         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5492         return;
5493      }
5494    e_comp->autoclose.obj = obj;
5495    e_comp->autoclose.del_cb = del_cb;
5496    e_comp->autoclose.key_cb = cb;
5497    e_comp->autoclose.data = (void*)data;
5498    if (evas_object_visible_get(obj))
5499      _e_comp_object_autoclose_setup(obj);
5500    else
5501      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5502    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5503 }
5504
5505 E_API unsigned int
5506 e_comp_object_is_animating(Evas_Object *obj)
5507 {
5508    API_ENTRY 0;
5509
5510    return cw->animating;
5511 }
5512
5513 E_API void
5514 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5515 {
5516    API_ENTRY;
5517
5518    if ((cw->external_content) &&
5519        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5520      {
5521         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5522             "But current external content is %d object for %p.",
5523             cw->content_type, cw->ec);
5524         return;
5525      }
5526
5527    cw->user_alpha_set = EINA_TRUE;
5528    cw->user_alpha = alpha;
5529
5530    if (!cw->obj) return;
5531
5532    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5533
5534    evas_object_image_alpha_set(cw->obj, alpha);
5535
5536    if ((!cw->native) && (!cw->external_content))
5537      evas_object_image_data_set(cw->obj, NULL);
5538 }
5539
5540 EINTERN Eina_Bool
5541 e_comp_object_alpha_get(Evas_Object *obj)
5542 {
5543    API_ENTRY EINA_FALSE;
5544
5545    return evas_object_image_alpha_get(cw->obj);
5546 }
5547
5548 E_API void
5549 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5550 {
5551    Eina_Bool mask_set = EINA_FALSE;
5552    Evas_Object *o;
5553
5554    API_ENTRY;
5555    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5556    if (cw->ec->input_only) return;
5557    mask_set = !!set;
5558
5559    if (mask_set)
5560      {
5561         if (!cw->mask.obj)
5562           {
5563              o = evas_object_rectangle_add(e_comp->evas);
5564              evas_object_color_set(o, 0, 0, 0, 0);
5565              evas_object_clip_set(o, cw->clip);
5566              evas_object_smart_member_add(o, obj);
5567              evas_object_move(o, 0, 0);
5568              evas_object_resize(o, cw->w, cw->h);
5569              /* save render op value to restore when clear a mask.
5570               *
5571               * NOTE: DO NOT change the render op on ec->frame while mask object
5572               * is set. it will overwrite the changed op value. */
5573              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5574              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5575              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5576              if (cw->visible) evas_object_show(o);
5577
5578              cw->mask.obj = o;
5579              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5580              ELOGF("COMP", "         |mask_obj", cw->ec);
5581              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5582           }
5583      }
5584    else
5585      {
5586         if (cw->mask.obj)
5587           {
5588              evas_object_smart_member_del(cw->mask.obj);
5589              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5590
5591              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5592              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5593           }
5594      }
5595 }
5596
5597 E_API Eina_Bool
5598 e_comp_object_mask_has(Evas_Object *obj)
5599 {
5600    API_ENTRY EINA_FALSE;
5601
5602    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5603 }
5604
5605 EINTERN void
5606 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5607 {
5608    int tw, th;
5609    API_ENTRY;
5610
5611    if ((cw->external_content) &&
5612        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5613      {
5614         WRN("Can set up size to ONLY evas \"image\" object. "
5615             "But current external content is %d object for %p.",
5616             cw->content_type, cw->ec);
5617         return;
5618      }
5619
5620    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5621
5622    evas_object_image_size_set(cw->obj, tw, th);
5623 }
5624
5625 E_API void
5626 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5627 {
5628    Eina_Bool transform_set = EINA_FALSE;
5629    API_ENTRY;
5630    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5631    if (cw->ec->input_only) return;
5632
5633    transform_set = !!set;
5634
5635    if (transform_set)
5636      {
5637         if (!cw->transform_bg_obj)
5638           {
5639              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5640              evas_object_move(o, 0, 0);
5641              evas_object_resize(o, 1, 1);
5642              if (cw->transform_bg_color.a >= 255)
5643                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5644              else
5645                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5646              evas_object_color_set(o,
5647                                    cw->transform_bg_color.r,
5648                                    cw->transform_bg_color.g,
5649                                    cw->transform_bg_color.b,
5650                                    cw->transform_bg_color.a);
5651              if (cw->visible) evas_object_show(o);
5652
5653              cw->transform_bg_obj = o;
5654              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5655           }
5656         _e_comp_object_transform_obj_stack_update(obj);
5657      }
5658    else
5659      {
5660         if (cw->transform_bg_obj)
5661           {
5662              evas_object_smart_member_del(cw->transform_bg_obj);
5663              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5664           }
5665      }
5666 }
5667
5668 E_API void
5669 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5670 {
5671    API_ENTRY;
5672
5673    cw->transform_bg_color.r = r;
5674    cw->transform_bg_color.g = g;
5675    cw->transform_bg_color.b = b;
5676    cw->transform_bg_color.a = a;
5677
5678    if (cw->transform_bg_obj)
5679      {
5680         evas_object_color_set(cw->transform_bg_obj,
5681                               cw->transform_bg_color.r,
5682                               cw->transform_bg_color.g,
5683                               cw->transform_bg_color.b,
5684                               cw->transform_bg_color.a);
5685      }
5686 }
5687
5688 EINTERN void
5689 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5690 {
5691    API_ENTRY;
5692    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5693    if (cw->ec->input_only) return;
5694    if (!cw->transform_bg_obj) return;
5695
5696    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5697 }
5698
5699 EINTERN void
5700 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5701 {
5702    API_ENTRY;
5703    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5704    if (cw->ec->input_only) return;
5705    if (!cw->transform_bg_obj) return;
5706
5707    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5708 }
5709
5710 E_API void
5711 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5712 {
5713    Eina_Bool transform_set = EINA_FALSE;
5714    API_ENTRY;
5715    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5716    if (cw->ec->input_only) return;
5717
5718    transform_set = !!set;
5719
5720    if (transform_set)
5721      {
5722         if (!cw->transform_tranp_obj)
5723           {
5724              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5725              evas_object_move(o, 0, 0);
5726              evas_object_resize(o, 1, 1);
5727              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5728              evas_object_color_set(o, 0, 0, 0, 0);
5729              if (cw->visible) evas_object_show(o);
5730
5731              cw->transform_tranp_obj = o;
5732              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5733           }
5734         _e_comp_object_transform_obj_stack_update(obj);
5735      }
5736    else
5737      {
5738         if (cw->transform_tranp_obj)
5739           {
5740              evas_object_smart_member_del(cw->transform_tranp_obj);
5741              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5742           }
5743      }
5744 }
5745
5746 EINTERN void
5747 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5748 {
5749    API_ENTRY;
5750    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5751    if (cw->ec->input_only) return;
5752    if (!cw->transform_tranp_obj) return;
5753
5754    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5755 }
5756
5757 EINTERN void
5758 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5759 {
5760    API_ENTRY;
5761    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5762    if (cw->ec->input_only) return;
5763    if (!cw->transform_tranp_obj) return;
5764
5765    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5766 }
5767
5768 EINTERN void
5769 e_comp_object_layer_update(Evas_Object *obj,
5770                            Evas_Object *above, Evas_Object *below)
5771 {
5772    E_Comp_Object *cw2 = NULL;
5773    Evas_Object *o = NULL;
5774    short layer;
5775
5776    API_ENTRY;
5777
5778    if (cw->ec->layer_block) return;
5779    if ((above) && (below))
5780      {
5781         ERR("Invalid layer update request! cw=%p", cw);
5782         return;
5783      }
5784
5785    o = above?:below;
5786
5787    if (o)
5788      {
5789         layer = evas_object_layer_get(o);
5790         cw2 = evas_object_data_get(o, "comp_obj");
5791         while (!cw2)
5792           {
5793              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5794
5795              o = evas_object_above_get(o);
5796              if ((!o) || (o == cw->smart_obj)) break;
5797              if (evas_object_layer_get(o) != layer)
5798                {
5799                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5800                }
5801              if (!o)
5802                {
5803                   E_Client *ec;
5804                   ec = e_client_top_get();
5805                   if (ec) o = ec->frame;
5806                }
5807
5808              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5809           }
5810      }
5811
5812    _e_comp_object_layers_remove(cw);
5813    if (cw2)
5814      {
5815         if (cw2->layer > cw->layer)
5816           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5817         else if (cw2->layer == cw->layer)
5818           {
5819              if (above)
5820                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5821              else if (o == obj)
5822                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5823              else if (below)
5824                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5825           }
5826         else
5827           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5828      }
5829    else
5830      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5831 }
5832
5833 EINTERN int
5834 e_comp_object_layer_get(Evas_Object *obj)
5835 {
5836    API_ENTRY -1;
5837    return cw->layer;
5838 }
5839
5840 E_API Eina_Bool
5841 e_comp_object_content_set(Evas_Object *obj,
5842                           Evas_Object *content,
5843                           E_Comp_Object_Content_Type type)
5844 {
5845    API_ENTRY EINA_FALSE;
5846
5847    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5848    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5849    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5850
5851    if (cw->obj)
5852      {
5853         ERR("Can't set e.swallow.content to requested content. "
5854             "Previous comp object should not be changed at all.");
5855         return EINA_FALSE;
5856      }
5857
5858    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5859
5860    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5861        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5862      {
5863         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5864             type, content, cw->ec, cw->ec->pixmap);
5865         return EINA_FALSE;
5866      }
5867
5868    cw->external_content = EINA_TRUE;
5869
5870    cw->obj = content;
5871    cw->content_type = type;
5872    e_util_size_debug_set(cw->obj, 1);
5873    evas_object_name_set(cw->obj, "cw->obj");
5874    _e_comp_object_alpha_set(cw);
5875
5876    if (cw->shobj)
5877      _e_comp_object_shadow_setup(cw);
5878
5879    return EINA_TRUE;
5880 }
5881
5882 EINTERN Eina_Bool
5883 e_comp_object_content_unset(Evas_Object *obj)
5884 {
5885    API_ENTRY EINA_FALSE;
5886
5887    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5888    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5889
5890    if (!cw->obj && !cw->ec->visible)
5891      {
5892         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5893         return EINA_TRUE;
5894      }
5895
5896    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5897      {
5898         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5899         return EINA_TRUE;
5900      }
5901
5902    if (cw->obj)
5903      {
5904         if (cw->frame_object)
5905           edje_object_part_unswallow(cw->frame_object, cw->obj);
5906         else if (cw->shobj)
5907           edje_object_part_unswallow(cw->shobj, cw->obj);
5908
5909         evas_object_del(cw->obj);
5910         evas_object_hide(cw->obj);
5911         cw->obj = NULL;
5912      }
5913
5914    cw->external_content = EINA_FALSE;
5915    if (cw->ec->is_cursor)
5916      {
5917         int pw, ph;
5918         DBG("%p is cursor surface..", cw->ec);
5919         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5920           pw = ph = 1;
5921         evas_object_resize(cw->ec->frame, pw, ph);
5922         evas_object_hide(cw->ec->frame);
5923         return EINA_TRUE;
5924      }
5925
5926
5927    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5928    cw->obj = evas_object_image_filled_add(e_comp->evas);
5929    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5930    e_util_size_debug_set(cw->obj, 1);
5931    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5932    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5933    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5934    evas_object_name_set(cw->obj, "cw->obj");
5935    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5936    _e_comp_object_alpha_set(cw);
5937
5938    if (cw->shobj)
5939      _e_comp_object_shadow_setup(cw);
5940
5941    if (cw->visible)
5942      {
5943         cw->visible = 0;
5944         _e_comp_intercept_show_helper(cw);
5945         cw->visible = 1;
5946      }
5947
5948    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5949    e_comp_object_dirty(cw->smart_obj);
5950    e_comp_object_render(cw->smart_obj);
5951    e_comp_object_render_update_add(obj);
5952
5953    return EINA_TRUE;
5954 }
5955
5956 EINTERN Evas_Object *
5957 e_comp_object_content_get(Evas_Object *obj)
5958 {
5959    API_ENTRY NULL;
5960
5961    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5962
5963    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5964      {
5965         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5966         return NULL;
5967      }
5968
5969    return cw->obj;
5970 }
5971
5972 E_API E_Comp_Object_Content_Type
5973 e_comp_object_content_type_get(Evas_Object *obj)
5974 {
5975    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
5976
5977    return cw->content_type;
5978 }
5979
5980 E_API void
5981 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
5982 {
5983    API_ENTRY;
5984    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5985    E_Comp_Config *conf = e_comp_config_get();
5986    if (cw->ec->input_only) return;
5987    if (!conf->dim_rect_enable) return;
5988
5989    cw->dim.mask_set = mask_set;
5990    cw->dim.mask_x = x;
5991    cw->dim.mask_y = y;
5992    cw->dim.mask_w = w;
5993    cw->dim.mask_h = h;
5994
5995    if (!cw->dim.enable) return;
5996    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
5997 }
5998
5999 EINTERN void
6000 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6001 {
6002    Eina_Bool mask_set = EINA_FALSE;
6003    Evas_Object *o;
6004
6005    API_ENTRY;
6006    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6007    E_Comp_Config *conf = e_comp_config_get();
6008    if (cw->ec->input_only) return;
6009    if (!conf->dim_rect_enable) return;
6010
6011    mask_set = !!set;
6012
6013    if (mask_set)
6014      {
6015         if (cw->dim.mask_obj)
6016           {
6017              evas_object_smart_member_del(cw->dim.mask_obj);
6018              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6019           }
6020
6021         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);
6022         o = evas_object_rectangle_add(e_comp->evas);
6023         evas_object_color_set(o, 0, 0, 0, 0);
6024         evas_object_smart_member_add(o, obj);
6025         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6026         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6027
6028         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6029         if (cw->visible) evas_object_show(o);
6030
6031         cw->dim.mask_obj = o;
6032         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6033
6034         evas_object_layer_set(cw->dim.mask_obj, 9998);
6035      }
6036    else
6037      {
6038         if (cw->dim.mask_obj)
6039           {
6040              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6041              evas_object_smart_member_del(cw->dim.mask_obj);
6042              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6043           }
6044      }
6045 }
6046
6047 E_API void
6048 e_comp_object_dim_client_set(E_Client *ec)
6049 {
6050    E_Comp_Config *conf = e_comp_config_get();
6051
6052    if (!conf->dim_rect_enable) return ;
6053    if (dim_client == ec) return;
6054
6055    Eina_Bool prev_dim = EINA_FALSE;
6056    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6057
6058    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6059       prev_dim = EINA_TRUE;
6060
6061    if (prev_dim && dim_client->visible && ec)
6062      {
6063         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6064         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6065      }
6066    else
6067      {
6068         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6069         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6070      }
6071    dim_client = ec;
6072 }
6073
6074 EINTERN E_Client *
6075 e_comp_object_dim_client_get(void)
6076 {
6077    E_Comp_Config *conf = e_comp_config_get();
6078
6079    if (!conf->dim_rect_enable ) return NULL;
6080
6081    return dim_client;
6082 }
6083
6084 static void
6085 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6086 {
6087    API_ENTRY;
6088    char emit[32] = "\0";
6089    E_Comp_Config *conf = e_comp_config_get();
6090
6091    if (!ec) return;
6092    if (!conf->dim_rect_enable) return;
6093    if (!cw->effect_obj) return;
6094    if (enable == cw->dim.enable) return;
6095
6096    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6097    if (noeffect || !conf->dim_rect_effect)
6098      {
6099         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6100      }
6101    else
6102      {
6103         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6104      }
6105
6106    cw->dim.enable = enable;
6107
6108    if (cw->dim.mask_set && !enable)
6109      {
6110         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6111         edje_object_signal_emit(cw->effect_obj, emit, "e");
6112      }
6113    else if (cw->dim.mask_set && enable)
6114      {
6115         edje_object_signal_emit(cw->effect_obj, emit, "e");
6116         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6117      }
6118    else
6119      {
6120         edje_object_signal_emit(cw->effect_obj, emit, "e");
6121      }
6122 }
6123
6124 static Eina_Bool
6125 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6126 {
6127    API_ENTRY EINA_FALSE;
6128    E_Comp_Config *conf = e_comp_config_get();
6129
6130    if (!ec) return EINA_FALSE;
6131    if (!conf->dim_rect_enable) return EINA_FALSE;
6132
6133    if (cw->dim.enable) return EINA_TRUE;
6134
6135    return EINA_FALSE;
6136 }
6137
6138 static void
6139 _e_comp_object_dim_update(E_Comp_Object *cw)
6140 {
6141    E_Comp_Config *conf = e_comp_config_get();
6142
6143    if (!cw) return;
6144    if (!conf->dim_rect_enable) return;
6145    if (!cw->effect_obj) return;
6146    if (cw->dim.enable)
6147      {
6148         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6149         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6150
6151         if (cw->dim.mask_set)
6152           {
6153              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6154           }
6155      }
6156 }
6157
6158 EINTERN void
6159 e_comp_object_clear(Evas_Object *obj)
6160 {
6161    API_ENTRY;
6162
6163    _e_comp_object_clear(cw);
6164 }
6165
6166 EINTERN Eina_Bool
6167 e_comp_object_hwc_update_exists(Evas_Object *obj)
6168 {
6169    API_ENTRY EINA_FALSE;
6170    return cw->hwc_need_update;
6171 }
6172
6173 // will remove out
6174 E_API void
6175 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6176 {
6177    API_ENTRY;
6178    cw->hwc_need_update = set;
6179 }
6180
6181 E_API Eina_Bool
6182 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6183 {
6184    API_ENTRY EINA_FALSE;
6185    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6186 }
6187
6188 EINTERN void
6189 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6190 {
6191    API_ENTRY;
6192    if (cw->indicator.obj != indicator)
6193      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6194    cw->indicator.obj = indicator;
6195    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6196 }
6197
6198 EINTERN void
6199 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6200 {
6201    API_ENTRY;
6202    if (cw->indicator.obj != indicator) return;
6203    cw->indicator.obj = NULL;
6204    edje_object_part_unswallow(cw->shobj, indicator);
6205 }
6206
6207 EINTERN void
6208 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6209 {
6210    API_ENTRY;
6211    Edje_Message_Int_Set *msg;
6212
6213    if (!cw->indicator.obj) return;
6214
6215    cw->indicator.w = w;
6216    cw->indicator.h = h;
6217
6218    if (!cw->shobj) return;
6219
6220    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6221    msg->count = 2;
6222    msg->val[0] = w;
6223    msg->val[1] = h;
6224    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6225    edje_object_message_signal_process(cw->shobj);
6226 }
6227
6228 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6229 EINTERN void
6230 e_comp_object_map_update(Evas_Object *obj)
6231 {
6232    API_ENTRY;
6233    E_Client *ec = cw->ec;
6234    E_Comp_Wl_Client_Data *cdata;
6235    E_Map *map;
6236    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6237    char buffer[128];
6238    char *p = buffer;
6239    int l, remain = sizeof buffer;
6240
6241    if (!ec) return;
6242    if (e_object_is_del(E_OBJECT(ec))) return;
6243    cdata = e_client_cdata_get(ec);
6244    if (!cdata) return;
6245
6246    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6247     * when new buffer is attached.
6248     */
6249    if (!cdata->buffer_ref.buffer) return;
6250
6251    if ((!cw->redirected) ||
6252        (e_client_video_hw_composition_check(ec)) ||
6253        (!e_comp_wl_output_buffer_transform_get(ec) &&
6254         cdata->scaler.buffer_viewport.buffer.scale == 1))
6255      {
6256         if (evas_object_map_enable_get(cw->effect_obj))
6257           {
6258              ELOGF("TRANSFORM", "map: disable", cw->ec);
6259              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6260              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6261              evas_object_resize(cw->effect_obj, tw, th);
6262           }
6263
6264         return;
6265      }
6266
6267    map = e_map_new();
6268    EINA_SAFETY_ON_NULL_RETURN(map);
6269
6270    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6271
6272    x1 = y1 = 0;
6273    x2 = bw;
6274    y2 = bh;
6275
6276    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6277
6278    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6279    e_map_point_image_uv_set(map, 0, x, y);
6280    l = snprintf(p, remain, "%d,%d", x, y);
6281    p += l, remain -= l;
6282
6283    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6284    e_map_point_image_uv_set(map, 1, x, y);
6285    l = snprintf(p, remain, " %d,%d", x, y);
6286    p += l, remain -= l;
6287
6288    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6289    e_map_point_image_uv_set(map, 2, x, y);
6290    l = snprintf(p, remain, " %d,%d", x, y);
6291    p += l, remain -= l;
6292
6293    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6294    e_map_point_image_uv_set(map, 3, x, y);
6295    l = snprintf(p, remain, " %d,%d", x, y);
6296    p += l, remain -= l;
6297
6298    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6299          cw->ec,
6300          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6301
6302    e_comp_object_map_set(cw->effect_obj, map);
6303    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6304
6305    e_map_free(map);
6306
6307    /* if there's screen rotation with comp mode, then ec->effect_obj and
6308     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6309     */
6310    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6311    evas_object_resize(cw->effect_obj, tw, th);
6312 }
6313
6314 EINTERN Eina_Bool
6315 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6316 {
6317    API_ENTRY EINA_FALSE;
6318
6319    cw->render_trace = set;
6320
6321    return EINA_TRUE;
6322 }
6323
6324 E_API Eina_Bool
6325 e_comp_object_native_usable_get(Evas_Object *obj)
6326 {
6327    API_ENTRY EINA_FALSE;
6328    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6329
6330    if (cw->ec->input_only) return EINA_FALSE;
6331    if (cw->external_content) return EINA_FALSE;
6332    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6333
6334    /* just return true value, if it is normal case */
6335    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6336
6337    /* abnormal case */
6338    Evas_Native_Surface *ns;
6339    ns = evas_object_image_native_surface_get(cw->obj);
6340
6341    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6342    if (ns)
6343      {
6344         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6345         return EINA_TRUE;
6346      }
6347
6348    return EINA_FALSE;
6349 }
6350
6351 EINTERN Eina_Bool
6352 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6353 {
6354    API_ENTRY EINA_FALSE;
6355    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6356    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6357    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6358
6359    switch (filter)
6360      {
6361       case E_COMP_IMAGE_FILTER_BLUR:
6362          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6363          break;
6364       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6365          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6366          break;
6367       case E_COMP_IMAGE_FILTER_INVERSE:
6368          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6369          break;
6370       case E_COMP_IMAGE_FILTER_NONE:
6371       default:
6372          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6373          break;
6374      }
6375
6376    cw->image_filter = filter;
6377
6378    return EINA_TRUE;
6379 }
6380
6381 EINTERN E_Comp_Image_Filter
6382 e_comp_object_image_filter_get(Evas_Object *obj)
6383 {
6384    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6385    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6386    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6387    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6388
6389    return cw->image_filter;
6390 }
6391
6392 static void
6393 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6394 {
6395    Evas_Object *obj;
6396
6397    if (!_damage_trace) return;
6398
6399    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6400      evas_object_del(obj);
6401
6402    _damage_trace_post_objs = NULL;
6403 }
6404
6405 static void
6406 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6407 {
6408    if (!_damage_trace) return;
6409
6410    _damage_trace_post_objs = _damage_trace_objs;
6411    _damage_trace_objs = NULL;
6412 }
6413
6414 EINTERN void
6415 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6416 {
6417    if (_damage_trace == onoff) return;
6418
6419    if (onoff)
6420      {
6421         evas_event_callback_add(e_comp->evas,
6422                                 EVAS_CALLBACK_RENDER_PRE,
6423                                 _e_comp_object_damage_trace_render_pre_cb,
6424                                 NULL);
6425
6426         evas_event_callback_add(e_comp->evas,
6427                                 EVAS_CALLBACK_RENDER_POST,
6428                                 _e_comp_object_damage_trace_render_post_cb,
6429                                 NULL);
6430      }
6431    else
6432      {
6433         Evas_Object *obj;
6434
6435         EINA_LIST_FREE(_damage_trace_objs, obj)
6436           evas_object_del(obj);
6437
6438         _damage_trace_objs = NULL;
6439
6440         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6441           evas_object_del(obj);
6442
6443         _damage_trace_post_objs = NULL;
6444
6445         evas_event_callback_del(e_comp->evas,
6446                                 EVAS_CALLBACK_RENDER_PRE,
6447                                 _e_comp_object_damage_trace_render_pre_cb);
6448
6449         evas_event_callback_del(e_comp->evas,
6450                                 EVAS_CALLBACK_RENDER_POST,
6451                                 _e_comp_object_damage_trace_render_post_cb);
6452      }
6453
6454    _damage_trace = onoff;
6455 }
6456
6457 EINTERN Eina_Bool
6458 e_comp_object_redirected_get(Evas_Object *obj)
6459 {
6460    API_ENTRY EINA_FALSE;
6461    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6462
6463    return cw->redirected;
6464 }
6465
6466 EINTERN Eina_Bool
6467 e_comp_object_color_visible_get(Evas_Object *obj)
6468 {
6469    API_ENTRY EINA_FALSE;
6470    int a;
6471
6472    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6473
6474    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6475    if (a <= 0)
6476      return EINA_FALSE;
6477
6478    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6479    if (a <= 0)
6480      return EINA_FALSE;
6481
6482    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6483    if (a <= 0)
6484      return EINA_FALSE;
6485
6486    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6487    if (a <= 0)
6488      return EINA_FALSE;
6489
6490    return EINA_TRUE;
6491 }
6492
6493 E_API Eina_Bool
6494 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6495 {
6496    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6497
6498    return e_map_set_to_comp_object(em, obj);
6499 }
6500
6501 EINTERN E_Map *
6502 e_comp_object_map_get(const Evas_Object *obj)
6503 {
6504    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6505
6506    return e_map_get_from_comp_object(obj);
6507 }
6508
6509 E_API Eina_Bool
6510 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6511 {
6512    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6513
6514    evas_object_map_enable_set(obj, enable);
6515
6516    return EINA_TRUE;
6517 }
6518
6519 E_API Eina_Bool
6520 e_comp_object_render_update_lock(Evas_Object *obj)
6521 {
6522    E_Comp_Wl_Buffer *buffer;
6523    struct wayland_tbm_client_queue *cqueue;
6524
6525    API_ENTRY EINA_FALSE;
6526
6527    if (cw->render_update_lock.lock == 0)
6528      {
6529         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6530
6531         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6532         if ((buffer) && (buffer->resource))
6533           {
6534              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6535              if (cqueue)
6536                wayland_tbm_server_client_queue_flush(cqueue);
6537           }
6538
6539         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6540         e_comp_object_render_update_del(obj);
6541
6542         ELOGF("COMP", "Render update lock enabled", cw->ec);
6543      }
6544
6545    cw->render_update_lock.lock++;
6546
6547    return EINA_TRUE;
6548 }
6549
6550 E_API void
6551 e_comp_object_render_update_unlock(Evas_Object *obj)
6552 {
6553    API_ENTRY;
6554
6555    if (cw->render_update_lock.lock == 0)
6556      return;
6557
6558    cw->render_update_lock.lock--;
6559
6560    if (cw->render_update_lock.lock == 0)
6561      {
6562
6563         if (cw->render_update_lock.pending_move_set)
6564           {
6565              evas_object_move(obj,
6566                               cw->render_update_lock.pending_move_x,
6567                               cw->render_update_lock.pending_move_y);
6568              cw->render_update_lock.pending_move_x = 0;
6569              cw->render_update_lock.pending_move_y = 0;
6570              cw->render_update_lock.pending_move_set = EINA_FALSE;
6571           }
6572
6573         if (cw->render_update_lock.pending_resize_set)
6574           {
6575              evas_object_resize(obj,
6576                                 cw->render_update_lock.pending_resize_w,
6577                                 cw->render_update_lock.pending_resize_h);
6578              cw->render_update_lock.pending_resize_w = 0;
6579              cw->render_update_lock.pending_resize_h = 0;
6580              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6581           }
6582
6583         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6584
6585         if ((cw->ec->exp_iconify.buffer_flush) &&
6586             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6587             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6588           e_comp_object_clear(obj);
6589         else
6590           e_comp_object_render_update_add(obj);
6591
6592         ELOGF("COMP", "Render update lock disabled", cw->ec);
6593      }
6594 }
6595
6596 E_API Eina_Bool
6597 e_comp_object_render_update_lock_get(Evas_Object *obj)
6598 {
6599    API_ENTRY EINA_FALSE;
6600
6601    if (cw->render_update_lock.lock > 0)
6602      return EINA_TRUE;
6603
6604    return EINA_FALSE;
6605 }
6606
6607 E_API void
6608 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6609 {
6610    API_ENTRY;
6611
6612    if (cw->transparent.set)
6613      {
6614         if (r) *r = cw->transparent.user_r;
6615         if (g) *g = cw->transparent.user_g;
6616         if (b) *b = cw->transparent.user_b;
6617         if (a) *a = cw->transparent.user_a;
6618      }
6619    else
6620      {
6621         evas_object_color_get(obj, r, g, b, a);
6622      }
6623 }
6624
6625 EINTERN void
6626 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6627 {
6628    API_ENTRY;
6629
6630    evas_object_render_op_set(cw->obj, op);
6631 }
6632
6633 EINTERN Evas_Render_Op
6634 e_comp_object_render_op_get(Evas_Object *obj)
6635 {
6636    API_ENTRY EVAS_RENDER_BLEND;
6637
6638    return evas_object_render_op_get(cw->obj);
6639 }