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