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