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