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