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