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