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