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